ITS#8882 Add slapo-emptyds to contrib

This commit is contained in:
Ondřej Kuzník 2022-05-06 11:34:14 +01:00 committed by Quanah Gibson-Mount
parent d75de4d6e9
commit d20577456f
13 changed files with 1193 additions and 0 deletions

View file

@ -0,0 +1,3 @@
# test suite
clients
servers

View file

@ -0,0 +1,78 @@
# $OpenLDAP$
# This work is part of OpenLDAP Software <http://www.openldap.org/>.
#
# Copyright 1998-2022 The OpenLDAP Foundation.
#
# 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>.
LDAP_SRC = ../../..
LDAP_BUILD = $(LDAP_SRC)
SRCDIR = ./
LDAP_INC = -I$(LDAP_BUILD)/include -I$(LDAP_SRC)/include -I$(LDAP_SRC)/servers/slapd
LDAP_LIB = $(LDAP_BUILD)/libraries/libldap/libldap.la \
$(LDAP_BUILD)/libraries/liblber/liblber.la
LIBTOOL = $(LDAP_BUILD)/libtool
INSTALL = /usr/bin/install
CC = gcc
OPT = -g -O2
DEFS = -DSLAPD_OVER_EDS=SLAPD_MOD_DYNAMIC
INCS = $(LDAP_INC)
LIBS = $(LDAP_LIB)
PROGRAMS = emptyds.la
MANPAGES = slapo-emptyds.5
CLEAN = *.o *.lo *.la .libs
LTVER = 0:0:0
prefix=/usr/local
exec_prefix=$(prefix)
ldap_subdir=/openldap
libdir=$(exec_prefix)/lib
libexecdir=$(exec_prefix)/libexec
moduledir = $(libexecdir)$(ldap_subdir)
mandir = $(exec_prefix)/share/man
man5dir = $(mandir)/man5
all: $(PROGRAMS)
d :=
sp :=
dir := tests
include $(dir)/Rules.mk
.SUFFIXES: .c .o .lo
.c.lo:
$(LIBTOOL) --mode=compile $(CC) $(CFLAGS) $(OPT) $(CPPFLAGS) $(DEFS) $(INCS) -c $<
all: $(PROGRAMS)
emptyds.la: emptyds.lo
$(LIBTOOL) --mode=link $(CC) $(LDFLAGS) -version-info $(LTVER) \
-rpath $(moduledir) -module -o $@ $? $(LIBS)
clean:
rm -rf $(CLEAN)
install: install-lib install-man FORCE
install-lib: $(PROGRAMS)
mkdir -p $(DESTDIR)$(moduledir)
for p in $(PROGRAMS) ; do \
$(LIBTOOL) --mode=install cp $$p $(DESTDIR)$(moduledir) ; \
done
install-man: $(MANPAGES)
mkdir -p $(DESTDIR)$(man5dir)
$(INSTALL) -m 644 $(MANPAGES) $(DESTDIR)$(man5dir)
FORCE:

View file

@ -0,0 +1,66 @@
emptyds Overlay README
DESCRIPTION
This package contains an OpenLDAP overlay called "emptyds" (empty
directory string) that eliminates empty values of type directory string
(OID 1.3.6.1.4.1.1466.115.121.1.15) from the list of the values in the
following manner:
- add: All empty attribute values will be removed before the add request
is executed
- mod-replace: A replace with empty values will be modified to a replace
without values. As result the attribute will be deleted
- mod-add: All empty attribute values will be removed before the mod-add
request is executed
- mod-delete: All empty attribute values will be removed before the
mod-delete request is executed
If removing all empty values from a modification makes it a no-op, that
modification is removed from the list.
At module load time the emptyds overlay manipulates the syntax checking
so that it intercepts the syntax check and allows empty values for
attributes of type directory string only. Non-empty values continue to
go through the normal check routines. It is therefore very important to
configure the overlays in a way that ensures that the emptyds overlay gets
the control over the operation before any other overlay. Otherwise it
could come to the situation with empty attribute values in the data base.
David Hawes' addpartial overlay has been used as starting point for this
overlay.
BUILDING
A Makefile is included, please set your LDAP_SRC directory properly.
INSTALLATION
After compiling the emptyds overlay, add the following to your
slapd.conf:
### slapd.conf
...
moduleload emptyds.la
...
overlay emptyds
...
# before database directive...
# this overlay must be the last overlay in the config file to ensure that
# requests are modified before other overlays get them.
...
### end slapd.conf
CAVEATS
- In order to ensure that emptyds does what it needs to do, it must be
the last overlay configured so it will run before the other overlays.
---
Copyright 2014-2022 The OpenLDAP Foundation.
Portions Copyright (C) DAASI International GmbH, Tamim Ziai.
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 file LICENSE in the
top-level directory of the distribution or, alternatively, at
http://www.OpenLDAP.org/license.html.

