1#! /bin/sh
2# $OpenLDAP$
3## This work is part of OpenLDAP Software <http://www.openldap.org/>.
4##
5## Copyright 1998-2021 The OpenLDAP Foundation.
6## All rights reserved.
7##
8## Redistribution and use in source and binary forms, with or without
9## modification, are permitted only as authorized by the OpenLDAP
10## Public License.
11##
12## A copy of this license is available in the file LICENSE in the
13## top-level directory of the distribution or, alternatively, at
14## <http://www.OpenLDAP.org/license.html>.
15
16echo "running defines.sh"
17. $SRCDIR/scripts/defines.sh
18
19if test $SYNCPROV = syncprovno; then
20	echo "Syncrepl provider overlay not available, test skipped"
21	exit 0
22fi
23if test $ACCESSLOG = accesslogno; then
24	echo "Accesslog overlay not available, test skipped"
25	exit 0
26fi
27
28MPR=${MPR-4}
29
30XDIR=$TESTDIR/srv
31TMP=$TESTDIR/tmp
32
33mkdir -p $TESTDIR
34
35$SLAPPASSWD -g -n >$CONFIGPWF
36
37if test x"$SYNCMODE" = x ; then
38	SYNCMODE=rp
39fi
40case "$SYNCMODE" in
41	ro)
42		SYNCTYPE="type=refreshOnly interval=00:00:00:03"
43		;;
44	rp)
45		SYNCTYPE="type=refreshAndPersist interval=00:00:00:03"
46		;;
47	*)
48		echo "unknown sync mode $SYNCMODE"
49		exit 1;
50		;;
51esac
52
53#
54# Test delta-sync mpr
55# - start servers
56# - configure over ldap
57# - populate over ldap
58# - configure syncrepl over ldap
59# - break replication
60# - modify each server separately
61# - restore replication
62# - compare results
63#
64
65nullExclude=""
66test $BACKEND = null && nullExclude="# "
67
68KILLPIDS=
69
70echo "Initializing server configurations..."
71n=1
72while [ $n -le $MPR ]; do
73
74DBDIR=${XDIR}$n/db
75CFDIR=${XDIR}$n/slapd.d
76
77mkdir -p ${XDIR}$n $DBDIR.1 $DBDIR.2 $CFDIR
78
79cat > $TMP <<EOF
80dn: cn=config
81objectClass: olcGlobal
82cn: config
83EOF
84
85o=1
86while [ $o -le $MPR ]; do
87PORT=`expr $BASEPORT + $o`
88URI="ldap://${LOCALHOST}:$PORT/"
89echo "olcServerID: $o $URI" >> $TMP
90o=`expr $o + 1`
91done
92echo "" >> $TMP
93
94if [ "$SYNCPROV" = syncprovmod -o "$ACCESSLOG" = accesslogmod ]; then
95  cat <<EOF >> $TMP
96dn: cn=module,cn=config
97objectClass: olcModuleList
98cn: module
99olcModulePath: $TESTWD/../servers/slapd/overlays
100EOF
101  if [ "$SYNCPROV" = syncprovmod ]; then
102  echo "olcModuleLoad: syncprov.la" >> $TMP
103  fi
104  if [ "$ACCESSLOG" = accesslogmod ]; then
105  echo "olcModuleLoad: accesslog.la" >> $TMP
106  fi
107  echo "" >> $TMP
108fi
109
110if [ "$BACKENDTYPE" = mod ]; then
111cat <<EOF >> $TMP
112dn: cn=module,cn=config
113objectClass: olcModuleList
114cn: module
115olcModulePath: $TESTWD/../servers/slapd/back-$BACKEND
116olcModuleLoad: back_$BACKEND.la
117
118EOF
119fi
120
121MYURI=`eval echo '$URI'$n`
122PROVIDERURI=`eval echo '$URI'$o`
123if test $INDEXDB = indexdb ; then
124INDEX1="olcDbIndex: objectClass,entryCSN,reqStart,reqDN,reqResult eq"
125INDEX2="olcDbIndex: objectClass,entryCSN,entryUUID eq"
126else
127INDEX1=
128INDEX2=
129fi
130cat >> $TMP <<EOF
131dn: cn=schema,cn=config
132objectclass: olcSchemaconfig
133cn: schema
134
135include: file://$ABS_SCHEMADIR/core.ldif
136
137include: file://$ABS_SCHEMADIR/cosine.ldif
138
139include: file://$ABS_SCHEMADIR/inetorgperson.ldif
140
141include: file://$ABS_SCHEMADIR/openldap.ldif
142
143include: file://$ABS_SCHEMADIR/nis.ldif
144
145dn: olcDatabase={0}config,cn=config
146objectClass: olcDatabaseConfig
147olcDatabase: {0}config
148olcRootPW:< file://$CONFIGPWF
149
150dn: olcDatabase={1}$BACKEND,cn=config
151objectClass: olcDatabaseConfig
152${nullExclude}objectClass: olc${BACKEND}Config
153olcDatabase: {1}$BACKEND
154olcSuffix: cn=log
155${nullExclude}olcDbDirectory: ${DBDIR}.1
156olcRootDN: $MANAGERDN
157$INDEX1
158
159dn: olcOverlay=syncprov,olcDatabase={1}$BACKEND,cn=config
160objectClass: olcOverlayConfig
161objectClass: olcSyncProvConfig
162olcOverlay: syncprov
163olcSpNoPresent: TRUE
164olcSpReloadHint: TRUE
165
166dn: olcDatabase={2}$BACKEND,cn=config
167objectClass: olcDatabaseConfig
168${nullExclude}objectClass: olc${BACKEND}Config
169olcDatabase: {2}$BACKEND
170olcSuffix: $BASEDN
171${nullExclude}olcDbDirectory: ${DBDIR}.2
172olcRootDN: $MANAGERDN
173olcRootPW: $PASSWD
174EOF
175
176o=1
177while [ $o -le $MPR ]; do
178PORT=`expr $BASEPORT + $o`
179URI="ldap://${LOCALHOST}:$PORT/"
180cat >>$TMP <<EOF
181olcSyncRepl: rid=00$o provider=$URI binddn="$MANAGERDN" bindmethod=simple
182  credentials=$PASSWD searchbase="$BASEDN" $SYNCTYPE
183  retry="3 +" timeout=3 logbase="cn=log"
184  logfilter="(&(objectclass=auditWriteObject)(reqresult=0))"
185  syncdata=accesslog
186EOF
187o=`expr $o + 1`
188done
189
190cat >> $TMP <<EOF
191olcMultiProvider: TRUE
192$INDEX2
193
194dn: olcOverlay=syncprov,olcDatabase={2}$BACKEND,cn=config
195objectClass: olcOverlayConfig
196objectClass: olcSyncProvConfig
197olcOverlay: syncprov
198
199dn: olcOverlay=accesslog,olcDatabase={2}$BACKEND,cn=config
200objectClass: olcOverlayConfig
201objectClass: olcAccessLogConfig
202olcOverlay: accesslog
203olcAccessLogDB: cn=log
204olcAccessLogOps: writes
205olcAccessLogSuccess: TRUE
206
207EOF
208cat <<EOF >> $TMP
209dn: olcDatabase={3}monitor,cn=config
210objectClass: olcDatabaseConfig
211objectClass: olcmonitorConfig
212olcDatabase: {3}monitor
213
214EOF
215
216$SLAPADD -F $CFDIR -n 0  -d-1< $TMP > $TESTOUT 2>&1
217PORT=`eval echo '$PORT'$n`
218echo "Starting server $n on TCP/IP port $PORT..."
219cd ${XDIR}${n}
220LOG=`eval echo '$LOG'$n`
221$SLAPD -F slapd.d -h $MYURI -d $LVL > $LOG 2>&1 &
222PID=$!
223if test $WAIT != 0 ; then
224    echo PID $PID
225    read foo
226fi
227KILLPIDS="$PID $KILLPIDS"
228cd $TESTWD
229
230echo "Using ldapsearch to check that server $n is running..."
231sleep 1
232for i in 0 1 2 3 4 5; do
233	$LDAPSEARCH -s base -b "" -H $MYURI \
234		'objectclass=*' > /dev/null 2>&1
235	RC=$?
236	if test $RC = 0 ; then
237		break
238	fi
239	echo "Waiting 5 seconds for slapd to start..."
240	sleep 5
241done
242
243if test $RC != 0 ; then
244	echo "ldapsearch failed ($RC)!"
245	test $KILLSERVERS != no && kill -HUP $KILLPIDS
246	exit $RC
247fi
248
249if [ $n = 1 ]; then
250echo "Using ldapadd for context on server 1..."
251$LDAPADD -D "$MANAGERDN" -H $URI1 -w $PASSWD -f $LDIFORDEREDCP \
252	>> $TESTOUT 2>&1
253RC=$?
254if test $RC != 0 ; then
255	echo "ldapadd failed for server $n database ($RC)!"
256	test $KILLSERVERS != no && kill -HUP $KILLPIDS
257	exit $RC
258fi
259fi
260
261n=`expr $n + 1`
262done
263
264echo "Using ldapadd to populate server 1..."
265$LDAPADD -D "$MANAGERDN" -H $URI1 -w $PASSWD -f $LDIFORDEREDNOCP \
266	>> $TESTOUT 2>&1
267RC=$?
268if test $RC != 0 ; then
269	echo "ldapadd failed for server $n database ($RC)!"
270	test $KILLSERVERS != no && kill -HUP $KILLPIDS
271	exit $RC
272fi
273
274echo "Waiting $SLEEP1 seconds for syncrepl to receive changes..."
275sleep $SLEEP1
276
277n=1
278while [ $n -le $MPR ]; do
279PORT=`expr $BASEPORT + $n`
280URI="ldap://${LOCALHOST}:$PORT/"
281
282echo "Using ldapsearch to read all the entries from server $n..."
283$LDAPSEARCH -S "" -b "$BASEDN" -D "$MANAGERDN" -H $URI -w $PASSWD  \
284	'objectclass=*' > $TESTDIR/server$n.out 2>&1
285RC=$?
286
287if test $RC != 0 ; then
288	echo "ldapsearch failed at server $n ($RC)!"
289	test $KILLSERVERS != no && kill -HUP $KILLPIDS
290	exit $RC
291fi
292$LDIFFILTER < $TESTDIR/server$n.out > $TESTDIR/server$n.flt
293n=`expr $n + 1`
294done
295
296n=2
297while [ $n -le $MPR ]; do
298echo "Comparing retrieved entries from server 1 and server $n..."
299$CMP $PROVIDERFLT $TESTDIR/server$n.flt > $CMPOUT
300
301if test $? != 0 ; then
302	echo "test failed - server 1 and server $n databases differ"
303	test $KILLSERVERS != no && kill -HUP $KILLPIDS
304	exit 1
305fi
306n=`expr $n + 1`
307done
308
309echo "Using ldapadd to populate server 2..."
310cp $LDIFADD1 $TESTDIR/add.ldif
311echo "displayName: The other" >>$TESTDIR/add.ldif
312$LDAPADD -D "$MANAGERDN" -H $URI2 -w $PASSWD -f $TESTDIR/add.ldif \
313	>> $TESTOUT 2>&1
314RC=$?
315if test $RC != 0 ; then
316	echo "ldapadd failed for server 2 database ($RC)!"
317	test $KILLSERVERS != no && kill -HUP $KILLPIDS
318	exit $RC
319fi
320
321THEDN="cn=James A Jones 2,ou=Alumni Association,ou=People,dc=example,dc=com"
322sleep 1
323for i in 1 2 3; do
324	$LDAPSEARCH -S "" -b "$THEDN" -H $URI1 \
325		-s base '(objectClass=*)' entryCSN > "${PROVIDEROUT}.$i" 2>&1
326	RC=$?
327
328	if test $RC = 0 ; then
329		break
330	fi
331
332	if test $RC != 32 ; then
333		echo "ldapsearch failed at consumer ($RC)!"
334		test $KILLSERVERS != no && kill -HUP $KILLPIDS
335		exit $RC
336	fi
337
338	echo "Waiting $SLEEP1 seconds for syncrepl to receive changes..."
339	sleep $SLEEP1
340done
341
342n=1
343while [ $n -le $MPR ]; do
344PORT=`expr $BASEPORT + $n`
345URI="ldap://${LOCALHOST}:$PORT/"
346
347echo "Using ldapsearch to read all the entries from server $n..."
348$LDAPSEARCH -S "" -b "$BASEDN" -D "$MANAGERDN" -H $URI -w $PASSWD  \
349	'objectclass=*' > $TESTDIR/server$n.out 2>&1
350RC=$?
351
352if test $RC != 0 ; then
353	echo "ldapsearch failed at server $n ($RC)!"
354	test $KILLSERVERS != no && kill -HUP $KILLPIDS
355	exit $RC
356fi
357$LDIFFILTER < $TESTDIR/server$n.out > $TESTDIR/server$n.flt
358n=`expr $n + 1`
359done
360
361n=2
362while [ $n -le $MPR ]; do
363echo "Comparing retrieved entries from server 1 and server $n..."
364$CMP $PROVIDERFLT $TESTDIR/server$n.flt > $CMPOUT
365
366if test $? != 0 ; then
367	echo "test failed - server 1 and server $n databases differ"
368	test $KILLSERVERS != no && kill -HUP $KILLPIDS
369	exit 1
370fi
371n=`expr $n + 1`
372done
373
374echo "Breaking replication between server 1 and 2..."
375n=1
376while [ $n -le 2 ]; do
377MYURI=`eval echo '$URI'$n`
378o=`expr $n - 1`
379$LDAPMODIFY -D cn=config -H $MYURI -y $CONFIGPWF > $TESTOUT 2>&1 <<EOF
380dn: olcDatabase={2}$BACKEND,cn=config
381changetype: modify
382delete: olcSyncRepl
383-
384
385EOF
386RC=$?
387if test $RC != 0 ; then
388	echo "ldapmodify failed for server $n config ($RC)!"
389	test $KILLSERVERS != no && kill -HUP $KILLPIDS
390	exit $RC
391fi
392n=`expr $n + 1`
393done
394
395echo "Using ldapmodify to force conflicts between server 1 and 2..."
396$LDAPMODIFY -D "$MANAGERDN" -H $URI1 -w $PASSWD \
397	>> $TESTOUT 2>&1 << EOF
398dn: $THEDN
399changetype: modify
400add: description
401description: Amazing
402-
403add: displayName
404displayName: James the Second
405-
406delete: displayName
407displayName: The other
408
409EOF
410RC=$?
411if test $RC != 0 ; then
412	echo "ldapmodify failed for server 1 database ($RC)!"
413	test $KILLSERVERS != no && kill -HUP $KILLPIDS
414	exit $RC
415fi
416
417$LDAPMODIFY -D "$MANAGERDN" -H $URI2 -w $PASSWD \
418	>> $TESTOUT 2>&1 << EOF
419dn: $THEDN
420changetype: modify
421replace: employeetype
422-
423add: description
424description: Stupendous
425-
426add: displayName
427displayName: James II
428-
429delete: displayName
430displayName: The other
431
432EOF
433RC=$?
434if test $RC != 0 ; then
435	echo "ldapmodify failed for server 2 database ($RC)!"
436	test $KILLSERVERS != no && kill -HUP $KILLPIDS
437	exit $RC
438fi
439
440$LDAPMODIFY -D "$MANAGERDN" -H $URI1 -w $PASSWD \
441	>> $TESTOUT 2>&1 << EOF
442dn: $THEDN
443changetype: modify
444delete: description
445description: Outstanding
446-
447add: description
448description: Mindboggling
449
450EOF
451RC=$?
452if test $RC != 0 ; then
453	echo "ldapmodify failed for server 1 database ($RC)!"
454	test $KILLSERVERS != no && kill -HUP $KILLPIDS
455	exit $RC
456fi
457
458$LDAPMODIFY -D "$MANAGERDN" -H $URI2 -w $PASSWD \
459	>> $TESTOUT 2>&1 << EOF
460dn: $THEDN
461changetype: modify
462delete: description
463description: OutStanding
464-
465add: description
466description: Bizarre
467
468EOF
469RC=$?
470if test $RC != 0 ; then
471	echo "ldapmodify failed for server 2 database ($RC)!"
472	test $KILLSERVERS != no && kill -HUP $KILLPIDS
473	exit $RC
474fi
475
476$LDAPMODIFY -D "$MANAGERDN" -H $URI1 -w $PASSWD \
477	>> $TESTOUT 2>&1 << EOF
478dn: $THEDN
479changetype: modify
480add: carLicense
481carLicense: 123-XYZ
482-
483add: employeeNumber
484employeeNumber: 32
485
486EOF
487RC=$?
488if test $RC != 0 ; then
489	echo "ldapmodify failed for server 1 database ($RC)!"
490	test $KILLSERVERS != no && kill -HUP $KILLPIDS
491	exit $RC
492fi
493
494$LDAPMODIFY -D "$MANAGERDN" -H $URI2 -w $PASSWD \
495	>> $TESTOUT 2>&1 << EOF
496dn: $THEDN
497changetype: modify
498add: employeeType
499employeeType: deadwood
500-
501add: employeeNumber
502employeeNumber: 64
503
504EOF
505RC=$?
506if test $RC != 0 ; then
507	echo "ldapmodify failed for server 2 database ($RC)!"
508	test $KILLSERVERS != no && kill -HUP $KILLPIDS
509	exit $RC
510fi
511
512$LDAPMODIFY -D "$MANAGERDN" -H $URI1 -w $PASSWD \
513	>> $TESTOUT 2>&1 << EOF
514dn: $THEDN
515changetype: modify
516replace: sn
517sn: Replaced later
518-
519replace: sn
520sn: Surname
521EOF
522RC=$?
523if test $RC != 0 ; then
524	echo "ldapmodify failed for server 1 database ($RC)!"
525	test $KILLSERVERS != no && kill -HUP $KILLPIDS
526	exit $RC
527fi
528
529echo "Restoring replication between server 1 and 2..."
530cat > $TMP <<EOF
531dn: olcDatabase={2}$BACKEND,cn=config
532changetype: modify
533add: olcSyncRepl
534EOF
535n=1
536while [ $n -le $MPR ]; do
537MYURI=`eval echo '$URI'$n`
538PROVIDERURI=`eval echo '$URI'$n`
539cat >> $TMP <<EOF
540olcSyncRepl: rid=00$n provider=$PROVIDERURI binddn="$MANAGERDN" bindmethod=simple
541  credentials=$PASSWD searchbase="$BASEDN" $SYNCTYPE
542  retry="3 +" timeout=3 logbase="cn=log"
543  logfilter="(&(objectclass=auditWriteObject)(reqresult=0))"
544  syncdata=accesslog
545EOF
546n=`expr $n + 1`
547done
548cat >> $TMP <<EOF
549-
550replace: olcMultiProvider
551olcMultiProvider: TRUE
552EOF
553n=1
554while [ $n -le 2 ]; do
555MYURI=`eval echo '$URI'$n`
556$LDAPMODIFY -D cn=config -H $MYURI -y $CONFIGPWF > $TESTOUT 2>&1 <$TMP
557RC=$?
558if test $RC != 0 ; then
559	echo "ldapmodify failed for server $n config ($RC)!"
560	test $KILLSERVERS != no && kill -HUP $KILLPIDS
561	exit $RC
562fi
563n=`expr $n + 1`
564done
565
566echo "Waiting $SLEEP1 seconds for syncrepl to receive changes..."
567sleep $SLEEP1
568
569n=1
570while [ $n -le $MPR ]; do
571PORT=`expr $BASEPORT + $n`
572URI="ldap://${LOCALHOST}:$PORT/"
573
574echo "Using ldapsearch to read all the entries from server $n..."
575$LDAPSEARCH -S "" -b "$BASEDN" -D "$MANAGERDN" -H $URI -w $PASSWD  \
576	'objectclass=*' > $TESTDIR/server$n.out 2>&1
577RC=$?
578
579if test $RC != 0 ; then
580	echo "ldapsearch failed at server $n ($RC)!"
581	test $KILLSERVERS != no && kill -HUP $KILLPIDS
582	exit $RC
583fi
584$LDIFFILTER -s a < $TESTDIR/server$n.out > $TESTDIR/server$n.flt
585n=`expr $n + 1`
586done
587
588n=2
589while [ $n -le $MPR ]; do
590echo "Comparing retrieved entries from server 1 and server $n..."
591$CMP $PROVIDERFLT $TESTDIR/server$n.flt > $CMPOUT
592
593if test $? != 0 ; then
594	echo "test failed - server 1 and server $n databases differ"
595	test $KILLSERVERS != no && kill -HUP $KILLPIDS
596	exit 1
597fi
598n=`expr $n + 1`
599done
600
601test $KILLSERVERS != no && kill -HUP $KILLPIDS
602
603echo ">>>>> Test succeeded"
604
605test $KILLSERVERS != no && wait
606
607exit 0
608