s4:heimdal: import lorikeet-heimdal-202201172009 (commit 5a0b45cd723628b3690ea848548b...
[samba.git] / source4 / heimdal / tests / kdc / check-iprop.in
1 #!/bin/sh
2 #
3 # Copyright (c) 2006 - 2007 Kungliga Tekniska Högskolan
4 # (Royal Institute of Technology, Stockholm, Sweden). 
5 # All rights reserved. 
6 #
7 # Redistribution and use in source and binary forms, with or without 
8 # modification, are permitted provided that the following conditions 
9 # are met: 
10 #
11 # 1. Redistributions of source code must retain the above copyright 
12 #    notice, this list of conditions and the following disclaimer. 
13 #
14 # 2. Redistributions in binary form must reproduce the above copyright 
15 #    notice, this list of conditions and the following disclaimer in the 
16 #    documentation and/or other materials provided with the distribution. 
17 #
18 # 3. Neither the name of the Institute nor the names of its contributors 
19 #    may be used to endorse or promote products derived from this software 
20 #    without specific prior written permission. 
21 #
22 # THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
23 # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
24 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
25 # ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
26 # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
27 # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
28 # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
29 # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
30 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
31 # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
32 # SUCH DAMAGE. 
33
34 top_builddir="@top_builddir@"
35 env_setup="@env_setup@"
36 objdir="@objdir@"
37
38 db_type=@db_type@
39
40 . ${env_setup}
41
42 # If there is no useful db support compiled in, disable test
43 ${have_db} || exit 77
44
45
46 # Don't run this test in AFS, since it lacks support for AF_UNIX
47 expr "X`/bin/pwd || pwd`" : "X/afs/.*" > /dev/null 2>/dev/null && exit 77
48
49 R=TEST.H5L.SE
50
51 port=@port@
52 ipropport=@ipropport@
53 ipropport2=@ipropport2@
54
55 cache="FILE:${objdir}/cache.krb5"
56 keytabfile=${objdir}/iprop.keytab
57 keytab="FILE:${keytabfile}"
58
59 kdc="${kdc} --addresses=localhost -P $port"
60 kadmin="${kadmin} -r $R"
61 kinit="${kinit} -c $cache ${afs_no_afslog}"
62
63 # We'll test iprop, and in particular, hierarchical iprop.  This means we'll
64 # have a setup like:
65 #
66 #  ipropd-master -> ipropd-slave -> 2nd ipropd-master -> 2nd ipropd-slave
67
68 # Waiting for incremental propagation is inherently difficult because we don't
69 # have a way for ipropd-slave to signal this script that it has received
70 # updates.  Well, it does have a way to signal a possible ipropd-master for
71 # hierarchical iprop, but we don't have a way to get that signal here.
72 #
73 # FIXME: Add a private interface for async waiting for iprop.
74 #
75 # What we do is we have a set of utility functions:
76 #
77 #  - get_iprop_ver   [N] -> checks that N (default to 1) ops have made it over
78 #  - get_iprop_ver2  [N] -> same, but for second ipropd-slave instance
79 #
80 #  - wait_for            -> repeat a command until it succeeds or too many tries
81 #  - wait_for_slave  [N] -> wait for N ops to make it over (calls get_iprop_ver)
82 #  - wait_for_slave2 [N] -> same, but for second ipropd-slave instance
83 #
84 # In particular the wait_for* functions busy-wait for a max amount of time,
85 # with sleeps in between.
86 #
87 # NOTE: get_iprop_ver and get_iprop_ver2 keep hidden state.
88 #
89 # When first called, get_iprop_ver / get_iprop_ver2 save the current version
90 # numbers.  Thereafter they check that N ops have been received.
91 #
92 # It is critical to account for every incremental op via get_iprop_ver /
93 # get_iprop_ver2, or wait_for_slave / wait_for_slave2, otherwise this test will
94 # be racy and will have spurious failures!
95 #
96 # The pattern should be something like this:
97 #
98 #   echo "Add host"
99 #   ${kadmin} -l add --random-key --use-defaults host/foo@${R} || exit 1
100 #   wait_for_slave
101 #   ^^^^^^^^^^^^^^
102 #      waits for 1 operation
103 #
104 # or
105 #
106 #   echo "Rollover host keys"
107 #   ${kadmin} -l cpw -r --keepold host/foo@${R} || exit 1
108 #   ${kadmin} -l cpw -r --keepold host/foo@${R} || exit 1
109 #   ${kadmin} -l cpw -r --keepold host/foo@${R} || exit 1
110 #   wait_for_slave 3
111 #   ^^^^^^^^^^^^^^^^
112 #      waits for the three operations
113 #
114 # So though all operations must be accounted for, they need not be accounted
115 # one by one.
116
117 slave_ver_from_master_old=
118 slave_ver_from_master_new=
119 slave_ver_old=
120 slave_ver_new=
121 get_iprop_ver () {
122     min_change=${1:-1}
123     slave_ver_from_master_new=`grep '^iprop/' iprop-stats | head -1 | awk '{print $3}'`
124     slave_ver_new=`grep 'up-to-date with version:' iprop-slave-status | awk '{print $4}'`
125     if [ -z "$slave_ver_from_master_new" -o -z "$slave_ver_new" ]; then
126         return 1
127     fi
128     if [ x"$slave_ver_from_master_new" != x"$slave_ver_new" ]; then
129         return 1
130     fi
131     if [ x"$slave_ver_from_master_old" != x ]; then
132         change=`expr "$slave_ver_from_master_new" - "$slave_ver_from_master_old"`
133         if [ "$change" -lt "$min_change" ]; then
134             return 1
135         fi
136     fi
137     slave_ver_from_master_old=$slave_ver_from_master_new
138     slave_ver_old=$slave_ver_new
139     return 0
140 }
141
142 slave_ver_from_master_old2=
143 slave_ver_from_master_new2=
144 slave_ver_old2=
145 slave_ver_new2=
146 get_iprop_ver2 () {
147     min_change=${1:-1}
148     slave_ver_from_master_new2=`grep '^iprop/' iprop-stats2 | head -1 | awk '{print $3}'`
149     slave_ver_new2=`grep 'up-to-date with version:' iprop-slave-status2 | awk '{print $4}'`
150     if [ -z "$slave_ver_from_master_new2" -o -z "$slave_ver_new2" ]; then
151         return 1
152     fi
153     if [ x"$slave_ver_from_master_new2" != x"$slave_ver_new2" ]; then
154         return 1
155     fi
156     if [ x"$slave_ver_from_master_old2" != x ]; then
157         change=`expr "$slave_ver_from_master_new2" - "$slave_ver_from_master_old2"`
158         if [ "$change" -lt "$min_change" ]; then
159             return 1
160         fi
161     fi
162     slave_ver_from_master_old2=$slave_ver_from_master_new2
163     slave_ver_old2=$slave_ver_new2
164     return 0
165 }
166
167 waitsec=65
168 sleeptime=2
169 wait_for () {
170     msg=$1
171     shift
172     t=0
173     while ! "$@"; do
174         sleep $sleeptime;
175         t=`expr $t + $sleeptime`
176         if [ $t -gt $waitsec ]; then
177             echo "Waited too long for $msg"
178             exit 1
179         fi
180     done
181     return 0
182 }
183
184 check_pidfile_is_dead () {
185     if test ! -f lt-${1}.pid -a ! -f ${1}.pid; then
186         return 0
187     fi
188     _pid=`cat lt-${1}.pid ${1}.pid 2>/dev/null`
189     if [ -z "$_pid" ]; then
190         return 0
191     fi
192     if kill -0 $_pid 2>/dev/null; then
193         return 1
194     fi
195     return 0
196 }
197
198 wait_for_slave () {
199     wait_for "iprop versions to change and/or slave to catch up" get_iprop_ver "$@"
200 }
201
202 wait_for_slave2 () {
203     wait_for "iprop versions to change and/or second slave to catch up" get_iprop_ver2 "$@"
204 }
205
206 wait_for_master_down () {
207     wait_for "master to exit" check_pidfile_is_dead ipropd-master
208 }
209
210 wait_for_slave_down () {
211     wait_for "slave to exit" check_pidfile_is_dead ipropd-slave
212 }
213
214 KRB5_CONFIG="${objdir}/krb5.conf"
215 export KRB5_CONFIG
216
217 rm -f ${keytabfile}
218 rm -f current-db*
219 rm -f current*.log
220 rm -f out-*
221 rm -f mkey.file*
222 rm -f messages.log messages.log
223
224 > messages.log
225 > messages.log2
226
227 echo Creating database
228 ${kadmin} -l \
229     init \
230     --realm-max-ticket-life=1day \
231     --realm-max-renewable-life=1month \
232     ${R} || exit 1
233
234 ${kadmin} -l add -p foo --use-defaults user@${R} || exit 1
235
236 ${kadmin} -l add --random-key --use-defaults iprop/localhost@${R} || exit 1
237 ${kadmin} -l ext -k ${keytab} iprop/localhost@${R} || exit 1
238 ${kadmin} -l add --random-key --use-defaults iprop/slave.test.h5l.se@${R} || exit 1
239 ${kadmin} -l ext -k ${keytab} iprop/slave.test.h5l.se@${R} || exit 1
240
241 echo foo > ${objdir}/foopassword
242
243 echo "Test log recovery"
244 ${kadmin} -l add --random-key --use-defaults recovtest@${R} || exit 1
245 # Test theory: save the log, make a change and save the record it
246 # produced, restore the log, append to it the saved record, then add dummy
247 # record.
248
249 # Save the log
250 cp current.log current.log.tmp
251 ls -l current.log.tmp | awk '{print $5}' > tmp
252 read sz < tmp
253 # Make a change
254 ${kadmin} -l mod -a requires-pre-auth recovtest@${R} || exit 1
255 ${kadmin} -l get recovtest@${R} | grep 'Attributes: requires-pre-auth$' > /dev/null || exit 1
256 # Save the resulting log record
257 ls -l current.log | awk '{print $5}' > tmp
258 read nsz < tmp
259 rm tmp
260 dd bs=1 if=current.log skip=$sz of=current.log.tmp.saved-record count=`expr $nsz - $sz` 2>/dev/null
261 # Undo the change
262 ${kadmin} -l mod -a -requires-pre-auth recovtest@${R} || exit 1
263 ${kadmin} -l get recovtest@${R} | grep 'Attributes:.$' > /dev/null || exit 1
264 # Restore the log
265 cp current.log current.log.save
266 mv current.log.tmp current.log
267 # Append the saved record
268 cat current.log.tmp.saved-record >> current.log
269 rm current.log.tmp.saved-record
270 # Check that we still see the principal as modified after another write forcing
271 # log recovery.
272 ${kadmin} -l add --random-key --use-defaults dummy@${R} || exit 1
273 ${kadmin} -l del dummy@${R} || exit 1
274 ${kadmin} -l get recovtest@${R} | grep 'Attributes: requires-pre-auth$' > /dev/null || exit 1
275
276 # -- foo
277 ipds=
278 ipdm=
279 kdcpid=
280
281 > iprop-stats
282 > iprop-stats2
283 rm -f iprop-slave-status iprop-slave-status2
284
285 ipropd_slave2=$ipropd_slave
286 ipropd_master2=$ipropd_master
287 ipropd_slave="${ipropd_slave} --status-file=iprop-slave-status --port=$ipropport"
288 ipropd_slave="${ipropd_slave} --hostname=slave.test.h5l.se -k ${keytab}"
289 ipropd_slave="${ipropd_slave} --detach localhost"
290 ipropd_master="${ipropd_master} --hostname=localhost -k ${keytab}"
291 ipropd_master="${ipropd_master} --port=$ipropport"
292 ipropd_master="${ipropd_master} --database=${objdir}/current-db --detach"
293
294 ipropd_slave2="${ipropd_slave2} --status-file=iprop-slave-status2 --port=$ipropport2"
295 ipropd_slave2="${ipropd_slave2} --hostname=slave.test.h5l.se -k ${keytab}"
296 ipropd_slave2="${ipropd_slave2} --pidfile-basename=ipropd-slave2"
297 ipropd_slave2="${ipropd_slave2} --detach localhost"
298 ipropd_master2="${ipropd_master2} --hostname=localhost -k ${keytab}"
299 ipropd_master2="${ipropd_master2} --port=$ipropport2"
300 ipropd_master2="${ipropd_master2} --pidfile-basename=ipropd-master2"
301 ipropd_master2="${ipropd_master2} --database=${objdir}/current-db.slave --detach"
302
303 cleanup() {
304     echo 'killing ipropd s + m + kdc'
305     test -n "$ipdm" && kill -9 $ipdm        >/dev/null 2>/dev/null
306     test -n "$ipdm2" && kill -9 $ipdm2      >/dev/null 2>/dev/null
307     test -n "$ipds" && kill -9 $ipds        >/dev/null 2>/dev/null
308     test -n "$ipds2" && kill -9 $ipds2      >/dev/null 2>/dev/null
309     test -n "$kdcpid" && kill -9 $kdcpid    >/dev/null 2>/dev/null
310     tail messages.log
311     tail iprop-stats
312     exit 1
313 }
314 trap cleanup EXIT
315
316 echo Starting kdc ; > messages.log
317 ${kdc} --detach --testing || { echo "kdc failed to start"; exit 1; }
318 kdcpid=`getpid kdc`
319
320 echo "starting master" ; > messages.log
321 env ${HEIM_MALLOC_DEBUG} \
322 ${ipropd_master} || { echo "ipropd-master failed to start"; exit 1; }
323 ipdm=`getpid ipropd-master`
324
325 echo "starting slave" ; > messages.log
326 env ${HEIM_MALLOC_DEBUG} \
327 KRB5_CONFIG="${objdir}/krb5-slave.conf" \
328 ${ipropd_slave} || { echo "ipropd-slave failed to start"; exit 1; }
329 ipds=`getpid ipropd-slave`
330 sh ${wait_kdc} ipropd-slave messages.log 'slave status change: up-to-date' || exit 1
331 get_iprop_ver || exit 1
332
333 echo "checking slave is up"
334 ${EGREP} 'iprop/slave.test.h5l.se@TEST.H5L.SE.*Up' iprop-stats >/dev/null || exit 1
335 ${EGREP} 'up-to-date with version' iprop-slave-status >/dev/null || { echo "slave to up to date" ; cat iprop-slave-status ; exit 1; }
336
337 # Also setup a second master on the slave, then a second slave to pull from the
338 # second master.
339 echo "starting master2" ; > messages.log
340 env ${HEIM_MALLOC_DEBUG} \
341 KRB5_CONFIG="${objdir}/krb5-master2.conf" \
342 ${ipropd_master2} || { echo "second ipropd-master failed to start"; exit 1; }
343 ipdm2=`getpid ipropd-master2`
344
345 echo "starting slave2" ; > messages.log
346 env ${HEIM_MALLOC_DEBUG} \
347 KRB5_CONFIG="${objdir}/krb5-slave2.conf" \
348 ${ipropd_slave2} || { echo "ipropd-slave failed to start"; exit 1; }
349 ipds2=`getpid ipropd-slave2`
350 sh ${wait_kdc} ipropd-slave messages2.log 'slave status change: up-to-date' || exit 1
351 wait_for "Slave sees new host" get_iprop_ver2 0 || exit 1
352
353 # ----------------- checking: pushing lives changes
354
355 slave_get() { KRB5_CONFIG="${objdir}/krb5-slave.conf" ${kadmin} -l get "$@"; }
356 slave_check_exists() {
357     # Creation with a random key is not atomic, there are at present
358     # 3 log entries to create a random key principal, the entry is
359     # "invalid" for the first two of these.  We wait for the entry to
360     # exist and not be invalid
361     #
362     attrs=`slave_get -o attributes "$@" 2>/dev/null` || return 1
363     echo $attrs | egrep 'Attributes:' | egrep -v invalid >/dev/null || return 1
364     get_iprop_ver 0
365 }
366
367 echo "Add host"
368 ${kadmin} -l add --random-key --use-defaults host/foo@${R} || exit 1
369 wait_for_slave
370 wait_for "Slave sees new host" slave_check_exists "host/foo@${R}"
371
372 echo "Rollover host keys"
373 ${kadmin} -l cpw -r --keepold host/foo@${R} || exit 1
374 ${kadmin} -l cpw -r --keepold host/foo@${R} || exit 1
375 ${kadmin} -l cpw -r --keepold host/foo@${R} || exit 1
376 wait_for_slave 3
377 slave_get host/foo@${R} | \
378     ${EGREP} Keytypes: | cut -d: -f2 | tr ' ' '
379 ' | sed 's/^.*[[]\(.*\)[]].*$/\1/' | grep '[0-9]' | sort -nu | tr -d '
380 ' | ${EGREP} 1234 > /dev/null || exit 1
381
382 wait_for_slave2 4
383
384 echo "Delete 3DES keys"
385 ${kadmin} -l del_enctype host/foo@${R} des3-cbc-sha1
386 wait_for_slave
387 KRB5_CONFIG="${objdir}/krb5-slave.conf" \
388 ${kadmin} -l get host/foo@${R} | \
389     ${EGREP} Keytypes: | cut -d: -f2 | tr ' ' '
390 ' | sed 's/^.*[[]\(.*\)[]].*$/\1/' | grep '[0-9]' | sort -nu | tr -d '
391 ' | ${EGREP} 1234 > /dev/null || exit 1
392 KRB5_CONFIG="${objdir}/krb5-slave.conf" \
393 ${kadmin} -l get host/foo@${R} | \
394     ${EGREP} 'Keytypes:.*des3-cbc-sha1' > /dev/null && exit 1
395
396 echo "Change policy host"
397 ${kadmin} -l modify --policy=default host/foo@${R} || exit 1
398 wait_for_slave
399 KRB5_CONFIG="${objdir}/krb5-slave.conf" \
400 ${kadmin} -l get host/foo@${R} > /dev/null 2>/dev/null || exit 1
401
402 echo "Rename host"
403 ${kadmin} -l rename host/foo@${R} host/bar@${R} || exit 1
404 wait_for_slave
405 KRB5_CONFIG="${objdir}/krb5-slave.conf" \
406 ${kadmin} -l get host/foo@${R} > /dev/null 2>/dev/null && exit 1
407 KRB5_CONFIG="${objdir}/krb5-slave.conf" \
408 ${kadmin} -l get host/bar@${R} > /dev/null || exit 1
409
410 wait_for_slave2 3
411
412 echo "Delete host"
413 ${kadmin} -l delete host/bar@${R} || exit 1
414 wait_for_slave
415 KRB5_CONFIG="${objdir}/krb5-slave.conf" \
416 ${kadmin} -l get host/bar@${R} > /dev/null 2>/dev/null && exit 1
417
418 # See note below in LMDB sanity checking
419 echo "Re-add host"
420 ${kadmin} -l add --random-key --use-defaults host/foo@${R} || exit 1
421 ${kadmin} -l add --random-key --use-defaults host/bar@${R} || exit 1
422 wait_for_slave 2
423 wait_for "Slave sees re-added host" slave_check_exists "host/bar@${R}"
424
425 wait_for_slave2 3
426
427 echo "kill slave and remove log and database"
428 > iprop-stats
429 sh ${leaks_kill} ipropd-slave $ipds || exit 1
430 rm -f iprop-slave-status
431
432 wait_for_slave_down
433 ${EGREP} 'iprop/slave.test.h5l.se@TEST.H5L.SE.*Down' iprop-stats >/dev/null || exit 1
434
435 # ----------------- checking: slave is missing changes while down
436
437 rm current.slave.log current-db.slave* || exit 1
438
439 echo "doing changes while slave is down"
440 ${kadmin} -l cpw --random-password user@${R} > /dev/null || exit 1
441 ${kadmin} -l cpw --random-password user@${R} > /dev/null || exit 1
442
443 echo "Making a copy of the master log file"
444 cp ${objdir}/current.log ${objdir}/current.log.tmp
445
446 # ----------------- checking: checking that master and slaves resyncs
447
448 echo "starting slave again" ; > messages.log
449 > iprop-stats
450 env ${HEIM_MALLOC_DEBUG} \
451 KRB5_CONFIG="${objdir}/krb5-slave.conf" \
452 ${ipropd_slave} || { echo "ipropd-slave failed to start"; exit 1; }
453 ipds=`getpid ipropd-slave`
454
455 echo "checking slave is up again"
456 wait_for "slave to start and connect to master" \
457     ${EGREP} 'iprop/slave.test.h5l.se@TEST.H5L.SE.*Up' iprop-stats >/dev/null
458 wait_for_slave 2
459 wait_for_slave2 2
460 ${EGREP} 'up-to-date with version' iprop-slave-status >/dev/null || { echo "slave not up to date" ; cat iprop-slave-status ; exit 1; }
461 echo "checking for replay problems"
462 ${EGREP} 'Entry already exists in database' messages.log && exit 1
463
464 echo "compare versions on master and slave logs (no lock)"
465 KRB5_CONFIG=${objdir}/krb5-slave.conf \
466 ${iprop_log} last-version -n > slave-last.tmp
467 ${iprop_log} last-version -n > master-last.tmp
468 cmp master-last.tmp slave-last.tmp || exit 1
469
470 echo "kill slave and remove log and database"
471 sh ${leaks_kill} ipropd-slave $ipds || exit 1
472 wait_for_slave_down
473
474 rm current.slave.log current-db.slave* || exit 1
475 > iprop-stats
476 rm -f iprop-slave-status
477 echo "starting slave" ; > messages.log
478 env ${HEIM_MALLOC_DEBUG} \
479 KRB5_CONFIG="${objdir}/krb5-slave.conf" \
480 ${ipropd_slave} || { echo "ipropd-slave failed to start"; exit 1; }
481 ipds=`getpid ipropd-slave`
482 wait_for_slave 0
483
484 echo "checking slave is up again"
485 wait_for "slave to start and connect to master" \
486     ${EGREP} 'iprop/slave.test.h5l.se@TEST.H5L.SE.*Up' iprop-stats >/dev/null
487 ${EGREP} 'up-to-date with version' iprop-slave-status >/dev/null || { echo "slave not up to date" ; cat iprop-slave-status ; exit 1; }
488 echo "checking for replay problems"
489 ${EGREP} 'Entry already exists in database' messages.log && exit 1
490
491 # ----------------- checking: checking live truncation of master log
492
493 ${kadmin} -l cpw --random-password user@${R} > /dev/null || exit 1
494 wait_for_slave
495 wait_for_slave2
496
497 echo "live truncate on master log"
498 ${iprop_log} truncate -K 5 || exit 1
499 wait_for_slave 0
500
501 echo "Killing master and slave"
502 sh ${leaks_kill} ipropd-master $ipdm || exit 1
503 sh ${leaks_kill} ipropd-slave $ipds || exit 1
504
505 rm -f iprop-slave-status
506
507 wait_for_slave_down
508 wait_for_master_down
509
510 echo "compare versions on master and slave logs"
511 KRB5_CONFIG=${objdir}/krb5-slave.conf \
512 ${iprop_log} last-version > slave-last.tmp
513 ${iprop_log} last-version > master-last.tmp
514 cmp master-last.tmp slave-last.tmp || exit 1
515
516 # ----------------- checking: master going backward
517 > iprop-stats
518 > messages.log
519
520 echo "Going back to old version of the master log file"
521 cp ${objdir}/current.log.tmp ${objdir}/current.log
522
523 echo "starting master"  ; > messages.log
524 env ${HEIM_MALLOC_DEBUG} \
525 ${ipropd_master} || { echo "ipropd-master failed to start"; exit 1; }
526 ipdm=`getpid ipropd-master`
527
528 echo "starting slave" ; > messages.log
529 env ${HEIM_MALLOC_DEBUG} \
530 KRB5_CONFIG="${objdir}/krb5-slave.conf" \
531 ${ipropd_slave} || { echo "ipropd-slave failed to start"; exit 1; }
532 ipds=`getpid ipropd-slave`
533 wait_for_slave -1
534
535 echo "checking slave is up again"
536 wait_for "slave to start and connect to master" \
537     ${EGREP} 'iprop/slave.test.h5l.se@TEST.H5L.SE.*Up' iprop-stats >/dev/null
538 ${EGREP} 'up-to-date with version' iprop-slave-status >/dev/null || { echo "slave to up to date" ; cat iprop-slave-status ; exit 1; }
539 echo "checking for replay problems"
540 ${EGREP} 'Entry already exists in database' messages.log && exit 1
541
542 echo "pushing one change"
543 ${kadmin} -l cpw --random-password user@${R} > /dev/null || exit 1
544 wait_for_slave
545 wait_for_slave2 0
546
547 echo "Killing master"
548 sh ${leaks_kill} ipropd-master $ipdm || exit 1
549
550 wait_for_master_down
551
552 wait_for "slave to disconnect" \
553   ${EGREP} 'disconnected' iprop-slave-status >/dev/null
554
555 if ! tail -30 messages.log | grep 'disconnected for server' > /dev/null; then
556     echo "client didnt disconnect"
557     exit 1
558 fi
559
560 echo "probing for slave pid"
561 kill -0 ${ipds}  || { echo "slave no longer there"; exit 1; }
562
563 > messages.log
564
565 echo "Staring master again" ; > messages.log
566 env ${HEIM_MALLOC_DEBUG} \
567 ${ipropd_master} || { echo "ipropd-master failed to start"; exit 1; }
568 ipdm=`getpid ipropd-master`
569
570 echo "probing for slave pid"
571 kill -0 ${ipds}  || { echo "slave no longer there"; exit 1; }
572
573
574 echo "pushing one change"
575 ${kadmin} -l cpw --random-password user@${R} > /dev/null || exit 1
576 wait_for_slave
577 wait_for_slave2
578
579 echo "shutting down all services"
580
581 leaked=false
582 sh ${leaks_kill} kdc $kdcpid || leaked=true
583 sh ${leaks_kill} ipropd-master $ipdm || leaked=true
584 sh ${leaks_kill} ipropd-slave $ipds || leaked=true
585 sh ${leaks_kill} ipropd-master $ipdm2 || leaked=true
586 sh ${leaks_kill} ipropd-slave $ipds2 || leaked=true
587 rm -f iprop-slave-status
588 trap "" EXIT
589 $leaked && exit 1
590
591 echo "compare versions on master and slave logs"
592 KRB5_CONFIG=${objdir}/krb5-slave.conf \
593 ${iprop_log} last-version > slave-last.tmp
594 ${iprop_log} last-version > master-last.tmp
595 cmp master-last.tmp slave-last.tmp || exit 1
596
597 if [ "$db_type" = lmdb ] && type mdb_stat > /dev/null 2>&1; then
598     # Sanity check that we have the same number of principals at the HDB
599     # and LMDB levels.
600     #
601     # We should also do this for the sqlite backend, but that would
602     # require a sqlite3(1) shell that is capable of opening our HDB
603     # files.
604     echo "checking that principals in DB == entries in LMDB"
605     # Add one to match lmdb overhead
606     princs=`(echo; ${kadmin} -l list '*') | wc -l`
607     entries=`mdb_stat -n current-db.mdb | grep 'Entries:' | awk '{print $2}'`
608     [ "$princs" -eq "$entries" ] || exit 1
609 fi
610
611 exit 0