View file

@ -0,0 +1,325 @@
/* emptyds.c */
/* $OpenLDAP$ */
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
*
* Copyright 2014-2022 The OpenLDAP Foundation.
* Portions Copyright (C) 2014 DAASI International GmbH, Tamim Ziai.
* Portions Copyright (C) 2022 Ondřej Kuzník, Symas Corporation.
* 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 file LICENSE in the
* top-level directory of the distribution or, alternatively, at
* http://www.OpenLDAP.org/license.html.
*/
/* ACKNOLEDGEDMENTS:
* This work was initially developed by Tamim Ziai of DAASI International GmbH
* for inclusion in OpenLDAP Software.
*/
/* slapo-emptyds
*
* This is an OpenLDAP overlay that accepts empty strings as attribute values
* without syntax violation but never actually stores them. This allows
* applications that used to work with LDAP implementations allowing empty
* strings (such as Novel eDirectory) to continue to work with OpenLDAP without
* any modifications. Add and modify change types will be proceeded as follows,
* other operations will be forwarded without modifications:
*
* changeType: add changeType: add
* sn: <empty> --> sn: blah
* sn: blah
*
* changeType: modify changeType: modify
* add: sn --> add: sn
* sn: <empty> sn: blah
* sn: blah
*
* changeType: modify changeType: modify
* delete: sn --> delete: sn
* sn: <empty> sn: blah
* sn: blah
*
* changeType: modify changeType: modify
* replace: sn --> replace: sn
* sn: <empty>
*
*/
#include "portable.h"
#include "slap.h"
static slap_overinst emptyds;
static const char ds_oid[] = "1.3.6.1.4.1.1466.115.121.1.15";
static slap_syntax_validate_func *ssyn_validate_original = NULL;
static slap_syntax_transform_func *ssyn_pretty_original = NULL;
static int emptyds_instances = 0;
static unsigned int
remove_empty_values( Modification *m, Attribute *a )
{
BerVarray vals = m ? m->sm_values : a->a_vals,
nvals = m ? m->sm_nvalues : a->a_nvals;
unsigned int i, j, numvals = m ? m->sm_numvals : a->a_numvals;
for ( i = 0; i < numvals && !BER_BVISEMPTY( &vals[i] ); i++ )
/* Find first empty */;
if ( i == numvals ) return i;
/*
* We have an empty value at index i, move all of them to the end of the
* list, preserving the order of non-empty values.
*/
j = i + 1;
for ( j = i + 1; j < numvals; j++ ) {
struct berval tmp;
if ( BER_BVISEMPTY( &vals[j] ) ) continue;
tmp = vals[i];
vals[i] = vals[j];
vals[j] = tmp;
if ( nvals && vals != nvals ) {
tmp = nvals[i];
nvals[i] = nvals[j];
nvals[j] = tmp;
}
if ( m && a && m->sm_values != a->a_vals ) {
tmp = a->a_vals[i];
a->a_vals[i] = a->a_vals[j];
a->a_vals[j] = tmp;
if ( a->a_nvals && a->a_vals != a->a_nvals ) {
tmp = a->a_nvals[i];
a->a_nvals[i] = a->a_nvals[j];
a->a_nvals[j] = tmp;
}
}
i++;
}
/* Free empty vals */
for ( ; j && i < j--; ) {
ber_memfree( vals[j].bv_val );
if ( nvals && vals != nvals ) {
ber_memfree( nvals[j].bv_val );
BER_BVZERO( &nvals[j] );
}
if ( m && a && m->sm_values != a->a_vals ) {
if ( m->sm_values[j].bv_val != a->a_vals[j].bv_val ) {
ber_memfree( a->a_vals[j].bv_val );
BER_BVZERO( &a->a_vals[j] );
if ( a->a_nvals && a->a_vals != a->a_nvals ) {
ber_memfree( a->a_nvals[j].bv_val );
BER_BVZERO( &a->a_nvals[j] );
}
}
}
BER_BVZERO( &vals[j] );
}
return i;
}
/**
* Remove all operations with empty strings.
*/
static int
emptyds_op_add( Operation *op, SlapReply *rs )
{
Attribute **ap, **nexta, *a;
Modifications **mlp, **nextp = NULL, *ml;
Entry *e = op->ora_e;
/*
* op->ora_modlist can be NULL, at least accesslog doesn't always populate
* it on an add.
*/
for ( ap = &e->e_attrs, a = e->e_attrs, mlp = &op->ora_modlist,
ml = op->ora_modlist;
a != NULL;
ap = nexta, a = *ap, mlp = nextp, ml = ml ? *mlp : NULL ) {
AttributeType *at = a->a_desc->ad_type;
unsigned int remaining;
nexta = &a->a_next;
if ( ml ) {
nextp = &ml->sml_next;
}
if ( at->sat_syntax != slap_schema.si_syn_directoryString ||
at->sat_atype.at_usage != LDAP_SCHEMA_USER_APPLICATIONS )
continue;
remaining = remove_empty_values( &ml->sml_mod, a );
if ( remaining == a->a_numvals ) continue;
/* Empty values found */
if ( !remaining ) {
/* All values are empty */
*ap = a->a_next;
a->a_next = NULL;
nexta = ap;
if ( ml ) {
*mlp = ml->sml_next;
ml->sml_next = NULL;
nextp = mlp;
/* Values are generally shared with attribute */
slap_mods_free( ml, ml->sml_values != a->a_vals );
}
attr_free( a );
} else {
a->a_numvals = remaining;
if ( ml ) {
ml->sml_mod.sm_numvals = remaining;
}
}
}
return SLAP_CB_CONTINUE;
}
static int
emptyds_op_modify( Operation *op, SlapReply *rs )
{
Modifications **mlp, **nextp, *ml;
for ( mlp = &op->orm_modlist, ml = op->orm_modlist; ml != NULL;
mlp = nextp, ml = *mlp ) {
AttributeType *at = ml->sml_desc->ad_type;
unsigned int remaining;
nextp = &ml->sml_next;
if ( at->sat_syntax != slap_schema.si_syn_directoryString ||
at->sat_atype.at_usage != LDAP_SCHEMA_USER_APPLICATIONS )
continue;
remaining = remove_empty_values( &ml->sml_mod, NULL );
if ( remaining == ml->sml_numvals ) continue;
if ( !remaining ) {
/* All values are empty */
if ( ml->sml_op == LDAP_MOD_REPLACE ) {
/* Replace is kept */
if ( ml->sml_nvalues && ml->sml_nvalues != ml->sml_values ) {
ber_bvarray_free( ml->sml_nvalues );
}
if ( ml->sml_values ) {
ber_bvarray_free( ml->sml_values );
}
ml->sml_numvals = 0;
ml->sml_values = NULL;
ml->sml_nvalues = NULL;
} else {
/* Remove modification */
*mlp = ml->sml_next;
ml->sml_next = NULL;
nextp = mlp;
slap_mods_free( ml, 1 );
}
} else {
ml->sml_numvals = remaining;
}
}
return SLAP_CB_CONTINUE;
}
static int
emptyds_ssyn_validate( Syntax *syntax, struct berval *in )
{
if ( BER_BVISEMPTY( in ) && syntax == slap_schema.si_syn_directoryString ) {
return LDAP_SUCCESS;
}
return ssyn_validate_original( syntax, in );
}
static int
emptyds_ssyn_pretty( Syntax *syntax,
struct berval *in,
struct berval *out,
void *memctx )
{
if ( BER_BVISEMPTY( in ) && syntax == slap_schema.si_syn_directoryString ) {
return LDAP_SUCCESS;
}
return ssyn_pretty_original( syntax, in, out, memctx );
}
static int
emptyds_db_init( BackendDB *be, ConfigReply *cr )
{
Syntax *syntax = syn_find( ds_oid );
if ( syntax == NULL ) {
Debug( LDAP_DEBUG_TRACE, "emptyds_db_init: "
"Syntax %s not found\n",
ds_oid );
} else {
Debug( LDAP_DEBUG_TRACE, "emptyds_db_init: "
"Found syntax: %s\n",
syntax->ssyn_bvoid.bv_val );
if ( ssyn_validate_original == NULL && syntax->ssyn_validate != NULL ) {
ssyn_validate_original = syntax->ssyn_validate;
syntax->ssyn_validate = emptyds_ssyn_validate;
}
if ( ssyn_pretty_original == NULL && syntax->ssyn_pretty != NULL ) {
ssyn_pretty_original = syntax->ssyn_pretty;
syntax->ssyn_pretty = &emptyds_ssyn_pretty;
}
}
emptyds_instances++;
return LDAP_SUCCESS;
}
static int
emptyds_db_destroy( BackendDB *be, ConfigReply *cr )
{
Syntax *syntax = syn_find( ds_oid );
if ( --emptyds_instances == 0 && syntax != NULL ) {
if ( syntax->ssyn_validate == emptyds_ssyn_validate ) {
syntax->ssyn_validate = ssyn_validate_original;
}
ssyn_validate_original = NULL;
if ( syntax->ssyn_pretty == emptyds_ssyn_pretty ) {
syntax->ssyn_pretty = ssyn_pretty_original;
}
ssyn_pretty_original = NULL;
}
assert( emptyds_instances >= 0 );
return LDAP_SUCCESS;
}
int
emptyds_init()
{
emptyds.on_bi.bi_type = "emptyds";
emptyds.on_bi.bi_op_add = emptyds_op_add;
emptyds.on_bi.bi_op_modify = emptyds_op_modify;
emptyds.on_bi.bi_db_init = emptyds_db_init;
emptyds.on_bi.bi_db_destroy = emptyds_db_destroy;
return overlay_register( &emptyds );
}
int
init_module( int argc, char *argv[] )
{
return emptyds_init();
}

