mirror of https://github.com/wolfSSL/wolfssh.git
Unbuffer stdin before a client password prompt
The password prompt reads stdin with fgets(), and a buffered stdin keeps its own copy of the line in libc for the life of the process. The clients make stdin unbuffered before any stdin I/O, so the typed password lands only in the buffer ClientUserAuth() wipes. - the wolfssh app, and the example client, sftp client and scp client whether or not -P was given, as keyboard-interactive reads stdin too - ClientUnbufferStdin() acts once per process and reports a failure - scripts/sshclient.test sends the session data right after the password, with no sleep Issue: F-15669pull/1360/merge
parent
9e206dd2f1
commit
b05fe9f4c9
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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.");
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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.");
|
||||
|
||||
|
|
|
|||
|
|
@ -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.");
|
||||
|
||||
|
|
|
|||
|
|
@ -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=$!
|
||||
|
|
|
|||
Loading…
Reference in New Issue