EML
EML

Reputation: 10280

Tcl expect not cleaning up on exit, or messing up FIFOs?

TL;DR: expect appears to be messing up named pipes in some obscure way, or not cleaning up on exit.

I'm trying to automate generation of ssh keys, without touching the disk with either the private key or the key encryption password. The output is a zip file containing the keys, on stdout. The general principle is:

  1. Run the keygen program, which reads a password from stdin, and writes the keys to two named pipes
  2. Run zip, reading the two named pipes as input files, and writing output to stdout

This works when generating keys with openssl or puttygen. However, ssh-keygen makes this difficult, because it has to be run from a pty. To handle this, I run ssh-keygen under expect. A test script is below; run as:

$ echo "password" | ./test.sh > test.zip

This correctly creates the new keys in two pipes (/tmp/foo and /tmp/foo.pub; see the 'debug' bit in the script). In principle, I can now create the zipfile in exactly the same way as for openssl and puttygen:

zip -j - --fifo /tmp/foo /tmp/foo.pub

However, this doesn't work when expect is involved. If I pipe the script output to xxd instead of writing it to test.zip I can see that zip's output actually starts with the expect data (spawn ssh-keygen ...) before moving on to the PK magic at the start of the correct zip output. zip doesn't complain about this, but unzip fails, saying that the file is invalid.

I can 'fix' the problem by running this as two separate scripts: the first one just cats the two FIFOs, and the second one just runs the zip command, reading the two FIFOs. This works, producing a valid zip file, but obviously I don't want to do this.

Any suggestions? Is there some way to run expect which doesn't add rubbish to the FIFO data? Or maybe I can do something in the script to flush everything before running zip?

#!/bin/bash

export SSH_ASKPASS_REQUIRE=never
rm -f  /tmp/foo /tmp/foo.pub
mkfifo /tmp/foo /tmp/foo.pub

passw=$(cat)

expect -c "
   spawn ssh-keygen -q -t ed25519 -a100 -C '' -f /tmp/foo
   expect \"Overwrite\"
   send \"y\r\"
   expect \"passphrase\"
   send \"$passw\r\"
   expect \"again\"
   send \"$passw\r\"
   expect eof
"&

# DEBUG: this creates valid keys
# cat /tmp/foo     > id25519
# cat /tmp/foo.pub > id25519.pub

# BUT zip generates invalid output here, UNLESS you run this command
# outside of this script
zip -j - --fifo /tmp/foo /tmp/foo.pub

Upvotes: 1

Views: 48

Answers (0)

Related Questions