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
28MMR=2
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 mmr
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 $MMR ]; do
73
74DBDIR=${XDIR}$n/db
75CFDIR=${XDIR}$n/slapd.d
76
77mkdir -p ${XDIR}$n $DBDIR.1 $DBDIR.2 $CFDIR
78
79o=`expr 3 - $n`
80cat > $TMP <<EOF
81dn: cn=config
82objectClass: olcGlobal
83cn: config
84olcServerID: $n
85
86EOF
87
88if [ "$SYNCPROV" = syncprovmod -o "$ACCESSLOG" = accesslogmod ]; then
89  cat <<EOF >> $TMP
90dn: cn=module,cn=config
91objectClass: olcModuleList
92cn: module
93olcModulePath: $TESTWD/../servers/slapd/overlays
94EOF
95  if [ "$SYNCPROV" = syncprovmod ]; then
96  echo "olcModuleLoad: syncprov.la" >> $TMP
97  fi
98  if [ "$ACCESSLOG" = accesslogmod ]; then
99  echo "olcModuleLoad: accesslog.la" >> $TMP
100  fi
101  echo "" >> $TMP
102fi
103
104if [ "$BACKENDTYPE" = mod ]; then
105cat <<EOF >> $TMP
106dn: cn=module,cn=config
107objectClass: olcModuleList
108cn: module
109olcModulePath: $TESTWD/../servers/slapd/back-$BACKEND
110olcModuleLoad: back_$BACKEND.la
111
112EOF
113fi
114MYURI=`eval echo '$URI'$n`
115PROVIDERURI=`eval echo '$URI'$o`
116if test $INDEXDB = indexdb ; then
117INDEX1="olcDbIndex: objectClass,entryCSN,reqStart,reqDN,reqResult eq"
118INDEX2="olcDbIndex: objectClass,entryCSN,entryUUID eq"
119else
120INDEX1=
121INDEX2=
122fi
123cat >> $TMP <<EOF
124dn: cn=schema,cn=config
125objectclass: olcSchemaconfig
126cn: schema
127
128include: file://$ABS_SCHEMADIR/core.ldif
129
130include: file://$ABS_SCHEMADIR/cosine.ldif
131
132include: file://$ABS_SCHEMADIR/inetorgperson.ldif
133
134include: file://$ABS_SCHEMADIR/openldap.ldif
135
136include: file://$ABS_SCHEMADIR/nis.ldif
137
138dn: olcDatabase={0}config,cn=config
139objectClass: olcDatabaseConfig
140olcDatabase: {0}config
141olcRootPW:< file://$CONFIGPWF
142
143dn: olcDatabase={1}$BACKEND,cn=config
144objectClass: olcDatabaseConfig
145${nullExclude}objectClass: olc${BACKEND}Config
146olcDatabase: {1}$BACKEND
147olcSuffix: cn=log
148${nullExclude}olcDbDirectory: ${DBDIR}.1
149olcRootDN: $MANAGERDN
150$INDEX1
151
152dn: olcOverlay=syncprov,olcDatabase={1}$BACKEND,cn=config
153objectClass: olcOverlayConfig
154objectClass: olcSyncProvConfig
155olcOverlay: syncprov
156olcSpNoPresent: TRUE
157olcSpReloadHint: TRUE
158
159dn: olcDatabase={2}$BACKEND,cn=config
160objectClass: olcDatabaseConfig
161${nullExclude}objectClass: olc${BACKEND}Config
162olcDatabase: {2}$BACKEND
163olcSuffix: $BASEDN
164${nullExclude}olcDbDirectory: ${DBDIR}.2
165olcRootDN: $MANAGERDN
166olcRootPW: $PASSWD
167olcSyncRepl: rid=001 provider=$PROVIDERURI binddn="$MANAGERDN" bindmethod=simple
168  credentials=$PASSWD searchbase="$BASEDN" $SYNCTYPE retry="3 +" timeout=3
169olcMirrorMode: TRUE
170$INDEX2
171
172dn: olcOverlay=syncprov,olcDatabase={2}$BACKEND,cn=config
173objectClass: olcOverlayConfig
174objectClass: olcSyncProvConfig
175olcOverlay: syncprov
176olcSpSessionlogSource: cn=log
177
178dn: olcOverlay=accesslog,olcDatabase={2}$BACKEND,cn=config
179objectClass: olcOverlayConfig
180objectClass: olcAccessLogConfig
181olcOverlay: accesslog
182olcAccessLogDB: cn=log
183olcAccessLogOps: writes
184olcAccessLogSuccess: TRUE
185
186EOF
187$SLAPADD -F $CFDIR -n 0  -d-1< $TMP > $TESTOUT 2>&1
188PORT=`eval echo '$PORT'$n`
189echo "Starting server $n on TCP/IP port $PORT..."
190cd ${XDIR}${n}
191LOG=`eval echo '$LOG'$n`
192$SLAPD -F slapd.d -h $MYURI -d $LVL > $LOG 2>&1 &
193PID=$!
194if test $WAIT != 0 ; then
195    echo PID $PID
196    read foo
197fi
198KILLPIDS="$PID $KILLPIDS"
199cd $TESTWD
200
201echo "Using ldapsearch to check that server $n is running..."
202for i in 0 1 2 3 4 5; do
203          $LDAPSEARCH -s base -b "" -H $MYURI \
204                    'objectclass=*' > /dev/null 2>&1
205          RC=$?
206          if test $RC = 0 ; then
207                    break
208          fi
209          echo "Waiting 5 seconds for slapd to start..."
210          sleep 5
211done
212
213if test $RC != 0 ; then
214          echo "ldapsearch failed ($RC)!"
215          test $KILLSERVERS != no && kill -HUP $KILLPIDS
216          exit $RC
217fi
218
219if [ $n = 1 ]; then
220echo "Using ldapadd for context on server 1..."
221$LDAPADD -D "$MANAGERDN" -H $URI1 -w $PASSWD -f $LDIFORDEREDCP \
222          >> $TESTOUT 2>&1
223RC=$?
224if test $RC != 0 ; then
225          echo "ldapadd failed for server $n database ($RC)!"
226          test $KILLSERVERS != no && kill -HUP $KILLPIDS
227          exit $RC
228fi
229fi
230
231n=`expr $n + 1`
232done
233
234echo "Using ldapadd to populate server 1..."
235$LDAPADD -D "$MANAGERDN" -H $URI1 -w $PASSWD -f $LDIFORDEREDNOCP \
236          >> $TESTOUT 2>&1
237RC=$?
238if test $RC != 0 ; then
239          echo "ldapadd failed for server 1 database ($RC)!"
240          test $KILLSERVERS != no && kill -HUP $KILLPIDS
241          exit $RC
242fi
243
244echo "Waiting $SLEEP1 seconds for syncrepl to receive changes..."
245sleep $SLEEP1
246
247n=1
248while [ $n -le $MMR ]; do
249URI=`eval echo '$URI'$n`
250
251echo "Using ldapsearch to read all the entries from server $n..."
252$LDAPSEARCH -S "" -b "$BASEDN" -D "$MANAGERDN" -H $URI -w $PASSWD  \
253          'objectclass=*' > $TESTDIR/server$n.out 2>&1
254RC=$?
255
256if test $RC != 0 ; then
257          echo "ldapsearch failed at server $n ($RC)!"
258          test $KILLSERVERS != no && kill -HUP $KILLPIDS
259          exit $RC
260fi
261$LDIFFILTER < $TESTDIR/server$n.out > $TESTDIR/server$n.flt
262n=`expr $n + 1`
263done
264
265n=2
266while [ $n -le $MMR ]; do
267echo "Comparing retrieved entries from server 1 and server $n..."
268$CMP $PROVIDERFLT $TESTDIR/server$n.flt > $CMPOUT
269
270if test $? != 0 ; then
271          echo "test failed - server 1 and server $n databases differ"
272          test $KILLSERVERS != no && kill -HUP $KILLPIDS
273          exit 1
274fi
275n=`expr $n + 1`
276done
277
278echo "Using ldapadd to populate server 2..."
279$LDAPADD -D "$MANAGERDN" -H $URI2 -w $PASSWD -f $LDIFADD1 \
280          >> $TESTOUT 2>&1
281RC=$?
282if test $RC != 0 ; then
283          echo "ldapadd failed for server 2 database ($RC)!"
284          test $KILLSERVERS != no && kill -HUP $KILLPIDS
285          exit $RC
286fi
287
288THEDN="cn=James A Jones 2,ou=Alumni Association,ou=People,dc=example,dc=com"
289sleep 1
290for i in 1 2 3; do
291          $LDAPSEARCH -S "" -b "$THEDN" -H $URI1 \
292                    -s base '(objectClass=*)' entryCSN > "${PROVIDEROUT}.$i" 2>&1
293          RC=$?
294
295          if test $RC = 0 ; then
296                    break
297          fi
298
299          if test $RC != 32 ; then
300                    echo "ldapsearch failed at slave ($RC)!"
301                    test $KILLSERVERS != no && kill -HUP $KILLPIDS
302                    exit $RC
303          fi
304
305          echo "Waiting $SLEEP1 seconds for syncrepl to receive changes..."
306          sleep $SLEEP1
307done
308
309n=1
310while [ $n -le $MMR ]; do
311URI=`eval echo '$URI'$n`
312
313echo "Using ldapsearch to read all the entries from server $n..."
314$LDAPSEARCH -S "" -b "$BASEDN" -D "$MANAGERDN" -H $URI -w $PASSWD  \
315          'objectclass=*' > $TESTDIR/server$n.out 2>&1
316RC=$?
317
318if test $RC != 0 ; then
319          echo "ldapsearch failed at server $n ($RC)!"
320          test $KILLSERVERS != no && kill -HUP $KILLPIDS
321          exit $RC
322fi
323$LDIFFILTER < $TESTDIR/server$n.out > $TESTDIR/server$n.flt
324n=`expr $n + 1`
325done
326
327n=2
328while [ $n -le $MMR ]; do
329echo "Comparing retrieved entries from server 1 and server $n..."
330$CMP $PROVIDERFLT $TESTDIR/server$n.flt > $CMPOUT
331
332if test $? != 0 ; then
333          echo "test failed - server 1 and server $n databases differ"
334          test $KILLSERVERS != no && kill -HUP $KILLPIDS
335          exit 1
336fi
337n=`expr $n + 1`
338done
339
340echo "Retrieving syncrepl cookie..."
341cookie=`$LDAPRSEARCH -b "$BASEDN" -D "$MANAGERDN" -H $URI1 -w $PASSWD \
342    -E "sync=ro" 'objectclass=*' 1.1 | grep cookie | sed "s/.*cookie: //"`
343
344if test -z "$cookie"; then
345          echo "Failed to retrieve cookie from server!"
346          test $KILLSERVERS != no && kill -HUP $KILLPIDS
347          exit 1
348fi
349
350echo "Deleting an entry from server 1..."
351$LDAPDELETE -D "$MANAGERDN" -H $URI1 -w $PASSWD \
352    "cn=Mark Elliot,ou=Alumni Association,ou=People,$BASEDN" \
353          >> $TESTOUT 2>&1
354RC=$?
355if test $RC != 0 ; then
356          echo "ldapdelete failed for server 1 database ($RC)!"
357          test $KILLSERVERS != no && kill -HUP $KILLPIDS
358          exit $RC
359fi
360
361
362echo "Restarting servers..."
363kill -HUP $KILLPIDS
364wait
365KILLPIDS=""
366n=1
367while [ $n -le $MMR ]; do
368o=`expr 3 - $n`
369MYURI=`eval echo '$URI'$n`
370PROVIDERURI=`eval echo '$URI'$o`
371
372echo "Starting server $n again..."
373cd ${XDIR}${n}
374LOG=`eval echo '$LOG'$n`
375echo "RESTART" >> $LOG
376#if test $n = 2; then
377#echo $SLAPD -F slapd.d -h $MYURI -d $LVL
378#else
379$SLAPD -F slapd.d -h $MYURI -d $LVL > $LOG 2>&1 &
380#fi
381PID=$!
382if test $WAIT != 0 ; then
383    echo PID $PID
384    read foo
385fi
386KILLPIDS="$PID $KILLPIDS"
387cd $TESTWD
388
389echo "Using ldapsearch to check that server $n is running..."
390for i in 0 1 2 3 4 5; do
391          $LDAPSEARCH -s base -b "" -H $MYURI \
392                    'objectclass=*' > /dev/null 2>&1
393          RC=$?
394          if test $RC = 0 ; then
395                    break
396          fi
397          echo "Waiting 5 seconds for slapd to start..."
398          sleep 5
399done
400
401echo "Breaking replication between server $n and $o..."
402$LDAPMODIFY -D cn=config -H $MYURI -y $CONFIGPWF > $TESTOUT 2>&1 <<EOF
403dn: olcDatabase={2}$BACKEND,cn=config
404changetype: modify
405replace: olcSyncRepl
406olcSyncRepl: rid=001 provider=$PROVIDERURI binddn="$MANAGERDN" bindmethod=simple
407  credentials=InvalidPw searchbase="$BASEDN" $SYNCTYPE retry="3 +" timeout=3
408-
409replace: olcMirrorMode
410olcMirrorMode: TRUE
411
412EOF
413RC=$?
414if test $RC != 0 ; then
415          echo "ldapmodify failed for server $n config ($RC)!"
416          test $KILLSERVERS != no && kill -HUP $KILLPIDS
417          exit $RC
418fi
419n=`expr $n + 1`
420done
421
422echo "Using ldapmodify to force conflicts between server 1 and 2..."
423$LDAPMODIFY -D "$MANAGERDN" -H $URI1 -w $PASSWD \
424          >> $TESTOUT 2>&1 << EOF
425dn: $THEDN
426changetype: modify
427add: description
428description: Amazing
429
430EOF
431RC=$?
432if test $RC != 0 ; then
433          echo "ldapmodify failed for server 1 database ($RC)!"
434          test $KILLSERVERS != no && kill -HUP $KILLPIDS
435          exit $RC
436fi
437
438$LDAPMODIFY -D "$MANAGERDN" -H $URI2 -w $PASSWD \
439          >> $TESTOUT 2>&1 << EOF
440dn: $THEDN
441changetype: modify
442add: description
443description: Stupendous
444
445EOF
446RC=$?
447if test $RC != 0 ; then
448          echo "ldapmodify failed for server 2 database ($RC)!"
449          test $KILLSERVERS != no && kill -HUP $KILLPIDS
450          exit $RC
451fi
452
453$LDAPMODIFY -D "$MANAGERDN" -H $URI1 -w $PASSWD \
454          >> $TESTOUT 2>&1 << EOF
455dn: $THEDN
456changetype: modify
457delete: description
458description: Outstanding
459-
460add: description
461description: Mindboggling
462
463EOF
464RC=$?
465if test $RC != 0 ; then
466          echo "ldapmodify failed for server 1 database ($RC)!"
467          test $KILLSERVERS != no && kill -HUP $KILLPIDS
468          exit $RC
469fi
470
471$LDAPMODIFY -D "$MANAGERDN" -H $URI2 -w $PASSWD \
472          >> $TESTOUT 2>&1 << EOF
473dn: $THEDN
474changetype: modify
475delete: description
476description: OutStanding
477-
478add: description
479description: Bizarre
480
481EOF
482RC=$?
483if test $RC != 0 ; then
484          echo "ldapmodify failed for server 2 database ($RC)!"
485          test $KILLSERVERS != no && kill -HUP $KILLPIDS
486          exit $RC
487fi
488
489$LDAPMODIFY -D "$MANAGERDN" -H $URI1 -w $PASSWD \
490          >> $TESTOUT 2>&1 << EOF
491dn: $THEDN
492changetype: modify
493add: carLicense
494carLicense: 123-XYZ
495-
496add: employeeNumber
497employeeNumber: 32
498
499EOF
500RC=$?
501if test $RC != 0 ; then
502          echo "ldapmodify failed for server 1 database ($RC)!"
503          test $KILLSERVERS != no && kill -HUP $KILLPIDS
504          exit $RC
505fi
506
507$LDAPMODIFY -D "$MANAGERDN" -H $URI2 -w $PASSWD \
508          >> $TESTOUT 2>&1 << EOF
509dn: $THEDN
510changetype: modify
511add: employeeType
512employeeType: deadwood
513-
514add: employeeNumber
515employeeNumber: 64
516
517EOF
518RC=$?
519if test $RC != 0 ; then
520          echo "ldapmodify failed for server 2 database ($RC)!"
521          test $KILLSERVERS != no && kill -HUP $KILLPIDS
522          exit $RC
523fi
524
525$LDAPMODIFY -D "$MANAGERDN" -H $URI1 -w $PASSWD \
526          >> $TESTOUT 2>&1 << EOF
527dn: $THEDN
528changetype: modify
529replace: sn
530sn: Replaced later
531-
532replace: sn
533sn: Surname
534EOF
535RC=$?
536if test $RC != 0 ; then
537          echo "ldapmodify failed for server 1 database ($RC)!"
538          test $KILLSERVERS != no && kill -HUP $KILLPIDS
539          exit $RC
540fi
541
542echo "Deleting an entry from both servers..."
543$LDAPDELETE -D "$MANAGERDN" -H $URI1 -w $PASSWD \
544    "cn=John Doe,ou=Information Technology Division,ou=People,$BASEDN" \
545          >> $TESTOUT 2>&1
546RC=$?
547if test $RC != 0 ; then
548          echo "ldapdelete failed for server 1 database ($RC)!"
549          test $KILLSERVERS != no && kill -HUP $KILLPIDS
550          exit $RC
551fi
552
553$LDAPDELETE -D "$MANAGERDN" -H $URI2 -w $PASSWD \
554    "cn=John Doe,ou=Information Technology Division,ou=People,$BASEDN" \
555          >> $TESTOUT 2>&1
556RC=$?
557if test $RC != 0 ; then
558          echo "ldapdelete failed for server 2 database ($RC)!"
559          test $KILLSERVERS != no && kill -HUP $KILLPIDS
560          exit $RC
561fi
562
563echo "Restoring replication between server 1 and 2..."
564n=1
565while [ $n -le $MMR ]; do
566o=`expr 3 - $n`
567MYURI=`eval echo '$URI'$n`
568PROVIDERURI=`eval echo '$URI'$o`
569$LDAPMODIFY -D cn=config -H $MYURI -y $CONFIGPWF > $TESTOUT 2>&1 <<EOF
570dn: olcDatabase={2}$BACKEND,cn=config
571changetype: modify
572replace: olcSyncRepl
573olcSyncRepl: rid=001 provider=$PROVIDERURI binddn="$MANAGERDN" bindmethod=simple
574  credentials=$PASSWD searchbase="$BASEDN" $SYNCTYPE retry="3 +" timeout=3
575-
576replace: olcMirrorMode
577olcMirrorMode: TRUE
578
579EOF
580RC=$?
581if test $RC != 0 ; then
582          echo "ldapmodify failed for server $n config ($RC)!"
583          test $KILLSERVERS != no && kill -HUP $KILLPIDS
584          exit $RC
585fi
586n=`expr $n + 1`
587done
588
589echo "Waiting $SLEEP1 seconds for syncrepl to receive changes..."
590sleep $SLEEP1
591
592echo 2 >$TESTDIR/repl.test
593echo 1 >>$TESTDIR/repl.test
594
595n=1
596while [ $n -le $MMR ]; do
597URI=`eval echo '$URI'$n`
598
599echo "Using ldapsearch to read all the entries from server $n..."
600$LDAPSEARCH -S "" -b "$BASEDN" -D "$MANAGERDN" -H $URI -w $PASSWD  \
601          'objectclass=*' > $TESTDIR/server$n.out 2>&1
602RC=$?
603
604if test $RC != 0 ; then
605          echo "ldapsearch failed at server $n ($RC)!"
606          test $KILLSERVERS != no && kill -HUP $KILLPIDS
607          exit $RC
608fi
609$LDIFFILTER -s a < $TESTDIR/server$n.out > $TESTDIR/server$n.flt
610
611echo "Checking server $n can remember which entries have been deleted even after it's been restarted..."
612$LDAPRSEARCH -b "$BASEDN" -D "$MANAGERDN" -H $URI -w $PASSWD \
613    -E "sync=ro/$cookie" 'objectclass=*' 1.1 | awk '/syncUUIDs/ {count++} END {print count}' >$TESTDIR/repl.out
614$LDAPRSEARCH -b "$BASEDN" -D "$MANAGERDN" -H $URI -w $PASSWD \
615    -E "sync=ro/$cookie" 'objectclass=*' 1.1 | grep SyncDone | awk '/refreshDeletes=1/ {count++} END {print count}' >>$TESTDIR/repl.out
616
617$CMP $TESTDIR/repl.out $TESTDIR/repl.test > $CMPOUT
618
619if test $? != 0 ; then
620          echo "test failed - server did not respond with delete phase"
621          test $KILLSERVERS != no && kill -HUP $KILLPIDS
622          exit 1
623fi
624n=`expr $n + 1`
625done
626
627n=2
628while [ $n -le $MMR ]; do
629echo "Comparing retrieved entries from server 1 and server $n..."
630$CMP $PROVIDERFLT $TESTDIR/server$n.flt > $CMPOUT
631
632if test $? != 0 ; then
633          echo "test failed - server 1 and server $n databases differ"
634          test $KILLSERVERS != no && kill -HUP $KILLPIDS
635          exit 1
636fi
637n=`expr $n + 1`
638done
639
640test $KILLSERVERS != no && kill -HUP $KILLPIDS
641
642echo ">>>>> Test succeeded"
643
644test $KILLSERVERS != no && wait
645
646exit 0
647