Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
95 changes: 60 additions & 35 deletions apps/wolfssh/wolfssh.c
Original file line number Diff line number Diff line change
Expand Up @@ -263,13 +263,6 @@ static void modes_reset(void)

#ifndef WOLFSSL_NUCLEUS

#if defined(WOLFSSH_AGENT)
static inline void ato32(const byte* c, word32* u32)
{
*u32 = (c[0] << 24) | (c[1] << 16) | (c[2] << 8) | c[3];
}
#endif

typedef struct thread_args {
WOLFSSH* ssh;
wolfSSL_Mutex lock;
Expand Down Expand Up @@ -582,6 +575,18 @@ static THREAD_RET readInput(void* in)
}


#ifdef WOLFSSH_AGENT
/* Statuses that say the relay still owes a reply rather than failing. */
static int AgentRelayHeld(int code, int* wantsWrite)
{
*wantsWrite = (code == WS_WANT_WRITE);
return code == WS_WANT_WRITE || code == WS_WINDOW_FULL
|| code == WS_REKEYING;
Comment thread
yosuke-wolfssl marked this conversation as resolved.
}


#endif

static THREAD_RET readPeer(void* in)
{
byte buf[256];
Expand All @@ -595,8 +600,14 @@ static THREAD_RET readPeer(void* in)
HANDLE stdoutHandle = GetStdHandle(STD_OUTPUT_HANDLE);
#endif
fd_set readSet;
fd_set writeSet;
fd_set errSet;
struct timeval timeout;
#ifdef WOLFSSH_AGENT
word32 agentChannel = 0;
int agentOwed = 0;
int agentWantsWrite = 0;
#endif

#ifdef USE_WINDOWS_API
if (args->rawMode == 0) {
Expand Down Expand Up @@ -630,13 +641,19 @@ static THREAD_RET readPeer(void* in)
(void)windowMonitor(args);
#endif
FD_ZERO(&readSet);
FD_ZERO(&writeSet);
FD_ZERO(&errSet);
FD_SET(fd, &readSet);
FD_SET(fd, &errSet);

#ifdef WOLFSSH_AGENT
if (agentWantsWrite)
FD_SET(fd, &writeSet);
#endif

timeout.tv_sec = 1;
timeout.tv_usec = 0;
bytes = select(fd + 1, &readSet, NULL, &errSet, &timeout);
bytes = select(fd + 1, &readSet, &writeSet, &errSet, &timeout);
if (bytes < 0) {
#ifdef USE_WINDOWS_API
if (WSAGetLastError() == WSAEINTR)
Expand All @@ -659,6 +676,19 @@ static THREAD_RET readPeer(void* in)
FD_SET(fd, &readSet);
}
wc_LockMutex(&args->lock);
#ifdef WOLFSSH_AGENT
/* Retry the owed reply on any wake */
if (agentOwed && !stop) {
int relayRet = wolfSSH_AGENT_RelayChannel(args->ssh, agentChannel);

agentOwed = AgentRelayHeld(relayRet, &agentWantsWrite);
if (relayRet < 0 && !agentOwed) {
args->readError = relayRet;
stop = 1;
bytes = 0;
}
}
#endif
while (bytes > 0 && (FD_ISSET(fd, &readSet) || FD_ISSET(fd, &errSet))) {
/* there is something to read off the wire */
WMEMSET(buf, 0, bufSz);
Expand Down Expand Up @@ -687,36 +717,31 @@ static THREAD_RET readPeer(void* in)
}
#ifdef WOLFSSH_AGENT
else if (err == WS_CHAN_RXD) {
byte agentBuf[512];
int rxd, txd;
word32 channel = 0;

wolfSSH_GetLastRxId(args->ssh, &channel);
rxd = wolfSSH_ChannelIdRead(args->ssh, channel,
agentBuf, sizeof(agentBuf));
if (rxd > 4) {
word32 msgSz = 0;

ato32(agentBuf, &msgSz);
if (msgSz > (word32)rxd - 4) {
rxd += wolfSSH_ChannelIdRead(args->ssh, channel,
agentBuf + rxd,
sizeof(agentBuf) - rxd);
}

txd = rxd;
rxd = sizeof(agentBuf);
ret = wolfSSH_AGENT_Relay(args->ssh,
agentBuf, (word32*)&txd,
agentBuf, (word32*)&rxd);
if (ret == WS_SUCCESS) {
ret = wolfSSH_ChannelIdSend(args->ssh, channel,
agentBuf, rxd);
}
}
WMEMSET(agentBuf, 0, sizeof(agentBuf));
continue;
if (wolfSSH_GetLastRxId(args->ssh, &channel)
== WS_SUCCESS) {
ret = wolfSSH_AGENT_RelayChannel(args->ssh, channel);
agentChannel = channel;
Comment thread
yosuke-wolfssl marked this conversation as resolved.
agentOwed = AgentRelayHeld(ret, &agentWantsWrite);
Comment thread
yosuke-wolfssl marked this conversation as resolved.
}
else {
ret = WS_FATAL_ERROR;
agentOwed = 0;
}
if (ret < 0 && !agentOwed) {
/* Stop the read thread; the channel is no longer
* safe to send on. */
args->readError = ret;
stop = 1;
bytes = 0;
}
/* Back to select(), which is where the owed reply is
* retried. */
if (agentOwed)
bytes = 0;
continue;
}
#endif /* WOLFSSH_AGENT */
else if (err == WS_CBIO_ERR_CONN_CLOSE ||
err == WS_SOCKET_ERROR_E ||
Expand Down
91 changes: 62 additions & 29 deletions examples/client/client.c
Original file line number Diff line number Diff line change
Expand Up @@ -401,11 +401,16 @@ static THREAD_RET readInput(void* in)
return THREAD_RET_SUCCESS;
}

#if defined(WOLFSSH_AGENT)
static inline void ato32(const byte* c, word32* u32)
#ifdef WOLFSSH_AGENT
/* Statuses that say the relay still owes a reply rather than failing. */
static int AgentRelayHeld(int code, int* wantsWrite)
{
*u32 = (c[0] << 24) | (c[1] << 16) | (c[2] << 8) | c[3];
*wantsWrite = (code == WS_WANT_WRITE);
return code == WS_WANT_WRITE || code == WS_WINDOW_FULL
|| code == WS_REKEYING;
Comment thread
yosuke-wolfssl marked this conversation as resolved.
}


#endif

static THREAD_RET readPeer(void* in)
Expand All @@ -420,7 +425,14 @@ static THREAD_RET readPeer(void* in)
HANDLE stdoutHandle = GetStdHandle(STD_OUTPUT_HANDLE);
#endif
fd_set readSet;
fd_set writeSet;
fd_set errSet;
#ifdef WOLFSSH_AGENT
struct timeval timeout;
word32 agentChannel = 0;
int agentOwed = 0;
int agentWantsWrite = 0;
#endif

#ifdef USE_WINDOWS_API
if (args->rawMode == 0) {
Expand Down Expand Up @@ -456,11 +468,26 @@ static THREAD_RET readPeer(void* in)

/* select() clears the sets, re-arm them every pass. */
FD_ZERO(&readSet);
FD_ZERO(&writeSet);
FD_ZERO(&errSet);
FD_SET(fd, &readSet);
FD_SET(fd, &errSet);

bytes = select(fd + 1, &readSet, NULL, &errSet, NULL);
#ifdef WOLFSSH_AGENT
/* Only a reply the transport is holding waits on a writable socket.
* One held by the peer's window or a rekey waits on the timeout. */
if (agentWantsWrite)
FD_SET(fd, &writeSet);

/* Time out so an owed reply is retried on a silent peer. Without one
* the wait stays event driven. */
timeout.tv_sec = 1;
timeout.tv_usec = 0;
bytes = select(fd + 1, &readSet, &writeSet, &errSet,
agentOwed ? &timeout : NULL);
#else
bytes = select(fd + 1, &readSet, &writeSet, &errSet, NULL);
#endif
if (bytes < 0) {
#ifdef USE_WINDOWS_API
if (WSAGetLastError() == WSAEINTR)
Expand All @@ -475,6 +502,18 @@ static THREAD_RET readPeer(void* in)
break;
}
wc_LockMutex(&args->lock);
#ifdef WOLFSSH_AGENT
/* Retry the owed reply on any wake */
if (agentOwed) {
int relayRet = wolfSSH_AGENT_RelayChannel(args->ssh, agentChannel);

agentOwed = AgentRelayHeld(relayRet, &agentWantsWrite);
if (relayRet < 0 && !agentOwed) {
wc_UnLockMutex(&args->lock);
break;
}
}
#endif
while (bytes > 0 && (FD_ISSET(fd, &readSet) || FD_ISSET(fd, &errSet))) {
/* there is something to read off the wire */
WMEMSET(buf, 0, bufSz);
Expand Down Expand Up @@ -504,34 +543,28 @@ static THREAD_RET readPeer(void* in)
}
#ifdef WOLFSSH_AGENT
else if (ret == WS_CHAN_RXD) {
byte agentBuf[512];
int rxd, txd;
word32 channel = 0;

wolfSSH_GetLastRxId(args->ssh, &channel);
rxd = wolfSSH_ChannelIdRead(args->ssh, channel,
agentBuf, sizeof(agentBuf));
if (rxd > 4) {
word32 msgSz = 0;

ato32(agentBuf, &msgSz);
if (msgSz > (word32)rxd - 4) {
rxd += wolfSSH_ChannelIdRead(args->ssh, channel,
agentBuf + rxd,
sizeof(agentBuf) - rxd);
}

txd = rxd;
rxd = sizeof(agentBuf);
ret = wolfSSH_AGENT_Relay(args->ssh,
agentBuf, (word32*)&txd,
agentBuf, (word32*)&rxd);
if (ret == WS_SUCCESS) {
ret = wolfSSH_ChannelIdSend(args->ssh, channel,
agentBuf, rxd);
}
if (wolfSSH_GetLastRxId(args->ssh, &channel)
== WS_SUCCESS) {
ret = wolfSSH_AGENT_RelayChannel(args->ssh,
channel);
Comment thread
yosuke-wolfssl marked this conversation as resolved.
agentChannel = channel;
agentOwed = AgentRelayHeld(ret, &agentWantsWrite);
Comment thread
yosuke-wolfssl marked this conversation as resolved.
}
else {
ret = WS_FATAL_ERROR;
agentOwed = 0;
}
if (ret < 0 && !agentOwed) {
/* Leave the read loop; the channel is no
* longer safe to send on. */
break;
}
WMEMSET(agentBuf, 0, sizeof(agentBuf));
/* Back to select(), which is where the owed reply
* is retried. */
if (agentOwed)
bytes = 0;
continue;
}
#endif /* WOLFSSH_AGENT */
Expand Down
Loading
Loading