Skip to content

Commit 96e3b80

Browse files
committed
agent: let the application open the agent channel
The one server-side site that opens auth-agent@openssh.com sits inside wolfSSH_accept(), so an application driving its own channels cannot reach it: the session records the request and no channel follows. - add wolfSSH_AGENT_ChannelOpen(), the same open lifted out of accept(), which still calls it - it reports WS_BAD_ARGUMENT until the peer asks and is idempotent afterward, so an application can poll it - publish the agent on a queued open too, so a retry after WS_WANT_WRITE finds it rather than opening a second channel and leaking the first
1 parent 557f3df commit 96e3b80

3 files changed

Lines changed: 74 additions & 41 deletions

File tree

src/agent.c

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1731,6 +1731,71 @@ int wolfSSH_AGENT_enable(WOLFSSH* ssh, byte isEnabled)
17311731
}
17321732

17331733

1734+
int wolfSSH_AGENT_ChannelOpen(WOLFSSH* ssh)
1735+
{
1736+
WOLFSSH_AGENT_CTX* newAgent = NULL;
1737+
WOLFSSH_CHANNEL* newChannel = NULL;
1738+
int ret = WS_SUCCESS;
1739+
1740+
WLOG_ENTER();
1741+
1742+
if (ssh == NULL)
1743+
ret = WS_SSH_NULL_E;
1744+
else if (!ssh->useAgent) {
1745+
/* Nothing asked for agent forwarding on this session. */
1746+
ret = WS_BAD_ARGUMENT;
1747+
}
1748+
else if (ssh->agent == NULL) {
1749+
/* Server side sets ssh->agent here and nowhere else, so a NULL one
1750+
* is the "not opened yet" test. Idempotent so a caller polling for
1751+
* the peer's request cannot end up with two agent channels. */
1752+
WLOG(WS_LOG_AGENT, "Starting agent channel");
1753+
1754+
newAgent = wolfSSH_AGENT_new(ssh->ctx->heap);
1755+
if (newAgent == NULL)
1756+
ret = WS_MEMORY_E;
1757+
1758+
if (ret == WS_SUCCESS) {
1759+
newChannel = ChannelNew(ssh, ID_CHANTYPE_AUTH_AGENT,
1760+
ssh->ctx->windowSz, ssh->ctx->maxPacketSz);
1761+
if (newChannel == NULL)
1762+
ret = WS_MEMORY_E;
1763+
}
1764+
1765+
if (ret == WS_SUCCESS) {
1766+
ret = SendChannelOpenSession(ssh, newChannel);
1767+
1768+
if (ret < WS_SUCCESS
1769+
&& ret != WS_WANT_WRITE && ret != WS_WANT_READ) {
1770+
ChannelDelete(newChannel, ssh->ctx->heap);
1771+
}
1772+
else {
1773+
/* Publish the agent even when the open is only queued, so
1774+
* a retry takes the already-open path above rather than
1775+
* opening a second channel. */
1776+
ChannelAppend(ssh, newChannel);
1777+
newAgent->channel = newChannel->channel;
1778+
ssh->agent = newAgent;
1779+
newAgent = NULL;
1780+
if (ssh->ctx->agentCb) {
1781+
ssh->ctx->agentCb(WOLFSSH_AGENT_LOCAL_SETUP,
1782+
ssh->agentCbCtx);
1783+
}
1784+
}
1785+
}
1786+
1787+
if (newAgent != NULL)
1788+
wolfSSH_AGENT_free(newAgent);
1789+
}
1790+
1791+
if (ssh != NULL)
1792+
ssh->error = ret;
1793+
1794+
WLOG_LEAVE(ret);
1795+
return ret;
1796+
}
1797+
1798+
17341799
int wolfSSH_AGENT_worker(WOLFSSH* ssh)
17351800
{
17361801
int ret = WS_SUCCESS;

src/ssh.c

Lines changed: 1 addition & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -764,52 +764,12 @@ int wolfSSH_accept(WOLFSSH* ssh)
764764
#endif /* WOLFSSH_SFTP and !NO_WOLFSSH_SERVER */
765765
#ifdef WOLFSSH_AGENT
766766
if (ssh->useAgent) {
767-
WOLFSSH_AGENT_CTX* newAgent;
768-
WOLFSSH_CHANNEL* newChannel;
769-
770-
WLOG(WS_LOG_AGENT, "Starting agent channel");
771-
772-
newAgent = wolfSSH_AGENT_new(ssh->ctx->heap);
773-
if (newAgent == NULL) {
774-
ssh->error = WS_MEMORY_E;
775-
WLOG(WS_LOG_DEBUG, acceptError,
776-
"SERVER_USERAUTH_ACCEPT_DONE", ssh->error);
777-
return WS_ERROR;
778-
}
779-
780-
newChannel = ChannelNew(ssh, ID_CHANTYPE_AUTH_AGENT,
781-
ssh->ctx->windowSz, ssh->ctx->maxPacketSz);
782-
if (newChannel == NULL) {
783-
wolfSSH_AGENT_free(newAgent);
784-
ssh->error = WS_MEMORY_E;
785-
WLOG(WS_LOG_DEBUG, acceptError,
786-
"SERVER_USERAUTH_ACCEPT_DONE", ssh->error);
787-
return WS_FATAL_ERROR;
788-
}
789-
790-
ssh->error = SendChannelOpenSession(ssh, newChannel);
767+
ssh->error = wolfSSH_AGENT_ChannelOpen(ssh);
791768
if (ssh->error < WS_SUCCESS) {
792-
if (ssh->error == WS_WANT_WRITE ||
793-
ssh->error == WS_WANT_READ) {
794-
ChannelAppend(ssh, newChannel);
795-
}
796-
else {
797-
ChannelDelete(newChannel, ssh->ctx->heap);
798-
wolfSSH_AGENT_free(newAgent);
799-
}
800769
WLOG(WS_LOG_DEBUG, acceptError,
801770
"SERVER_USERAUTH_ACCEPT_DONE", ssh->error);
802771
return WS_FATAL_ERROR;
803772
}
804-
ChannelAppend(ssh, newChannel);
805-
newAgent->channel = newChannel->channel;
806-
if (ssh->ctx->agentCb) {
807-
ssh->ctx->agentCb(WOLFSSH_AGENT_LOCAL_SETUP,
808-
ssh->agentCbCtx);
809-
}
810-
if (ssh->agent != NULL)
811-
wolfSSH_AGENT_free(ssh->agent);
812-
ssh->agent = newAgent;
813773
}
814774
#endif /* WOLFSSH_AGENT */
815775
ssh->acceptState = ACCEPT_CLIENT_SESSION_ESTABLISHED;

wolfssh/agent.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,14 @@ WOLFSSH_API int wolfSSH_CTX_set_agent_cb(WOLFSSH_CTX* ctx,
181181
WOLFSSH_API int wolfSSH_set_agent_cb_ctx(WOLFSSH* ssh, void* ctx);
182182
WOLFSSH_API int wolfSSH_CTX_AGENT_enable(WOLFSSH_CTX* ctx, byte isEnabled);
183183
WOLFSSH_API int wolfSSH_AGENT_enable(WOLFSSH* ssh, byte isEnabled);
184+
/* Server side. Opens the auth-agent@openssh.com channel back to the client
185+
* once an auth-agent-req@openssh.com request has set the session up for it.
186+
* wolfSSH_accept() does this itself on the default path; an application that
187+
* drives its own channels returns from accept() before that point and calls
188+
* this instead. Idempotent, so it is safe to poll while waiting for the
189+
* peer's request. Returns WS_SUCCESS, or WS_BAD_ARGUMENT when the session
190+
* never asked for agent forwarding. */
191+
WOLFSSH_API int wolfSSH_AGENT_ChannelOpen(WOLFSSH* ssh);
184192
WOLFSSH_LOCAL int wolfSSH_AGENT_worker(WOLFSSH* ssh);
185193
WOLFSSH_API int wolfSSH_AGENT_Relay(WOLFSSH* ssh,
186194
const byte* msg, word32* msgSz, byte* rsp, word32* rspSz);

0 commit comments

Comments
 (0)