diff --git a/examples/echoserver/echoserver.c b/examples/echoserver/echoserver.c index 6ffd3ce2..7be6a451 100644 --- a/examples/echoserver/echoserver.c +++ b/examples/echoserver/echoserver.c @@ -131,6 +131,17 @@ static int callbackReqSuccess(WOLFSSH *ssh, void *buf, word32 sz, void *ctx) return WS_SUCCESS; } +static int callbackReqFailure(WOLFSSH *ssh, void *buf, word32 sz, void *ctx) +{ + if ((WOLFSSH *)ssh != *(WOLFSSH **)ctx) + { + printf("ssh(%x) != ctx(%x)\n", (unsigned int)ssh, (unsigned int)*(WOLFSSH **)ctx); + return WS_FATAL_ERROR; + } + printf("Global Request Failure[%d]: %s\n", sz, sz > 0 ? buf : "No payload"); + return WS_SUCCESS; +} + static void *global_req(void *ctx) { int ret; @@ -140,7 +151,9 @@ static void *global_req(void *ctx) wolfSSH_SetReqSuccess(threadCtx->ctx, callbackReqSuccess); wolfSSH_SetReqSuccessCtx(threadCtx->ssh, &threadCtx->ssh); /* dummy ctx */ - + wolfSSH_SetReqFailure(threadCtx->ctx, callbackReqFailure); + wolfSSH_SetReqFailureCtx(threadCtx->ssh, &threadCtx->ssh); /* dummy ctx */ + while(1){ sleep(SSH_TIMEOUT); diff --git a/src/internal.c b/src/internal.c index 7108c6ce..9426cba5 100644 --- a/src/internal.c +++ b/src/internal.c @@ -2970,6 +2970,27 @@ static int DoRequestSuccess(WOLFSSH *ssh, byte *buf, word32 len, word32 *idx) } +static int DoRequestFailure(WOLFSSH *ssh, byte *buf, word32 len, word32 *idx) +{ + word32 dataSz; + word32 begin = *idx; + int ret = WS_SUCCESS; + + (void)ssh; + (void)len; + + WLOG(WS_LOG_DEBUG, "DoRequestFalure, *idx=%d, len=%d", *idx, len); + ato32(buf + begin, &dataSz); + begin += LENGTH_SZ + dataSz; + + if (ssh->ctx->reqFailureCb != NULL) + ret = ssh->ctx->reqFailureCb(ssh, &(buf[*idx]), len, ssh->reqFailureCtx); + + *idx = begin; + + return ret; +} + static int DoDebug(WOLFSSH* ssh, byte* buf, word32 len, word32* idx) { byte alwaysDisplay; @@ -3819,7 +3840,6 @@ static int DoGlobalRequest(WOLFSSH* ssh, { word32 begin; int ret = WS_SUCCESS; - int cb_ret; char name[80]; word32 nameSz = sizeof(name); byte wantReply = 0; @@ -3842,15 +3862,15 @@ static int DoGlobalRequest(WOLFSSH* ssh, ret = GetBoolean(&wantReply, buf, len, &begin); } - cb_ret = WS_SUCCESS; - if (ssh->ctx->globalReqCb != NULL) - cb_ret = ssh->ctx->globalReqCb(ssh, name, nameSz, wantReply, (void *)ssh->globalReqCtx); + if (ret == WS_SUCCESS && ssh->ctx->globalReqCb != NULL) + ret = ssh->ctx->globalReqCb(ssh, name, nameSz, wantReply, (void *)ssh->globalReqCtx); - if (ret == WS_SUCCESS && (cb_ret == 0 || cb_ret == 1)) { + if (ret == WS_SUCCESS) { *idx += len; if (wantReply) - ret = SendRequestSuccess(ssh, cb_ret); + ret = SendRequestSuccess(ssh, 0); + /* response SSH_MSG_REQUEST_FAILURE to Keep-Alive. IETF:draft-ssh-global-requests */ } WLOG(WS_LOG_DEBUG, "Leaving DoGlobalRequest(), ret = %d", ret); @@ -4530,6 +4550,11 @@ static int DoPacket(WOLFSSH* ssh) ret = DoRequestSuccess(ssh, buf + idx, payloadSz, &payloadIdx); break; + case MSGID_REQUEST_FAILURE: + WLOG(WS_LOG_DEBUG, "Decoding MSGID_REQUEST_FAILURE"); + ret = DoRequestFailure(ssh, buf + idx, payloadSz, &payloadIdx); + break; + case MSGID_DEBUG: WLOG(WS_LOG_DEBUG, "Decoding MSGID_DEBUG"); ret = DoDebug(ssh, buf + idx, payloadSz, &payloadIdx); @@ -7544,10 +7569,9 @@ int SendUserAuthBanner(WOLFSSH* ssh) return ret; } - -int SendRequestSuccess(WOLFSSH* ssh, int success) +int SendRequestSuccess(WOLFSSH *ssh, int success) { - byte* output; + byte *output; word32 idx; int ret = WS_SUCCESS; @@ -7560,12 +7584,12 @@ int SendRequestSuccess(WOLFSSH* ssh, int success) if (ret == WS_SUCCESS) ret = PreparePacket(ssh, MSG_ID_SZ); - if (ret == WS_SUCCESS) { + if (ret == WS_SUCCESS) + { output = ssh->outputBuffer.buffer; idx = ssh->outputBuffer.length; - output[idx++] = success ? - MSGID_REQUEST_SUCCESS : MSGID_REQUEST_FAILURE; + output[idx++] = success ? MSGID_REQUEST_SUCCESS : MSGID_REQUEST_FAILURE; ssh->outputBuffer.length = idx; @@ -7578,8 +7602,7 @@ int SendRequestSuccess(WOLFSSH* ssh, int success) WLOG(WS_LOG_DEBUG, "Leaving SendRequestSuccess(), ret = %d", ret); return ret; } - - + static int SendChannelOpen(WOLFSSH* ssh, WOLFSSH_CHANNEL* channel, byte* channelData, word32 channelDataSz) { diff --git a/src/ssh.c b/src/ssh.c index d08aae92..96914a42 100644 --- a/src/ssh.c +++ b/src/ssh.c @@ -239,6 +239,12 @@ void wolfSSH_SetReqSuccess(WOLFSSH_CTX *ctx, WS_CallbackReqSuccess cb) ctx->reqSuccessCb = cb; } +void wolfSSH_SetReqFailure(WOLFSSH_CTX *ctx, WS_CallbackReqSuccess cb) +{ + if (ctx) + ctx->reqFailureCb = cb; +} + void wolfSSH_SetGlobalReqCtx(WOLFSSH* ssh, void *ctx) { WLOG(WS_LOG_DEBUG, "Entering wolfSSH_SetGlobalReqCtx()"); @@ -275,6 +281,24 @@ void *wolfSSH_GetReqSuccessCtx(WOLFSSH *ssh) return NULL; } +void wolfSSH_SetReqFailureCtx(WOLFSSH *ssh, void *ctx) +{ + WLOG(WS_LOG_DEBUG, "Entering wolfSSH_SetReqFailureCtx()"); + + if (ssh) + ssh->reqFailureCtx = ctx; +} + +void *wolfSSH_GetReqFailureCtx(WOLFSSH *ssh) +{ + WLOG(WS_LOG_DEBUG, "Entering wolfSSH_GetReqFailureCtx()"); + + if (ssh) + return ssh->reqFailureCtx; + + return NULL; +} + int wolfSSH_get_error(const WOLFSSH* ssh) { WLOG(WS_LOG_DEBUG, "Entering wolfSSH_get_error()"); diff --git a/wolfssh/internal.h b/wolfssh/internal.h index c987ab8c..668ec312 100644 --- a/wolfssh/internal.h +++ b/wolfssh/internal.h @@ -180,6 +180,7 @@ struct WOLFSSH_CTX { WS_CallbackHighwater highwaterCb; /* Data Highwater Mark Callback */ WS_CallbackGlobalReq globalReqCb; /* Global Request Callback */ WS_CallbackReqSuccess reqSuccessCb; /* Global Request Success Callback */ + WS_CallbackReqSuccess reqFailureCb; /* Global Request Failure Callback */ #ifdef WOLFSSH_SCP WS_CallbackScpRecv scpRecvCb; /* SCP receive callback */ WS_CallbackScpSend scpSendCb; /* SCP send callback */ @@ -298,6 +299,7 @@ struct WOLFSSH { void* highwaterCtx; void* globalReqCtx; /* Global Request CB context */ void* reqSuccessCtx; /* Global Request Sucess CB context */ + void* reqFailureCtx; /* Global Request Failure CB context */ word32 curSz; word32 seq; word32 peerSeq; diff --git a/wolfssh/ssh.h b/wolfssh/ssh.h index df49c637..7cf9f28b 100644 --- a/wolfssh/ssh.h +++ b/wolfssh/ssh.h @@ -117,6 +117,10 @@ typedef int (*WS_CallbackReqSuccess)(WOLFSSH*, void*, word32, void*); WOLFSSH_API void wolfSSH_SetReqSuccess(WOLFSSH_CTX*, WS_CallbackReqSuccess); WOLFSSH_API void wolfSSH_SetReqSuccessCtx(WOLFSSH*, void *); WOLFSSH_API void* wolfSSH_GetReqSuccessCtx(WOLFSSH*); +typedef int (*WS_CallbackReqFailure)(WOLFSSH *, void *, word32, void *); +WOLFSSH_API void wolfSSH_SetReqFailure(WOLFSSH_CTX *, WS_CallbackReqSuccess); +WOLFSSH_API void wolfSSH_SetReqFailureCtx(WOLFSSH *, void *); +WOLFSSH_API void *wolfSSH_GetReqFailureCtx(WOLFSSH *); /* User Authentication callback */ typedef struct WS_UserAuthData_Password {