View file

@ -0,0 +1,68 @@
.TH SLAPO-EDS 5 "RELEASEDATE" "OpenLDAP LDVERSION"
.\" Copyright 2022 The OpenLDAP Foundation, All Rights Reserved.
.\" Copyright 2018 Tamim Ziai
.\" Copying restrictions apply. See COPYRIGHT/LICENSE.
.\" $OpenLDAP$
.SH NAME
slapo-emptyds \- Remove Empty values from Directory String attributes
Overlay to slapd
.SH SYNOPSIS
ETCDIR/slapd.conf
.SH DESCRIPTION
Some non-conformant clients will provide empty values for Directory String
attributes with certain operations. This overlay makes empty values acceptable
for the Directory String syntax and will adjust all operations to make sure
these values are never actually stored in the database.
.LP
.nf
.ft tt
dn: cn=alex,cn=people,dc=example,dc=org
changeType: add changeType: add
sn: <empty> --> sn: blah
sn: blah
dn: cn=alex,cn=people,dc=example,dc=org
changeType: modify changeType: modify
add: sn --> add: sn
sn: <empty> sn: blah
sn: blah
dn: cn=alex,cn=people,dc=example,dc=org
changeType: modify changeType: modify
delete: sn --> delete: sn
sn: <empty> sn: blah
sn: blah
dn: cn=alex,cn=people,dc=example,dc=org
changeType: modify changeType: modify
replace: sn --> replace: sn
sn: <empty>
dn: cn=alex,cn=people,dc=example,dc=org
changeType: modify changeType: modify
replace: sn --> replace: sn
sn: <empty> sn: blah
sn: blah
.ft
.fi
.LP
.SH CONFIGURATION
This overlay has no specific configuration, however in order to ensure that it
does what it needs to do, it should be the last overlay configured so it will
run before the other overlays.
.SH EXAMPLES
.LP
.RS
.nf
overlay emptyds
.RE
.SH FILES
.TP
ETCDIR/slapd.conf
default slapd configuration file
.SH SEE ALSO
.BR slapd.conf (5).
.SH ACKNOWLEDGEMENTS
This module was written in 2014 by Tamim Ziai for DAASI International and
updated in 2022 by Ondřej Kuzník for inclusion in the OpenLDAP project.
.so ../Project

