summaryrefslogtreecommitdiffstats
path: root/servers/slapd/back-sock
diff options
context:
space:
mode:
Diffstat (limited to 'servers/slapd/back-sock')
-rw-r--r--servers/slapd/back-sock/Makefile.in47
-rw-r--r--servers/slapd/back-sock/add.c69
-rw-r--r--servers/slapd/back-sock/back-sock.h61
-rw-r--r--servers/slapd/back-sock/bind.c80
-rw-r--r--servers/slapd/back-sock/compare.c88
-rw-r--r--servers/slapd/back-sock/config.c452
-rw-r--r--servers/slapd/back-sock/delete.c75
-rw-r--r--servers/slapd/back-sock/extended.c76
-rw-r--r--servers/slapd/back-sock/init.c97
-rw-r--r--servers/slapd/back-sock/modify.c117
-rw-r--r--servers/slapd/back-sock/modrdn.c81
-rw-r--r--servers/slapd/back-sock/opensock.c71
-rw-r--r--servers/slapd/back-sock/proto-sock.h49
-rw-r--r--servers/slapd/back-sock/result.c168
-rw-r--r--servers/slapd/back-sock/search.c74
-rw-r--r--servers/slapd/back-sock/searchexample.conf23
-rw-r--r--servers/slapd/back-sock/searchexample.pl90
-rw-r--r--servers/slapd/back-sock/unbind.c57
18 files changed, 1775 insertions, 0 deletions
diff --git a/servers/slapd/back-sock/Makefile.in b/servers/slapd/back-sock/Makefile.in
new file mode 100644
index 0000000..1db07bf
--- /dev/null
+++ b/servers/slapd/back-sock/Makefile.in
@@ -0,0 +1,47 @@
+# Makefile.in for back-sock
+# $OpenLDAP$
+## This work is part of OpenLDAP Software <http://www.openldap.org/>.
+##
+## Copyright 2007-2022 The OpenLDAP Foundation.
+## 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 Brian Candler for inclusion
+## in OpenLDAP Software.
+
+SRCS = init.c config.c opensock.c search.c bind.c unbind.c add.c \
+ delete.c modify.c modrdn.c compare.c result.c extended.c
+OBJS = init.lo config.lo opensock.lo search.lo bind.lo unbind.lo add.lo \
+ delete.lo modify.lo modrdn.lo compare.lo result.lo extended.lo
+
+LDAP_INCDIR= ../../../include
+LDAP_LIBDIR= ../../../libraries
+
+BUILD_OPT = "--enable-sock"
+BUILD_MOD = @BUILD_SOCK@
+
+mod_DEFS = -DSLAPD_IMPORT
+MOD_DEFS = $(@BUILD_SOCK@_DEFS)
+
+shared_LDAP_LIBS = $(LDAP_LIBLDAP_LA) $(LDAP_LIBLBER_LA)
+NT_LINK_LIBS = -L.. -lslapd $(@BUILD_LIBS_DYNAMIC@_LDAP_LIBS)
+UNIX_LINK_LIBS = $(@BUILD_LIBS_DYNAMIC@_LDAP_LIBS)
+
+LIBBASE = back_sock
+
+XINCPATH = -I.. -I$(srcdir)/..
+XDEFS = $(MODULES_CPPFLAGS)
+
+all-local-lib: ../.backend
+
+../.backend: lib$(LIBBASE).a
+ @touch $@
+
diff --git a/servers/slapd/back-sock/add.c b/servers/slapd/back-sock/add.c
new file mode 100644
index 0000000..0e96d95
--- /dev/null
+++ b/servers/slapd/back-sock/add.c
@@ -0,0 +1,69 @@
+/* add.c - sock backend add function */
+/* $OpenLDAP$ */
+/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
+ *
+ * Copyright 2007-2022 The OpenLDAP Foundation.
+ * 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 Brian Candler for inclusion
+ * in OpenLDAP Software.
+ */
+
+#include "portable.h"
+
+#include <stdio.h>
+
+#include <ac/string.h>
+#include <ac/socket.h>
+
+#include "slap.h"
+#include "back-sock.h"
+
+int
+sock_back_add(
+ Operation *op,
+ SlapReply *rs )
+{
+ struct sockinfo *si = (struct sockinfo *) op->o_bd->be_private;
+ AttributeDescription *entry = slap_schema.si_ad_entry;
+ FILE *fp;
+ int len;
+
+ if ( ! access_allowed( op, op->oq_add.rs_e,
+ entry, NULL, ACL_WADD, NULL ) )
+ {
+ send_ldap_error( op, rs, LDAP_INSUFFICIENT_ACCESS, NULL );
+ return -1;
+ }
+
+ if ( (fp = opensock( si->si_sockpath )) == NULL ) {
+ send_ldap_error( op, rs, LDAP_OTHER,
+ "could not open socket" );
+ return( -1 );
+ }
+
+ /* write out the request to the add process */
+ fprintf( fp, "ADD\n" );
+ fprintf( fp, "msgid: %ld\n", (long) op->o_msgid );
+ sock_print_conn( fp, op->o_conn, si );
+ sock_print_suffixes( fp, op->o_bd );
+ ldap_pvt_thread_mutex_lock( &entry2str_mutex );
+ fprintf( fp, "%s", entry2str( op->oq_add.rs_e, &len ) );
+ ldap_pvt_thread_mutex_unlock( &entry2str_mutex );
+ fprintf (fp, "\n" );
+
+ /* read in the result and send it along */
+ sock_read_and_send_results( op, rs, fp );
+
+ fclose( fp );
+ return( 0 );
+}
diff --git a/servers/slapd/back-sock/back-sock.h b/servers/slapd/back-sock/back-sock.h
new file mode 100644
index 0000000..55dbe75
--- /dev/null
+++ b/servers/slapd/back-sock/back-sock.h
@@ -0,0 +1,61 @@
+/* sock.h - socket backend header file */
+/* $OpenLDAP$ */
+/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
+ *
+ * Copyright 2007-2022 The OpenLDAP Foundation.
+ * 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 Brian Candler for inclusion
+ * in OpenLDAP Software.
+ */
+
+#ifndef SLAPD_SOCK_H
+#define SLAPD_SOCK_H
+
+#include "proto-sock.h"
+
+LDAP_BEGIN_DECL
+
+struct sockinfo {
+ const char *si_sockpath;
+ slap_mask_t si_extensions;
+ slap_mask_t si_ops; /* overlay: operations to act on */
+ slap_mask_t si_resps; /* overlay: responses to forward */
+ regex_t si_dnpat; /* overlay: DN pattern to match */
+ struct berval si_dnpatstr;
+};
+
+#define SOCK_EXT_BINDDN 1
+#define SOCK_EXT_PEERNAME 2
+#define SOCK_EXT_SSF 4
+#define SOCK_EXT_CONNID 8
+
+extern FILE *opensock LDAP_P((
+ const char *sockpath));
+
+extern void sock_print_suffixes LDAP_P((
+ FILE *fp,
+ BackendDB *bd));
+
+extern void sock_print_conn LDAP_P((
+ FILE *fp,
+ Connection *conn,
+ struct sockinfo *si));
+
+extern int sock_read_and_send_results LDAP_P((
+ Operation *op,
+ SlapReply *rs,
+ FILE *fp));
+
+LDAP_END_DECL
+
+#endif
diff --git a/servers/slapd/back-sock/bind.c b/servers/slapd/back-sock/bind.c
new file mode 100644
index 0000000..8e8ec97
--- /dev/null
+++ b/servers/slapd/back-sock/bind.c
@@ -0,0 +1,80 @@
+/* bind.c - sock backend bind function */
+/* $OpenLDAP$ */
+/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
+ *
+ * Copyright 2007-2022 The OpenLDAP Foundation.
+ * 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 Brian Candler for inclusion
+ * in OpenLDAP Software.
+ */
+
+#include "portable.h"
+
+#include <stdio.h>
+
+#include <ac/socket.h>
+#include <ac/string.h>
+
+#include "slap.h"
+#include "back-sock.h"
+
+int
+sock_back_bind(
+ Operation *op,
+ SlapReply *rs )
+{
+ struct sockinfo *si = (struct sockinfo *) op->o_bd->be_private;
+ AttributeDescription *entry = slap_schema.si_ad_entry;
+ Entry e;
+ FILE *fp;
+ int rc;
+
+ e.e_id = NOID;
+ e.e_name = op->o_req_dn;
+ e.e_nname = op->o_req_ndn;
+ e.e_attrs = NULL;
+ e.e_ocflags = 0;
+ e.e_bv.bv_len = 0;
+ e.e_bv.bv_val = NULL;
+ e.e_private = NULL;
+
+ if ( ! access_allowed( op, &e,
+ entry, NULL, ACL_AUTH, NULL ) )
+ {
+ send_ldap_error( op, rs, LDAP_INSUFFICIENT_ACCESS, NULL );
+ return -1;
+ }
+
+ if ( (fp = opensock( si->si_sockpath )) == NULL ) {
+ send_ldap_error( op, rs, LDAP_OTHER,
+ "could not open socket" );
+ return( -1 );
+ }
+
+ /* write out the request to the bind process */
+ fprintf( fp, "BIND\n" );
+ fprintf( fp, "msgid: %ld\n", (long) op->o_msgid );
+ sock_print_conn( fp, op->o_conn, si );
+ sock_print_suffixes( fp, op->o_bd );
+ fprintf( fp, "dn: %s\n", op->o_req_dn.bv_val );
+ fprintf( fp, "method: %d\n", op->oq_bind.rb_method );
+ fprintf( fp, "credlen: %lu\n", op->oq_bind.rb_cred.bv_len );
+ fprintf( fp, "cred: %s\n", op->oq_bind.rb_cred.bv_val ); /* XXX */
+ fprintf( fp, "\n" );
+
+ /* read in the results and send them along */
+ rc = sock_read_and_send_results( op, rs, fp );
+ fclose( fp );
+
+ return( rc );
+}
diff --git a/servers/slapd/back-sock/compare.c b/servers/slapd/back-sock/compare.c
new file mode 100644
index 0000000..735e688
--- /dev/null
+++ b/servers/slapd/back-sock/compare.c
@@ -0,0 +1,88 @@
+/* compare.c - sock backend compare function */
+/* $OpenLDAP$ */
+/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
+ *
+ * Copyright 1998-2022 The OpenLDAP Foundation.
+ * 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 Brian Candler for inclusion
+ * in OpenLDAP Software.
+ */
+
+#include "portable.h"
+
+#include <stdio.h>
+
+#include <ac/string.h>
+#include <ac/socket.h>
+
+#include "slap.h"
+#include "back-sock.h"
+#include "ldif.h"
+
+int
+sock_back_compare(
+ Operation *op,
+ SlapReply *rs )
+{
+ struct sockinfo *si = (struct sockinfo *) op->o_bd->be_private;
+ AttributeDescription *entry = slap_schema.si_ad_entry;
+ Entry e;
+ FILE *fp;
+ char *text;
+
+ e.e_id = NOID;
+ e.e_name = op->o_req_dn;
+ e.e_nname = op->o_req_ndn;
+ e.e_attrs = NULL;
+ e.e_ocflags = 0;
+ e.e_bv.bv_len = 0;
+ e.e_bv.bv_val = NULL;
+ e.e_private = NULL;
+
+ if ( ! access_allowed( op, &e,
+ entry, NULL, ACL_COMPARE, NULL ) )
+ {
+ send_ldap_error( op, rs, LDAP_INSUFFICIENT_ACCESS, NULL );
+ return -1;
+ }
+
+ if ( (fp = opensock( si->si_sockpath )) == NULL ) {
+ send_ldap_error( op, rs, LDAP_OTHER,
+ "could not open socket" );
+ return( -1 );
+ }
+
+ /* write out the request to the compare process */
+ fprintf( fp, "COMPARE\n" );
+ fprintf( fp, "msgid: %ld\n", (long) op->o_msgid );
+ sock_print_conn( fp, op->o_conn, si );
+ sock_print_suffixes( fp, op->o_bd );
+ fprintf( fp, "dn: %s\n", op->o_req_dn.bv_val );
+ /* could be binary */
+ text = ldif_put_wrap( LDIF_PUT_VALUE,
+ op->orc_ava->aa_desc->ad_cname.bv_val,
+ op->orc_ava->aa_value.bv_val,
+ op->orc_ava->aa_value.bv_len, LDIF_LINE_WIDTH_MAX );
+ if ( text ) {
+ fprintf( fp, "%s\n", text );
+ ber_memfree( text );
+ } else {
+ fprintf( fp, "\n\n" );
+ }
+
+ /* read in the result and send it along */
+ sock_read_and_send_results( op, rs, fp );
+
+ fclose( fp );
+ return( 0 );
+}
diff --git a/servers/slapd/back-sock/config.c b/servers/slapd/back-sock/config.c
new file mode 100644
index 0000000..e6d3183
--- /dev/null
+++ b/servers/slapd/back-sock/config.c
@@ -0,0 +1,452 @@
+/* config.c - sock backend configuration file routine */
+/* $OpenLDAP$ */
+/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
+ *
+ * Copyright 2007-2022 The OpenLDAP Foundation.
+ * 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 Brian Candler for inclusion
+ * in OpenLDAP Software. Dynamic config support by Howard Chu.
+ */
+
+#include "portable.h"
+
+#include <stdio.h>
+
+#include <ac/string.h>
+#include <ac/socket.h>
+
+#include "slap.h"
+#include "slap-config.h"
+#include "back-sock.h"
+
+static ConfigDriver bs_cf_gen;
+static int sock_over_setup();
+static slap_response sock_over_response;
+
+enum {
+ BS_EXT = 1,
+ BS_OPS,
+ BS_RESP,
+ BS_DNPAT
+};
+
+/* The number of overlay-only config attrs */
+#define NUM_OV_ATTRS 3
+
+static ConfigTable bscfg[] = {
+ { "sockops", "ops", 2, 0, 0, ARG_MAGIC|BS_OPS,
+ bs_cf_gen, "( OLcfgDbAt:7.3 NAME 'olcOvSocketOps' "
+ "DESC 'Operation types to forward' "
+ "EQUALITY caseIgnoreMatch "
+ "SYNTAX OMsDirectoryString )", NULL, NULL },
+ { "sockresps", "resps", 2, 0, 0, ARG_MAGIC|BS_RESP,
+ bs_cf_gen, "( OLcfgDbAt:7.4 NAME 'olcOvSocketResps' "
+ "DESC 'Response types to forward' "
+ "EQUALITY caseIgnoreMatch "
+ "SYNTAX OMsDirectoryString )", NULL, NULL },
+ { "sockdnpat", "regexp", 2, 2, 0, ARG_MAGIC|BS_DNPAT,
+ bs_cf_gen, "( OLcfgDbAt:7.5 NAME 'olcOvSocketDNpat' "
+ "DESC 'DN pattern to match' "
+ "EQUALITY caseIgnoreMatch "
+ "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
+
+ { "socketpath", "pathname", 2, 2, 0, ARG_STRING|ARG_OFFSET,
+ (void *)offsetof(struct sockinfo, si_sockpath),
+ "( OLcfgDbAt:7.1 NAME 'olcDbSocketPath' "
+ "DESC 'Pathname for Unix domain socket' "
+ "EQUALITY caseExactMatch "
+ "SYNTAX OMsDirectoryString SINGLE-VALUE )", NULL, NULL },
+ { "extensions", "ext", 2, 0, 0, ARG_MAGIC|BS_EXT,
+ bs_cf_gen, "( OLcfgDbAt:7.2 NAME 'olcDbSocketExtensions' "
+ "DESC 'binddn, peername, or ssf' "
+ "EQUALITY caseIgnoreMatch "
+ "SYNTAX OMsDirectoryString )", NULL, NULL },
+ { NULL, NULL }
+};
+
+static ConfigOCs bsocs[] = {
+ { "( OLcfgDbOc:7.1 "
+ "NAME 'olcDbSocketConfig' "
+ "DESC 'Socket backend configuration' "
+ "SUP olcDatabaseConfig "
+ "MUST olcDbSocketPath "
+ "MAY olcDbSocketExtensions )",
+ Cft_Database, bscfg+NUM_OV_ATTRS },
+ { NULL, 0, NULL }
+};
+
+static ConfigOCs osocs[] = {
+ { "( OLcfgDbOc:7.2 "
+ "NAME 'olcOvSocketConfig' "
+ "DESC 'Socket overlay configuration' "
+ "SUP olcOverlayConfig "
+ "MUST olcDbSocketPath "
+ "MAY ( olcDbSocketExtensions $ "
+ " olcOvSocketOps $ olcOvSocketResps $ "
+ " olcOvSocketDNpat ) )",
+ Cft_Overlay, bscfg },
+ { NULL, 0, NULL }
+};
+
+#define SOCK_OP_BIND 0x001
+#define SOCK_OP_UNBIND 0x002
+#define SOCK_OP_SEARCH 0x004
+#define SOCK_OP_COMPARE 0x008
+#define SOCK_OP_MODIFY 0x010
+#define SOCK_OP_MODRDN 0x020
+#define SOCK_OP_ADD 0x040
+#define SOCK_OP_DELETE 0x080
+#define SOCK_OP_EXTENDED 0x100
+
+#define SOCK_REP_RESULT 0x001
+#define SOCK_REP_SEARCH 0x002
+
+static slap_verbmasks bs_exts[] = {
+ { BER_BVC("binddn"), SOCK_EXT_BINDDN },
+ { BER_BVC("peername"), SOCK_EXT_PEERNAME },
+ { BER_BVC("ssf"), SOCK_EXT_SSF },
+ { BER_BVC("connid"), SOCK_EXT_CONNID },
+ { BER_BVNULL, 0 }
+};
+
+static slap_verbmasks ov_ops[] = {
+ { BER_BVC("bind"), SOCK_OP_BIND },
+ { BER_BVC("unbind"), SOCK_OP_UNBIND },
+ { BER_BVC("search"), SOCK_OP_SEARCH },
+ { BER_BVC("compare"), SOCK_OP_COMPARE },
+ { BER_BVC("modify"), SOCK_OP_MODIFY },
+ { BER_BVC("modrdn"), SOCK_OP_MODRDN },
+ { BER_BVC("add"), SOCK_OP_ADD },
+ { BER_BVC("delete"), SOCK_OP_DELETE },
+ { BER_BVC("extended"), SOCK_OP_EXTENDED },
+ { BER_BVNULL, 0 }
+};
+
+static slap_verbmasks ov_resps[] = {
+ { BER_BVC("result"), SOCK_REP_RESULT },
+ { BER_BVC("search"), SOCK_REP_SEARCH },
+ { BER_BVNULL, 0 }
+};
+
+static int
+bs_cf_gen( ConfigArgs *c )
+{
+ struct sockinfo *si;
+ int rc;
+
+ if ( c->be && c->table == Cft_Database )
+ si = c->be->be_private;
+ else if ( c->bi )
+ si = c->bi->bi_private;
+ else
+ return ARG_BAD_CONF;
+
+ if ( c->op == SLAP_CONFIG_EMIT ) {
+ switch( c->type ) {
+ case BS_EXT:
+ return mask_to_verbs( bs_exts, si->si_extensions, &c->rvalue_vals );
+ case BS_OPS:
+ return mask_to_verbs( ov_ops, si->si_ops, &c->rvalue_vals );
+ case BS_RESP:
+ return mask_to_verbs( ov_resps, si->si_resps, &c->rvalue_vals );
+ case BS_DNPAT:
+ if ( BER_BVISEMPTY( &si->si_dnpatstr ) )
+ return 1;
+ value_add_one( &c->rvalue_vals, &si->si_dnpatstr );
+ return 0;
+ }
+ } else if ( c->op == LDAP_MOD_DELETE ) {
+ switch( c->type ) {
+ case BS_EXT:
+ if ( c->valx < 0 ) {
+ si->si_extensions = 0;
+ rc = 0;
+ } else {
+ slap_mask_t dels = 0;
+ rc = verbstring_to_mask( bs_exts, c->line, ' ', &dels );
+ if ( rc == 0 )
+ si->si_extensions &= ~dels;
+ }
+ return rc;
+ case BS_OPS:
+ if ( c->valx < 0 ) {
+ si->si_ops = 0;
+ rc = 0;
+ } else {
+ slap_mask_t dels = 0;
+ rc = verbstring_to_mask( ov_ops, c->line, ' ', &dels );
+ if ( rc == 0 )
+ si->si_ops &= ~dels;
+ }
+ return rc;
+ case BS_RESP:
+ if ( c->valx < 0 ) {
+ si->si_resps = 0;
+ rc = 0;
+ } else {
+ slap_mask_t dels = 0;
+ rc = verbstring_to_mask( ov_resps, c->line, ' ', &dels );
+ if ( rc == 0 )
+ si->si_resps &= ~dels;
+ }
+ return rc;
+ case BS_DNPAT:
+ regfree( &si->si_dnpat );
+ ch_free( si->si_dnpatstr.bv_val );
+ BER_BVZERO( &si->si_dnpatstr );
+ return 0;
+ }
+
+ } else {
+ switch( c->type ) {
+ case BS_EXT: {
+ slap_mask_t adds = 0;
+ if ( verbs_to_mask( c->argc, c->argv, bs_exts, &adds ) ) {
+ return LDAP_INVALID_SYNTAX;
+ }
+ /* Tolerate overlaps in slapd.conf */
+ if ( c->op != SLAP_CONFIG_ADD && adds & si->si_extensions ) {
+ return LDAP_TYPE_OR_VALUE_EXISTS;
+ }
+ si->si_extensions |= adds;
+ return 0;
+ }
+ case BS_OPS: {
+ slap_mask_t adds = 0;
+ if ( verbs_to_mask( c->argc, c->argv, ov_ops, &adds ) ) {
+ return LDAP_INVALID_SYNTAX;
+ }
+ /* Tolerate overlaps in slapd.conf */
+ if ( c->op != SLAP_CONFIG_ADD && adds & si->si_ops ) {
+ return LDAP_TYPE_OR_VALUE_EXISTS;
+ }
+ si->si_ops |= adds;
+ return 0;
+ }
+ case BS_RESP: {
+ slap_mask_t adds = 0;
+ if ( verbs_to_mask( c->argc, c->argv, ov_resps, &adds ) ) {
+ return LDAP_INVALID_SYNTAX;
+ }
+ /* Tolerate overlaps in slapd.conf */
+ if ( c->op != SLAP_CONFIG_ADD && adds & si->si_resps ) {
+ return LDAP_TYPE_OR_VALUE_EXISTS;
+ }
+ si->si_resps |= adds;
+ return 0;
+ }
+ case BS_DNPAT:
+ if ( !regcomp( &si->si_dnpat, c->argv[1], REG_EXTENDED|REG_ICASE|REG_NOSUB )) {
+ ber_str2bv( c->argv[1], 0, 1, &si->si_dnpatstr );
+ return 0;
+ } else {
+ return 1;
+ }
+ }
+ }
+ return 1;
+}
+
+int
+sock_back_init_cf( BackendInfo *bi )
+{
+ int rc;
+ bi->bi_cf_ocs = bsocs;
+
+ rc = config_register_schema( bscfg, bsocs );
+ if ( !rc )
+ rc = sock_over_setup();
+ return rc;
+}
+
+/* sock overlay wrapper */
+static slap_overinst sockover;
+
+static int sock_over_db_init( Backend *be, struct config_reply_s *cr );
+static int sock_over_db_destroy( Backend *be, struct config_reply_s *cr );
+
+static BI_op_bind *sockfuncs[] = {
+ sock_back_bind,
+ sock_back_unbind,
+ sock_back_search,
+ sock_back_compare,
+ sock_back_modify,
+ sock_back_modrdn,
+ sock_back_add,
+ sock_back_delete,
+ 0, /* abandon not supported */
+ sock_back_extended
+};
+
+static const int sockopflags[] = {
+ SOCK_OP_BIND,
+ SOCK_OP_UNBIND,
+ SOCK_OP_SEARCH,
+ SOCK_OP_COMPARE,
+ SOCK_OP_MODIFY,
+ SOCK_OP_MODRDN,
+ SOCK_OP_ADD,
+ SOCK_OP_DELETE,
+ 0, /* abandon not supported */
+ SOCK_OP_EXTENDED
+};
+
+static int sock_over_op(
+ Operation *op,
+ SlapReply *rs
+)
+{
+ slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
+ void *private = op->o_bd->be_private;
+ slap_callback *sc;
+ struct sockinfo *si;
+ slap_operation_t which;
+
+ switch (op->o_tag) {
+ case LDAP_REQ_BIND: which = op_bind; break;
+ case LDAP_REQ_UNBIND: which = op_unbind; break;
+ case LDAP_REQ_SEARCH: which = op_search; break;
+ case LDAP_REQ_COMPARE: which = op_compare; break;
+ case LDAP_REQ_MODIFY: which = op_modify; break;
+ case LDAP_REQ_MODRDN: which = op_modrdn; break;
+ case LDAP_REQ_ADD: which = op_add; break;
+ case LDAP_REQ_DELETE: which = op_delete; break;
+ case LDAP_REQ_EXTENDED: which = op_extended; break;
+ default:
+ return SLAP_CB_CONTINUE;
+ }
+ si = on->on_bi.bi_private;
+ if ( !(si->si_ops & sockopflags[which]))
+ return SLAP_CB_CONTINUE;
+
+ if ( !BER_BVISEMPTY( &si->si_dnpatstr ) &&
+ regexec( &si->si_dnpat, op->o_req_ndn.bv_val, 0, NULL, 0 ))
+ return SLAP_CB_CONTINUE;
+
+ op->o_bd->be_private = si;
+ sc = op->o_callback;
+ op->o_callback = NULL;
+ sockfuncs[which]( op, rs );
+ op->o_bd->be_private = private;
+ op->o_callback = sc;
+ return rs->sr_err;
+}
+
+static int
+sock_over_response( Operation *op, SlapReply *rs )
+{
+ slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
+ struct sockinfo *si = (struct sockinfo *)on->on_bi.bi_private;
+ FILE *fp;
+
+ if ( rs->sr_type == REP_RESULT ) {
+ if ( !( si->si_resps & SOCK_REP_RESULT ))
+ return SLAP_CB_CONTINUE;
+ } else if ( rs->sr_type == REP_SEARCH ) {
+ if ( !( si->si_resps & SOCK_REP_SEARCH ))
+ return SLAP_CB_CONTINUE;
+ } else
+ return SLAP_CB_CONTINUE;
+
+ if (( fp = opensock( si->si_sockpath )) == NULL )
+ return SLAP_CB_CONTINUE;
+
+ if ( rs->sr_type == REP_RESULT ) {
+ /* write out the result */
+ fprintf( fp, "RESULT\n" );
+ fprintf( fp, "msgid: %ld\n", (long) op->o_msgid );
+ sock_print_conn( fp, op->o_conn, si );
+ fprintf( fp, "code: %d\n", rs->sr_err );
+ if ( rs->sr_matched )
+ fprintf( fp, "matched: %s\n", rs->sr_matched );
+ if (rs->sr_text )
+ fprintf( fp, "info: %s\n", rs->sr_text );
+ } else {
+ /* write out the search entry */
+ int len;
+ fprintf( fp, "ENTRY\n" );
+ fprintf( fp, "msgid: %ld\n", (long) op->o_msgid );
+ sock_print_conn( fp, op->o_conn, si );
+ ldap_pvt_thread_mutex_lock( &entry2str_mutex );
+ fprintf( fp, "%s", entry2str( rs->sr_entry, &len ) );
+ ldap_pvt_thread_mutex_unlock( &entry2str_mutex );
+ }
+ fprintf( fp, "\n" );
+ fclose( fp );
+
+ return SLAP_CB_CONTINUE;
+}
+
+static int
+sock_over_setup()
+{
+ int rc;
+
+ sockover.on_bi.bi_type = "sock";
+ sockover.on_bi.bi_db_init = sock_over_db_init;
+ sockover.on_bi.bi_db_destroy = sock_over_db_destroy;
+
+ sockover.on_bi.bi_op_bind = sock_over_op;
+ sockover.on_bi.bi_op_unbind = sock_over_op;
+ sockover.on_bi.bi_op_search = sock_over_op;
+ sockover.on_bi.bi_op_compare = sock_over_op;
+ sockover.on_bi.bi_op_modify = sock_over_op;
+ sockover.on_bi.bi_op_modrdn = sock_over_op;
+ sockover.on_bi.bi_op_add = sock_over_op;
+ sockover.on_bi.bi_op_delete = sock_over_op;
+ sockover.on_bi.bi_extended = sock_over_op;
+ sockover.on_response = sock_over_response;
+
+ sockover.on_bi.bi_cf_ocs = osocs;
+
+ rc = config_register_schema( bscfg, osocs );
+ if ( rc ) return rc;
+
+ return overlay_register( &sockover );
+}
+
+static int
+sock_over_db_init(
+ Backend *be,
+ struct config_reply_s *cr
+)
+{
+ slap_overinst *on = (slap_overinst *)be->bd_info;
+ void *private = be->be_private;
+ void *cf_ocs = be->be_cf_ocs;
+ int rc;
+
+ be->be_private = NULL;
+ rc = sock_back_db_init( be, cr );
+ on->on_bi.bi_private = be->be_private;
+ be->be_private = private;
+ be->be_cf_ocs = cf_ocs;
+ return rc;
+}
+
+static int
+sock_over_db_destroy(
+ Backend *be,
+ struct config_reply_s *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 = sock_back_db_destroy( be, cr );
+ on->on_bi.bi_private = be->be_private;
+ be->be_private = private;
+ return rc;
+}
diff --git a/servers/slapd/back-sock/delete.c b/servers/slapd/back-sock/delete.c
new file mode 100644
index 0000000..89a268f
--- /dev/null
+++ b/servers/slapd/back-sock/delete.c
@@ -0,0 +1,75 @@
+/* delete.c - sock backend delete function */
+/* $OpenLDAP$ */
+/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
+ *
+ * Copyright 2007-2022 The OpenLDAP Foundation.
+ * 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 Brian Candler for inclusion
+ * in OpenLDAP Software.
+ */
+
+#include "portable.h"
+
+#include <stdio.h>
+
+#include <ac/string.h>
+#include <ac/socket.h>
+
+#include "slap.h"
+#include "back-sock.h"
+
+int
+sock_back_delete(
+ Operation *op,
+ SlapReply *rs )
+{
+ struct sockinfo *si = (struct sockinfo *) op->o_bd->be_private;
+ AttributeDescription *entry = slap_schema.si_ad_entry;
+ Entry e;
+ FILE *fp;
+
+ e.e_id = NOID;
+ e.e_name = op->o_req_dn;
+ e.e_nname = op->o_req_ndn;
+ e.e_attrs = NULL;
+ e.e_ocflags = 0;
+ e.e_bv.bv_len = 0;
+ e.e_bv.bv_val = NULL;
+ e.e_private = NULL;
+
+ if ( ! access_allowed( op, &e,
+ entry, NULL, ACL_WDEL, NULL ) )
+ {
+ send_ldap_error( op, rs, LDAP_INSUFFICIENT_ACCESS, NULL );
+ return -1;
+ }
+
+ if ( (fp = opensock( si->si_sockpath )) == NULL ) {
+ send_ldap_error( op, rs, LDAP_OTHER,
+ "could not open socket" );
+ return( -1 );
+ }
+
+ /* write out the request to the delete process */
+ fprintf( fp, "DELETE\n" );
+ fprintf( fp, "msgid: %ld\n", (long) op->o_msgid );
+ sock_print_conn( fp, op->o_conn, si );
+ sock_print_suffixes( fp, op->o_bd );
+ fprintf( fp, "dn: %s\n", op->o_req_dn.bv_val );
+ fprintf( fp, "\n" );
+
+ /* read in the results and send them along */
+ sock_read_and_send_results( op, rs, fp );
+ fclose( fp );
+ return( 0 );
+}
diff --git a/servers/slapd/back-sock/extended.c b/servers/slapd/back-sock/extended.c
new file mode 100644
index 0000000..e065761
--- /dev/null
+++ b/servers/slapd/back-sock/extended.c
@@ -0,0 +1,76 @@
+/* extended.c - sock backend extended routines */
+/* $OpenLDAP$ */
+/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
+ *
+ * Copyright 2000-2022 The OpenLDAP Foundation.
+ * 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>.
+ */
+
+#include "portable.h"
+
+#include <stdio.h>
+#include <ac/string.h>
+
+#include "slap.h"
+#include "back-sock.h"
+
+#include "lutil.h"
+
+int
+sock_back_extended( Operation *op, SlapReply *rs )
+{
+ int rc;
+ struct sockinfo *si = (struct sockinfo *) op->o_bd->be_private;
+ FILE *fp;
+ struct berval b64;
+
+ Debug( LDAP_DEBUG_ARGS, "==> sock_back_extended(%s, %s)\n",
+ op->ore_reqoid.bv_val, op->o_req_dn.bv_val );
+
+ if ( (fp = opensock( si->si_sockpath )) == NULL ) {
+ send_ldap_error( op, rs, LDAP_OTHER,
+ "could not open socket" );
+ return( -1 );
+ }
+
+ /* write out the request to the extended process */
+ fprintf( fp, "EXTENDED\n" );
+ fprintf( fp, "msgid: %ld\n", (long) op->o_msgid );
+ sock_print_conn( fp, op->o_conn, si );
+ sock_print_suffixes( fp, op->o_bd );
+ fprintf( fp, "oid: %s\n", op->ore_reqoid.bv_val );
+
+ if (op->ore_reqdata) {
+
+ b64.bv_len = LUTIL_BASE64_ENCODE_LEN( op->ore_reqdata->bv_len ) + 1;
+ b64.bv_val = op->o_tmpalloc( b64.bv_len + 1, op->o_tmpmemctx );
+
+ rc = lutil_b64_ntop(
+ (unsigned char *) op->ore_reqdata->bv_val, op->ore_reqdata->bv_len,
+ b64.bv_val, b64.bv_len );
+
+ b64.bv_len = rc;
+ assert( strlen(b64.bv_val) == b64.bv_len );
+
+ fprintf( fp, "value: %s\n", b64.bv_val );
+
+ op->o_tmpfree( b64.bv_val, op->o_tmpmemctx );
+
+ }
+
+ fprintf( fp, "\n" );
+
+ /* read in the results and send them along */
+ rc = sock_read_and_send_results( op, rs, fp );
+ fclose( fp );
+
+ return( rc );
+}
diff --git a/servers/slapd/back-sock/init.c b/servers/slapd/back-sock/init.c
new file mode 100644
index 0000000..02b7bc8
--- /dev/null
+++ b/servers/slapd/back-sock/init.c
@@ -0,0 +1,97 @@
+/* init.c - initialize sock backend */
+/* $OpenLDAP$ */
+/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
+ *
+ * Copyright 2007-2022 The OpenLDAP Foundation.
+ * 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 Brian Candler for inclusion
+ * in OpenLDAP Software.
+ */
+
+#include "portable.h"
+
+#include <stdio.h>
+
+#include <ac/socket.h>
+
+#include "slap.h"
+#include "back-sock.h"
+
+int
+sock_back_initialize(
+ BackendInfo *bi
+)
+{
+ bi->bi_open = 0;
+ bi->bi_config = 0;
+ bi->bi_close = 0;
+ bi->bi_destroy = 0;
+
+ bi->bi_db_init = sock_back_db_init;
+ bi->bi_db_config = 0;
+ bi->bi_db_open = 0;
+ bi->bi_db_close = 0;
+ bi->bi_db_destroy = sock_back_db_destroy;
+
+ bi->bi_op_bind = sock_back_bind;
+ bi->bi_op_unbind = sock_back_unbind;
+ bi->bi_op_search = sock_back_search;
+ bi->bi_op_compare = sock_back_compare;
+ bi->bi_op_modify = sock_back_modify;
+ bi->bi_op_modrdn = sock_back_modrdn;
+ bi->bi_op_add = sock_back_add;
+ bi->bi_op_delete = sock_back_delete;
+ bi->bi_op_abandon = 0;
+
+ bi->bi_extended = sock_back_extended;
+
+ bi->bi_chk_referrals = 0;
+
+ bi->bi_connection_init = 0;
+ bi->bi_connection_destroy = 0;
+
+ return sock_back_init_cf( bi );
+}
+
+int
+sock_back_db_init(
+ Backend *be,
+ struct config_reply_s *cr
+)
+{
+ struct sockinfo *si;
+
+ si = (struct sockinfo *) ch_calloc( 1, sizeof(struct sockinfo) );
+
+ be->be_private = si;
+ be->be_cf_ocs = be->bd_info->bi_cf_ocs;
+
+ return si == NULL;
+}
+
+int
+sock_back_db_destroy(
+ Backend *be,
+ struct config_reply_s *cr
+)
+{
+ free( be->be_private );
+ return 0;
+}
+
+#if SLAPD_SOCK == SLAPD_MOD_DYNAMIC
+
+/* conditionally define the init_module() function */
+SLAP_BACKEND_INIT_MODULE( sock )
+
+#endif /* SLAPD_SOCK == SLAPD_MOD_DYNAMIC */
diff --git a/servers/slapd/back-sock/modify.c b/servers/slapd/back-sock/modify.c
new file mode 100644
index 0000000..a5ec012
--- /dev/null
+++ b/servers/slapd/back-sock/modify.c
@@ -0,0 +1,117 @@
+/* modify.c - sock backend modify function */
+/* $OpenLDAP$ */
+/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
+ *
+ * Copyright 2007-2022 The OpenLDAP Foundation.
+ * 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 Brian Candler for inclusion
+ * in OpenLDAP Software.
+ */
+
+#include "portable.h"
+
+#include <stdio.h>
+
+#include <ac/string.h>
+#include <ac/socket.h>
+
+#include "slap.h"
+#include "back-sock.h"
+#include "ldif.h"
+
+int
+sock_back_modify(
+ Operation *op,
+ SlapReply *rs )
+{
+ Modification *mod;
+ struct sockinfo *si = (struct sockinfo *) op->o_bd->be_private;
+ AttributeDescription *entry = slap_schema.si_ad_entry;
+ Modifications *ml = op->orm_modlist;
+ Entry e;
+ FILE *fp;
+ int i;
+
+ e.e_id = NOID;
+ e.e_name = op->o_req_dn;
+ e.e_nname = op->o_req_ndn;
+ e.e_attrs = NULL;
+ e.e_ocflags = 0;
+ e.e_bv.bv_len = 0;
+ e.e_bv.bv_val = NULL;
+ e.e_private = NULL;
+
+ if ( ! access_allowed( op, &e,
+ entry, NULL, ACL_WRITE, NULL ) )
+ {
+ send_ldap_error( op, rs, LDAP_INSUFFICIENT_ACCESS, NULL );
+ return -1;
+ }
+
+ if ( (fp = opensock( si->si_sockpath )) == NULL ) {
+ send_ldap_error( op, rs, LDAP_OTHER,
+ "could not open socket" );
+ return( -1 );
+ }
+
+ /* write out the request to the modify process */
+ fprintf( fp, "MODIFY\n" );
+ fprintf( fp, "msgid: %ld\n", (long) op->o_msgid );
+ sock_print_conn( fp, op->o_conn, si );
+ sock_print_suffixes( fp, op->o_bd );
+ fprintf( fp, "dn: %s\n", op->o_req_dn.bv_val );
+ for ( ; ml != NULL; ml = ml->sml_next ) {
+ mod = &ml->sml_mod;
+
+ switch ( mod->sm_op ) {
+ case LDAP_MOD_ADD:
+ fprintf( fp, "add: %s\n", mod->sm_desc->ad_cname.bv_val );
+ break;
+
+ case LDAP_MOD_DELETE:
+ fprintf( fp, "delete: %s\n", mod->sm_desc->ad_cname.bv_val );
+ break;
+
+ case LDAP_MOD_REPLACE:
+ fprintf( fp, "replace: %s\n", mod->sm_desc->ad_cname.bv_val );
+ break;
+
+ case LDAP_MOD_INCREMENT:
+ fprintf( fp, "increment: %s\n", mod->sm_desc->ad_cname.bv_val );
+ break;
+ }
+
+ if( mod->sm_values != NULL ) {
+ for ( i = 0; mod->sm_values[i].bv_val != NULL; i++ ) {
+ char *text = ldif_put_wrap( LDIF_PUT_VALUE,
+ mod->sm_desc->ad_cname.bv_val,
+ mod->sm_values[i].bv_val,
+ mod->sm_values[i].bv_len, LDIF_LINE_WIDTH_MAX );
+ if ( text ) {
+ fprintf( fp, "%s", text );
+ ber_memfree( text );
+ } else {
+ break;
+ }
+ }
+ }
+
+ fprintf( fp, "-\n" );
+ }
+ fprintf( fp, "\n" );
+
+ /* read in the results and send them along */
+ sock_read_and_send_results( op, rs, fp );
+ fclose( fp );
+ return( 0 );
+}
diff --git a/servers/slapd/back-sock/modrdn.c b/servers/slapd/back-sock/modrdn.c
new file mode 100644
index 0000000..c5a9195
--- /dev/null
+++ b/servers/slapd/back-sock/modrdn.c
@@ -0,0 +1,81 @@
+/* modrdn.c - sock backend modrdn function */
+/* $OpenLDAP$ */
+/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
+ *
+ * Copyright 2007-2022 The OpenLDAP Foundation.
+ * 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 Brian Candler for inclusion
+ * in OpenLDAP Software.
+ */
+
+#include "portable.h"
+
+#include <stdio.h>
+
+#include <ac/socket.h>
+#include <ac/string.h>
+
+#include "slap.h"
+#include "back-sock.h"
+
+int
+sock_back_modrdn(
+ Operation *op,
+ SlapReply *rs )
+{
+ struct sockinfo *si = (struct sockinfo *) op->o_bd->be_private;
+ AttributeDescription *entry = slap_schema.si_ad_entry;
+ Entry e;
+ FILE *fp;
+
+ e.e_id = NOID;
+ e.e_name = op->o_req_dn;
+ e.e_nname = op->o_req_ndn;
+ e.e_attrs = NULL;
+ e.e_ocflags = 0;
+ e.e_bv.bv_len = 0;
+ e.e_bv.bv_val = NULL;
+ e.e_private = NULL;
+
+ if ( ! access_allowed( op, &e, entry, NULL,
+ op->oq_modrdn.rs_newSup ? ACL_WDEL : ACL_WRITE,
+ NULL ) )
+ {
+ send_ldap_error( op, rs, LDAP_INSUFFICIENT_ACCESS, NULL );
+ return -1;
+ }
+
+ if ( (fp = opensock( si->si_sockpath )) == NULL ) {
+ send_ldap_error( op, rs, LDAP_OTHER,
+ "could not open socket" );
+ return( -1 );
+ }
+
+ /* write out the request to the modrdn process */
+ fprintf( fp, "MODRDN\n" );
+ fprintf( fp, "msgid: %ld\n", (long) op->o_msgid );
+ sock_print_conn( fp, op->o_conn, si );
+ sock_print_suffixes( fp, op->o_bd );
+ fprintf( fp, "dn: %s\n", op->o_req_dn.bv_val );
+ fprintf( fp, "newrdn: %s\n", op->oq_modrdn.rs_newrdn.bv_val );
+ fprintf( fp, "deleteoldrdn: %d\n", op->oq_modrdn.rs_deleteoldrdn ? 1 : 0 );
+ if ( op->oq_modrdn.rs_newSup != NULL ) {
+ fprintf( fp, "newSuperior: %s\n", op->oq_modrdn.rs_newSup->bv_val );
+ }
+ fprintf( fp, "\n" );
+
+ /* read in the results and send them along */
+ sock_read_and_send_results( op, rs, fp );
+ fclose( fp );
+ return( 0 );
+}
diff --git a/servers/slapd/back-sock/opensock.c b/servers/slapd/back-sock/opensock.c
new file mode 100644
index 0000000..9b4826d
--- /dev/null
+++ b/servers/slapd/back-sock/opensock.c
@@ -0,0 +1,71 @@
+/* opensock.c - open a unix domain socket */
+/* $OpenLDAP$ */
+/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
+ *
+ * Copyright 2007-2022 The OpenLDAP Foundation.
+ * 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 Brian Candler for inclusion
+ * in OpenLDAP Software.
+ */
+
+#include "portable.h"
+
+#include <stdio.h>
+
+#include <ac/errno.h>
+#include <ac/string.h>
+#include <ac/socket.h>
+#include <ac/unistd.h>
+
+#include "slap.h"
+#include "back-sock.h"
+
+/*
+ * FIXME: count the number of concurrent open sockets (since each thread
+ * may open one). Perhaps block here if a soft limit is reached, and fail
+ * if a hard limit reached
+ */
+
+FILE *
+opensock(
+ const char *sockpath
+)
+{
+ int fd;
+ FILE *fp;
+ struct sockaddr_un sockun;
+
+ fd = socket(PF_UNIX, SOCK_STREAM, 0);
+ if ( fd < 0 ) {
+ Debug( LDAP_DEBUG_ANY, "socket create failed\n" );
+ return( NULL );
+ }
+
+ sockun.sun_family = AF_UNIX;
+ sprintf(sockun.sun_path, "%.*s", (int)(sizeof(sockun.sun_path)-1),
+ sockpath);
+ if ( connect( fd, (struct sockaddr *)&sockun, sizeof(sockun) ) < 0 ) {
+ Debug( LDAP_DEBUG_ANY, "socket connect(%s) failed\n",
+ sockpath ? sockpath : "<null>" );
+ close( fd );
+ return( NULL );
+ }
+
+ if ( ( fp = fdopen( fd, "r+" ) ) == NULL ) {
+ Debug( LDAP_DEBUG_ANY, "fdopen failed\n" );
+ close( fd );
+ return( NULL );
+ }
+
+ return( fp );
+}
diff --git a/servers/slapd/back-sock/proto-sock.h b/servers/slapd/back-sock/proto-sock.h
new file mode 100644
index 0000000..0808329
--- /dev/null
+++ b/servers/slapd/back-sock/proto-sock.h
@@ -0,0 +1,49 @@
+/* $OpenLDAP$ */
+/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
+ *
+ * Copyright 2007-2022 The OpenLDAP Foundation.
+ * 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 Brian Candler for inclusion
+ * in OpenLDAP Software.
+ */
+
+#ifndef _PROTO_SOCK_H
+#define _PROTO_SOCK_H
+
+LDAP_BEGIN_DECL
+
+extern BI_init sock_back_initialize;
+
+extern BI_open sock_back_open;
+extern BI_close sock_back_close;
+extern BI_destroy sock_back_destroy;
+
+extern BI_db_init sock_back_db_init;
+extern BI_db_destroy sock_back_db_destroy;
+
+extern BI_op_bind sock_back_bind;
+extern BI_op_unbind sock_back_unbind;
+extern BI_op_search sock_back_search;
+extern BI_op_compare sock_back_compare;
+extern BI_op_modify sock_back_modify;
+extern BI_op_modrdn sock_back_modrdn;
+extern BI_op_add sock_back_add;
+extern BI_op_delete sock_back_delete;
+
+extern BI_op_extended sock_back_extended;
+
+extern int sock_back_init_cf( BackendInfo *bi );
+
+LDAP_END_DECL
+
+#endif /* _PROTO_SOCK_H */
diff --git a/servers/slapd/back-sock/result.c b/servers/slapd/back-sock/result.c
new file mode 100644
index 0000000..55a4060
--- /dev/null
+++ b/servers/slapd/back-sock/result.c
@@ -0,0 +1,168 @@
+/* result.c - sock backend result reading function */
+/* $OpenLDAP$ */
+/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
+ *
+ * Copyright 2007-2022 The OpenLDAP Foundation.
+ * 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 Brian Candler for inclusion
+ * in OpenLDAP Software.
+ */
+
+#include "portable.h"
+
+#include <stdio.h>
+
+#include <ac/errno.h>
+#include <ac/string.h>
+#include <ac/socket.h>
+#include <ac/unistd.h>
+
+#include "slap.h"
+#include "back-sock.h"
+
+/*
+ * FIXME: make a RESULT section compulsory from the socket response.
+ * Otherwise, a partial/aborted response is treated as 'success'.
+ * This is a divergence from the back-shell protocol, but makes things
+ * more robust.
+ */
+
+int
+sock_read_and_send_results(
+ Operation *op,
+ SlapReply *rs,
+ FILE *fp )
+{
+ int bsize, len;
+ char *buf, *bp;
+ char line[BUFSIZ];
+ char ebuf[128];
+
+ (void) fflush(fp);
+ /* read in the result and send it along */
+ buf = (char *) ch_malloc( BUFSIZ );
+ buf[0] = '\0';
+ bsize = BUFSIZ;
+ bp = buf;
+ while ( !feof(fp) ) {
+ errno = 0;
+ if ( fgets( line, sizeof(line), fp ) == NULL ) {
+ int saved_errno = errno;
+ if ( errno == EINTR ) continue;
+
+ Debug( LDAP_DEBUG_ANY, "sock: fgets failed: %s (%d)\n",
+ AC_STRERROR_R(saved_errno, ebuf, sizeof ebuf), saved_errno );
+ break;
+ }
+
+ Debug( LDAP_DEBUG_SHELL, "sock search reading line (%s)\n",
+ line );
+
+ /* ignore lines beginning with # (LDIFv1 comments) */
+ if ( *line == '#' ) {
+ continue;
+ }
+
+ /* ignore lines beginning with DEBUG: */
+ if ( strncasecmp( line, "DEBUG:", 6 ) == 0 ) {
+ continue;
+ }
+
+ if ( strncasecmp( line, "CONTINUE", 8 ) == 0 ) {
+ struct sockinfo *si = (struct sockinfo *) op->o_bd->be_private;
+ /* Only valid when operating as an overlay! */
+ assert( si->si_ops != 0 );
+ rs->sr_err = SLAP_CB_CONTINUE;
+ goto skip;
+ }
+
+ len = strlen( line );
+ while ( bp + len + 1 - buf > bsize ) {
+ size_t offset = bp - buf;
+ bsize += BUFSIZ;
+ buf = (char *) ch_realloc( buf, bsize );
+ bp = &buf[offset];
+ }
+ strcpy( bp, line );
+ bp += len;
+
+ /* line marked the end of an entry or result */
+ if ( *line == '\n' ) {
+ if ( strncasecmp( buf, "RESULT", 6 ) == 0 ) {
+ break;
+ }
+
+ if ( (rs->sr_entry = str2entry( buf )) == NULL ) {
+ Debug( LDAP_DEBUG_ANY, "str2entry(%s) failed\n",
+ buf );
+ } else {
+ rs->sr_attrs = op->oq_search.rs_attrs;
+ rs->sr_flags = REP_ENTRY_MODIFIABLE;
+ send_search_entry( op, rs );
+ entry_free( rs->sr_entry );
+ rs->sr_attrs = NULL;
+ }
+
+ bp = buf;
+ }
+ }
+ (void) str2result( buf, &rs->sr_err, (char **)&rs->sr_matched, (char **)&rs->sr_text );
+
+ /* otherwise, front end will send this result */
+ if ( rs->sr_err != 0 || op->o_tag != LDAP_REQ_BIND ) {
+ send_ldap_result( op, rs );
+ }
+
+skip:
+ ch_free( buf );
+
+ return( rs->sr_err );
+}
+
+void
+sock_print_suffixes(
+ FILE *fp,
+ Backend *be
+)
+{
+ int i;
+
+ for ( i = 0; be->be_suffix[i].bv_val != NULL; i++ ) {
+ fprintf( fp, "suffix: %s\n", be->be_suffix[i].bv_val );
+ }
+}
+
+void
+sock_print_conn(
+ FILE *fp,
+ Connection *conn,
+ struct sockinfo *si
+)
+{
+ if ( conn == NULL ) return;
+
+ if( si->si_extensions & SOCK_EXT_BINDDN ) {
+ fprintf( fp, "binddn: %s\n",
+ conn->c_dn.bv_len ? conn->c_dn.bv_val : "" );
+ }
+ if( si->si_extensions & SOCK_EXT_PEERNAME ) {
+ fprintf( fp, "peername: %s\n",
+ conn->c_peer_name.bv_len ? conn->c_peer_name.bv_val : "" );
+ }
+ if( si->si_extensions & SOCK_EXT_SSF ) {
+ fprintf( fp, "ssf: %d\n", conn->c_ssf );
+ }
+ if( si->si_extensions & SOCK_EXT_CONNID ) {
+ fprintf( fp, "connid: %lu\n", conn->c_connid );
+ }
+}
diff --git a/servers/slapd/back-sock/search.c b/servers/slapd/back-sock/search.c
new file mode 100644
index 0000000..9812e99
--- /dev/null
+++ b/servers/slapd/back-sock/search.c
@@ -0,0 +1,74 @@
+/* search.c - sock backend search function */
+/* $OpenLDAP$ */
+/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
+ *
+ * Copyright 2007-2022 The OpenLDAP Foundation.
+ * 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 Brian Candler for inclusion
+ * in OpenLDAP Software.
+ */
+
+#include "portable.h"
+
+#include <stdio.h>
+
+#include <ac/socket.h>
+#include <ac/string.h>
+
+#include "slap.h"
+#include "back-sock.h"
+
+/*
+ * FIXME: add a filterSearchResults option like back-perl has
+ */
+
+int
+sock_back_search(
+ Operation *op,
+ SlapReply *rs )
+{
+ struct sockinfo *si = (struct sockinfo *) op->o_bd->be_private;
+ FILE *fp;
+ AttributeName *an;
+
+ if ( (fp = opensock( si->si_sockpath )) == NULL ) {
+ send_ldap_error( op, rs, LDAP_OTHER,
+ "could not open socket" );
+ return( -1 );
+ }
+
+ /* write out the request to the search process */
+ fprintf( fp, "SEARCH\n" );
+ fprintf( fp, "msgid: %ld\n", (long) op->o_msgid );
+ sock_print_conn( fp, op->o_conn, si );
+ sock_print_suffixes( fp, op->o_bd );
+ fprintf( fp, "base: %s\n", op->o_req_dn.bv_val );
+ fprintf( fp, "scope: %d\n", op->oq_search.rs_scope );
+ fprintf( fp, "deref: %d\n", op->oq_search.rs_deref );
+ fprintf( fp, "sizelimit: %d\n", op->oq_search.rs_slimit );
+ fprintf( fp, "timelimit: %d\n", op->oq_search.rs_tlimit );
+ fprintf( fp, "filter: %s\n", op->oq_search.rs_filterstr.bv_val );
+ fprintf( fp, "attrsonly: %d\n", op->oq_search.rs_attrsonly ? 1 : 0 );
+ fprintf( fp, "attrs:%s", op->oq_search.rs_attrs == NULL ? " all" : "" );
+ for ( an = op->oq_search.rs_attrs; an && an->an_name.bv_val; an++ ) {
+ fprintf( fp, " %s", an->an_name.bv_val );
+ }
+ fprintf( fp, "\n\n" ); /* end of attr line plus blank line */
+
+ /* read in the results and send them along */
+ rs->sr_attrs = op->oq_search.rs_attrs;
+ sock_read_and_send_results( op, rs, fp );
+
+ fclose( fp );
+ return( 0 );
+}
diff --git a/servers/slapd/back-sock/searchexample.conf b/servers/slapd/back-sock/searchexample.conf
new file mode 100644
index 0000000..842d6aa
--- /dev/null
+++ b/servers/slapd/back-sock/searchexample.conf
@@ -0,0 +1,23 @@
+# $OpenLDAP$
+## This work is part of OpenLDAP Software <http://www.openldap.org/>.
+##
+## Copyright 2007-2022 The OpenLDAP Foundation.
+## 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 Brian Candler for inclusion
+## in OpenLDAP Software.
+
+include /usr/local/etc/openldap/schema/core.schema
+
+database sock
+suffix "dc=example,dc=com"
+socketpath /tmp/example.sock
diff --git a/servers/slapd/back-sock/searchexample.pl b/servers/slapd/back-sock/searchexample.pl
new file mode 100644
index 0000000..f867005
--- /dev/null
+++ b/servers/slapd/back-sock/searchexample.pl
@@ -0,0 +1,90 @@
+#!/usr/bin/perl -w -T
+# $OpenLDAP$
+## This work is part of OpenLDAP Software <http://www.openldap.org/>.
+##
+## Copyright 2007-2022 The OpenLDAP Foundation.
+## 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 Brian Candler for inclusion
+## in OpenLDAP Software.
+
+# See: http://search.cpan.org/dist/Net-Server/
+
+package ExampleDB;
+
+use strict;
+use vars qw(@ISA);
+use Net::Server::PreFork; # any personality will do
+
+@ISA = qw(Net::Server::PreFork);
+
+ExampleDB->run(
+ port=>"/tmp/example.sock|unix"
+ #conf_file=>"/etc/example.conf"
+);
+exit;
+
+### over-ridden subs below
+# The protocol is the same as back-shell
+
+sub process_request {
+ my $self = shift;
+
+ eval {
+
+ local $SIG{ALRM} = sub { die "Timed Out!\n" };
+ my $timeout = 30; # give the user 30 seconds to type a line
+ alarm($timeout);
+
+ my $request = <STDIN>;
+
+ if ($request eq "SEARCH\n") {
+ my %req = ();
+ while (my $line = <STDIN>) {
+ chomp($line);
+ last if $line eq "";
+ if ($line =~ /^([^:]+):\s*(.*)$/) { # FIXME: handle base64 encoded
+ $req{$1} = $2;
+ }
+ }
+ #sleep(2); # to test concurrency
+ print "dn: cn=test, dc=example, dc=com\n";
+ print "cn: test\n";
+ print "objectclass: cnobject\n";
+ print "\n";
+ print "RESULT\n";
+ print "code: 0\n";
+ print "info: answered by process $$\n";
+ }
+ else {
+ print "RESULT\n";
+ print "code: 53\n"; # unwillingToPerform
+ print "info: I don't implement $request";
+ }
+
+ };
+
+ return unless $@;
+ if( $@=~/timed out/i ){
+ print "RESULT\n";
+ print "code: 3\n"; # timeLimitExceeded
+ print "info: Timed out\n";
+ }
+ else {
+ print "RESULT\n";
+ print "code: 1\n"; # operationsError
+ print "info: $@\n"; # FIXME: remove CR/LF
+ }
+
+}
+
+1;
diff --git a/servers/slapd/back-sock/unbind.c b/servers/slapd/back-sock/unbind.c
new file mode 100644
index 0000000..0b349e1
--- /dev/null
+++ b/servers/slapd/back-sock/unbind.c
@@ -0,0 +1,57 @@
+/* unbind.c - sock backend unbind function */
+/* $OpenLDAP$ */
+/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
+ *
+ * Copyright 2007-2022 The OpenLDAP Foundation.
+ * 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 Brian Candler for inclusion
+ * in OpenLDAP Software.
+ */
+
+#include "portable.h"
+
+#include <stdio.h>
+
+#include <ac/socket.h>
+#include <ac/string.h>
+
+#include "slap.h"
+#include "back-sock.h"
+
+int
+sock_back_unbind(
+ Operation *op,
+ SlapReply *rs
+)
+{
+ struct sockinfo *si = (struct sockinfo *) op->o_bd->be_private;
+ FILE *fp;
+
+ if ( (fp = opensock( si->si_sockpath )) == NULL ) {
+ send_ldap_error( op, rs, LDAP_OTHER,
+ "could not open socket" );
+ return( -1 );
+ }
+
+ /* write out the request to the unbind process */
+ fprintf( fp, "UNBIND\n" );
+ fprintf( fp, "msgid: %ld\n", (long) op->o_msgid );
+ sock_print_conn( fp, op->o_conn, si );
+ sock_print_suffixes( fp, op->o_bd );
+ fprintf( fp, "\n" );
+
+ /* no response to unbind */
+ fclose( fp );
+
+ return 0;
+}