Looking at the source code it seems that s_client only reads from console or TTY devices and not from just any stdin.
You can work around that by interposing a program that wraps a (pseudo)TTY around the command.
screen
can do that, but it makes it a bit hard, I sometimes use the ssh
trick.
Also there is the goto for interactive console programs (expect): https://linux.die.net/man/1/expect, but never tried that.
with SSH
echo -e 'GET / HTTP/1.0\nHost: www.example.com\n\n' | ssh -tt user@localhost 'openssl s_client -crlf -servername www.example.com -brief -connect www.example.com:443'
The -tt forces TTY allocation, which ssh by default wouldn't do, if it detects a pipe.
Disadvantage is that you have to set this loopback SSH connection to logon automatically to use it in a script.
This is NOT binary safe. For simple ASCII it will do.
with Screen
Somewhat harder, but minus the logon hassle.
Prepare a file query
with lines for input to the server.
For example:
GET / HTTP/1.0
Host: www.example.com
Make a detached screen with name myscreen
and save output to ./out.log
screen -d -m -S myscreen -L -Logfile ./out.log
Send the openssl connection command (-X stuff) to the first window (-p 0) of the screen named myscreen
(-S myscreen) and then immediately send the data from file ./query
. Note that the $(cat..) process substitution will chomp any trailing newlines in file ./query
and the openssl command MUST have -crlf in case of HTTP protocol. The query data MUST be send not long after opening the connection or the s_client will timeout.
screen -S myscreen -p 0 -X stuff "openssl s_client -crlf -servername www.example.com -brief -connect www.example.com:443^M";screen -S myscreen -p 0 -X stuff "$(cat ./query)^M^M"
Finally exit the screen, to erase the myscreen
session (This assumes the preceding query made the server already drop the connection and s_client exited itself):
screen -S myscreen -p 0 -X stuff "exit^M"
Output including the query and exit and s_client output is now in ./out.log
If s_client does not exit after the query you could first send an interrupt signal.
screen -S myscreen -p 0 -X stuff "^C"