summaryrefslogtreecommitdiffstats
path: root/servers/slapd/shell-backends
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--servers/slapd/shell-backends/Makefile.in40
-rw-r--r--servers/slapd/shell-backends/passwd-shell.c207
-rw-r--r--servers/slapd/shell-backends/shellutil.c396
-rw-r--r--servers/slapd/shell-backends/shellutil.h123
4 files changed, 766 insertions, 0 deletions
diff --git a/servers/slapd/shell-backends/Makefile.in b/servers/slapd/shell-backends/Makefile.in
new file mode 100644
index 0000000..d032ead
--- /dev/null
+++ b/servers/slapd/shell-backends/Makefile.in
@@ -0,0 +1,40 @@
+# Makefile.in for shell-backends
+# $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>.
+
+PROGRAMS = passwd-shell
+
+SRCS = passwd-shell.c shellutil.c
+XSRCS = pwd-version.c
+OBJS = passwd-shell.o shellutil.o
+
+LDAP_INCDIR= ../../../include
+LDAP_LIBDIR= ../../../libraries
+
+BUILD_OPT = "--enable-shell"
+BUILD_SRV = @BUILD_SHELL@
+
+all-local-srv: $(PROGRAMS)
+
+# create programs also when using modules
+depend-mod: depend-yes
+all-mod: all-yes
+install-mod: install-yes
+
+passwd-shell: pwd-version.o
+ $(CC) $(LDFLAGS) -o $@ $(OBJS) pwd-version.o $(LIBS)
+
+pwd-version.c: $(OBJS) $(LDAP_LIBDEPEND)
+ @-$(RM) $@
+ $(MKVERSION) passwd-shell > $@
diff --git a/servers/slapd/shell-backends/passwd-shell.c b/servers/slapd/shell-backends/passwd-shell.c
new file mode 100644
index 0000000..2414431
--- /dev/null
+++ b/servers/slapd/shell-backends/passwd-shell.c
@@ -0,0 +1,207 @@
+/* passwd-shell.c - passwd(5) shell-based backend for slapd(8) */
+/* $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/stdlib.h>
+
+#include <ac/string.h>
+#include <ac/unistd.h>
+
+#include <pwd.h>
+
+#include <lber.h>
+#include <ldap.h>
+
+#include "shellutil.h"
+
+static void pwdfile_search LDAP_P(( struct ldop *op, FILE *ofp ));
+static struct ldentry *pw2entry LDAP_P(( struct ldop *op, struct passwd *pw ));
+
+static char tmpbuf[ MAXLINELEN * 2 ];
+
+
+int
+main( int argc, char **argv )
+{
+ int c, errflg;
+ struct ldop op;
+
+ if (( progname = strrchr( argv[ 0 ], '/' )) == NULL ) {
+ progname = estrdup( argv[ 0 ] );
+ } else {
+ progname = estrdup( progname + 1 );
+ }
+
+ errflg = debugflg = 0;
+
+ while (( c = getopt( argc, argv, "d" )) != EOF ) {
+ switch( c ) {
+ case 'd':
+#ifdef LDAP_DEBUG
+ ++debugflg;
+#else /* LDAP_DEBUG */
+ fprintf( stderr, "%s: compile with -DLDAP_DEBUG for debugging\n",
+ progname );
+#endif /* LDAP_DEBUG */
+ break;
+ default:
+ ++errflg;
+ }
+ }
+
+ if ( errflg || optind < argc ) {
+ fprintf( stderr, "usage: %s [-d]\n", progname );
+ exit( EXIT_FAILURE );
+ }
+
+ debug_printf( "started\n" );
+
+ (void) memset( (char *)&op, '\0', sizeof( op ));
+
+ if ( parse_input( stdin, stdout, &op ) < 0 ) {
+ exit( EXIT_SUCCESS );
+ }
+
+ if ( op.ldop_op != LDOP_SEARCH ) {
+ write_result( stdout, LDAP_UNWILLING_TO_PERFORM, NULL,
+ "Command Not Implemented" );
+ exit( EXIT_SUCCESS );
+ }
+
+#ifdef LDAP_DEBUG
+ dump_ldop( &op );
+#endif /* LDAP_DEBUG */
+
+ pwdfile_search( &op, stdout );
+
+ exit( EXIT_SUCCESS );
+}
+
+
+static void
+pwdfile_search( struct ldop *op, FILE *ofp )
+{
+ struct passwd *pw;
+ struct ldentry *entry;
+ int oneentry;
+
+ oneentry = ( strchr( op->ldop_dn, '@' ) != NULL );
+
+ for ( pw = getpwent(); pw != NULL; pw = getpwent()) {
+ if (( entry = pw2entry( op, pw )) != NULL ) {
+ if ( oneentry ) {
+ if ( strcasecmp( op->ldop_dn, entry->lde_dn ) == 0 ) {
+ write_entry( op, entry, ofp );
+ break;
+ }
+ } else if ( test_filter( op, entry ) == LDAP_COMPARE_TRUE ) {
+ write_entry( op, entry, ofp );
+ }
+ free_entry( entry );
+ }
+ }
+ endpwent();
+
+ write_result( ofp, LDAP_SUCCESS, NULL, NULL );
+}
+
+
+static struct ldentry *
+pw2entry( struct ldop *op, struct passwd *pw )
+{
+ struct ldentry *entry;
+ struct ldattr *attr;
+ int i;
+
+ /*
+ * construct the DN from pw_name
+ */
+ if ( strchr( op->ldop_suffixes[ 0 ], '=' ) != NULL ) {
+ /*
+ * X.500 style DN
+ */
+ i = snprintf( tmpbuf, sizeof( tmpbuf ), "cn=%s, %s", pw->pw_name, op->ldop_suffixes[ 0 ] );
+ } else {
+ /*
+ * RFC-822 style DN
+ */
+ i = snprintf( tmpbuf, sizeof( tmpbuf ), "%s@%s", pw->pw_name, op->ldop_suffixes[ 0 ] );
+ }
+
+ if ( i < 0 || i >= sizeof( tmpbuf ) ) {
+ return NULL;
+ }
+
+ entry = (struct ldentry *) ecalloc( 1, sizeof( struct ldentry ));
+ entry->lde_dn = estrdup( tmpbuf );
+
+ /*
+ * for now, we simply derive the LDAP attribute values as follows:
+ * objectClass = person
+ * uid = pw_name
+ * sn = pw_name
+ * cn = pw_name
+ * cn = pw_gecos (second common name)
+ */
+ entry->lde_attrs = (struct ldattr **)ecalloc( 5, sizeof( struct ldattr * ));
+ i = 0;
+ attr = (struct ldattr *)ecalloc( 1, sizeof( struct ldattr ));
+ attr->lda_name = estrdup( "objectClass" );
+ attr->lda_values = (char **)ecalloc( 2, sizeof( char * ));
+ attr->lda_values[ 0 ] = estrdup( "person" );
+ entry->lde_attrs[ i++ ] = attr;
+
+ attr = (struct ldattr *)ecalloc( 1, sizeof( struct ldattr ));
+ attr->lda_name = estrdup( "uid" );
+ attr->lda_values = (char **)ecalloc( 2, sizeof( char * ));
+ attr->lda_values[ 0 ] = estrdup( pw->pw_name );
+ entry->lde_attrs[ i++ ] = attr;
+
+ attr = (struct ldattr *)ecalloc( 1, sizeof( struct ldattr ));
+ attr->lda_name = estrdup( "sn" );
+ attr->lda_values = (char **)ecalloc( 2, sizeof( char * ));
+ attr->lda_values[ 0 ] = estrdup( pw->pw_name );
+ entry->lde_attrs[ i++ ] = attr;
+
+ attr = (struct ldattr *)ecalloc( 1, sizeof( struct ldattr ));
+ attr->lda_name = estrdup( "cn" );
+ attr->lda_values = (char **)ecalloc( 3, sizeof( char * ));
+ attr->lda_values[ 0 ] = estrdup( pw->pw_name );
+ if ( pw->pw_gecos != NULL && *pw->pw_gecos != '\0' ) {
+ attr->lda_values[ 1 ] = estrdup( pw->pw_gecos );
+ }
+ entry->lde_attrs[ i++ ] = attr;
+
+ return( entry );
+}
diff --git a/servers/slapd/shell-backends/shellutil.c b/servers/slapd/shell-backends/shellutil.c
new file mode 100644
index 0000000..605114e
--- /dev/null
+++ b/servers/slapd/shell-backends/shellutil.c
@@ -0,0 +1,396 @@
+/* shellutil.c - common routines useful when building shell-based backends */
+/* $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/stdlib.h>
+#include <ac/stdarg.h>
+
+#include <pwd.h>
+
+#include <ac/ctype.h>
+#include <ac/string.h>
+
+#include <lber.h>
+#include <ldap.h>
+#include "shellutil.h"
+
+
+int debugflg;
+char *progname;
+
+static struct inputparams ips[] = {
+ IP_TYPE_SUFFIX, "suffix",
+ IP_TYPE_BASE, "base",
+ IP_TYPE_SCOPE, "scope",
+ IP_TYPE_ALIASDEREF, "deref",
+ IP_TYPE_SIZELIMIT, "sizelimit",
+ IP_TYPE_TIMELIMIT, "timelimit",
+ IP_TYPE_FILTER, "filter",
+ IP_TYPE_ATTRS, "attrs",
+ IP_TYPE_ATTRSONLY, "attrsonly",
+ 0, NULL
+};
+
+
+void
+write_result( FILE *fp, int code, char *matched, char *info )
+{
+ fprintf( fp, "RESULT\ncode: %d\n", code );
+ debug_printf( ">> RESULT\n" );
+ debug_printf( ">> code: %d\n", code );
+
+ if ( matched != NULL ) {
+ fprintf( fp, "matched: %s\n", matched );
+ debug_printf( ">> matched: %s\n", matched );
+ }
+
+ if ( info != NULL ) {
+ fprintf( fp, "info: %s\n", info );
+ debug_printf( ">> info: %s\n", info );
+ }
+}
+
+
+void
+write_entry( struct ldop *op, struct ldentry *entry, FILE *ofp )
+{
+ struct ldattr **app;
+ char **valp;
+
+ fprintf( ofp, "dn: %s\n", entry->lde_dn );
+ for ( app = entry->lde_attrs; *app != NULL; ++app ) {
+ if ( attr_requested( (*app)->lda_name, op )) {
+ for ( valp = (*app)->lda_values; *valp != NULL; ++valp ) {
+ fprintf( ofp, "%s: %s\n", (*app)->lda_name, *valp );
+ }
+ }
+ }
+ fputc( '\n', ofp );
+}
+
+
+int
+test_filter( struct ldop *op, struct ldentry *entry )
+{
+ return ((random() & 0x07 ) == 0x07) /* XXX random for now */
+ ? LDAP_COMPARE_TRUE : LDAP_COMPARE_FALSE;
+}
+
+
+int
+attr_requested( char *name, struct ldop *op )
+{
+ char **ap;
+
+ if ( op->ldop_srch.ldsp_attrs == NULL ) { /* special case */
+ return( 1 );
+ }
+
+ for ( ap = op->ldop_srch.ldsp_attrs; *ap != NULL; ++ap ) {
+ if ( strcasecmp( name, *ap ) == 0 ) {
+ return( 1 );
+ }
+ }
+
+ return( 0 );
+}
+
+
+void
+free_entry( struct ldentry *entry )
+{
+ struct ldattr **app;
+ char **valp;
+
+ free( entry->lde_dn );
+
+ for ( app = entry->lde_attrs; *app != NULL; ++app ) {
+ for ( valp = (*app)->lda_values; *valp != NULL; ++valp ) {
+ free( *valp );
+ }
+ free( (*app)->lda_values );
+ free( (*app)->lda_name );
+ }
+
+ free( entry->lde_attrs );
+ free( entry );
+}
+
+
+int
+parse_input( FILE *ifp, FILE *ofp, struct ldop *op )
+{
+ char *p, *args, line[ MAXLINELEN + 1 ];
+ struct inputparams *ip;
+
+ if ( fgets( line, MAXLINELEN, ifp ) == NULL ) {
+ write_result( ofp, LDAP_OTHER, NULL, "Empty Input" );
+ }
+ line[ strlen( line ) - 1 ] = '\0';
+ if ( strncasecmp( line, STR_OP_SEARCH, sizeof( STR_OP_SEARCH ) - 1 )
+ != 0 ) {
+ write_result( ofp, LDAP_UNWILLING_TO_PERFORM, NULL,
+ "Operation Not Supported" );
+ return( -1 );
+ }
+
+ op->ldop_op = LDOP_SEARCH;
+
+ while ( fgets( line, MAXLINELEN, ifp ) != NULL ) {
+ line[ strlen( line ) - 1 ] = '\0';
+ debug_printf( "<< %s\n", line );
+
+ args = line;
+ if (( ip = find_input_tag( &args )) == NULL ) {
+ debug_printf( "ignoring %s\n", line );
+ continue;
+ }
+
+ switch( ip->ip_type ) {
+ case IP_TYPE_SUFFIX:
+ add_strval( &op->ldop_suffixes, args );
+ break;
+ case IP_TYPE_BASE:
+ op->ldop_dn = estrdup( args );
+ break;
+ case IP_TYPE_SCOPE:
+ if ( lutil_atoi( &op->ldop_srch.ldsp_scope, args ) != 0 ||
+ ( op->ldop_srch.ldsp_scope != LDAP_SCOPE_BASE &&
+ op->ldop_srch.ldsp_scope != LDAP_SCOPE_ONELEVEL &&
+ op->ldop_srch.ldsp_scope != LDAP_SCOPE_SUBTREE ) )
+ {
+ write_result( ofp, LDAP_OTHER, NULL, "Bad scope" );
+ return( -1 );
+ }
+ break;
+ case IP_TYPE_ALIASDEREF:
+ if ( lutil_atoi( &op->ldop_srch.ldsp_aliasderef, args ) != 0 ) {
+ write_result( ofp, LDAP_OTHER, NULL, "Bad alias deref" );
+ return( -1 );
+ }
+ break;
+ case IP_TYPE_SIZELIMIT:
+ if ( lutil_atoi( &op->ldop_srch.ldsp_sizelimit, args ) != 0 ) {
+ write_result( ofp, LDAP_OTHER, NULL, "Bad size limit" );
+ return( -1 );
+ }
+ break;
+ case IP_TYPE_TIMELIMIT:
+ if ( lutil_atoi( &op->ldop_srch.ldsp_timelimit, args ) != 0 ) {
+ write_result( ofp, LDAP_OTHER, NULL, "Bad time limit" );
+ return( -1 );
+ }
+ break;
+ case IP_TYPE_FILTER:
+ op->ldop_srch.ldsp_filter = estrdup( args );
+ break;
+ case IP_TYPE_ATTRSONLY:
+ op->ldop_srch.ldsp_attrsonly = ( *args != '0' );
+ break;
+ case IP_TYPE_ATTRS:
+ if ( strcmp( args, "all" ) == 0 ) {
+ op->ldop_srch.ldsp_attrs = NULL;
+ } else {
+ while ( args != NULL ) {
+ if (( p = strchr( args, ' ' )) != NULL ) {
+ *p++ = '\0';
+ while ( isspace( (unsigned char) *p )) {
+ ++p;
+ }
+ }
+ add_strval( &op->ldop_srch.ldsp_attrs, args );
+ args = p;
+ }
+ }
+ break;
+ }
+ }
+
+ if ( op->ldop_suffixes == NULL || op->ldop_dn == NULL ||
+ op->ldop_srch.ldsp_filter == NULL ) {
+ write_result( ofp, LDAP_OTHER, NULL,
+ "Required suffix:, base:, or filter: missing" );
+ return( -1 );
+ }
+
+ return( 0 );
+}
+
+
+struct inputparams *
+find_input_tag( char **linep ) /* linep is set to start of args */
+{
+ int i;
+ char *p;
+
+ if (( p = strchr( *linep, ':' )) == NULL || p == *linep ) {
+ return( NULL );
+ }
+
+ for ( i = 0; ips[ i ].ip_type != 0; ++i ) {
+ if ( strncasecmp( *linep, ips[ i ].ip_tag, p - *linep ) == 0 ) {
+ while ( isspace( (unsigned char) *(++p) )) {
+ ;
+ }
+ *linep = p;
+ return( &ips[ i ] );
+ }
+ }
+
+ return( NULL );
+}
+
+
+void
+add_strval( char ***sp, char *val )
+{
+ int i;
+ char **vallist;
+
+ vallist = *sp;
+
+ if ( vallist == NULL ) {
+ i = 0;
+ } else {
+ for ( i = 0; vallist[ i ] != NULL; ++i ) {
+ ;
+ }
+ }
+
+ vallist = (char **)erealloc( vallist, ( i + 2 ) * sizeof( char * ));
+ vallist[ i ] = estrdup( val );
+ vallist[ ++i ] = NULL;
+ *sp = vallist;
+}
+
+
+char *
+estrdup( char *s )
+{
+ char *p;
+
+ if (( p = strdup( s )) == NULL ) {
+ debug_printf( "strdup failed\n" );
+ exit( EXIT_FAILURE );
+ }
+
+ return( p );
+}
+
+
+void *
+erealloc( void *s, unsigned size )
+{
+ char *p;
+
+ if ( s == NULL ) {
+ p = malloc( size );
+ } else {
+ p = realloc( s, size );
+ }
+
+ if ( p == NULL ) {
+ debug_printf( "realloc( p, %d ) failed\n", size );
+ exit( EXIT_FAILURE );
+ }
+
+ return( p );
+}
+
+
+char *
+ecalloc( unsigned nelem, unsigned elsize )
+{
+ char *p;
+
+ if (( p = calloc( nelem, elsize )) == NULL ) {
+ debug_printf( "calloc( %d, %d ) failed\n", nelem, elsize );
+ exit( EXIT_FAILURE );
+ }
+
+ return( p );
+}
+
+
+#ifdef LDAP_DEBUG
+
+/* VARARGS */
+void
+debug_printf( const char *fmt, ... )
+{
+ va_list ap;
+
+ if ( debugflg ) {
+ va_start( ap, fmt );
+ fprintf( stderr, "%s: ", progname );
+ vfprintf( stderr, fmt, ap );
+ va_end( ap );
+ }
+}
+
+
+void
+dump_ldop( struct ldop *op )
+{
+ if ( !debugflg ) {
+ return;
+ }
+
+ debug_printf( "SEARCH operation\n" );
+ if ( op->ldop_suffixes == NULL ) {
+ debug_printf( " suffix: NONE\n" );
+ } else {
+ int i;
+ for ( i = 0; op->ldop_suffixes[ i ] != NULL; ++i ) {
+ debug_printf( " suffix: <%s>\n", op->ldop_suffixes[ i ] );
+ }
+ }
+ debug_printf( " dn: <%s>\n", op->ldop_dn );
+ debug_printf( " scope: <%d>\n", op->ldop_srch.ldsp_scope );
+ debug_printf( " filter: <%s>\n", op->ldop_srch.ldsp_filter );
+ debug_printf( "aliasderef: <%d>\n", op->ldop_srch.ldsp_aliasderef );
+ debug_printf( " sizelimit: <%d>\n", op->ldop_srch.ldsp_sizelimit );
+ debug_printf( " timelimit: <%d>\n", op->ldop_srch.ldsp_timelimit );
+ debug_printf( " attrsonly: <%d>\n", op->ldop_srch.ldsp_attrsonly );
+ if ( op->ldop_srch.ldsp_attrs == NULL ) {
+ debug_printf( " attrs: ALL\n" );
+ } else {
+ int i;
+
+ for ( i = 0; op->ldop_srch.ldsp_attrs[ i ] != NULL; ++i ) {
+ debug_printf( " attrs: <%s>\n", op->ldop_srch.ldsp_attrs[ i ] );
+ }
+ }
+}
+#endif /* LDAP_DEBUG */
diff --git a/servers/slapd/shell-backends/shellutil.h b/servers/slapd/shell-backends/shellutil.h
new file mode 100644
index 0000000..a359aa2
--- /dev/null
+++ b/servers/slapd/shell-backends/shellutil.h
@@ -0,0 +1,123 @@
+/* shellutil.h */
+/* $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 SHELLUTIL_H
+#define SHELLUTIL_H
+
+#include <ldap_cdefs.h>
+
+LDAP_BEGIN_DECL
+
+#define MAXLINELEN 512
+
+#define STR_OP_SEARCH "SEARCH"
+
+
+struct inputparams {
+ int ip_type;
+#define IP_TYPE_SUFFIX 0x01
+#define IP_TYPE_BASE 0x02
+#define IP_TYPE_SCOPE 0x03
+#define IP_TYPE_ALIASDEREF 0x04
+#define IP_TYPE_SIZELIMIT 0x05
+#define IP_TYPE_TIMELIMIT 0x06
+#define IP_TYPE_FILTER 0x07
+#define IP_TYPE_ATTRSONLY 0x08
+#define IP_TYPE_ATTRS 0x09
+ char *ip_tag;
+};
+
+
+struct ldsrchparms {
+ int ldsp_scope;
+ int ldsp_aliasderef;
+ int ldsp_sizelimit;
+ int ldsp_timelimit;
+ int ldsp_attrsonly;
+ char *ldsp_filter;
+ char **ldsp_attrs;
+};
+
+
+struct ldop {
+ int ldop_op;
+#define LDOP_SEARCH 0x01
+ char **ldop_suffixes;
+ char *ldop_dn;
+ union ldapop_params_u {
+ struct ldsrchparms LDsrchparams;
+ } ldop_params;
+#define ldop_srch ldop_params.LDsrchparams
+};
+
+
+struct ldattr {
+ char *lda_name;
+ char **lda_values;
+};
+
+
+struct ldentry {
+ char *lde_dn;
+ struct ldattr **lde_attrs;
+};
+
+
+#ifdef LDAP_DEBUG
+void debug_printf(const char *, ...) LDAP_GCCATTR((format(printf, 1, 2)));
+#else /* LDAP_DEBUG */
+#define debug_printf (void) /* Ignore "arguments" */
+#endif /* LDAP_DEBUG */
+
+/*
+ * function prototypes
+ */
+void write_result( FILE *fp, int code, char *matched, char *info );
+void write_entry( struct ldop *op, struct ldentry *entry, FILE *ofp );
+int test_filter( struct ldop *op, struct ldentry *entry );
+void free_entry( struct ldentry *entry );
+int attr_requested( char *name, struct ldop *op );
+int parse_input( FILE *ifp, FILE *ofp, struct ldop *op );
+struct inputparams *find_input_tag( char **linep );
+void add_strval( char ***sp, char *val );
+char *ecalloc( unsigned nelem, unsigned elsize );
+void *erealloc( void *s, unsigned size );
+char *estrdup( char *s );
+extern void dump_ldop (struct ldop *op);
+
+
+/*
+ * global variables
+ */
+extern int debugflg;
+extern char *progname;
+
+LDAP_END_DECL
+#endif