There is a race condition inside the client-side sendbackup. The short version is that any output from the compression or encryption pipes that gets send before the "sendbackup:" headers gets discarded by the server on receipt. For any pipe command that outputs headers, a sufficiently fast machine will allow this to happen. As a solution, we buffer the header from amcrypt-ossl-asym, and only output it after we have started receiving real data. At the time of writing this patch, amaespipe looks to suffer from the same problem. Signed-off-by: Robin H. Johnson diff -Nuar amanda-2.5.2p1.orig/server-src/amcrypt-ossl-asym.sh.in amanda-2.5.2p1/server-src/amcrypt-ossl-asym.sh.in --- amanda-2.5.2p1.orig/server-src/amcrypt-ossl-asym.sh.in 2008-09-21 22:09:10.973248726 -0700 +++ amanda-2.5.2p1/server-src/amcrypt-ossl-asym.sh.in 2008-09-21 22:09:46.575745504 -0700 @@ -88,7 +88,7 @@ perl -pe 'BEGIN { $bs = 96; $/ = \8192 } $nbytes = ($nbytes + length) % $bs; END { print "\0" x ($bs - $nbytes) }' } -encrypt() { +encrypt_setup() { # generate a random printable cipher key (on one line) echo `"${OPENSSL}" rand -base64 80` >"${WORKDIR}/pass" @@ -98,11 +98,20 @@ # print magic printf %s "${MAGIC}" + [ $? -eq 0 ] || return 1 # print the encrypted cipher key, preceded by size ls -l "${WORKDIR}/pass.ciphertext" | awk '{ printf("%-10d", $5) }' + [ $? -eq 0 ] || return 1 cat "${WORKDIR}/pass.ciphertext" + [ $? -eq 0 ] || return 1 + # Do a test encryption to see that it will work and we will not lose data + echo foo | encrypt >/dev/null + [ $? -eq 0 ] || return 1 +} + +encrypt() { # encrypt data using the cipher key and print pad | "${OPENSSL}" enc "-${CIPHER}" -nopad -e -pass "file:${WORKDIR}/pass" -nosalt [ $? -eq 0 ] || return 1 @@ -173,7 +182,26 @@ exit 1 fi - encrypt + # we must perform the encryption setup, but not produce any output until we start getting input + encrypt_setup >"${WORKDIR}/encryption-header" + if [ $? -ne 0 ]; then + echo "${ME}: encryption setup failed" >&2 + exit 1 + fi + # block until the first of the input + dd of="${WORKDIR}/data.buffer" bs=4 count=1 status=noxfer + if [ $? -ne 0 ]; then + echo "${ME}: encryption failed to get input data" >&2 + exit 1 + fi + # now spit out the encryption header + cat "${WORKDIR}/encryption-header" + if [ $? -ne 0 ]; then + echo "${ME}: encryption failed to output encryption header" >&2 + exit 1 + fi + # followed by our first bit of input, then the rest + cat "${WORKDIR}/data.buffer" - | encrypt if [ $? -ne 0 ]; then echo "${ME}: encryption failed" >&2 exit 1