From 91a545fa15dd62b0234bac11e56d9478cb996e01 Mon Sep 17 00:00:00 2001 From: John Safranek Date: Wed, 17 Jan 2024 21:59:33 -0800 Subject: [PATCH 1/9] Channel Callbacks (Open) 1. Add the new Channel Open callback support APIs. --- src/internal.c | 3 +++ src/ssh.c | 38 ++++++++++++++++++++++++++++++++++++++ wolfssh/internal.h | 2 ++ wolfssh/ssh.h | 6 ++++++ 4 files changed, 49 insertions(+) diff --git a/src/internal.c b/src/internal.c index bcf7e6b1a..e50912aa4 100644 --- a/src/internal.c +++ b/src/internal.c @@ -7761,6 +7761,9 @@ static int DoChannelOpen(WOLFSSH* ssh, else { ChannelUpdatePeer(newChannel, peerChannelId, peerInitialWindowSz, peerMaxPacketSz); + if (ssh->ctx->channelOpenCb) { + ret = ssh->ctx->channelOpenCb(newChannel, ssh->channelOpenCtx); + } if (ssh->channelListSz == 0) ssh->defaultPeerChannelId = peerChannelId; #ifdef WOLFSSH_FWD diff --git a/src/ssh.c b/src/ssh.c index 563e2d421..9e72678e5 100644 --- a/src/ssh.c +++ b/src/ssh.c @@ -3049,6 +3049,44 @@ void wolfSSH_SetKeyingCompletionCbCtx(WOLFSSH* ssh, void* ctx) } +int wolfSSH_CTX_SetChannelOpenCb(WOLFSSH_CTX* ctx, WS_CallbackChannelOpen cb) +{ + int ret = WS_SSH_CTX_NULL_E; + + if (ctx != NULL) { + ctx->channelOpenCb = cb; + ret = WS_SUCCESS; + } + + return ret; +} + + +int wolfSSH_SetChannelOpenCtx(WOLFSSH* ssh, void* ctx) +{ + int ret = WS_SSH_NULL_E; + + if (ssh != NULL) { + ssh->channelOpenCtx = ctx; + ret = WS_SUCCESS; + } + + return ret; +} + + +void* wolfSSH_GetChannelOpenCtx(WOLFSSH* ssh) +{ + void* ctx = NULL; + + if (ssh != NULL) { + ctx = ssh->channelOpenCtx; + } + + return ctx; +} + + #if (defined(WOLFSSH_SFTP) || defined(WOLFSSH_SCP)) && \ !defined(NO_WOLFSSH_SERVER) diff --git a/wolfssh/internal.h b/wolfssh/internal.h index 680555de6..a83511da2 100644 --- a/wolfssh/internal.h +++ b/wolfssh/internal.h @@ -498,6 +498,7 @@ struct WOLFSSH_CTX { WS_CallbackGlobalReq globalReqCb; /* Global Request Callback */ WS_CallbackReqSuccess reqSuccessCb; /* Global Request Success Callback */ WS_CallbackReqSuccess reqFailureCb; /* Global Request Failure Callback */ + WS_CallbackChannelOpen channelOpenCb; #ifdef WOLFSSH_SCP WS_CallbackScpRecv scpRecvCb; /* SCP receive callback */ WS_CallbackScpSend scpSendCb; /* SCP send callback */ @@ -662,6 +663,7 @@ struct WOLFSSH { void* globalReqCtx; /* Global Request CB context */ void* reqSuccessCtx; /* Global Request Sucess CB context */ void* reqFailureCtx; /* Global Request Failure CB context */ + void* channelOpenCtx; /* Channel Open CB context */ void* fs; /* File system handle */ word32 curSz; word32 seq; diff --git a/wolfssh/ssh.h b/wolfssh/ssh.h index caee02547..63d1ea9b1 100644 --- a/wolfssh/ssh.h +++ b/wolfssh/ssh.h @@ -210,6 +210,12 @@ WOLFSSH_API int wolfSSH_ChannelSend(WOLFSSH_CHANNEL*, const byte*, word32); WOLFSSH_API int wolfSSH_ChannelExit(WOLFSSH_CHANNEL*); WOLFSSH_API int wolfSSH_ChannelGetEof(WOLFSSH_CHANNEL*); +/* Channel callbacks */ +typedef int (*WS_CallbackChannelOpen)(WOLFSSH_CHANNEL* channel, void* ctx); +WOLFSSH_API int wolfSSH_CTX_SetChannelOpenCb(WOLFSSH_CTX* ctx, + WS_CallbackChannelOpen cb); +WOLFSSH_API int wolfSSH_SetChannelOpenCtx(WOLFSSH* ssh, void* ctx); +WOLFSSH_API void* wolfSSH_GetChannelOpenCtx(WOLFSSH* ssh); WOLFSSH_API int wolfSSH_get_error(const WOLFSSH*); WOLFSSH_API const char* wolfSSH_get_error_name(const WOLFSSH*); From bb0809ceca75cd199d5e449bae508b0164cc7cca Mon Sep 17 00:00:00 2001 From: John Safranek Date: Wed, 31 Jan 2024 14:29:16 -0800 Subject: [PATCH 2/9] Channel Callbacks (Open Conf and Open Fail) 1. Add channel open callback APIs to support two client callback functions, Channel Open Conf and Fail. --- src/internal.c | 20 ++++++++++++++++++++ src/ssh.c | 15 +++++++++++++++ wolfssh/internal.h | 2 ++ wolfssh/ssh.h | 2 ++ 4 files changed, 39 insertions(+) diff --git a/src/internal.c b/src/internal.c index e50912aa4..938e67eff 100644 --- a/src/internal.c +++ b/src/internal.c @@ -7859,6 +7859,12 @@ static int DoChannelOpenConf(WOLFSSH* ssh, ret = ChannelUpdatePeer(channel, peerChannelId, peerInitialWindowSz, peerMaxPacketSz); + if (ret == WS_SUCCESS) { + if (ssh->ctx->channelOpenConfCb != NULL) { + ret = ssh->ctx->channelOpenConfCb(channel, ssh->channelOpenCtx); + } + } + if (ret == WS_SUCCESS) { ssh->serverState = SERVER_CHANNEL_OPEN_DONE; ssh->defaultPeerChannelId = peerChannelId; @@ -7872,6 +7878,7 @@ static int DoChannelOpenConf(WOLFSSH* ssh, static int DoChannelOpenFail(WOLFSSH* ssh, byte* buf, word32 len, word32* idx) { + WOLFSSH_CHANNEL* channel = NULL; char desc[80]; word32 begin, channelId, reasonId, descSz, langSz; int ret = WS_SUCCESS; @@ -7905,6 +7912,19 @@ static int DoChannelOpenFail(WOLFSSH* ssh, WLOG(WS_LOG_INFO, "description: %s", desc); } + if (ssh->ctx->channelOpenFailCb != NULL) { + channel = ChannelFind(ssh, channelId, WS_CHANNEL_ID_SELF); + + if (channel != NULL) { + ret = ssh->ctx->channelOpenFailCb(channel, ssh->channelOpenCtx); + } + else { + ret = WS_INVALID_CHANID; + } + } + } + + if (ret == WS_SUCCESS) { ret = ChannelRemove(ssh, channelId, WS_CHANNEL_ID_SELF); } diff --git a/src/ssh.c b/src/ssh.c index 9e72678e5..087e9b0ac 100644 --- a/src/ssh.c +++ b/src/ssh.c @@ -3062,6 +3062,21 @@ int wolfSSH_CTX_SetChannelOpenCb(WOLFSSH_CTX* ctx, WS_CallbackChannelOpen cb) } +int wolfSSH_CTX_SetChannelOpenRespCb(WOLFSSH_CTX* ctx, + WS_CallbackChannelOpen confCb, WS_CallbackChannelOpen failCb) +{ + int ret = WS_SSH_CTX_NULL_E; + + if (ctx != NULL) { + ctx->channelOpenConfCb = confCb; + ctx->channelOpenFailCb = failCb; + ret = WS_SUCCESS; + } + + return ret; +} + + int wolfSSH_SetChannelOpenCtx(WOLFSSH* ssh, void* ctx) { int ret = WS_SSH_NULL_E; diff --git a/wolfssh/internal.h b/wolfssh/internal.h index a83511da2..0bcb7fff0 100644 --- a/wolfssh/internal.h +++ b/wolfssh/internal.h @@ -499,6 +499,8 @@ struct WOLFSSH_CTX { WS_CallbackReqSuccess reqSuccessCb; /* Global Request Success Callback */ WS_CallbackReqSuccess reqFailureCb; /* Global Request Failure Callback */ WS_CallbackChannelOpen channelOpenCb; + WS_CallbackChannelOpen channelOpenConfCb; + WS_CallbackChannelOpen channelOpenFailCb; #ifdef WOLFSSH_SCP WS_CallbackScpRecv scpRecvCb; /* SCP receive callback */ WS_CallbackScpSend scpSendCb; /* SCP send callback */ diff --git a/wolfssh/ssh.h b/wolfssh/ssh.h index 63d1ea9b1..141434a03 100644 --- a/wolfssh/ssh.h +++ b/wolfssh/ssh.h @@ -214,6 +214,8 @@ WOLFSSH_API int wolfSSH_ChannelGetEof(WOLFSSH_CHANNEL*); typedef int (*WS_CallbackChannelOpen)(WOLFSSH_CHANNEL* channel, void* ctx); WOLFSSH_API int wolfSSH_CTX_SetChannelOpenCb(WOLFSSH_CTX* ctx, WS_CallbackChannelOpen cb); +WOLFSSH_API int wolfSSH_CTX_SetChannelOpenRespCb(WOLFSSH_CTX* ctx, + WS_CallbackChannelOpen confCb, WS_CallbackChannelOpen failCb); WOLFSSH_API int wolfSSH_SetChannelOpenCtx(WOLFSSH* ssh, void* ctx); WOLFSSH_API void* wolfSSH_GetChannelOpenCtx(WOLFSSH* ssh); From 45d5e916e42b594ff6aa9d4142765737b3445c14 Mon Sep 17 00:00:00 2001 From: John Safranek Date: Wed, 21 Feb 2024 11:41:31 -0800 Subject: [PATCH 3/9] Channel Callbacks (EOF and Close) 1. Added callbacks for receiving a Channel EOF message and a Channel Close message. 2. Added accessors for the new callback's ctx parameters. 3. Add some missing comments on the channel open callbacks. --- src/ssh.c | 101 +++++++++++++++++++++++++++++++++++++++++++++ wolfssh/internal.h | 14 +++++-- wolfssh/ssh.h | 19 +++++++++ 3 files changed, 130 insertions(+), 4 deletions(-) diff --git a/src/ssh.c b/src/ssh.c index 087e9b0ac..4238abe69 100644 --- a/src/ssh.c +++ b/src/ssh.c @@ -3102,6 +3102,107 @@ void* wolfSSH_GetChannelOpenCtx(WOLFSSH* ssh) } +int wolfSSH_SetChannelReqCtx(WOLFSSH* ssh, void* ctx) +{ + int ret = WS_SSH_NULL_E; + + if (ssh != NULL) { + ssh->channelReqCtx = ctx; + ret = WS_SUCCESS; + } + + return ret; +} + + +void* wolfSSH_GetChannelReqCtx(WOLFSSH* ssh) +{ + void* ctx = NULL; + + if (ssh != NULL) { + ctx = ssh->channelReqCtx; + } + + return ctx; +} + + +int wolfSSH_CTX_SetChannelEofCb(WOLFSSH_CTX* ctx, WS_CallbackChannelEof cb) +{ + int ret = WS_SSH_CTX_NULL_E; + + if (ctx != NULL) { + ctx->channelEofCb = cb; + ret = WS_SUCCESS; + } + + return ret; +} + + +int wolfSSH_SetChannelEofCtx(WOLFSSH* ssh, void* ctx) +{ + int ret = WS_SSH_NULL_E; + + if (ssh != NULL) { + ssh->channelEofCtx = ctx; + ret = WS_SUCCESS; + } + + return ret; +} + + +void* wolfSSH_GetChannelEofCtx(WOLFSSH* ssh) +{ + void* ctx = NULL; + + if (ssh != NULL) { + ctx = ssh->channelEofCtx; + } + + return ctx; +} + + +int wolfSSH_CTX_SetChannelCloseCb(WOLFSSH_CTX* ctx, WS_CallbackChannelClose cb) +{ + int ret = WS_SSH_CTX_NULL_E; + + if (ctx != NULL) { + ctx->channelCloseCb = cb; + ret = WS_SUCCESS; + } + + return ret; +} + + +int wolfSSH_SetChannelCloseCtx(WOLFSSH* ssh, void* ctx) +{ + int ret = WS_SSH_NULL_E; + + if (ssh != NULL) { + ssh->channelCloseCtx = ctx; + ret = WS_SUCCESS; + } + + return ret; +} + + +void* wolfSSH_GetChannelCloseCtx(WOLFSSH* ssh) +{ + void* ctx = NULL; + + if (ssh != NULL) { + ctx = ssh->channelCloseCtx; + } + + return ctx; +} + + #if (defined(WOLFSSH_SFTP) || defined(WOLFSSH_SCP)) && \ !defined(NO_WOLFSSH_SERVER) diff --git a/wolfssh/internal.h b/wolfssh/internal.h index 0bcb7fff0..3d728d17d 100644 --- a/wolfssh/internal.h +++ b/wolfssh/internal.h @@ -498,9 +498,12 @@ struct WOLFSSH_CTX { WS_CallbackGlobalReq globalReqCb; /* Global Request Callback */ WS_CallbackReqSuccess reqSuccessCb; /* Global Request Success Callback */ WS_CallbackReqSuccess reqFailureCb; /* Global Request Failure Callback */ - WS_CallbackChannelOpen channelOpenCb; - WS_CallbackChannelOpen channelOpenConfCb; - WS_CallbackChannelOpen channelOpenFailCb; + WS_CallbackChannelOpen channelOpenCb; /* Channel Open Requested */ + WS_CallbackChannelOpen channelOpenConfCb; /* Channel Open Confirm */ + WS_CallbackChannelOpen channelOpenFailCb; /* Channel Open Fail */ + WS_CallbackChannelReqShell channelReqShellCb; /* Channel Request "Shell" */ + WS_CallbackChannelEof channelEofCb; /* Channel Eof Callback */ + WS_CallbackChannelClose channelCloseCb; /* Channel Close Callback */ #ifdef WOLFSSH_SCP WS_CallbackScpRecv scpRecvCb; /* SCP receive callback */ WS_CallbackScpSend scpSendCb; /* SCP send callback */ @@ -661,11 +664,14 @@ struct WOLFSSH { word32 rxCount; word32 highwaterMark; byte highwaterFlag; /* Set when highwater CB called */ - void* highwaterCtx; + void* highwaterCtx; /* Highwater CB context */ void* globalReqCtx; /* Global Request CB context */ void* reqSuccessCtx; /* Global Request Sucess CB context */ void* reqFailureCtx; /* Global Request Failure CB context */ void* channelOpenCtx; /* Channel Open CB context */ + void* channelReqCtx; /* Channel Request CB context */ + void* channelEofCtx; /* Channel EOF CB context */ + void* channelCloseCtx; /* Channel Close CB context */ void* fs; /* File system handle */ word32 curSz; word32 seq; diff --git a/wolfssh/ssh.h b/wolfssh/ssh.h index 141434a03..e23acbaf9 100644 --- a/wolfssh/ssh.h +++ b/wolfssh/ssh.h @@ -219,6 +219,25 @@ WOLFSSH_API int wolfSSH_CTX_SetChannelOpenRespCb(WOLFSSH_CTX* ctx, WOLFSSH_API int wolfSSH_SetChannelOpenCtx(WOLFSSH* ssh, void* ctx); WOLFSSH_API void* wolfSSH_GetChannelOpenCtx(WOLFSSH* ssh); +typedef int (*WS_CallbackChannelReqShell)(WOLFSSH_CHANNEL* channel, + void* ctx); +WOLFSSH_API int wolfSSH_CTX_SetChannelReqShellCb(WOLFSSH_CTX* ctx, + WS_CallbackChannelReqShell cb); +WOLFSSH_API int wolfSSH_SetChannelReqCtx(WOLFSSH* ssh, void* ctx); +WOLFSSH_API void* wolfSSH_GetChannelReqCtx(WOLFSSH* ssh); + +typedef int (*WS_CallbackChannelEof)(WOLFSSH_CHANNEL* channel, void* ctx); +WOLFSSH_API int wolfSSH_CTX_SetChannelEofCb(WOLFSSH_CTX* ctx, + WS_CallbackChannelEof cb); +WOLFSSH_API int wolfSSH_SetChannelEofCtx(WOLFSSH* ssh, void* ctx); +WOLFSSH_API void* wolfSSH_GetChannelEofCtx(WOLFSSH* ssh); + +typedef int (*WS_CallbackChannelClose)(WOLFSSH_CHANNEL* channel, void* ctx); +WOLFSSH_API int wolfSSH_CTX_SetChannelCloseCb(WOLFSSH_CTX* ctx, + WS_CallbackChannelClose cb); +WOLFSSH_API int wolfSSH_SetChannelCloseCtx(WOLFSSH* ssh, void* ctx); +WOLFSSH_API void* wolfSSH_GetChannelCloseCtx(WOLFSSH* ssh); + WOLFSSH_API int wolfSSH_get_error(const WOLFSSH*); WOLFSSH_API const char* wolfSSH_get_error_name(const WOLFSSH*); WOLFSSH_API const char* wolfSSH_ErrorToName(int); From 06b70db8f47941271f3195e726372ec6e58d040b Mon Sep 17 00:00:00 2001 From: John Safranek Date: Thu, 8 Feb 2024 13:25:37 -0800 Subject: [PATCH 4/9] Channel Callbacks (Request Shell) 1. Add callback for the "shell" Channel Request message for the server. 2. Whitespace and braces changes. 3. Relabel the string for administratively prohibited channel opens. 4. Add some comment. --- src/internal.c | 16 +++++++++++----- src/ssh.c | 14 ++++++++++++++ 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/src/internal.c b/src/internal.c index 938e67eff..e43f88cae 100644 --- a/src/internal.c +++ b/src/internal.c @@ -7794,16 +7794,18 @@ static int DoChannelOpen(WOLFSSH* ssh, const char *description = NULL; if (fail_reason == OPEN_ADMINISTRATIVELY_PROHIBITED) - description = "Each session cannot have more than one channel open."; + description = "Administratively prohibited."; else if (fail_reason == OPEN_UNKNOWN_CHANNEL_TYPE) description = "Channel type not supported."; else if (fail_reason == OPEN_RESOURCE_SHORTAGE) description = "Not enough resources."; - if (description != NULL) - ret = SendChannelOpenFail(ssh, peerChannelId, fail_reason, description, "en"); + if (description != NULL) { + ret = SendChannelOpenFail(ssh, peerChannelId, + fail_reason, description, "en"); + } else - ret = SendRequestSuccess(ssh, 0); + ret = SendRequestSuccess(ssh, 0); /* XXX Is this right? */ } #ifdef WOLFSSH_FWD @@ -8357,6 +8359,9 @@ static int DoChannelRequest(WOLFSSH* ssh, } else if (WSTRNCMP(type, "shell", typeSz) == 0) { channel->sessionType = WOLFSSH_SESSION_SHELL; + if (ssh->ctx->channelReqShellCb) { + ssh->ctx->channelReqShellCb(channel, ssh->channelReqCtx); + } ssh->clientState = CLIENT_DONE; } else if (WSTRNCMP(type, "exec", typeSz) == 0) { @@ -8451,8 +8456,9 @@ static int DoChannelRequest(WOLFSSH* ssh, #endif } - if (ret == WS_SUCCESS) + if (ret == WS_SUCCESS) { *idx = len; + } if (wantReply) { int replyRet; diff --git a/src/ssh.c b/src/ssh.c index 4238abe69..d39bc17a8 100644 --- a/src/ssh.c +++ b/src/ssh.c @@ -3077,6 +3077,20 @@ int wolfSSH_CTX_SetChannelOpenRespCb(WOLFSSH_CTX* ctx, } +int wolfSSH_CTX_SetChannelReqShellCb(WOLFSSH_CTX* ctx, + WS_CallbackChannelReqShell cb) +{ + int ret = WS_SSH_CTX_NULL_E; + + if (ctx != NULL) { + ctx->channelReqShellCb = cb; + ret = WS_SUCCESS; + } + + return ret; +} + + int wolfSSH_SetChannelOpenCtx(WOLFSSH* ssh, void* ctx) { int ret = WS_SSH_NULL_E; From e1a5ffd231e9910bd14a9a9a00be79c432224e4b Mon Sep 17 00:00:00 2001 From: John Safranek Date: Wed, 21 Feb 2024 18:51:43 -0800 Subject: [PATCH 5/9] Channel Callbacks (EOF and Close) 1. Add checks for the Channel EOF or Close callbacks to the Do functions for those messages, and call them. --- src/internal.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/internal.c b/src/internal.c index e43f88cae..11e8bc5c1 100644 --- a/src/internal.c +++ b/src/internal.c @@ -7958,6 +7958,12 @@ static int DoChannelEof(WOLFSSH* ssh, ret = WS_INVALID_CHANID; } + if (ret == WS_SUCCESS) { + if (ssh->ctx->channelEofCb) { + ssh->ctx->channelEofCb(channel, ssh->channelEofCtx); + } + } + if (ret == WS_SUCCESS) { channel->eofRxd = 1; if (!channel->eofTxd) { @@ -7991,6 +7997,12 @@ static int DoChannelClose(WOLFSSH* ssh, ret = WS_INVALID_CHANID; } + if (ret == WS_SUCCESS) { + if (ssh->ctx->channelCloseCb) { + ssh->ctx->channelCloseCb(channel, ssh->channelCloseCtx); + } + } + if (ret == WS_SUCCESS) { if (!channel->closeTxd) { ret = SendChannelClose(ssh, channel->peerChannel); From 5d40f8af62c36e2a8d52cf647425a284b67a3772 Mon Sep 17 00:00:00 2001 From: John Safranek Date: Mon, 11 Mar 2024 09:26:02 -0700 Subject: [PATCH 6/9] Channel Callbacks (Get Session Type and Command) 1. Move the session types earlier in the ssh.h header. 2. Add functions wolfSSH_ChannelGetSessionType() and wolfSSH_ChannelGetSessionCommand() to requestion information about a session. --- src/internal.c | 3 +++ src/ssh.c | 44 +++++++++++++++++++++++++++++++++++++++++++- wolfssh/internal.h | 3 ++- wolfssh/ssh.h | 27 +++++++++++++++++---------- 4 files changed, 65 insertions(+), 12 deletions(-) diff --git a/src/internal.c b/src/internal.c index 11e8bc5c1..9e8843c40 100644 --- a/src/internal.c +++ b/src/internal.c @@ -8388,6 +8388,9 @@ static int DoChannelRequest(WOLFSSH* ssh, ret = GetStringAlloc(ssh->ctx->heap, &channel->command, buf, len, &begin); channel->sessionType = WOLFSSH_SESSION_SUBSYSTEM; + if (ssh->ctx->channelReqSubsysCb) { + ssh->ctx->channelReqSubsysCb(channel, ssh->channelReqCtx); + } ssh->clientState = CLIENT_DONE; WLOG(WS_LOG_DEBUG, " subsystem = %s", channel->command); diff --git a/src/ssh.c b/src/ssh.c index d39bc17a8..1fbec64af 100644 --- a/src/ssh.c +++ b/src/ssh.c @@ -3049,6 +3049,34 @@ void wolfSSH_SetKeyingCompletionCbCtx(WOLFSSH* ssh, void* ctx) } +WS_SessionType wolfSSH_ChannelGetSessionType(const WOLFSSH_CHANNEL* channel) +{ + WS_SessionType type = WOLFSSH_SESSION_UNKNOWN; + + WLOG(WS_LOG_DEBUG, "Entering wolfSSH_ChannelGetType()"); + + if (channel) { + type = (WS_SessionType)channel->sessionType; + } + + return type; +} + + +const char* wolfSSH_ChannelGetSessionCommand(const WOLFSSH_CHANNEL* channel) +{ + const char* cmd = NULL; + + WLOG(WS_LOG_DEBUG, "Entering wolfSSH_ChannelGetCommand()"); + + if (channel) { + cmd = channel->command; + } + + return cmd; +} + + int wolfSSH_CTX_SetChannelOpenCb(WOLFSSH_CTX* ctx, WS_CallbackChannelOpen cb) { int ret = WS_SSH_CTX_NULL_E; @@ -3078,7 +3106,7 @@ int wolfSSH_CTX_SetChannelOpenRespCb(WOLFSSH_CTX* ctx, int wolfSSH_CTX_SetChannelReqShellCb(WOLFSSH_CTX* ctx, - WS_CallbackChannelReqShell cb) + WS_CallbackChannelReq cb) { int ret = WS_SSH_CTX_NULL_E; @@ -3091,6 +3119,20 @@ int wolfSSH_CTX_SetChannelReqShellCb(WOLFSSH_CTX* ctx, } +int wolfSSH_CTX_SetChannelReqSubsysCb(WOLFSSH_CTX* ctx, + WS_CallbackChannelReq cb) +{ + int ret = WS_SSH_CTX_NULL_E; + + if (ctx != NULL) { + ctx->channelReqSubsysCb = cb; + ret = WS_SUCCESS; + } + + return ret; +} + + int wolfSSH_SetChannelOpenCtx(WOLFSSH* ssh, void* ctx) { int ret = WS_SSH_NULL_E; diff --git a/wolfssh/internal.h b/wolfssh/internal.h index 3d728d17d..e1d425c1a 100644 --- a/wolfssh/internal.h +++ b/wolfssh/internal.h @@ -501,7 +501,8 @@ struct WOLFSSH_CTX { WS_CallbackChannelOpen channelOpenCb; /* Channel Open Requested */ WS_CallbackChannelOpen channelOpenConfCb; /* Channel Open Confirm */ WS_CallbackChannelOpen channelOpenFailCb; /* Channel Open Fail */ - WS_CallbackChannelReqShell channelReqShellCb; /* Channel Request "Shell" */ + WS_CallbackChannelReq channelReqShellCb; /* Channel Request "Shell" */ + WS_CallbackChannelReq channelReqSubsysCb; /* Channel Request "Subsystem" */ WS_CallbackChannelEof channelEofCb; /* Channel Eof Callback */ WS_CallbackChannelClose channelCloseCb; /* Channel Close Callback */ #ifdef WOLFSSH_SCP diff --git a/wolfssh/ssh.h b/wolfssh/ssh.h index e23acbaf9..8b4a4eb66 100644 --- a/wolfssh/ssh.h +++ b/wolfssh/ssh.h @@ -162,6 +162,15 @@ WOLFSSH_API void wolfSSH_SetKeyingCompletionCbCtx(WOLFSSH*, #define WS_CHANNEL_ID_PEER 1 +typedef enum { + WOLFSSH_SESSION_UNKNOWN = 0, + WOLFSSH_SESSION_SHELL, + WOLFSSH_SESSION_EXEC, + WOLFSSH_SESSION_SUBSYSTEM, + WOLFSSH_SESSION_TERMINAL, +} WS_SessionType; + + typedef enum WS_FwdCbAction { WOLFSSH_FWD_LOCAL_SETUP, WOLFSSH_FWD_LOCAL_CLEANUP, @@ -209,6 +218,10 @@ WOLFSSH_API int wolfSSH_ChannelRead(WOLFSSH_CHANNEL*, byte*, word32); WOLFSSH_API int wolfSSH_ChannelSend(WOLFSSH_CHANNEL*, const byte*, word32); WOLFSSH_API int wolfSSH_ChannelExit(WOLFSSH_CHANNEL*); WOLFSSH_API int wolfSSH_ChannelGetEof(WOLFSSH_CHANNEL*); +WOLFSSH_API WS_SessionType wolfSSH_ChannelGetSessionType( + const WOLFSSH_CHANNEL* channel); +WOLFSSH_API const char* wolfSSH_ChannelGetSessionCommand( + const WOLFSSH_CHANNEL* channel); /* Channel callbacks */ typedef int (*WS_CallbackChannelOpen)(WOLFSSH_CHANNEL* channel, void* ctx); @@ -219,10 +232,11 @@ WOLFSSH_API int wolfSSH_CTX_SetChannelOpenRespCb(WOLFSSH_CTX* ctx, WOLFSSH_API int wolfSSH_SetChannelOpenCtx(WOLFSSH* ssh, void* ctx); WOLFSSH_API void* wolfSSH_GetChannelOpenCtx(WOLFSSH* ssh); -typedef int (*WS_CallbackChannelReqShell)(WOLFSSH_CHANNEL* channel, - void* ctx); +typedef int (*WS_CallbackChannelReq)(WOLFSSH_CHANNEL* channel, void* ctx); WOLFSSH_API int wolfSSH_CTX_SetChannelReqShellCb(WOLFSSH_CTX* ctx, - WS_CallbackChannelReqShell cb); + WS_CallbackChannelReq cb); +WOLFSSH_API int wolfSSH_CTX_SetChannelReqSubsysCb(WOLFSSH_CTX* ctx, + WS_CallbackChannelReq cb); WOLFSSH_API int wolfSSH_SetChannelReqCtx(WOLFSSH* ssh, void* ctx); WOLFSSH_API void* wolfSSH_GetChannelReqCtx(WOLFSSH* ssh); @@ -369,13 +383,6 @@ WOLFSSH_API int wolfSSH_KDF(byte, byte, byte*, word32, const byte*, word32, WOLFSSH_API int wolfSSH_ConvertConsole(WOLFSSH*, WOLFSSH_HANDLE, byte*, word32); #endif -typedef enum { - WOLFSSH_SESSION_UNKNOWN = 0, - WOLFSSH_SESSION_SHELL, - WOLFSSH_SESSION_EXEC, - WOLFSSH_SESSION_SUBSYSTEM, - WOLFSSH_SESSION_TERMINAL, -} WS_SessionType; WOLFSSH_API int wolfSSH_DoModes(const byte* modes, word32 modesSz, int fd); WOLFSSH_API WS_SessionType wolfSSH_GetSessionType(const WOLFSSH*); From b89c938000e6f8103f9f02cfb23dce63808cb7d9 Mon Sep 17 00:00:00 2001 From: John Safranek Date: Wed, 20 Mar 2024 19:20:20 -0700 Subject: [PATCH 7/9] Channel Callbacks (Request Exec) 1. Add a callback hook for channel requests of the exec type. --- src/internal.c | 3 +++ src/ssh.c | 14 ++++++++++++++ wolfssh/internal.h | 1 + wolfssh/ssh.h | 2 ++ 4 files changed, 20 insertions(+) diff --git a/src/internal.c b/src/internal.c index 9e8843c40..fc817b8a9 100644 --- a/src/internal.c +++ b/src/internal.c @@ -8380,6 +8380,9 @@ static int DoChannelRequest(WOLFSSH* ssh, ret = GetStringAlloc(ssh->ctx->heap, &channel->command, buf, len, &begin); channel->sessionType = WOLFSSH_SESSION_EXEC; + if (ssh->ctx->channelReqExecCb) { + ssh->ctx->channelReqExecCb(channel, ssh->channelReqCtx); + } ssh->clientState = CLIENT_DONE; WLOG(WS_LOG_DEBUG, " command = %s", channel->command); diff --git a/src/ssh.c b/src/ssh.c index 1fbec64af..6e67d0ac3 100644 --- a/src/ssh.c +++ b/src/ssh.c @@ -3119,6 +3119,20 @@ int wolfSSH_CTX_SetChannelReqShellCb(WOLFSSH_CTX* ctx, } +int wolfSSH_CTX_SetChannelReqExecCb(WOLFSSH_CTX* ctx, + WS_CallbackChannelReq cb) +{ + int ret = WS_SSH_CTX_NULL_E; + + if (ctx != NULL) { + ctx->channelReqExecCb = cb; + ret = WS_SUCCESS; + } + + return ret; +} + + int wolfSSH_CTX_SetChannelReqSubsysCb(WOLFSSH_CTX* ctx, WS_CallbackChannelReq cb) { diff --git a/wolfssh/internal.h b/wolfssh/internal.h index e1d425c1a..2c26c8187 100644 --- a/wolfssh/internal.h +++ b/wolfssh/internal.h @@ -502,6 +502,7 @@ struct WOLFSSH_CTX { WS_CallbackChannelOpen channelOpenConfCb; /* Channel Open Confirm */ WS_CallbackChannelOpen channelOpenFailCb; /* Channel Open Fail */ WS_CallbackChannelReq channelReqShellCb; /* Channel Request "Shell" */ + WS_CallbackChannelReq channelReqExecCb; /* Channel Request "Exec" */ WS_CallbackChannelReq channelReqSubsysCb; /* Channel Request "Subsystem" */ WS_CallbackChannelEof channelEofCb; /* Channel Eof Callback */ WS_CallbackChannelClose channelCloseCb; /* Channel Close Callback */ diff --git a/wolfssh/ssh.h b/wolfssh/ssh.h index 8b4a4eb66..8f6a2a115 100644 --- a/wolfssh/ssh.h +++ b/wolfssh/ssh.h @@ -235,6 +235,8 @@ WOLFSSH_API void* wolfSSH_GetChannelOpenCtx(WOLFSSH* ssh); typedef int (*WS_CallbackChannelReq)(WOLFSSH_CHANNEL* channel, void* ctx); WOLFSSH_API int wolfSSH_CTX_SetChannelReqShellCb(WOLFSSH_CTX* ctx, WS_CallbackChannelReq cb); +WOLFSSH_API int wolfSSH_CTX_SetChannelReqExecCb(WOLFSSH_CTX* ctx, + WS_CallbackChannelReq cb); WOLFSSH_API int wolfSSH_CTX_SetChannelReqSubsysCb(WOLFSSH_CTX* ctx, WS_CallbackChannelReq cb); WOLFSSH_API int wolfSSH_SetChannelReqCtx(WOLFSSH* ssh, void* ctx); From 57f14518e740c12bc5680cb02256f3fe8634037b Mon Sep 17 00:00:00 2001 From: John Safranek Date: Thu, 28 Mar 2024 09:54:46 -0700 Subject: [PATCH 8/9] Channel Callbacks (Rearrange Checks) 1. In DoChannelRequest(), rearrange the test cases. Start with the requests that are always expected as possible, and make the optional ones follow. --- src/internal.c | 119 ++++++++++++++++++++++++------------------------- 1 file changed, 59 insertions(+), 60 deletions(-) diff --git a/src/internal.c b/src/internal.c index fc817b8a9..653d395e5 100644 --- a/src/internal.c +++ b/src/internal.c @@ -8305,54 +8305,6 @@ static int DoChannelRequest(WOLFSSH* ssh, WLOG(WS_LOG_DEBUG, " type = %s", type); WLOG(WS_LOG_DEBUG, " wantReply = %u", wantReply); -#ifdef WOLFSSH_TERM - if (WSTRNCMP(type, "pty-req", typeSz) == 0) { - char term[32]; - const byte* modes; - word32 termSz, modesSz = 0; - word32 widthChar, heightRows, widthPixels, heightPixels; - - termSz = (word32)sizeof(term); - ret = GetString(term, &termSz, buf, len, &begin); - if (ret == WS_SUCCESS) - ret = GetUint32(&widthChar, buf, len, &begin); - if (ret == WS_SUCCESS) - ret = GetUint32(&heightRows, buf, len, &begin); - if (ret == WS_SUCCESS) - ret = GetUint32(&widthPixels, buf, len, &begin); - if (ret == WS_SUCCESS) - ret = GetUint32(&heightPixels, buf, len, &begin); - if (ret == WS_SUCCESS) - ret = GetStringRef(&modesSz, &modes, buf, len, &begin); - if (ret == WS_SUCCESS) { - ssh->modes = (byte*)WMALLOC(modesSz, - ssh->ctx->heap, DYNTYPE_STRING); - if (ssh->modes == NULL) - ret = WS_MEMORY_E; - } - if (ret == WS_SUCCESS) { - ssh->modesSz = modesSz; - WMEMCPY(ssh->modes, modes, modesSz); - WLOG(WS_LOG_DEBUG, " term = %s", term); - WLOG(WS_LOG_DEBUG, " widthChar = %u", widthChar); - WLOG(WS_LOG_DEBUG, " heightRows = %u", heightRows); - WLOG(WS_LOG_DEBUG, " widthPixels = %u", widthPixels); - WLOG(WS_LOG_DEBUG, " heightPixels = %u", heightPixels); - ssh->widthChar = widthChar; - ssh->heightRows = heightRows; - ssh->widthPixels = widthPixels; - ssh->heightPixels = heightPixels; - if (ssh->termResizeCb) { - if (ssh->termResizeCb(ssh, widthChar, heightRows, - widthPixels, heightPixels, - ssh->termCtx) != WS_SUCCESS) { - ret = WS_FATAL_ERROR; - } - } - } - } - else -#endif /* WOLFSSH_TERM */ if (WSTRNCMP(type, "env", typeSz) == 0) { char name[WOLFSSH_MAX_NAMESZ]; word32 nameSz; @@ -8398,16 +8350,54 @@ static int DoChannelRequest(WOLFSSH* ssh, WLOG(WS_LOG_DEBUG, " subsystem = %s", channel->command); } -#ifdef WOLFSSH_AGENT - else if (WSTRNCMP(type, "auth-agent-req@openssh.com", typeSz) == 0) { - WLOG(WS_LOG_AGENT, " ssh-agent"); - if (ssh->ctx->agentCb != NULL) - ssh->useAgent = 1; - else - WLOG(WS_LOG_AGENT, "Agent callback not set, not using."); + #ifdef WOLFSSH_TERM + else if (WSTRNCMP(type, "pty-req", typeSz) == 0) { + char term[32]; + const byte* modes; + word32 termSz, modesSz = 0; + word32 widthChar, heightRows, widthPixels, heightPixels; + + termSz = (word32)sizeof(term); + ret = GetString(term, &termSz, buf, len, &begin); + if (ret == WS_SUCCESS) + ret = GetUint32(&widthChar, buf, len, &begin); + if (ret == WS_SUCCESS) + ret = GetUint32(&heightRows, buf, len, &begin); + if (ret == WS_SUCCESS) + ret = GetUint32(&widthPixels, buf, len, &begin); + if (ret == WS_SUCCESS) + ret = GetUint32(&heightPixels, buf, len, &begin); + if (ret == WS_SUCCESS) + ret = GetStringRef(&modesSz, &modes, buf, len, &begin); + if (ret == WS_SUCCESS) { + ssh->modes = (byte*)WMALLOC(modesSz, + ssh->ctx->heap, DYNTYPE_STRING); + if (ssh->modes == NULL) + ret = WS_MEMORY_E; + } + if (ret == WS_SUCCESS) { + ssh->modesSz = modesSz; + WMEMCPY(ssh->modes, modes, modesSz); + WLOG(WS_LOG_DEBUG, " term = %s", term); + WLOG(WS_LOG_DEBUG, " widthChar = %u", widthChar); + WLOG(WS_LOG_DEBUG, " heightRows = %u", heightRows); + WLOG(WS_LOG_DEBUG, " widthPixels = %u", widthPixels); + WLOG(WS_LOG_DEBUG, " heightPixels = %u", heightPixels); + ssh->widthChar = widthChar; + ssh->heightRows = heightRows; + ssh->widthPixels = widthPixels; + ssh->heightPixels = heightPixels; + if (ssh->termResizeCb) { + if (ssh->termResizeCb(ssh, widthChar, heightRows, + widthPixels, heightPixels, + ssh->termCtx) != WS_SUCCESS) { + ret = WS_FATAL_ERROR; + } + } + } } -#endif /* WOLFSSH_AGENT */ -#if defined(WOLFSSH_SHELL) && defined(WOLFSSH_TERM) + #endif /* WOLFSSH_TERM */ + #if defined(WOLFSSH_SHELL) && defined(WOLFSSH_TERM) else if (WSTRNCMP(type, "window-change", typeSz) == 0) { word32 widthChar, heightRows, widthPixels, heightPixels; @@ -8437,8 +8427,8 @@ static int DoChannelRequest(WOLFSSH* ssh, } } } -#endif /* WOLFSSH_SHELL && WOLFSSH_TERM */ -#if defined(WOLFSSH_TERM) || defined(WOLFSSH_SHELL) + #endif /* WOLFSSH_SHELL && WOLFSSH_TERM */ + #if defined(WOLFSSH_TERM) || defined(WOLFSSH_SHELL) else if (WSTRNCMP(type, "exit-status", typeSz) == 0) { ret = GetUint32(&ssh->exitStatus, buf, len, &begin); WLOG(WS_LOG_AGENT, "Got exit status %u.", ssh->exitStatus); @@ -8471,7 +8461,16 @@ static int DoChannelRequest(WOLFSSH* ssh, ret = GetString(sig, &sigSz, buf, len, &begin); } } -#endif + #endif /* WOLFSSH_TERM or WOLFSSH_SHELL */ + #ifdef WOLFSSH_AGENT + else if (WSTRNCMP(type, "auth-agent-req@openssh.com", typeSz) == 0) { + WLOG(WS_LOG_AGENT, " ssh-agent"); + if (ssh->ctx->agentCb != NULL) + ssh->useAgent = 1; + else + WLOG(WS_LOG_AGENT, "Agent callback not set, not using."); + } + #endif /* WOLFSSH_AGENT */ } if (ret == WS_SUCCESS) { From 015ae8483b55489e18bc301cff22515a7fd31eee Mon Sep 17 00:00:00 2001 From: John Safranek Date: Fri, 5 Apr 2024 12:01:49 -0700 Subject: [PATCH 9/9] Channel Callbacks (Request Rejection) 1. Treat any non-zero response from any of the channel request callback functions as a rejection of the channel request. 2. If a channel request reply is wanted, return the failure message if the callback function had rejected the request. --- src/internal.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/internal.c b/src/internal.c index 653d395e5..9ccac69a7 100644 --- a/src/internal.c +++ b/src/internal.c @@ -8276,7 +8276,7 @@ static int DoChannelRequest(WOLFSSH* ssh, word32 typeSz; char type[32]; byte wantReply; - int ret; + int ret, rej = 0; WLOG(WS_LOG_DEBUG, "Entering DoChannelRequest()"); @@ -8324,7 +8324,7 @@ static int DoChannelRequest(WOLFSSH* ssh, else if (WSTRNCMP(type, "shell", typeSz) == 0) { channel->sessionType = WOLFSSH_SESSION_SHELL; if (ssh->ctx->channelReqShellCb) { - ssh->ctx->channelReqShellCb(channel, ssh->channelReqCtx); + rej = ssh->ctx->channelReqShellCb(channel, ssh->channelReqCtx); } ssh->clientState = CLIENT_DONE; } @@ -8333,7 +8333,7 @@ static int DoChannelRequest(WOLFSSH* ssh, buf, len, &begin); channel->sessionType = WOLFSSH_SESSION_EXEC; if (ssh->ctx->channelReqExecCb) { - ssh->ctx->channelReqExecCb(channel, ssh->channelReqCtx); + rej = ssh->ctx->channelReqExecCb(channel, ssh->channelReqCtx); } ssh->clientState = CLIENT_DONE; @@ -8344,7 +8344,7 @@ static int DoChannelRequest(WOLFSSH* ssh, buf, len, &begin); channel->sessionType = WOLFSSH_SESSION_SUBSYSTEM; if (ssh->ctx->channelReqSubsysCb) { - ssh->ctx->channelReqSubsysCb(channel, ssh->channelReqCtx); + rej = ssh->ctx->channelReqSubsysCb(channel, ssh->channelReqCtx); } ssh->clientState = CLIENT_DONE; @@ -8480,7 +8480,11 @@ static int DoChannelRequest(WOLFSSH* ssh, if (wantReply) { int replyRet; - replyRet = SendChannelSuccess(ssh, channelId, (ret == WS_SUCCESS)); + if (rej) { + WLOG(WS_LOG_DEBUG, "Callback rejecting channel request."); + } + replyRet = SendChannelSuccess(ssh, channelId, + (ret == WS_SUCCESS && !rej)); if (replyRet != WS_SUCCESS) ret = replyRet; }