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