reading SSH password from stdin – the openssh 5.6p1 compatible way

Linux 10 Comments »

There are several solutions for piping a password to ssh. One of the solutions can be found under But starting from openssh 5.6p1 the approach described there won’t work anymore. The reason behind is the following piece of code, that was added in version 5.6:

 * Discard other fds that are hanging around. 
 * These can cause problem  with backgrounded 
 * ssh processes started by ControlPersist.

closefrom(STDERR_FILENO + 1);

closefrom(int startingfd); closes all opened file descriptors starting from startingfd. In this case it closes all file descriptors starting from stderr (stderr is equivalent to two). At this point every approach that passes the password by inheriting file descriptors to ssh will fail. That means another solution must be found, mine is the usage of SSH_ASKPASS.

The SSH_ASKPASS approach

As stated in the ssh man page, the environment variable SSH_ASKPASS can be used to pass a password to ssh:

If ssh needs a passphrase, it will read the passphrase from the current terminal if it was run from a terminal. If ssh does not have a terminal associated with it but DISPLAY and SSH_ASKPASS are set, it will execute the program specified by SSH_ASKPASS and open an X11 window to read the passphrase. This is particularly useful when calling ssh from a .xsession or related script. (Note that on some machines it may be necessary to redirect the input from /dev/null to make this work.)

To retrieve the password, ssh calls the program specified in the SSH_ASKPASS environment variable. In a perfect world it would be sufficient to set the DISPLAY variable to a bogus value and tell ssh to use the program in SSH_ASKPASS to retrieve the password. But this is not enough, because ssh always looks for a valid terminal and always asks there for a password. The trick is to detach ssh from the current terminal by starting it in a new session. The command setsid – a wrapper around the setsid system call – does exactly this.

sshaskpass script

I put the pieces together and wrote a script that passes a password from stdin to ssh. First the script creates a temp file by callin mktemp and sets then the file permissions so that only the user can read/write the file. Then it writes the password to the temp file where it is read later via the SSH_ASKPASS mechanism. The temp file containing the password is delete at the end of the script or in case the script receives a signal, the file is delete by a signal handler.

# script that passes password from stdin to ssh. 
# Copyright (C) 2010 André Frimberger <andre OBVIOUS_SIGN>
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or 
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <>.

if [ -n "$SSH_ASKPASS_TMPFILE" ]; then
    exit 0
elif [ $# -lt 1 ]; then
    echo “Usage: echo password | $0 <ssh command line options>” >&2
    exit 1

sighandler() {
    rm “$TMP_PWD”

chmod 600 “$TMP_PWD”

export SSH_ASKPASS=$0

[ "$DISPLAY" ] || export DISPLAY=dummydisplay:0
read password
echo $password >> “$TMP_PWD”

# use setsid to detach from tty
exec setsid “$@”

rm “$TMP_PWD”

Q & A

Q: How to use the script

echo “my_password” | ./ ssh user@someMachine “ls -l”

Q: Why don’t you use public keys instead?

Public key authentication doesn’t work with pam_mount. This is because pam_mount passes the ssh password to mount.fuse.

Retrieve HTTPS certificate chain and import it to java keystore

Linux No Comments »

Normally a download link is provided where you can download someone else’s certificate. But sometimes a download link isn’t provided or it is easier to export the certificate yourself.

The script mentioned in the ”OpenSSL Command-Line Howto” ( retrieves only the root certificate but not the complete certificate chain. To solve this problem I extended that script a little bit so that it exports every certificate of the certificate chain in a seperate file. Later on you can import the certificates into the keystore using the keytool command.

Example: Usage of the script

Here you can see how to use this script:

$ ./
2 certificates found. 

Each certificate must be exported to a different file, 
otherwise the import with keytool won’t work.

Please enter a filename prefix for the certificate files: amazon 
starting export:
amazon1.crt generated.
amazon2.crt generated.

Import the certificates using keytool:

$ $JAVA_HOME/bin/keytool -import -alias amazon1 -file ./amazon1.crt -keystore $JAVA_HOME/jre/lib/security/jssecacerts
$ $JAVA_HOME/bin/keytool -import -alias amazon2 -file ./amazon2.crt -keystore $JAVA_HOME/jre/lib/security/jssecacerts

The script

Here is the script that retrieves every certificate of a certificate chain:

# usage: remote_host_name [port]

echo “” | openssl s_client -showcerts -connect ${REMOTEHOST}:${REMOTEPORT} 2>&1 |\
tr -d ‘\n’ |\

NUM_CERTS=$(wc -l “${TMPFILE}” | awk ‘{print $1}’)

if [ ${NUM_CERTS} -lt 1 ]; then
    echo “No certificates found.”
    exit 0;

echo “${NUM_CERTS} certificates found. ”
echo “”
echo “Each certificate must be exported to a different file, ”
echo “otherwise the import with keytool won\’t work.”
echo “”
echo -n “Please enter a filename prefix for the certificate files: ”
read crtfile

if [ ! -n "$crtfile" ]; then
    echo “no filename given. Exiting”
    exit 0;
echo “starting export:”

while read LINE
    let i=$i+1
    if [ -f "${filename}" ]; then
        echo “Error: ${filename} exists.”
        echo ”       This script does not override files. Delete them before running this script.”
    # change this line according for automatic keytool import
    echo $LINE | sed -e ’s/-BEGIN CERTIFICATE—–/-BEGIN CERTIFICATE—–\n/’ -e ’s/—–END /\n—–END /’  > “${filename}”
    echo “${filename} generated.”
done < “${TMPFILE}”

rm “${TMPFILE}”