View file

@ -0,0 +1,4 @@
progs
schema
testdata
testrun

View file

@ -0,0 +1,23 @@
sp := $(sp).x
dirstack_$(sp) := $(d)
d := $(dir)
.PHONY: test
CLEAN += clients servers tests/progs tests/schema tests/testdata tests/testrun
test: all clients servers tests/progs
test:
cd tests; \
SRCDIR=$(abspath $(LDAP_SRC)) \
LDAP_BUILD=$(abspath $(LDAP_BUILD)) \
TOPDIR=$(abspath $(SRCDIR)) \
LIBTOOL=$(abspath $(LIBTOOL)) \
$(abspath $(SRCDIR))/tests/run all
servers clients tests/progs:
ln -s $(abspath $(LDAP_BUILD))/$@ $@
d := $(dirstack_$(sp))
sp := $(basename $(sp))

View file

@ -0,0 +1,54 @@
# basic slapd config -- for testing of slapo-emptyds
# $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>.
include @SCHEMADIR@/core.schema
include @SCHEMADIR@/cosine.schema
include @SCHEMADIR@/inetorgperson.schema
include @SCHEMADIR@/openldap.schema
include @SCHEMADIR@/nis.schema
include @DATADIR@/test.schema
#
pidfile @TESTDIR@/slapd.1.pid
argsfile @TESTDIR@/slapd.1.args
#mod#modulepath ../servers/slapd/back-@BACKEND@/
#mod#moduleload back_@BACKEND@.la
#accesslogmod#modulepath ../servers/slapd/overlays/
#accesslogmod#moduleload accesslog.la
moduleload ../emptyds.la
database @BACKEND@
suffix "dc=example,dc=com"
rootdn "cn=Manager,dc=example,dc=com"
rootpw secret
#~null~#directory @TESTDIR@/db.1.a
overlay accesslog
logdb cn=log
logops writes
logsuccess true
overlay emptyds
database @BACKEND@
suffix "cn=log"
rootdn "cn=Manager,dc=example,dc=com"
#~null~#directory @TESTDIR@/db.1.b
## This one makes no difference except we want to make sure we can
## safely instantiate the overlay on multiple databases
overlay emptyds
database monitor

