summaryrefslogtreecommitdiffstats
path: root/servers/slapd/back-shell
diff options
context:
space:
mode:
Diffstat (limited to 'servers/slapd/back-shell')
-rw-r--r--servers/slapd/back-shell/Makefile.in43
-rw-r--r--servers/slapd/back-shell/add.c84
-rw-r--r--servers/slapd/back-shell/bind.c105
-rw-r--r--servers/slapd/back-shell/compare.c99
-rw-r--r--servers/slapd/back-shell/config.c137
-rw-r--r--servers/slapd/back-shell/delete.c90
-rw-r--r--servers/slapd/back-shell/fork.c118
-rw-r--r--servers/slapd/back-shell/init.c111
-rw-r--r--servers/slapd/back-shell/modify.c126
-rw-r--r--servers/slapd/back-shell/modrdn.c96
-rw-r--r--servers/slapd/back-shell/proto-shell.h56
-rw-r--r--servers/slapd/back-shell/result.c135
-rw-r--r--servers/slapd/back-shell/search.c86
-rw-r--r--servers/slapd/back-shell/searchexample.conf29
-rw-r--r--servers/slapd/back-shell/searchexample.sh65
-rw-r--r--servers/slapd/back-shell/shell.h65
-rw-r--r--servers/slapd/back-shell/unbind.c69
17 files changed, 1514 insertions, 0 deletions
diff --git a/servers/slapd/back-shell/Makefile.in b/servers/slapd/back-shell/Makefile.in
new file mode 100644
index 0000000..1fed787
--- /dev/null
+++ b/servers/slapd/back-shell/Makefile.in
@@ -0,0 +1,43 @@
+# Makefile.in for back-shell
+# $OpenLDAP$
+## This work is part of OpenLDAP Software <http://www.openldap.org/>.
+##
+## Copyright 1998-2021 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>.
+
+SRCS = init.c config.c fork.c search.c bind.c unbind.c add.c \
+ delete.c modify.c modrdn.c compare.c result.c
+OBJS = init.lo config.lo fork.lo search.lo bind.lo unbind.lo add.lo \
+ delete.lo modify.lo modrdn.lo compare.lo result.lo
+
+LDAP_INCDIR= ../../../include
+LDAP_LIBDIR= ../../../libraries
+
+BUILD_OPT = "--enable-shell"
+BUILD_MOD = @BUILD_SHELL@
+
+mod_DEFS = -DSLAPD_IMPORT
+MOD_DEFS = $(@BUILD_SHELL@_DEFS)
+
+shared_LDAP_LIBS = $(LDAP_LIBLDAP_R_LA) $(LDAP_LIBLBER_LA)
+NT_LINK_LIBS = -L.. -lslapd $(@BUILD_LIBS_DYNAMIC@_LDAP_LIBS)
+UNIX_LINK_LIBS = $(@BUILD_LIBS_DYNAMIC@_LDAP_LIBS)
+
+LIBBASE = back_shell
+
+XINCPATH = -I.. -I$(srcdir)/..
+XDEFS = $(MODULES_CPPFLAGS)
+
+all-local-lib: ../.backend
+
+../.backend: lib$(LIBBASE).a
+ @touch $@
+
diff --git a/servers/slapd/back-shell/add.c b/servers/slapd/back-shell/add.c
new file mode 100644
index 0000000..19a96d1
--- /dev/null
+++ b/servers/slapd/back-shell/add.c
@@ -0,0 +1,84 @@
+/* add.c - shell backend add function */
+/* $OpenLDAP$ */
+/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
+ *
+ * Copyright 1998-2021 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>.
+ */
+/* Portions Copyright (c) 1995 Regents of the University of Michigan.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and that due credit is given
+ * to the University of Michigan at Ann Arbor. The name of the University
+ * may not be used to endorse or promote products derived from this
+ * software without specific prior written permission. This software
+ * is provided ``as is'' without express or implied warranty.
+ */
+/* ACKNOWLEDGEMENTS:
+ * This work was originally developed by the University of Michigan
+ * (as part of U-MICH LDAP).
+ */
+
+#include "portable.h"
+
+#include <stdio.h>
+
+#include <ac/string.h>
+#include <ac/socket.h>
+
+#include "slap.h"
+#include "shell.h"
+
+int
+shell_back_add(
+ Operation *op,
+ SlapReply *rs )
+{
+ struct shellinfo *si = (struct shellinfo *) op->o_bd->be_private;
+ AttributeDescription *entry = slap_schema.si_ad_entry;
+ FILE *rfp, *wfp;
+ int len;
+
+ if ( si->si_add == NULL ) {
+ send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
+ "add not implemented" );
+ return( -1 );
+ }
+
+ 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 ( forkandexec( si->si_add, &rfp, &wfp ) == (pid_t)-1 ) {
+ send_ldap_error( op, rs, LDAP_OTHER,
+ "could not fork/exec" );
+ return( -1 );
+ }
+
+ /* write out the request to the add process */
+ fprintf( wfp, "ADD\n" );
+ fprintf( wfp, "msgid: %ld\n", (long) op->o_msgid );
+ print_suffixes( wfp, op->o_bd );
+ ldap_pvt_thread_mutex_lock( &entry2str_mutex );
+ fprintf( wfp, "%s", entry2str( op->oq_add.rs_e, &len ) );
+ ldap_pvt_thread_mutex_unlock( &entry2str_mutex );
+ fclose( wfp );
+
+ /* read in the result and send it along */
+ read_and_send_results( op, rs, rfp );
+
+ fclose( rfp );
+ return( 0 );
+}
diff --git a/servers/slapd/back-shell/bind.c b/servers/slapd/back-shell/bind.c
new file mode 100644
index 0000000..28b9e05
--- /dev/null
+++ b/servers/slapd/back-shell/bind.c
@@ -0,0 +1,105 @@
+/* bind.c - shell backend bind function */
+/* $OpenLDAP$ */
+/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
+ *
+ * Copyright 1998-2021 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>.
+ */
+/* Portions Copyright (c) 1995 Regents of the University of Michigan.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and that due credit is given
+ * to the University of Michigan at Ann Arbor. The name of the University
+ * may not be used to endorse or promote products derived from this
+ * software without specific prior written permission. This software
+ * is provided ``as is'' without express or implied warranty.
+ */
+/* ACKNOWLEDGEMENTS:
+ * This work was originally developed by the University of Michigan
+ * (as part of U-MICH LDAP).
+ */
+
+#include "portable.h"
+
+#include <stdio.h>
+
+#include <ac/socket.h>
+#include <ac/string.h>
+
+#include "slap.h"
+#include "shell.h"
+
+int
+shell_back_bind(
+ Operation *op,
+ SlapReply *rs )
+{
+ struct shellinfo *si = (struct shellinfo *) op->o_bd->be_private;
+ AttributeDescription *entry = slap_schema.si_ad_entry;
+ Entry e;
+ FILE *rfp, *wfp;
+ int rc;
+
+ /* allow rootdn as a means to auth without the need to actually
+ * contact the proxied DSA */
+ switch ( be_rootdn_bind( op, rs ) ) {
+ case SLAP_CB_CONTINUE:
+ break;
+
+ default:
+ return rs->sr_err;
+ }
+
+ if ( si->si_bind == NULL ) {
+ send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
+ "bind not implemented" );
+ return( -1 );
+ }
+
+ 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 ( forkandexec( si->si_bind, &rfp, &wfp ) == (pid_t)-1 ) {
+ send_ldap_error( op, rs, LDAP_OTHER,
+ "could not fork/exec" );
+ return( -1 );
+ }
+
+ /* write out the request to the bind process */
+ fprintf( wfp, "BIND\n" );
+ fprintf( wfp, "msgid: %ld\n", (long) op->o_msgid );
+ print_suffixes( wfp, op->o_bd );
+ fprintf( wfp, "dn: %s\n", op->o_req_dn.bv_val );
+ fprintf( wfp, "method: %d\n", op->oq_bind.rb_method );
+ fprintf( wfp, "credlen: %lu\n", op->oq_bind.rb_cred.bv_len );
+ fprintf( wfp, "cred: %s\n", op->oq_bind.rb_cred.bv_val ); /* XXX */
+ fclose( wfp );
+
+ /* read in the results and send them along */
+ rc = read_and_send_results( op, rs, rfp );
+ fclose( rfp );
+
+ return( rc );
+}
diff --git a/servers/slapd/back-shell/compare.c b/servers/slapd/back-shell/compare.c
new file mode 100644
index 0000000..2b1949a
--- /dev/null
+++ b/servers/slapd/back-shell/compare.c
@@ -0,0 +1,99 @@
+/* compare.c - shell backend compare function */
+/* $OpenLDAP$ */
+/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
+ *
+ * Copyright 1998-2021 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>.
+ */
+/* Portions Copyright (c) 1995 Regents of the University of Michigan.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and that due credit is given
+ * to the University of Michigan at Ann Arbor. The name of the University
+ * may not be used to endorse or promote products derived from this
+ * software without specific prior written permission. This software
+ * is provided ``as is'' without express or implied warranty.
+ */
+/* ACKNOWLEDGEMENTS:
+ * This work was originally developed by the University of Michigan
+ * (as part of U-MICH LDAP).
+ */
+
+#include "portable.h"
+
+#include <stdio.h>
+
+#include <ac/string.h>
+#include <ac/socket.h>
+
+#include "slap.h"
+#include "shell.h"
+
+int
+shell_back_compare(
+ Operation *op,
+ SlapReply *rs )
+{
+ struct shellinfo *si = (struct shellinfo *) op->o_bd->be_private;
+ AttributeDescription *entry = slap_schema.si_ad_entry;
+ Entry e;
+ FILE *rfp, *wfp;
+
+ if ( si->si_compare == NULL ) {
+ send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
+ "compare not implemented" );
+ return( -1 );
+ }
+
+ 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_READ, NULL ) )
+ {
+ send_ldap_error( op, rs, LDAP_INSUFFICIENT_ACCESS, NULL );
+ return -1;
+ }
+
+ if ( forkandexec( si->si_compare, &rfp, &wfp ) == (pid_t)-1 ) {
+ send_ldap_error( op, rs, LDAP_OTHER,
+ "could not fork/exec" );
+ return( -1 );
+ }
+
+ /*
+ * FIX ME: This should use LDIF routines so that binary
+ * values are properly dealt with
+ */
+
+ /* write out the request to the compare process */
+ fprintf( wfp, "COMPARE\n" );
+ fprintf( wfp, "msgid: %ld\n", (long) op->o_msgid );
+ print_suffixes( wfp, op->o_bd );
+ fprintf( wfp, "dn: %s\n", op->o_req_dn.bv_val );
+ fprintf( wfp, "%s: %s\n",
+ op->oq_compare.rs_ava->aa_desc->ad_cname.bv_val,
+ op->oq_compare.rs_ava->aa_value.bv_val /* could be binary! */ );
+ fclose( wfp );
+
+ /* read in the result and send it along */
+ read_and_send_results( op, rs, rfp );
+
+ fclose( rfp );
+ return( 0 );
+}
diff --git a/servers/slapd/back-shell/config.c b/servers/slapd/back-shell/config.c
new file mode 100644
index 0000000..3b99e35
--- /dev/null
+++ b/servers/slapd/back-shell/config.c
@@ -0,0 +1,137 @@
+/* config.c - shell backend configuration file routine */
+/* $OpenLDAP$ */
+/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
+ *
+ * Copyright 1998-2021 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>.
+ */
+/* Portions Copyright (c) 1995 Regents of the University of Michigan.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and that due credit is given
+ * to the University of Michigan at Ann Arbor. The name of the University
+ * may not be used to endorse or promote products derived from this
+ * software without specific prior written permission. This software
+ * is provided ``as is'' without express or implied warranty.
+ */
+/* ACKNOWLEDGEMENTS:
+ * This work was originally developed by the University of Michigan
+ * (as part of U-MICH LDAP).
+ */
+
+#include "portable.h"
+
+#include <stdio.h>
+
+#include <ac/string.h>
+#include <ac/socket.h>
+
+#include "slap.h"
+#include "shell.h"
+#include "config.h"
+
+static ConfigDriver shell_cf;
+
+enum {
+ SHELL_BIND = 0,
+ SHELL_UNBIND = 1,
+ SHELL_SEARCH,
+ SHELL_COMPARE,
+ SHELL_MODIFY,
+ SHELL_MODRDN,
+ SHELL_ADD,
+ SHELL_DELETE
+};
+
+static ConfigTable shellcfg[] = {
+ { "bind", "args", 2, 0, 0, ARG_MAGIC|SHELL_BIND, shell_cf,
+ "( OLcfgDbAt:10.1 NAME 'olcShellBind' "
+ "DESC 'Bind command and arguments' "
+ "EQUALITY caseExactMatch "
+ "SYNTAX OMsDirectoryString SINGLE-VALUE ) ", NULL, NULL },
+ { "unbind", "args", 2, 0, 0, ARG_MAGIC|SHELL_UNBIND, shell_cf,
+ "( OLcfgDbAt:10.2 NAME 'olcShellUnbind' "
+ "DESC 'Unbind command and arguments' "
+ "EQUALITY caseExactMatch "
+ "SYNTAX OMsDirectoryString SINGLE-VALUE ) ", NULL, NULL },
+ { "search", "args", 2, 0, 0, ARG_MAGIC|SHELL_SEARCH, shell_cf,
+ "( OLcfgDbAt:10.3 NAME 'olcShellSearch' "
+ "DESC 'Search command and arguments' "
+ "EQUALITY caseExactMatch "
+ "SYNTAX OMsDirectoryString SINGLE-VALUE ) ", NULL, NULL },
+ { "compare", "args", 2, 0, 0, ARG_MAGIC|SHELL_COMPARE, shell_cf,
+ "( OLcfgDbAt:10.4 NAME 'olcShellCompare' "
+ "DESC 'Compare command and arguments' "
+ "EQUALITY caseExactMatch "
+ "SYNTAX OMsDirectoryString SINGLE-VALUE ) ", NULL, NULL },
+ { "modify", "args", 2, 0, 0, ARG_MAGIC|SHELL_MODIFY, shell_cf,
+ "( OLcfgDbAt:10.5 NAME 'olcShellModify' "
+ "DESC 'Modify command and arguments' "
+ "EQUALITY caseExactMatch "
+ "SYNTAX OMsDirectoryString SINGLE-VALUE ) ", NULL, NULL },
+ { "modrdn", "args", 2, 0, 0, ARG_MAGIC|SHELL_MODRDN, shell_cf,
+ "( OLcfgDbAt:10.6 NAME 'olcShellModRDN' "
+ "DESC 'ModRDN command and arguments' "
+ "EQUALITY caseExactMatch "
+ "SYNTAX OMsDirectoryString SINGLE-VALUE ) ", NULL, NULL },
+ { "add", "args", 2, 0, 0, ARG_MAGIC|SHELL_ADD, shell_cf,
+ "( OLcfgDbAt:10.7 NAME 'olcShellAdd' "
+ "DESC 'Add command and arguments' "
+ "EQUALITY caseExactMatch "
+ "SYNTAX OMsDirectoryString SINGLE-VALUE ) ", NULL, NULL },
+ { "delete", "args", 2, 0, 0, ARG_MAGIC|SHELL_DELETE, shell_cf,
+ "( OLcfgDbAt:10.8 NAME 'olcShellDelete' "
+ "DESC 'Delete command and arguments' "
+ "EQUALITY caseExactMatch "
+ "SYNTAX OMsDirectoryString SINGLE-VALUE ) ", NULL, NULL },
+ { NULL }
+};
+
+static ConfigOCs shellocs[] = {
+ { "( OLcfgDbOc:10.1 "
+ "NAME 'olcShellConfig' "
+ "DESC 'Shell backend configuration' "
+ "SUP olcDatabaseConfig "
+ "MAY ( olcShellBind $ olcShellUnbind $ olcShellSearch $ "
+ "olcShellCompare $ olcShellModify $ olcShellModRDN $ "
+ "olcShellAdd $ olcShellDelete ) )",
+ Cft_Database, shellcfg },
+ { NULL }
+};
+
+static int
+shell_cf( ConfigArgs *c )
+{
+ struct shellinfo *si = (struct shellinfo *) c->be->be_private;
+ char ***arr = &si->si_bind;
+
+ if ( c->op == SLAP_CONFIG_EMIT ) {
+ struct berval bv;
+ if ( !arr[c->type] ) return 1;
+ bv.bv_val = ldap_charray2str( arr[c->type], " " );
+ bv.bv_len = strlen( bv.bv_val );
+ ber_bvarray_add( &c->rvalue_vals, &bv );
+ } else if ( c->op == LDAP_MOD_DELETE ) {
+ ldap_charray_free( arr[c->type] );
+ arr[c->type] = NULL;
+ } else {
+ arr[c->type] = ldap_charray_dup( &c->argv[1] );
+ }
+ return 0;
+}
+
+int
+shell_back_init_cf( BackendInfo *bi )
+{
+ bi->bi_cf_ocs = shellocs;
+ return config_register_schema( shellcfg, shellocs );
+}
diff --git a/servers/slapd/back-shell/delete.c b/servers/slapd/back-shell/delete.c
new file mode 100644
index 0000000..bb2f317
--- /dev/null
+++ b/servers/slapd/back-shell/delete.c
@@ -0,0 +1,90 @@
+/* delete.c - shell backend delete function */
+/* $OpenLDAP$ */
+/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
+ *
+ * Copyright 1998-2021 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>.
+ */
+/* Portions Copyright (c) 1995 Regents of the University of Michigan.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and that due credit is given
+ * to the University of Michigan at Ann Arbor. The name of the University
+ * may not be used to endorse or promote products derived from this
+ * software without specific prior written permission. This software
+ * is provided ``as is'' without express or implied warranty.
+ */
+/* ACKNOWLEDGEMENTS:
+ * This work was originally developed by the University of Michigan
+ * (as part of U-MICH LDAP).
+ */
+
+#include "portable.h"
+
+#include <stdio.h>
+
+#include <ac/string.h>
+#include <ac/socket.h>
+
+#include "slap.h"
+#include "shell.h"
+
+int
+shell_back_delete(
+ Operation *op,
+ SlapReply *rs )
+{
+ struct shellinfo *si = (struct shellinfo *) op->o_bd->be_private;
+ AttributeDescription *entry = slap_schema.si_ad_entry;
+ Entry e;
+ FILE *rfp, *wfp;
+
+ if ( si->si_delete == NULL ) {
+ send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
+ "delete not implemented" );
+ return( -1 );
+ }
+
+ 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 ( forkandexec( si->si_delete, &rfp, &wfp ) == (pid_t)-1 ) {
+ send_ldap_error( op, rs, LDAP_OTHER,
+ "could not fork/exec" );
+ return( -1 );
+ }
+
+ /* write out the request to the delete process */
+ fprintf( wfp, "DELETE\n" );
+ fprintf( wfp, "msgid: %ld\n", (long) op->o_msgid );
+ print_suffixes( wfp, op->o_bd );
+ fprintf( wfp, "dn: %s\n", op->o_req_dn.bv_val );
+ fclose( wfp );
+
+ /* read in the results and send them along */
+ read_and_send_results( op, rs, rfp );
+ fclose( rfp );
+ return( 0 );
+}
diff --git a/servers/slapd/back-shell/fork.c b/servers/slapd/back-shell/fork.c
new file mode 100644
index 0000000..54100f7
--- /dev/null
+++ b/servers/slapd/back-shell/fork.c
@@ -0,0 +1,118 @@
+/* fork.c - fork and exec a process, connecting stdin/out w/pipes */
+/* $OpenLDAP$ */
+/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
+ *
+ * Copyright 1998-2021 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>.
+ */
+/* Portions Copyright (c) 1995 Regents of the University of Michigan.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and that due credit is given
+ * to the University of Michigan at Ann Arbor. The name of the University
+ * may not be used to endorse or promote products derived from this
+ * software without specific prior written permission. This software
+ * is provided ``as is'' without express or implied warranty.
+ */
+/* ACKNOWLEDGEMENTS:
+ * This work was originally developed by the University of Michigan
+ * (as part of U-MICH LDAP).
+ */
+
+#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 "shell.h"
+
+pid_t
+forkandexec(
+ char **args,
+ FILE **rfp,
+ FILE **wfp
+)
+{
+ int p2c[2] = { -1, -1 }, c2p[2];
+ pid_t pid;
+
+ if ( pipe( p2c ) != 0 || pipe( c2p ) != 0 ) {
+ Debug( LDAP_DEBUG_ANY, "pipe failed\n", 0, 0, 0 );
+ close( p2c[0] );
+ close( p2c[1] );
+ return( -1 );
+ }
+
+ /*
+ * what we're trying to set up looks like this:
+ * parent *wfp -> p2c[1] | p2c[0] -> stdin child
+ * parent *rfp <- c2p[0] | c2p[1] <- stdout child
+ */
+
+ fflush( NULL );
+# ifdef HAVE_THR
+ pid = fork1();
+# else
+ pid = fork();
+# endif
+ if ( pid == 0 ) { /* child */
+ /*
+ * child could deadlock here due to resources locked
+ * by our parent
+ *
+ * If so, configure --without-threads.
+ */
+ if ( dup2( p2c[0], 0 ) == -1 || dup2( c2p[1], 1 ) == -1 ) {
+ Debug( LDAP_DEBUG_ANY, "dup2 failed\n", 0, 0, 0 );
+ exit( EXIT_FAILURE );
+ }
+ }
+ close( p2c[0] );
+ close( c2p[1] );
+ if ( pid <= 0 ) {
+ close( p2c[1] );
+ close( c2p[0] );
+ }
+ switch ( pid ) {
+ case 0:
+ execv( args[0], args );
+
+ Debug( LDAP_DEBUG_ANY, "execv failed\n", 0, 0, 0 );
+ exit( EXIT_FAILURE );
+
+ case -1: /* trouble */
+ Debug( LDAP_DEBUG_ANY, "fork failed\n", 0, 0, 0 );
+ return( -1 );
+ }
+
+ /* parent */
+ if ( (*rfp = fdopen( c2p[0], "r" )) == NULL || (*wfp = fdopen( p2c[1],
+ "w" )) == NULL ) {
+ Debug( LDAP_DEBUG_ANY, "fdopen failed\n", 0, 0, 0 );
+ if ( *rfp ) {
+ fclose( *rfp );
+ *rfp = NULL;
+ } else {
+ close( c2p[0] );
+ }
+ close( p2c[1] );
+
+ return( -1 );
+ }
+
+ return( pid );
+}
diff --git a/servers/slapd/back-shell/init.c b/servers/slapd/back-shell/init.c
new file mode 100644
index 0000000..e60cd6e
--- /dev/null
+++ b/servers/slapd/back-shell/init.c
@@ -0,0 +1,111 @@
+/* init.c - initialize shell backend */
+/* $OpenLDAP$ */
+/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
+ *
+ * Copyright 1998-2021 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>.
+ */
+/* Portions Copyright (c) 1995 Regents of the University of Michigan.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and that due credit is given
+ * to the University of Michigan at Ann Arbor. The name of the University
+ * may not be used to endorse or promote products derived from this
+ * software without specific prior written permission. This software
+ * is provided ``as is'' without express or implied warranty.
+ */
+/* ACKNOWLEDGEMENTS:
+ * This work was originally developed by the University of Michigan
+ * (as part of U-MICH LDAP).
+ */
+
+#include "portable.h"
+
+#include <stdio.h>
+
+#include <ac/socket.h>
+
+#include "slap.h"
+
+#include "config.h"
+
+#include "shell.h"
+
+int
+shell_back_initialize(
+ BackendInfo *bi
+)
+{
+ bi->bi_open = 0;
+ bi->bi_config = 0;
+ bi->bi_close = 0;
+ bi->bi_destroy = 0;
+
+ bi->bi_db_init = shell_back_db_init;
+ bi->bi_db_config = 0;
+ bi->bi_db_open = 0;
+ bi->bi_db_close = 0;
+ bi->bi_db_destroy = shell_back_db_destroy;
+
+ bi->bi_op_bind = shell_back_bind;
+ bi->bi_op_unbind = shell_back_unbind;
+ bi->bi_op_search = shell_back_search;
+ bi->bi_op_compare = shell_back_compare;
+ bi->bi_op_modify = shell_back_modify;
+ bi->bi_op_modrdn = shell_back_modrdn;
+ bi->bi_op_add = shell_back_add;
+ bi->bi_op_delete = shell_back_delete;
+ bi->bi_op_abandon = 0;
+
+ bi->bi_extended = 0;
+
+ bi->bi_chk_referrals = 0;
+
+ bi->bi_connection_init = 0;
+ bi->bi_connection_destroy = 0;
+
+ return shell_back_init_cf( bi );
+}
+
+int
+shell_back_db_init(
+ Backend *be,
+ ConfigReply *cr
+)
+{
+ struct shellinfo *si;
+
+ si = (struct shellinfo *) ch_calloc( 1, sizeof(struct shellinfo) );
+
+ be->be_private = si;
+ be->be_cf_ocs = be->bd_info->bi_cf_ocs;
+
+ return si == NULL;
+}
+
+int
+shell_back_db_destroy(
+ Backend *be,
+ ConfigReply *cr
+)
+{
+ free( be->be_private );
+ return 0;
+}
+
+#if SLAPD_SHELL == SLAPD_MOD_DYNAMIC
+
+/* conditionally define the init_module() function */
+SLAP_BACKEND_INIT_MODULE( shell )
+
+#endif /* SLAPD_SHELL == SLAPD_MOD_DYNAMIC */
+
diff --git a/servers/slapd/back-shell/modify.c b/servers/slapd/back-shell/modify.c
new file mode 100644
index 0000000..8ddb674
--- /dev/null
+++ b/servers/slapd/back-shell/modify.c
@@ -0,0 +1,126 @@
+/* modify.c - shell backend modify function */
+/* $OpenLDAP$ */
+/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
+ *
+ * Copyright 1998-2021 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>.
+ */
+/* Portions Copyright (c) 1995 Regents of the University of Michigan.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and that due credit is given
+ * to the University of Michigan at Ann Arbor. The name of the University
+ * may not be used to endorse or promote products derived from this
+ * software without specific prior written permission. This software
+ * is provided ``as is'' without express or implied warranty.
+ */
+/* ACKNOWLEDGEMENTS:
+ * This work was originally developed by the University of Michigan
+ * (as part of U-MICH LDAP).
+ */
+
+#include "portable.h"
+
+#include <stdio.h>
+
+#include <ac/string.h>
+#include <ac/socket.h>
+
+#include "slap.h"
+#include "shell.h"
+#include "ldif.h"
+
+int
+shell_back_modify(
+ Operation *op,
+ SlapReply *rs )
+{
+ Modification *mod;
+ struct shellinfo *si = (struct shellinfo *) op->o_bd->be_private;
+ AttributeDescription *entry = slap_schema.si_ad_entry;
+ Modifications *ml = op->orm_modlist;
+ Entry e;
+ FILE *rfp, *wfp;
+ int i;
+
+ if ( si->si_modify == NULL ) {
+ send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
+ "modify not implemented" );
+ return( -1 );
+ }
+
+ 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 ( forkandexec( si->si_modify, &rfp, &wfp ) == (pid_t)-1 ) {
+ send_ldap_error( op, rs, LDAP_OTHER,
+ "could not fork/exec" );
+ return( -1 );
+ }
+
+ /* write out the request to the modify process */
+ fprintf( wfp, "MODIFY\n" );
+ fprintf( wfp, "msgid: %ld\n", (long) op->o_msgid );
+ print_suffixes( wfp, op->o_bd );
+ fprintf( wfp, "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( wfp, "add: %s\n", mod->sm_desc->ad_cname.bv_val );
+ break;
+
+ case LDAP_MOD_DELETE:
+ fprintf( wfp, "delete: %s\n", mod->sm_desc->ad_cname.bv_val );
+ break;
+
+ case LDAP_MOD_REPLACE:
+ fprintf( wfp, "replace: %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 *out = ldif_put( LDIF_PUT_VALUE,
+ mod->sm_desc->ad_cname.bv_val,
+ mod->sm_values[i].bv_val,
+ mod->sm_values[i].bv_len );
+ if ( out ) {
+ fprintf( wfp, "%s", out );
+ ber_memfree( out );
+ }
+ }
+ }
+
+ fprintf( wfp, "-\n" );
+ }
+ fclose( wfp );
+
+ /* read in the results and send them along */
+ read_and_send_results( op, rs, rfp );
+ fclose( rfp );
+ return( 0 );
+}
diff --git a/servers/slapd/back-shell/modrdn.c b/servers/slapd/back-shell/modrdn.c
new file mode 100644
index 0000000..7c56fa5
--- /dev/null
+++ b/servers/slapd/back-shell/modrdn.c
@@ -0,0 +1,96 @@
+/* modrdn.c - shell backend modrdn function */
+/* $OpenLDAP$ */
+/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
+ *
+ * Copyright 1998-2021 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>.
+ */
+/* Portions Copyright (c) 1995 Regents of the University of Michigan.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and that due credit is given
+ * to the University of Michigan at Ann Arbor. The name of the University
+ * may not be used to endorse or promote products derived from this
+ * software without specific prior written permission. This software
+ * is provided ``as is'' without express or implied warranty.
+ */
+/* ACKNOWLEDGEMENTS:
+ * This work was originally developed by the University of Michigan
+ * (as part of U-MICH LDAP).
+ */
+
+#include "portable.h"
+
+#include <stdio.h>
+
+#include <ac/socket.h>
+#include <ac/string.h>
+
+#include "slap.h"
+#include "shell.h"
+
+int
+shell_back_modrdn(
+ Operation *op,
+ SlapReply *rs )
+{
+ struct shellinfo *si = (struct shellinfo *) op->o_bd->be_private;
+ AttributeDescription *entry = slap_schema.si_ad_entry;
+ Entry e;
+ FILE *rfp, *wfp;
+
+ if ( si->si_modrdn == NULL ) {
+ send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
+ "modrdn not implemented" );
+ return( -1 );
+ }
+
+ 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 ( forkandexec( si->si_modrdn, &rfp, &wfp ) == (pid_t)-1 ) {
+ send_ldap_error( op, rs, LDAP_OTHER,
+ "could not fork/exec" );
+ return( -1 );
+ }
+
+ /* write out the request to the modrdn process */
+ fprintf( wfp, "MODRDN\n" );
+ fprintf( wfp, "msgid: %ld\n", (long) op->o_msgid );
+ print_suffixes( wfp, op->o_bd );
+ fprintf( wfp, "dn: %s\n", op->o_req_dn.bv_val );
+ fprintf( wfp, "newrdn: %s\n", op->oq_modrdn.rs_newrdn.bv_val );
+ fprintf( wfp, "deleteoldrdn: %d\n", op->oq_modrdn.rs_deleteoldrdn ? 1 : 0 );
+ if ( op->oq_modrdn.rs_newSup != NULL ) {
+ fprintf( wfp, "newSuperior: %s\n", op->oq_modrdn.rs_newSup->bv_val );
+ }
+ fclose( wfp );
+
+ /* read in the results and send them along */
+ read_and_send_results( op, rs, rfp );
+ fclose( rfp );
+ return( 0 );
+}
diff --git a/servers/slapd/back-shell/proto-shell.h b/servers/slapd/back-shell/proto-shell.h
new file mode 100644
index 0000000..f6a9aad
--- /dev/null
+++ b/servers/slapd/back-shell/proto-shell.h
@@ -0,0 +1,56 @@
+/* $OpenLDAP$ */
+/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
+ *
+ * Copyright 1998-2021 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>.
+ */
+/* Portions Copyright (c) 1995 Regents of the University of Michigan.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and that due credit is given
+ * to the University of Michigan at Ann Arbor. The name of the University
+ * may not be used to endorse or promote products derived from this
+ * software without specific prior written permission. This software
+ * is provided ``as is'' without express or implied warranty.
+ */
+/* ACKNOWLEDGEMENTS:
+ * This work was originally developed by the University of Michigan
+ * (as part of U-MICH LDAP).
+ */
+
+#ifndef PROTO_SHELL_H
+#define PROTO_SHELL_H
+
+LDAP_BEGIN_DECL
+
+extern BI_init shell_back_initialize;
+
+extern BI_open shell_back_open;
+extern BI_close shell_back_close;
+extern BI_destroy shell_back_destroy;
+
+extern BI_db_init shell_back_db_init;
+extern BI_db_destroy shell_back_db_destroy;
+
+extern BI_op_bind shell_back_bind;
+extern BI_op_unbind shell_back_unbind;
+extern BI_op_search shell_back_search;
+extern BI_op_compare shell_back_compare;
+extern BI_op_modify shell_back_modify;
+extern BI_op_modrdn shell_back_modrdn;
+extern BI_op_add shell_back_add;
+extern BI_op_delete shell_back_delete;
+
+extern int shell_back_init_cf( BackendInfo *bi );
+LDAP_END_DECL
+
+#endif /* PROTO_SHELL_H */
diff --git a/servers/slapd/back-shell/result.c b/servers/slapd/back-shell/result.c
new file mode 100644
index 0000000..9133eaf
--- /dev/null
+++ b/servers/slapd/back-shell/result.c
@@ -0,0 +1,135 @@
+/* result.c - shell backend result reading function */
+/* $OpenLDAP$ */
+/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
+ *
+ * Copyright 1998-2021 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>.
+ */
+/* Portions Copyright (c) 1995 Regents of the University of Michigan.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and that due credit is given
+ * to the University of Michigan at Ann Arbor. The name of the University
+ * may not be used to endorse or promote products derived from this
+ * software without specific prior written permission. This software
+ * is provided ``as is'' without express or implied warranty.
+ */
+/* ACKNOWLEDGEMENTS:
+ * This work was originally developed by the University of Michigan
+ * (as part of U-MICH LDAP).
+ */
+
+#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 "shell.h"
+
+int
+read_and_send_results(
+ Operation *op,
+ SlapReply *rs,
+ FILE *fp )
+{
+ int bsize, len;
+ char *buf, *bp;
+ char line[BUFSIZ];
+ char ebuf[128];
+
+ /* 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 ) {
+ if ( errno == EINTR ) continue;
+
+ Debug( LDAP_DEBUG_ANY, "shell: fgets failed: %s (%d)\n",
+ AC_STRERROR_R(errno, ebuf, sizeof ebuf), errno, 0 );
+ break;
+ }
+
+ Debug( LDAP_DEBUG_SHELL, "shell search reading line (%s)\n",
+ line, 0, 0 );
+
+ /* ignore lines beginning with # (LDIFv1 comments) */
+ if ( *line == '#' ) {
+ continue;
+ }
+
+ /* ignore lines beginning with DEBUG: */
+ if ( strncasecmp( line, "DEBUG:", 6 ) == 0 ) {
+ continue;
+ }
+
+ 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, 0, 0 );
+ } 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 );
+ }
+
+ free( buf );
+
+ return( rs->sr_err );
+}
+
+void
+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 );
+ }
+}
diff --git a/servers/slapd/back-shell/search.c b/servers/slapd/back-shell/search.c
new file mode 100644
index 0000000..b628b9f
--- /dev/null
+++ b/servers/slapd/back-shell/search.c
@@ -0,0 +1,86 @@
+/* search.c - shell backend search function */
+/* $OpenLDAP$ */
+/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
+ *
+ * Copyright 1998-2021 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>.
+ */
+/* Portions Copyright (c) 1995 Regents of the University of Michigan.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and that due credit is given
+ * to the University of Michigan at Ann Arbor. The name of the University
+ * may not be used to endorse or promote products derived from this
+ * software without specific prior written permission. This software
+ * is provided ``as is'' without express or implied warranty.
+ */
+/* ACKNOWLEDGEMENTS:
+ * This work was originally developed by the University of Michigan
+ * (as part of U-MICH LDAP).
+ */
+
+#include "portable.h"
+
+#include <stdio.h>
+
+#include <ac/socket.h>
+#include <ac/string.h>
+
+#include "slap.h"
+#include "shell.h"
+
+int
+shell_back_search(
+ Operation *op,
+ SlapReply *rs )
+{
+ struct shellinfo *si = (struct shellinfo *) op->o_bd->be_private;
+ FILE *rfp, *wfp;
+ AttributeName *an;
+
+ if ( si->si_search == NULL ) {
+ send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
+ "search not implemented" );
+ return( -1 );
+ }
+
+ if ( forkandexec( si->si_search, &rfp, &wfp ) == (pid_t)-1 ) {
+ send_ldap_error( op, rs, LDAP_OTHER,
+ "could not fork/exec" );
+ return( -1 );
+ }
+
+ /* write out the request to the search process */
+ fprintf( wfp, "SEARCH\n" );
+ fprintf( wfp, "msgid: %ld\n", (long) op->o_msgid );
+ print_suffixes( wfp, op->o_bd );
+ fprintf( wfp, "base: %s\n", op->o_req_dn.bv_val );
+ fprintf( wfp, "scope: %d\n", op->oq_search.rs_scope );
+ fprintf( wfp, "deref: %d\n", op->oq_search.rs_deref );
+ fprintf( wfp, "sizelimit: %d\n", op->oq_search.rs_slimit );
+ fprintf( wfp, "timelimit: %d\n", op->oq_search.rs_tlimit );
+ fprintf( wfp, "filter: %s\n", op->oq_search.rs_filterstr.bv_val );
+ fprintf( wfp, "attrsonly: %d\n", op->oq_search.rs_attrsonly ? 1 : 0 );
+ fprintf( wfp, "attrs:%s", op->oq_search.rs_attrs == NULL ? " all" : "" );
+ for ( an = op->oq_search.rs_attrs; an && an->an_name.bv_val; an++ ) {
+ fprintf( wfp, " %s", an->an_name.bv_val );
+ }
+ fprintf( wfp, "\n" );
+ fclose( wfp );
+
+ /* read in the results and send them along */
+ rs->sr_attrs = op->oq_search.rs_attrs;
+ read_and_send_results( op, rs, rfp );
+
+ fclose( rfp );
+ return( 0 );
+}
diff --git a/servers/slapd/back-shell/searchexample.conf b/servers/slapd/back-shell/searchexample.conf
new file mode 100644
index 0000000..a450ad3
--- /dev/null
+++ b/servers/slapd/back-shell/searchexample.conf
@@ -0,0 +1,29 @@
+# $OpenLDAP$
+## This work is part of OpenLDAP Software <http://www.openldap.org/>.
+##
+## Copyright 1998-2021 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>.
+#
+## Portions Copyright (c) 1995 Regents of the University of Michigan.
+## All rights reserved.
+##
+## Redistribution and use in source and binary forms are permitted
+## provided that this notice is preserved and that due credit is given
+## to the University of Michigan at Ann Arbor. The name of the University
+## may not be used to endorse or promote products derived from this
+## software without specific prior written permission. This software
+## is provided ``as is'' without express or implied warranty.
+
+include /usr/local/etc/openldap/schema/core.schema
+
+database shell
+suffix "dc=example,dc=com"
+search /usr/local/etc/searchexample.sh
diff --git a/servers/slapd/back-shell/searchexample.sh b/servers/slapd/back-shell/searchexample.sh
new file mode 100644
index 0000000..9ded406
--- /dev/null
+++ b/servers/slapd/back-shell/searchexample.sh
@@ -0,0 +1,65 @@
+#! /bin/sh
+# $OpenLDAP$
+## This work is part of OpenLDAP Software <http://www.openldap.org/>.
+##
+## Copyright 1998-2021 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>.
+#
+## Portions Copyright (c) 1995 Regents of the University of Michigan.
+## All rights reserved.
+##
+## Redistribution and use in source and binary forms are permitted
+## provided that this notice is preserved and that due credit is given
+## to the University of Michigan at Ann Arbor. The name of the University
+## may not be used to endorse or promote products derived from this
+## software without specific prior written permission. This software
+## is provided ``as is'' without express or implied warranty.
+
+while [ 1 ]; do
+ read TAG VALUE
+ if [ $? -ne 0 ]; then
+ break
+ fi
+ case "$TAG" in
+ base:)
+ BASE=$VALUE
+ ;;
+ filter:)
+ FILTER=$VALUE
+ ;;
+ # include other parameters here
+ esac
+done
+
+LOGIN=`echo $FILTER | sed -e 's/.*=\(.*\))/\1/'`
+
+PWLINE=`grep -i "^$LOGIN" /etc/passwd`
+
+#sleep 60
+# if we found an entry that matches
+if [ $? = 0 ]; then
+ echo $PWLINE | awk -F: '{
+ printf("dn: cn=%s,%s\n", $1, base);
+ printf("objectclass: top\n");
+ printf("objectclass: person\n");
+ printf("cn: %s\n", $1);
+ printf("cn: %s\n", $5);
+ printf("sn: %s\n", $1);
+ printf("uid: %s\n", $1);
+ }' base="$BASE"
+ echo ""
+fi
+
+# result
+echo "RESULT"
+echo "code: 0"
+
+exit 0
diff --git a/servers/slapd/back-shell/shell.h b/servers/slapd/back-shell/shell.h
new file mode 100644
index 0000000..ec239b3
--- /dev/null
+++ b/servers/slapd/back-shell/shell.h
@@ -0,0 +1,65 @@
+/* shell.h - shell backend header file */
+/* $OpenLDAP$ */
+/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
+ *
+ * Copyright 1998-2021 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>.
+ */
+/* Portions Copyright (c) 1995 Regents of the University of Michigan.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and that due credit is given
+ * to the University of Michigan at Ann Arbor. The name of the University
+ * may not be used to endorse or promote products derived from this
+ * software without specific prior written permission. This software
+ * is provided ``as is'' without express or implied warranty.
+ */
+/* ACKNOWLEDGEMENTS:
+ * This work was originally developed by the University of Michigan
+ * (as part of U-MICH LDAP).
+ */
+
+#ifndef SLAPD_SHELL_H
+#define SLAPD_SHELL_H
+
+#include "proto-shell.h"
+
+LDAP_BEGIN_DECL
+
+struct shellinfo {
+ char **si_bind; /* cmd + args to exec for bind */
+ char **si_unbind; /* cmd + args to exec for unbind */
+ char **si_search; /* cmd + args to exec for search */
+ char **si_compare; /* cmd + args to exec for compare */
+ char **si_modify; /* cmd + args to exec for modify */
+ char **si_modrdn; /* cmd + args to exec for modrdn */
+ char **si_add; /* cmd + args to exec for add */
+ char **si_delete; /* cmd + args to exec for delete */
+};
+
+extern pid_t forkandexec LDAP_P((
+ char **args,
+ FILE **rfp,
+ FILE **wfp));
+
+extern void print_suffixes LDAP_P((
+ FILE *fp,
+ BackendDB *bd));
+
+extern int read_and_send_results LDAP_P((
+ Operation *op,
+ SlapReply *rs,
+ FILE *fp));
+
+LDAP_END_DECL
+
+#endif
diff --git a/servers/slapd/back-shell/unbind.c b/servers/slapd/back-shell/unbind.c
new file mode 100644
index 0000000..77016e2
--- /dev/null
+++ b/servers/slapd/back-shell/unbind.c
@@ -0,0 +1,69 @@
+/* unbind.c - shell backend unbind function */
+/* $OpenLDAP$ */
+/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
+ *
+ * Copyright 1998-2021 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>.
+ */
+/* Portions Copyright (c) 1995 Regents of the University of Michigan.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and that due credit is given
+ * to the University of Michigan at Ann Arbor. The name of the University
+ * may not be used to endorse or promote products derived from this
+ * software without specific prior written permission. This software
+ * is provided ``as is'' without express or implied warranty.
+ */
+/* ACKNOWLEDGEMENTS:
+ * This work was originally developed by the University of Michigan
+ * (as part of U-MICH LDAP).
+ */
+
+#include "portable.h"
+
+#include <stdio.h>
+
+#include <ac/socket.h>
+#include <ac/string.h>
+
+#include "slap.h"
+#include "shell.h"
+
+int
+shell_back_unbind(
+ Operation *op,
+ SlapReply *rs
+)
+{
+ struct shellinfo *si = (struct shellinfo *) op->o_bd->be_private;
+ FILE *rfp, *wfp;
+
+ if ( si->si_unbind == NULL ) {
+ return 0;
+ }
+
+ if ( forkandexec( si->si_unbind, &rfp, &wfp ) == (pid_t)-1 ) {
+ return 0;
+ }
+
+ /* write out the request to the unbind process */
+ fprintf( wfp, "UNBIND\n" );
+ fprintf( wfp, "msgid: %ld\n", (long) op->o_msgid );
+ print_suffixes( wfp, op->o_bd );
+ fprintf( wfp, "dn: %s\n", (op->o_conn->c_dn.bv_len ? op->o_conn->c_dn.bv_val : "") );
+ fclose( wfp );
+
+ /* no response to unbind */
+ fclose( rfp );
+
+ return 0;
+}