diff --git a/apps/wolfssh/wolfssh.c b/apps/wolfssh/wolfssh.c index c012c710..8e5689d1 100644 --- a/apps/wolfssh/wolfssh.c +++ b/apps/wolfssh/wolfssh.c @@ -1270,6 +1270,9 @@ static THREAD_RETURN WOLFSSH_THREAD wolfSSH_Client(void* args) #endif MODES_STORE(); + /* No stdio buffer keeps a copy of a typed password. */ + if (setvbuf(stdin, NULL, _IONBF, 0) != 0) + fprintf(stderr, "Couldn't unbuffer stdin.\n"); ((func_args*)args)->return_code = 0; diff --git a/examples/client/client.c b/examples/client/client.c index fe5a9844..153fcfd0 100644 --- a/examples/client/client.c +++ b/examples/client/client.c @@ -1006,6 +1006,10 @@ THREAD_RETURN WOLFSSH_THREAD client_test(void* args) } myoptind = 0; /* reset for test cases */ +#ifdef WOLFSSH_TERM + ClientUnbufferStdin(); +#endif + if (username == NULL) err_sys("client requires a username parameter."); diff --git a/examples/client/common.c b/examples/client/common.c index eaadf956..d4bc1107 100644 --- a/examples/client/common.c +++ b/examples/client/common.c @@ -675,6 +675,18 @@ void ClientClearPassword(void) #ifdef WOLFSSH_TERM +void ClientUnbufferStdin(void) +{ + static int done = 0; + + if (!done) { + done = 1; + if (setvbuf(stdin, NULL, _IONBF, 0) != 0) + fprintf(stderr, "Couldn't unbuffer stdin.\n"); + } +} + + /* type = 2 : shell / execute command settings * type = 0 : password * type = 1 : restore default diff --git a/examples/client/common.h b/examples/client/common.h index 21f3adfa..2198a8ac 100644 --- a/examples/client/common.h +++ b/examples/client/common.h @@ -32,6 +32,10 @@ int ClientSetPrivateKey(const char* privKeyName, int userEcc, void* heap, const char* tpmKeyAuth); int ClientUseCert(const char* certName, void* heap); int ClientSetEcho(int type); +/* Makes stdin unbuffered, so no stdio buffer keeps a copy of a typed + * password or response. Call before any other stdin I/O; only the first + * call in a process acts. */ +void ClientUnbufferStdin(void); int ClientUserAuth(byte authType, WS_UserAuthData* authData, void* ctx); int ClientPublicKeyCheck(const byte* pubKey, word32 pubKeySz, void* ctx); diff --git a/examples/scpclient/scpclient.c b/examples/scpclient/scpclient.c index dae2afda..ecade33d 100644 --- a/examples/scpclient/scpclient.c +++ b/examples/scpclient/scpclient.c @@ -193,6 +193,10 @@ THREAD_RETURN WOLFSSH_THREAD scp_client(void* args) myoptind = 0; /* reset for test cases */ +#ifdef WOLFSSH_TERM + ClientUnbufferStdin(); +#endif + if (username == NULL) err_sys("client requires a username parameter."); diff --git a/examples/sftpclient/sftpclient.c b/examples/sftpclient/sftpclient.c index 2e4024c7..15d57d94 100644 --- a/examples/sftpclient/sftpclient.c +++ b/examples/sftpclient/sftpclient.c @@ -1719,6 +1719,10 @@ THREAD_RETURN WOLFSSH_THREAD sftpclient_test(void* args) } myoptind = 0; /* reset for test cases */ +#ifdef WOLFSSH_TERM + ClientUnbufferStdin(); +#endif + if (username == NULL) err_sys("client requires a username parameter."); diff --git a/scripts/sshclient.test b/scripts/sshclient.test index 4e8c2684..2feaa775 100755 --- a/scripts/sshclient.test +++ b/scripts/sshclient.test @@ -136,10 +136,9 @@ wait_for_output() { # Run the client with its stdin coming from a fifo. # -# The client answers its prompts with stdio, which buffers everything that -# is ready to be read, so anything written along with a prompt's answer is -# swallowed with it and never reaches the session. Writing each piece only -# once the client has asked for it keeps them in separate reads. The +# The client reads its prompt answers from an unbuffered stdin, so the +# session data can follow the password at once and is left in the fifo for +# the session. Each answer is still written only once its prompt is up. The # echoserver only ends the session when it receives a 0x03, so every # session has to send one or both ends wait for the other forever. # @@ -161,11 +160,6 @@ run_client() { wait_for_output "Password:" || exit 1 printf 'upthehill\n' - - # Let the client consume the password before sending the session - # data. A single read that catches both loses the data. - sleep 2 - printf 'hello\003' ) > "$input_file" 2>/dev/null & input_pid=$!