View file

@ -0,0 +1,71 @@
# slapd prevents us from adding the same value multiple times
dn: cn=Ursula Hampster,ou=Alumni Association,ou=People,dc=example,dc=com
changetype: modify
add: description
description: one
description:
description: two
description: three
description: four
# a space is distinct from an empty value
description:: ICAg
-
replace: drink
drink: Earl Grey, hot
-
delete: description
description:
-
replace: drink
drink: Earl Grey, hot
# there is no such restriction on deletes, so we exercise this part of the overlay here
dn: cn=Ursula Hampster,ou=Alumni Association,ou=People,dc=example,dc=com
changetype: modify
delete: description
description:
description: four
description:
description: three
description: two
description:
description:
description: one
description:
-
add: description
description:
dn: cn=James A Jones 1,ou=Alumni Association,ou=People,dc=example,dc=com
changetype: modify
replace: drink
drink:
dn: cn=All Staff,ou=Groups,dc=example,dc=com
changetype: modify
delete: member
-
add: member
# an empty DN should not be stripped
member:
member: cn=Dorothy Stevens,ou=Alumni Association,ou=People,dc=example,dc=com
dn: cn=Gern Jensen,ou=Information Technology Division,ou=People,dc=example,dc=com
changetype: add
objectclass: testPerson
cn: Gern Jensen
sn: Jensen
uid: gjensen
title:
postaladdress: ITD $ 535 W. William St $ Anytown, MI 48103
seealso: cn=All Staff,ou=Groups,dc=example,dc=com
drink: Coffee
homepostaladdress: 844 Brown St. Apt. 4 $ Anytown, MI 48104
description: Very odd
description:
description: More than you think
facsimiletelephonenumber: +1 313 555 7557
telephonenumber: +1 313 555 8343
mail: gjensen@mailgw.example.com
homephone: +1 313 555 8844
testTime: 20050304001801.234Z

View file

@ -0,0 +1,54 @@
dn: reqStart=timestamp,cn=log
reqDN: cn=Ursula Hampster,ou=Alumni Association,ou=People,dc=example,dc=com
reqMod: description:+ one
reqMod: description:+ two
reqMod: description:+ three
reqMod: description:+ four
# "description:+ " that's a space, then 3 spaces for value
reqMod:: ZGVzY3JpcHRpb246KyAgICA=
reqMod: drink:= Earl Grey, hot
# second mod was removed, so we have two replaces in succession now and need
# to separate them (":")
reqMod:: Og==
reqMod: drink:= Earl Grey, hot
dn: reqStart=timestamp,cn=log
reqDN: cn=Ursula Hampster,ou=Alumni Association,ou=People,dc=example,dc=com
reqMod: description:- four
reqMod: description:- three
reqMod: description:- two
reqMod: description:- one
# second mod is removed
dn: reqStart=timestamp,cn=log
reqDN: cn=James A Jones 1,ou=Alumni Association,ou=People,dc=example,dc=com
reqMod: drink:=
dn: reqStart=timestamp,cn=log
reqDN: cn=All Staff,ou=Groups,dc=example,dc=com
reqMod: member:-
# "member:+ " adding an empty DN
reqMod:: bWVtYmVyOisg
reqMod: member:+ cn=Dorothy Stevens,ou=Alumni Association,ou=People,dc=example
,dc=com
dn: reqStart=timestamp,cn=log
reqDN: cn=Gern Jensen,ou=Information Technology Division,ou=People,dc=example,
dc=com
reqMod: objectClass:+ testPerson
reqMod: cn:+ Gern Jensen
reqMod: sn:+ Jensen
reqMod: uid:+ gjensen
reqMod: postalAddress:+ ITD $ 535 W. William St $ Anytown, MI 48103
reqMod: seeAlso:+ cn=All Staff,ou=Groups,dc=example,dc=com
reqMod: drink:+ Coffee
reqMod: homePostalAddress:+ 844 Brown St. Apt. 4 $ Anytown, MI 48104
reqMod: description:+ Very odd
reqMod: description:+ More than you think
reqMod: facsimileTelephoneNumber:+ +1 313 555 7557
reqMod: telephoneNumber:+ +1 313 555 8343
reqMod: mail:+ gjensen@mailgw.example.com
reqMod: homePhone:+ +1 313 555 8844
reqMod: testTime:+ 20050304001801.234Z
reqMod: structuralObjectClass:+ testPerson

View file

@ -0,0 +1,218 @@
#!/bin/sh
## $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 module was written in 2016 by Ondřej Kuzník for Symas Corp.
USAGE="$0 [-b <backend>] [-c] [-k] [-l #] [-p] [-s {ro|rp}] [-u] [-w] <script>"
TOPSRCDIR="${SRCDIR-$LDAP_SRC}"
SRCDIR="${TOPSRCDIR}/tests"
eval `grep EGREP_CMD= ${LDAP_BUILD}/tests/run`
eval `$EGREP_CMD -e '^LN_S=' ${LDAP_BUILD}/tests/run`
export SRCDIR TOPSRCDIR LN_S EGREP_CMD
. "${SRCDIR}/scripts/defines.sh"
BACKEND=
CLEAN=no
WAIT=0
KILLSERVERS=yes
PRESERVE=${PRESERVE-no}
SYNCMODE=${SYNCMODE-rp}
USERDATA=no
LOOP=1
COUNTER=1
while test $# -gt 0 ; do
case "$1" in
-b | -backend)
BACKEND="$2"
shift; shift ;;
-c | -clean)
CLEAN=yes
shift ;;
-k | -kill)
KILLSERVERS=no
shift ;;
-l | -loop)
NUM="`echo $2 | sed 's/[0-9]//g'`"
if [ -z "$NUM" ]; then
LOOP=$2
else
echo "Loop variable not an int: $2"
echo "$USAGE"; exit 1
fi
shift ;
shift ;;
-p | -preserve)
PRESERVE=yes
shift ;;
-s | -syncmode)
case "$2" in
ro | rp)
SYNCMODE="$2"
;;
*)
echo "unknown sync mode $2"
echo "$USAGE"; exit 1
;;
esac
shift; shift ;;
-u | -userdata)
USERDATA=yes
shift ;;
-w | -wait)
WAIT=1
shift ;;
-)
shift
break ;;
-*)
echo "$USAGE"; exit 1
;;
*)
break ;;
esac
done
eval `$EGREP_CMD -e '^AC' ${LDAP_BUILD}/tests/run`
export `$EGREP_CMD -e '^AC' ${LDAP_BUILD}/tests/run | sed 's/=.*//'`
if test -z "$BACKEND" ; then
for b in mdb ; do
if eval "test \"\$AC_$b\" != no" ; then
BACKEND=$b
break
fi
done
if test -z "$BACKEND" ; then
echo "No suitable default database backend configured" >&2
exit 1
fi
fi
BACKENDTYPE=`eval 'echo $AC_'$BACKEND`
if test "x$BACKENDTYPE" = "x" ; then
BACKENDTYPE="unknown"
fi
# Backend features. indexdb: indexing and unchecked limit.
# maindb: main storage backend. Currently index,limits,mode,paged results.
INDEXDB=noindexdb MAINDB=nomaindb
case $BACKEND in
mdb) INDEXDB=indexdb MAINDB=maindb ;;
esac
export BACKEND BACKENDTYPE INDEXDB MAINDB \
WAIT KILLSERVERS PRESERVE SYNCMODE USERDATA \
SRCDIR
if test $# = 0 ; then
echo "$USAGE"; exit 1
fi
# need defines.sh for the definitions of the directories
. $SRCDIR/scripts/defines.sh
SCRIPTDIR="${TOPDIR}/tests/scripts"
export SCRIPTDIR
SCRIPTNAME="$1"
shift
if test -x "${SCRIPTDIR}/${SCRIPTNAME}" ; then
SCRIPT="${SCRIPTDIR}/${SCRIPTNAME}"
elif test -x "`echo ${SCRIPTDIR}/test*-${SCRIPTNAME}`"; then
SCRIPT="`echo ${SCRIPTDIR}/test*-${SCRIPTNAME}`"
elif test -x "`echo ${SCRIPTDIR}/${SCRIPTNAME}-*`"; then
SCRIPT="`echo ${SCRIPTDIR}/${SCRIPTNAME}-*`"
else
echo "run: ${SCRIPTNAME} not found (or not executable)"
exit 1;
fi
if test ! -r ${DATADIR}/test.ldif ; then
${LN_S} ${SRCDIR}/data ${DATADIR}
fi
if test ! -r ${SCHEMADIR}/core.schema ; then
${LN_S} ${TOPSRCDIR}/servers/slapd/schema ${SCHEMADIR}
fi
if test ! -r ./data; then
${LN_S} ${TOPDIR}/tests/data ./
fi
if test -d ${TESTDIR} ; then
if test $PRESERVE = no ; then
echo "Cleaning up test run directory leftover from previous run."
/bin/rm -rf ${TESTDIR}
elif test $PRESERVE = yes ; then
echo "Cleaning up only database directories leftover from previous run."
/bin/rm -rf ${TESTDIR}/db.*
fi
fi
mkdir -p ${TESTDIR}
if test $USERDATA = yes ; then
if test ! -d userdata ; then
echo "User data directory (userdata) does not exist."
exit 1
fi
cp -R userdata/* ${TESTDIR}
fi
# disable LDAP initialization
LDAPNOINIT=true; export LDAPNOINIT
echo "Running ${SCRIPT} for ${BACKEND}..."
while [ $COUNTER -le $LOOP ]; do
if [ $LOOP -gt 1 ]; then
echo "Running $COUNTER of $LOOP iterations"
fi
$SCRIPT $*
RC=$?
if test $CLEAN = yes ; then
echo "Cleaning up test run directory from this run."
/bin/rm -rf ${TESTDIR}
echo "Cleaning up symlinks."
/bin/rm -f ${DATADIR} ${SCHEMADIR}
fi
if [ $RC -ne 0 ]; then
if [ $LOOP -gt 1 ]; then
echo "Failed after $COUNTER of $LOOP iterations"
fi
exit $RC
else
COUNTER=`expr $COUNTER + 1`
if [ $COUNTER -le $LOOP ]; then
echo "Cleaning up test run directory from this run."
/bin/rm -rf ${TESTDIR}
fi
fi
done
exit $RC

View file

@ -0,0 +1,92 @@
#! /bin/sh
# $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>.
. $SRCDIR/scripts/defines.sh
TB="" TN=""
if test -t 1 ; then
TB=`$SHTOOL echo -e "%B" 2>/dev/null`
TN=`$SHTOOL echo -e "%b" 2>/dev/null`
fi
FAILCOUNT=0
SKIPCOUNT=0
SLEEPTIME=10
echo ">>>>> Executing all LDAP tests for $BACKEND"
if [ -n "$NOEXIT" ]; then
echo "Result Test" > $TESTWD/results
fi
for CMD in ${SCRIPTDIR}/test*; do
case "$CMD" in
*~) continue;;
*.bak) continue;;
*.orig) continue;;
*.sav) continue;;
*) test -f "$CMD" || continue;;
esac
# remove cruft from prior test
if test $PRESERVE = yes ; then
/bin/rm -rf $TESTDIR/db.*
else
/bin/rm -rf $TESTDIR
fi
BCMD=`basename $CMD`
if [ -x "$CMD" ]; then
echo ">>>>> Starting ${TB}$BCMD${TN} for $BACKEND..."
$CMD
RC=$?
if test $RC -eq 0 ; then
echo ">>>>> $BCMD completed ${TB}OK${TN} for $BACKEND."
else
echo ">>>>> $BCMD ${TB}failed${TN} for $BACKEND"
FAILCOUNT=`expr $FAILCOUNT + 1`
if [ -n "$NOEXIT" ]; then
echo "Continuing."
else
echo "(exit $RC)"
exit $RC
fi
fi
else
echo ">>>>> Skipping ${TB}$BCMD${TN} for $BACKEND."
SKIPCOUNT=`expr $SKIPCOUNT + 1`
RC="-"
fi
if [ -n "$NOEXIT" ]; then
echo "$RC $BCMD" >> $TESTWD/results
fi
# echo ">>>>> waiting $SLEEPTIME seconds for things to exit"
# sleep $SLEEPTIME
echo ""
done
if [ -n "$NOEXIT" ]; then
if [ "$FAILCOUNT" -gt 0 ]; then
cat $TESTWD/results
echo "$FAILCOUNT tests for $BACKEND ${TB}failed${TN}. Please review the test log."
else
echo "All executed tests for $BACKEND ${TB}succeeded${TN}."
fi
fi
echo "$SKIPCOUNT tests for $BACKEND were ${TB}skipped${TN}."

View file

@ -0,0 +1,137 @@
#! /bin/sh
# $OpenLDAP$
## This work is part of OpenLDAP Software <http://www.openldap.org/>.
##
## Copyright 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 module was written in 2019 by Tamim Ziai for DAASI International
echo "running defines.sh"
. $SRCDIR/scripts/defines.sh
LDIF=${TOPDIR}/tests/data/test001.out
if test $ACCESSLOG = accesslogno; then
echo "Accesslog overlay not available, test skipped"
exit 0
fi
mkdir -p $TESTDIR $DBDIR1A $DBDIR1B
. $CONFFILTER $BACKEND < "${TOPDIR}/tests/data/emptyds.conf" > $CONF1
echo "Running slapadd to build slapd database... "
$SLAPADD -f $CONF1 -l $LDIFORDERED
RC=$?
if test $RC != 0 ; then
echo "slapadd failed ($RC)!"
exit $RC
fi
echo "Starting slapd on TCP/IP port $PORT1..."
$SLAPD -f $CONF1 -h $URI1 -d $LVL >> $LOG1 2>&1 &
PID=$!
if test $WAIT != 0 ; then
echo PID $PID
read foo
fi
KILLPIDS="$PID"
sleep $SLEEP0
for i in 0 1 2 3 4 5; do
$LDAPSEARCH -s base -b "$MONITOR" -H $URI1 \
'objectclass=*' > /dev/null 2>&1
RC=$?
if test $RC = 0 ; then
break
fi
echo "Waiting ${SLEEP1} seconds for slapd to start..."
sleep ${SLEEP1}
done
echo "Checking add/modify handling... "
$LDAPMODIFY -D "$MANAGERDN" -H $URI1 -w $PASSWD \
> $TESTOUT -f "${TOPDIR}/tests/data/test001.ldif"
RC=$?
if test $RC != 0 ; then
echo "ldapmodify failed ($RC)!"
test $KILLSERVERS != no && kill -HUP $KILLPIDS
exit $RC
fi
echo "Checking modrdn handling (should still fail with invalidDNSyntax)... "
$LDAPMODIFY -D "$MANAGERDN" -H $URI1 -w $PASSWD \
>> $TESTOUT 2>&1 <<EOMOD
dn: cn=Ursula Hampster,ou=Alumni Association,ou=People,dc=example,dc=com
changetype: modrdn
newrdn: cn=
deleteoldrdn: 0
EOMOD
RC=$?
case $RC in
34)
echo " ldapmodify failed ($RC)"
;;
0)
echo " ldapmodify should have failed ($RC)!"
test $KILLSERVERS != no && kill -HUP $KILLPIDS
exit 1
;;
*)
echo " ldapmodify failed ($RC)!"
test $KILLSERVERS != no && kill -HUP $KILLPIDS
exit $RC
;;
esac
echo "Dumping accesslog..."
$LDAPSEARCH -b "cn=log" -H $URI1 \
'objectClass=auditWriteObject' reqDN reqMod | \
grep -v -e 'entryCSN' -e '\(create\|modify\)Timestamp' \
-e '\(modifier\|creator\)sName' -e 'entryUUID' | \
sed -e 's/reqStart=[^,]*,/reqStart=timestamp,/' \
> $SEARCHOUT 2>&1
RC=$?
if test $RC != 0 ; then
echo "ldapsearch failed ($RC)!"
exit $RC
fi
test $KILLSERVERS != no && kill -HUP $KILLPIDS
# Expectations:
# - all empty values for directoryString pruned
# - empty adds/deletes removed, empty replaces kept
# - remaining values keep the same order as submitted
# - other syntaxes (especially DNs) are kept intact
echo "Filtering ldapsearch results..."
$LDIFFILTER < $SEARCHOUT > $SEARCHFLT
$LDIFFILTER < $LDIF > $LDIFFLT
echo "Comparing filter output..."
$CMP $LDIFFLT $SEARCHFLT > $CMPOUT
if test $? != 0 ; then
echo "Comparison failed"
exit 1
fi
echo ">>>>> Test succeeded"
test $KILLSERVERS != no && wait
exit 0