From 5c3fd6ecafe6ea6b58ff6f9caddb81cb6e83d7ac Mon Sep 17 00:00:00 2001 From: John Safranek Date: Thu, 4 Jun 2026 13:29:02 -0700 Subject: [PATCH 1/6] Add parameter names to function declarations Clean up clang-tidy readability-named-parameter findings across wolfSSH headers and sources. --- apps/wolfsshd/test/test_configuration.c | 2 +- examples/scpclient/scpclient.h | 2 +- examples/sftpclient/sftpclient.c | 2 +- src/log.c | 3 +- wolfssh/agent.h | 42 ++-- wolfssh/internal.h | 193 +++++++++-------- wolfssh/log.h | 4 +- wolfssh/misc.h | 10 +- wolfssh/port.h | 36 ++-- wolfssh/ssh.h | 264 ++++++++++++++---------- wolfssh/wolfscp.h | 49 +++-- wolfssh/wolfsftp.h | 2 +- 12 files changed, 347 insertions(+), 262 deletions(-) diff --git a/apps/wolfsshd/test/test_configuration.c b/apps/wolfsshd/test/test_configuration.c index 72cacf195..711bac6bb 100644 --- a/apps/wolfsshd/test/test_configuration.c +++ b/apps/wolfsshd/test/test_configuration.c @@ -35,7 +35,7 @@ #endif /* __GNUC__ */ -void Log(const char *const, ...) FMTCHECK; +void Log(const char *const fmt, ...) FMTCHECK; void Log(const char *const fmt, ...) { va_list vlist; diff --git a/examples/scpclient/scpclient.h b/examples/scpclient/scpclient.h index 93c1704bb..3690a823f 100644 --- a/examples/scpclient/scpclient.h +++ b/examples/scpclient/scpclient.h @@ -22,6 +22,6 @@ #ifndef _WOLFSSH_EXAMPLES_SCPCLIENT_H_ #define _WOLFSSH_EXAMPLES_SCPCLIENT_H_ -THREAD_RETURN WOLFSSH_THREAD scp_client(void*); +THREAD_RETURN WOLFSSH_THREAD scp_client(void* args); #endif /* _WOLFSSH_EXAMPLES_SCPCLIENT_H_ */ diff --git a/examples/sftpclient/sftpclient.c b/examples/sftpclient/sftpclient.c index 24d593494..b73e89244 100644 --- a/examples/sftpclient/sftpclient.c +++ b/examples/sftpclient/sftpclient.c @@ -105,7 +105,7 @@ static void err_msg(const char* s) static word32 startTime; #define TIMEOUT_VALUE 120 - word32 current_time(int); + word32 current_time(int reset); #ifdef USE_WINDOWS_API #include #define WIN32_LEAN_AND_MEAN diff --git a/src/log.c b/src/log.c index 25f209ef6..355e1e495 100644 --- a/src/log.c +++ b/src/log.c @@ -50,7 +50,8 @@ #ifndef WOLFSSL_NO_DEFAULT_LOGGING_CB - static void DefaultLoggingCb(enum wolfSSH_LogLevel, const char *const); + static void DefaultLoggingCb(enum wolfSSH_LogLevel level, + const char *const msgStr); static wolfSSH_LoggingCb logFunction = DefaultLoggingCb; #else /* WOLFSSH_NO_DEFAULT_LOGGING_CB */ static wolfSSH_LoggingCb logFunction = NULL; diff --git a/wolfssh/agent.h b/wolfssh/agent.h index 362a4a728..581e3eba9 100644 --- a/wolfssh/agent.h +++ b/wolfssh/agent.h @@ -165,25 +165,29 @@ typedef enum WS_AgentCbError { } WS_AgentCbError; -typedef int (*WS_CallbackAgent)(WS_AgentCbAction, void*); -typedef int (*WS_CallbackAgentIO)(WS_AgentIoCbAction, void*, word32, void*); - - -WOLFSSH_API WOLFSSH_AGENT_CTX* wolfSSH_AGENT_new(void*); -WOLFSSH_API void wolfSSH_AGENT_free(WOLFSSH_AGENT_CTX*); -WOLFSSH_LOCAL WOLFSSH_AGENT_ID* wolfSSH_AGENT_ID_new(byte, word32, void*); -WOLFSSH_LOCAL void wolfSSH_AGENT_ID_free(WOLFSSH_AGENT_ID*, void*); -WOLFSSH_LOCAL void wolfSSH_AGENT_ID_list_free(WOLFSSH_AGENT_ID*, void*); -WOLFSSH_API int wolfSSH_CTX_set_agent_cb(WOLFSSH_CTX*, - WS_CallbackAgent, WS_CallbackAgentIO); -WOLFSSH_API int wolfSSH_set_agent_cb_ctx(WOLFSSH*, void*); -WOLFSSH_API int wolfSSH_CTX_AGENT_enable(WOLFSSH_CTX*, byte); -WOLFSSH_API int wolfSSH_AGENT_enable(WOLFSSH*, byte); -WOLFSSH_LOCAL int wolfSSH_AGENT_worker(WOLFSSH*); -WOLFSSH_API int wolfSSH_AGENT_Relay(WOLFSSH*, - const byte*, word32*, byte*, word32*); -WOLFSSH_API int wolfSSH_AGENT_SignRequest(WOLFSSH*, const byte*, word32, - byte*, word32*, const byte*, word32, word32); +typedef int (*WS_CallbackAgent)(WS_AgentCbAction action, void* agentCbCtx); +typedef int (*WS_CallbackAgentIO)(WS_AgentIoCbAction action, void* buf, + word32 bufSz, void* agentCbCtx); + + +WOLFSSH_API WOLFSSH_AGENT_CTX* wolfSSH_AGENT_new(void* heap); +WOLFSSH_API void wolfSSH_AGENT_free(WOLFSSH_AGENT_CTX* agent); +WOLFSSH_LOCAL WOLFSSH_AGENT_ID* wolfSSH_AGENT_ID_new(byte keyType, + word32 keySz, void* heap); +WOLFSSH_LOCAL void wolfSSH_AGENT_ID_free(WOLFSSH_AGENT_ID* id, void* heap); +WOLFSSH_LOCAL void wolfSSH_AGENT_ID_list_free(WOLFSSH_AGENT_ID* id, void* heap); +WOLFSSH_API int wolfSSH_CTX_set_agent_cb(WOLFSSH_CTX* ctx, + WS_CallbackAgent agentCb, WS_CallbackAgentIO agentIoCb); +WOLFSSH_API int wolfSSH_set_agent_cb_ctx(WOLFSSH* ssh, void* ctx); +WOLFSSH_API int wolfSSH_CTX_AGENT_enable(WOLFSSH_CTX* ctx, byte isEnabled); +WOLFSSH_API int wolfSSH_AGENT_enable(WOLFSSH* ssh, byte isEnabled); +WOLFSSH_LOCAL int wolfSSH_AGENT_worker(WOLFSSH* ssh); +WOLFSSH_API int wolfSSH_AGENT_Relay(WOLFSSH* ssh, + const byte* msg, word32* msgSz, byte* rsp, word32* rspSz); +WOLFSSH_API int wolfSSH_AGENT_SignRequest(WOLFSSH* ssh, + const byte* digest, word32 digestSz, + byte* sig, word32* sigSz, + const byte* keyBlob, word32 keyBlobSz, word32 flags); #ifdef __cplusplus diff --git a/wolfssh/internal.h b/wolfssh/internal.h index 98d2c9524..3b5abd48c 100644 --- a/wolfssh/internal.h +++ b/wolfssh/internal.h @@ -316,7 +316,7 @@ extern "C" { #endif -WOLFSSH_LOCAL const char* GetErrorString(int); +WOLFSSH_LOCAL const char* GetErrorString(int err); enum { @@ -1009,24 +1009,30 @@ struct WOLFSSH_CHANNEL { }; -WOLFSSH_LOCAL WOLFSSH_CTX* CtxInit(WOLFSSH_CTX*, byte, void*); -WOLFSSH_LOCAL void CtxResourceFree(WOLFSSH_CTX*); -WOLFSSH_LOCAL WOLFSSH* SshInit(WOLFSSH*, WOLFSSH_CTX*); -WOLFSSH_LOCAL void SshResourceFree(WOLFSSH*, void*); +WOLFSSH_LOCAL WOLFSSH_CTX* CtxInit(WOLFSSH_CTX* ctx, byte side, void* heap); +WOLFSSH_LOCAL void CtxResourceFree(WOLFSSH_CTX* ctx); +WOLFSSH_LOCAL WOLFSSH* SshInit(WOLFSSH* ssh, WOLFSSH_CTX* ctx); +WOLFSSH_LOCAL void SshResourceFree(WOLFSSH* ssh, void* heap); -WOLFSSH_LOCAL WOLFSSH_CHANNEL* ChannelNew(WOLFSSH*, byte, word32, word32); -WOLFSSH_LOCAL int ChannelUpdatePeer(WOLFSSH_CHANNEL*, word32, word32, word32); -WOLFSSH_LOCAL int ChannelUpdateForward(WOLFSSH_CHANNEL*, - const char*, word32, const char*, word32, int); +WOLFSSH_LOCAL WOLFSSH_CHANNEL* ChannelNew(WOLFSSH* ssh, byte channelType, + word32 initialWindowSz, word32 maxPacketSz); +WOLFSSH_LOCAL int ChannelUpdatePeer(WOLFSSH_CHANNEL* channel, + word32 peerChannelId, word32 peerInitialWindowSz, + word32 peerMaxPacketSz); +WOLFSSH_LOCAL int ChannelUpdateForward(WOLFSSH_CHANNEL* channel, + const char* host, word32 hostPort, + const char* origin, word32 originPort, int isDirect); WOLFSSH_LOCAL int ChannelAppend(WOLFSSH* ssh, WOLFSSH_CHANNEL* channel); -WOLFSSH_LOCAL void ChannelDelete(WOLFSSH_CHANNEL*, void*); -WOLFSSH_LOCAL WOLFSSH_CHANNEL* ChannelFind(WOLFSSH*, word32, byte); -WOLFSSH_LOCAL int ChannelRemove(WOLFSSH*, word32, byte); -WOLFSSH_LOCAL int ChannelPutData(WOLFSSH_CHANNEL*, byte*, word32); -WOLFSSH_LOCAL int wolfSSH_ProcessBuffer(WOLFSSH_CTX*, - const byte*, word32, - int, int); -WOLFSSH_LOCAL int wolfSSH_FwdWorker(WOLFSSH*); +WOLFSSH_LOCAL void ChannelDelete(WOLFSSH_CHANNEL* channel, void* heap); +WOLFSSH_LOCAL WOLFSSH_CHANNEL* ChannelFind(WOLFSSH* ssh, word32 channel, + byte peer); +WOLFSSH_LOCAL int ChannelRemove(WOLFSSH* ssh, word32 channel, byte peer); +WOLFSSH_LOCAL int ChannelPutData(WOLFSSH_CHANNEL* channel, byte* data, + word32 dataSz); +WOLFSSH_LOCAL int wolfSSH_ProcessBuffer(WOLFSSH_CTX* ctx, + const byte* in, word32 inSz, + int format, int type); +WOLFSSH_LOCAL int wolfSSH_FwdWorker(WOLFSSH* ssh); typedef struct WS_KeySignature { @@ -1084,8 +1090,8 @@ WOLFSSH_LOCAL int GetStringRef(word32* strSz, const byte **str, #ifndef WOLFSSH_USER_IO /* default I/O handlers */ -WOLFSSH_LOCAL int wsEmbedRecv(WOLFSSH*, void*, word32, void*); -WOLFSSH_LOCAL int wsEmbedSend(WOLFSSH*, void*, word32, void*); +WOLFSSH_LOCAL int wsEmbedRecv(WOLFSSH* ssh, void* data, word32 sz, void* ctx); +WOLFSSH_LOCAL int wsEmbedSend(WOLFSSH* ssh, void* data, word32 sz, void* ctx); #endif /* WOLFSSH_USER_IO */ @@ -1097,63 +1103,78 @@ enum ChannelOpenFailReasons { OPEN_RESOURCE_SHORTAGE }; -WOLFSSH_LOCAL int DoReceive(WOLFSSH*); -WOLFSSH_LOCAL int DoProtoId(WOLFSSH*); -WOLFSSH_LOCAL int wolfSSH_SendPacket(WOLFSSH*); -WOLFSSH_LOCAL int wolfSSH_OutputPending(WOLFSSH*); -WOLFSSH_LOCAL int SendProtoId(WOLFSSH*); -WOLFSSH_LOCAL int SendKexInit(WOLFSSH*); -WOLFSSH_LOCAL int SendKexDhInit(WOLFSSH*); -WOLFSSH_LOCAL int SendKexDhReply(WOLFSSH*); -WOLFSSH_LOCAL int SendKexDhGexRequest(WOLFSSH*); -WOLFSSH_LOCAL int SendKexDhGexGroup(WOLFSSH*); -WOLFSSH_LOCAL int SendNewKeys(WOLFSSH*); -WOLFSSH_LOCAL int SendUnimplemented(WOLFSSH*); -WOLFSSH_LOCAL int SendDisconnect(WOLFSSH*, word32); -WOLFSSH_LOCAL int SendIgnore(WOLFSSH*, const unsigned char*, word32); -WOLFSSH_LOCAL int SendGlobalRequestFwdSuccess(WOLFSSH *, int, word32); -WOLFSSH_LOCAL int SendGlobalRequest(WOLFSSH *, const unsigned char *, word32, int); -WOLFSSH_LOCAL int SendDebug(WOLFSSH*, byte, const char*); -WOLFSSH_LOCAL int SendServiceRequest(WOLFSSH*, byte); -WOLFSSH_LOCAL int SendServiceAccept(WOLFSSH*, byte); +WOLFSSH_LOCAL int DoReceive(WOLFSSH* ssh); +WOLFSSH_LOCAL int DoProtoId(WOLFSSH* ssh); +WOLFSSH_LOCAL int wolfSSH_SendPacket(WOLFSSH* ssh); +WOLFSSH_LOCAL int wolfSSH_OutputPending(WOLFSSH* ssh); +WOLFSSH_LOCAL int SendProtoId(WOLFSSH* ssh); +WOLFSSH_LOCAL int SendKexInit(WOLFSSH* ssh); +WOLFSSH_LOCAL int SendKexDhInit(WOLFSSH* ssh); +WOLFSSH_LOCAL int SendKexDhReply(WOLFSSH* ssh); +WOLFSSH_LOCAL int SendKexDhGexRequest(WOLFSSH* ssh); +WOLFSSH_LOCAL int SendKexDhGexGroup(WOLFSSH* ssh); +WOLFSSH_LOCAL int SendNewKeys(WOLFSSH* ssh); +WOLFSSH_LOCAL int SendUnimplemented(WOLFSSH* ssh); +WOLFSSH_LOCAL int SendDisconnect(WOLFSSH* ssh, word32 reason); +WOLFSSH_LOCAL int SendIgnore(WOLFSSH* ssh, const unsigned char* data, + word32 dataSz); +WOLFSSH_LOCAL int SendGlobalRequestFwdSuccess(WOLFSSH * ssh, int success, + word32 port); +WOLFSSH_LOCAL int SendGlobalRequest(WOLFSSH * ssh, + const unsigned char * data, word32 dataSz, int reply); +WOLFSSH_LOCAL int SendDebug(WOLFSSH* ssh, byte alwaysDisplay, const char* msg); +WOLFSSH_LOCAL int SendServiceRequest(WOLFSSH* ssh, byte serviceId); +WOLFSSH_LOCAL int SendServiceAccept(WOLFSSH* ssh, byte serviceId); WOLFSSH_LOCAL int SendExtInfo(WOLFSSH* ssh); -WOLFSSH_LOCAL int SendUserAuthRequest(WOLFSSH*, byte, int); +WOLFSSH_LOCAL int SendUserAuthRequest(WOLFSSH* ssh, byte authType, int addSig); #ifdef WOLFSSH_KEYBOARD_INTERACTIVE -WOLFSSH_LOCAL int SendUserAuthKeyboardResponse(WOLFSSH*); -WOLFSSH_LOCAL int SendUserAuthKeyboardRequest(WOLFSSH*, WS_UserAuthData*); -#endif -WOLFSSH_LOCAL int SendUserAuthSuccess(WOLFSSH*); -WOLFSSH_LOCAL int SendUserAuthFailure(WOLFSSH*, byte); -WOLFSSH_LOCAL int SendUserAuthBanner(WOLFSSH*); -WOLFSSH_LOCAL int SendUserAuthPkOk(WOLFSSH*, const byte*, word32, - const byte*, word32); -WOLFSSH_LOCAL int SendRequestSuccess(WOLFSSH*, int); -WOLFSSH_LOCAL int SendChannelOpenSession(WOLFSSH*, WOLFSSH_CHANNEL*); -WOLFSSH_LOCAL int SendChannelOpenForward(WOLFSSH*, WOLFSSH_CHANNEL*); -WOLFSSH_LOCAL int SendChannelOpenConf(WOLFSSH*, WOLFSSH_CHANNEL*); +WOLFSSH_LOCAL int SendUserAuthKeyboardResponse(WOLFSSH* ssh); +WOLFSSH_LOCAL int SendUserAuthKeyboardRequest(WOLFSSH* ssh, + WS_UserAuthData* authData); +#endif +WOLFSSH_LOCAL int SendUserAuthSuccess(WOLFSSH* ssh); +WOLFSSH_LOCAL int SendUserAuthFailure(WOLFSSH* ssh, byte partialSuccess); +WOLFSSH_LOCAL int SendUserAuthBanner(WOLFSSH* ssh); +WOLFSSH_LOCAL int SendUserAuthPkOk(WOLFSSH* ssh, + const byte* algoName, word32 algoNameSz, + const byte* publicKey, word32 publicKeySz); +WOLFSSH_LOCAL int SendRequestSuccess(WOLFSSH* ssh, int success); +WOLFSSH_LOCAL int SendChannelOpenSession(WOLFSSH* ssh, + WOLFSSH_CHANNEL* channel); +WOLFSSH_LOCAL int SendChannelOpenForward(WOLFSSH* ssh, + WOLFSSH_CHANNEL* channel); +WOLFSSH_LOCAL int SendChannelOpenConf(WOLFSSH* ssh, WOLFSSH_CHANNEL* channel); WOLFSSH_LOCAL int SendChannelOpenFail(WOLFSSH* ssh, word32 channel, word32 reason, const char* description, const char* language); -WOLFSSH_LOCAL int SendChannelEof(WOLFSSH*, word32); -WOLFSSH_LOCAL int SendChannelEow(WOLFSSH*, word32); -WOLFSSH_LOCAL int SendChannelClose(WOLFSSH*, word32); -WOLFSSH_LOCAL int SendChannelExit(WOLFSSH*, word32, int); -WOLFSSH_LOCAL int SendChannelData(WOLFSSH*, word32, byte*, word32); -WOLFSSH_LOCAL int SendChannelExtendedData(WOLFSSH*, word32, byte*, word32); -WOLFSSH_LOCAL int SendChannelWindowAdjust(WOLFSSH*, word32, word32); -WOLFSSH_LOCAL int SendChannelRequest(WOLFSSH*, byte*, word32); -WOLFSSH_LOCAL int SendChannelTerminalResize(WOLFSSH*, word32, word32, word32, - word32); +WOLFSSH_LOCAL int SendChannelEof(WOLFSSH* ssh, word32 peerChannelId); +WOLFSSH_LOCAL int SendChannelEow(WOLFSSH* ssh, word32 peerChannelId); +WOLFSSH_LOCAL int SendChannelClose(WOLFSSH* ssh, word32 peerChannelId); +WOLFSSH_LOCAL int SendChannelExit(WOLFSSH* ssh, word32 peerChannelId, + int status); +WOLFSSH_LOCAL int SendChannelData(WOLFSSH* ssh, word32 channelId, + byte* data, word32 dataSz); +WOLFSSH_LOCAL int SendChannelExtendedData(WOLFSSH* ssh, word32 channelId, + byte* data, word32 dataSz); +WOLFSSH_LOCAL int SendChannelWindowAdjust(WOLFSSH* ssh, word32 channelId, + word32 bytesToAdd); +WOLFSSH_LOCAL int SendChannelRequest(WOLFSSH* ssh, byte* name, word32 nameSz); +WOLFSSH_LOCAL int SendChannelTerminalResize(WOLFSSH* ssh, word32 columns, + word32 rows, word32 widthPixels, word32 heightPixels); WOLFSSH_LOCAL int SendChannelTerminalRequest(WOLFSSH* ssh); WOLFSSH_LOCAL int SendChannelAgentRequest(WOLFSSH* ssh); -WOLFSSH_LOCAL int SendChannelSuccess(WOLFSSH*, word32, int); +WOLFSSH_LOCAL int SendChannelSuccess(WOLFSSH* ssh, word32 channelId, + int success); WOLFSSH_LOCAL int SendChannelExitStatus(WOLFSSH* ssh, word32 channelId, word32 exitStatus); -WOLFSSH_LOCAL int GenerateKey(byte, byte, byte*, word32, const byte*, word32, - const byte*, word32, const byte*, word32, byte doKeyPad); +WOLFSSH_LOCAL int GenerateKey(byte hashId, byte keyId, byte* key, + word32 keySz, const byte* k, word32 kSz, + const byte* h, word32 hSz, + const byte* sessionId, word32 sessionIdSz, + byte doKeyPad); #if !defined(WOLFSSH_NO_ECDSA) || !defined(WOLFSSH_NO_ECDH) -WOLFSSH_LOCAL int wcPrimeForId(byte); +WOLFSSH_LOCAL int wcPrimeForId(byte id); #endif -WOLFSSH_LOCAL enum wc_HashType HashForId(byte); +WOLFSSH_LOCAL enum wc_HashType HashForId(byte id); enum AcceptStates { @@ -1375,7 +1396,8 @@ enum WS_MessageIdLimits { word32 len, word32* idx); WOLFSSH_API int wolfSSH_TestDoKexDhReply(WOLFSSH* ssh, byte* buf, word32 len, word32* idx); - WOLFSSH_API int wolfSSH_TestChannelPutData(WOLFSSH_CHANNEL*, byte*, word32); + WOLFSSH_API int wolfSSH_TestChannelPutData(WOLFSSH_CHANNEL* channel, + byte* data, word32 dataSz); WOLFSSH_API int wolfSSH_TestDoUserAuthRequest(WOLFSSH* ssh, byte* buf, word32 len, word32* idx); WOLFSSH_API int wolfSSH_TestHighwaterCheck(WOLFSSH* ssh, byte side); @@ -1489,23 +1511,30 @@ enum WS_ScpDirection { WOLFSSH_SCP_FROM }; -WOLFSSH_LOCAL int ChannelCommandIsScp(WOLFSSH*); -WOLFSSH_LOCAL int DoScpRequest(WOLFSSH*); +WOLFSSH_LOCAL int ChannelCommandIsScp(WOLFSSH* ssh); +WOLFSSH_LOCAL int DoScpRequest(WOLFSSH* ssh); WOLFSSH_LOCAL int DoScpSink(WOLFSSH* ssh); WOLFSSH_LOCAL int DoScpSource(WOLFSSH* ssh); -WOLFSSH_LOCAL int ParseScpCommand(WOLFSSH*); -WOLFSSH_LOCAL int ReceiveScpMessage(WOLFSSH*); -WOLFSSH_LOCAL int ReceiveScpFile(WOLFSSH*); -WOLFSSH_LOCAL int SendScpConfirmation(WOLFSSH*); -WOLFSSH_LOCAL int ReceiveScpConfirmation(WOLFSSH*); +WOLFSSH_LOCAL int ParseScpCommand(WOLFSSH* ssh); +WOLFSSH_LOCAL int ReceiveScpMessage(WOLFSSH* ssh); +WOLFSSH_LOCAL int ReceiveScpFile(WOLFSSH* ssh); +WOLFSSH_LOCAL int SendScpConfirmation(WOLFSSH* ssh); +WOLFSSH_LOCAL int ReceiveScpConfirmation(WOLFSSH* ssh); /* default SCP callbacks */ -WOLFSSH_LOCAL int wsScpRecvCallback(WOLFSSH*, int, const char*, const char*, - int, word64, word64, word32, byte*, - word32, word32, void*); -WOLFSSH_LOCAL int wsScpSendCallback(WOLFSSH*, int, const char*, char*, word32, - word64*, word64*, int*, word32, word32*, - byte*, word32, void*); +WOLFSSH_LOCAL int wsScpRecvCallback(WOLFSSH* ssh, int state, + const char* basePath, + const char* fileName, int fileMode, + word64 mTime, word64 aTime, + word32 totalFileSz, byte* buf, + word32 bufSz, word32 fileOffset, + void* ctx); +WOLFSSH_LOCAL int wsScpSendCallback(WOLFSSH* ssh, int state, + const char* peerRequest, char* fileName, + word32 fileNameSz, word64* mTime, + word64* aTime, int* fileMode, + word32 fileOffset, word32* totalFileSz, + byte* buf, word32 bufSz, void* ctx); #endif @@ -1516,9 +1545,9 @@ WOLFSSH_LOCAL int wolfSSH_RsaVerify( const byte* encDigest, word32 encDigestSz, RsaKey* key, void* heap, const char* loc); #endif -WOLFSSH_LOCAL void DumpOctetString(const byte*, word32); +WOLFSSH_LOCAL void DumpOctetString(const byte* input, word32 inputSz); WOLFSSH_LOCAL int wolfSSH_oct2dec(WOLFSSH* ssh, byte* oct, word32 octSz); -WOLFSSH_LOCAL void AddAssign64(word32*, word32); +WOLFSSH_LOCAL void AddAssign64(word32* addend1, word32 addend2); #ifdef WOLFSSH_TERM /* values from section 8 of rfc 4254 */ diff --git a/wolfssh/log.h b/wolfssh/log.h index c1b4fd2d6..0139fc04b 100644 --- a/wolfssh/log.h +++ b/wolfssh/log.h @@ -69,8 +69,8 @@ WOLFSSH_API int wolfSSH_LogEnabled(void); #endif /* __GNUC__ */ -WOLFSSH_API void wolfSSH_Log(enum wolfSSH_LogLevel, - const char *const, ...) FMTCHECK; +WOLFSSH_API void wolfSSH_Log(enum wolfSSH_LogLevel level, + const char *const fmt, ...) FMTCHECK; #if defined(DEBUG_WOLFSSH) || defined(WOLFSSH_SSHD) #define WLOG(...) do { \ diff --git a/wolfssh/misc.h b/wolfssh/misc.h index 03588e87c..2e0e51d07 100644 --- a/wolfssh/misc.h +++ b/wolfssh/misc.h @@ -37,13 +37,13 @@ #ifndef min -WOLFSSH_LOCAL word32 min(word32, word32); +WOLFSSH_LOCAL word32 min(word32 a, word32 b); #endif /* min */ -WOLFSSH_LOCAL void ato32(const byte*, word32*); -WOLFSSH_LOCAL void c32toa(word32, byte*); -WOLFSSH_LOCAL void ForceZero(const void*, word32); -WOLFSSH_LOCAL int ConstantCompare(const byte*, const byte*, word32); +WOLFSSH_LOCAL void ato32(const byte* c, word32* u32); +WOLFSSH_LOCAL void c32toa(word32 u32, byte* c); +WOLFSSH_LOCAL void ForceZero(const void* mem, word32 length); +WOLFSSH_LOCAL int ConstantCompare(const byte* a, const byte* b, word32 length); #endif /* NO_INLINE */ diff --git a/wolfssh/port.h b/wolfssh/port.h index fee7ab39b..73645ea71 100644 --- a/wolfssh/port.h +++ b/wolfssh/port.h @@ -112,7 +112,7 @@ extern "C" { #include "storage/nu_storage.h" #define WFILE int - WOLFSSH_API int wfopen(WFILE**, const char*, const char*); + WOLFSSH_API int wfopen(WFILE** f, const char* filename, const char* mode); #define WFOPEN(fs,f,fn,m) wfopen((f),(fn),(m)) #define WFCLOSE(fs,f) NU_Close(*(f)) @@ -191,7 +191,7 @@ extern "C" { #define MQX_MFS_DEVICE "a:" #endif - WOLFSSH_API int wfopen(WFILE**, const char*, const char*); + WOLFSSH_API int wfopen(WFILE** f, const char* filename, const char* mode); #define WFOPEN(fs,f,fn,m) wfopen((f),(fn),(m)) #define WFCLOSE(fs,f) fclose((f)) @@ -438,7 +438,7 @@ extern "C" { #include #endif #define WFILE FILE - WOLFSSH_API int wfopen(WFILE**, const char*, const char*); + WOLFSSH_API int wfopen(WFILE** f, const char* filename, const char* mode); #define WFFLUSH fflush @@ -538,9 +538,9 @@ extern "C" { #define WSTRCPY(s1,s2) strcpy((s1),(s2)) /* for these string functions use internal versions */ - WOLFSSH_API char* wstrnstr(const char*, const char*, unsigned int); - WOLFSSH_API char* wstrncat(char*, const char*, size_t); - WOLFSSH_API char* wstrdup(const char*, void*, int); + WOLFSSH_API char* wstrnstr(const char* s1, const char* s2, unsigned int n); + WOLFSSH_API char* wstrncat(char* s1, const char* s2, size_t n); + WOLFSSH_API char* wstrdup(const char* s1, void* heap, int type); #define WSTRNSTR(s1,s2,n) wstrnstr((s1),(s2),(n)) #define WSTRNCAT(s1,s2,n) wstrncat((s1),(s2),(n)) #define WSTRDUP(s,h,t) wstrdup((s),(h),(t)) @@ -1325,8 +1325,10 @@ extern "C" { #define WCLOSE(fs,fd) _close((fd)) #define WFD int - int wPwrite(WFD, unsigned char*, unsigned int, const unsigned int*); - int wPread(WFD, unsigned char*, unsigned int, const unsigned int*); + int wPwrite(WFD fd, unsigned char* buf, unsigned int sz, + const unsigned int* shortOffset); + int wPread(WFD fd, unsigned char* buf, unsigned int sz, + const unsigned int* shortOffset); #define WPWRITE(fs,fd,b,s,o) wPwrite((fd),(b),(s),(o)) #define WPREAD(fs,fd,b,s,o) wPread((fd),(b),(s),(o)) #define WS_DELIM '\\' @@ -1382,8 +1384,10 @@ extern "C" { #define WOPEN(fs,p,f,m) wssh_z_open((p),(f)) int wssh_z_close(WFD fd); #define WCLOSE(fs,fd) wssh_z_close((fd)) - int wPwrite(WFD, unsigned char*, unsigned int, const unsigned int*); - int wPread(WFD, unsigned char*, unsigned int, const unsigned int*); + int wPwrite(WFD fd, unsigned char* buf, unsigned int sz, + const unsigned int* shortOffset); + int wPread(WFD fd, unsigned char* buf, unsigned int sz, + const unsigned int* shortOffset); #define WPWRITE(fs,fd,b,s,o) wPwrite((fd),(b),(s),(o)) #define WPREAD(fs,fd,b,s,o) wPread((fd),(b),(s),(o)) @@ -1451,8 +1455,10 @@ extern "C" { /* Our "file descriptor" wrapper */ #define WFD SYS_FS_HANDLE - int wPwrite(WFD, unsigned char*, unsigned int, const unsigned int*); - int wPread(WFD, unsigned char*, unsigned int, const unsigned int*); + int wPwrite(WFD fd, unsigned char* buf, unsigned int sz, + const unsigned int* shortOffset); + int wPread(WFD fd, unsigned char* buf, unsigned int sz, + const unsigned int* shortOffset); #define WPWRITE(fs,fd,b,s,o) wPwrite((fd),(b),(s),(o)) #define WPREAD(fs,fd,b,s,o) wPread((fd),(b),(s),(o)) @@ -1487,8 +1493,10 @@ extern "C" { #define WOPEN(fs,f,m,p) open((f),(m),(p)) #define WCLOSE(fs,fd) close((fd)) - int wPwrite(WFD, unsigned char*, unsigned int, const unsigned int*); - int wPread(WFD, unsigned char*, unsigned int, const unsigned int*); + int wPwrite(WFD, unsigned char* buf, unsigned int sz, + const unsigned int* shortOffset); + int wPread(WFD, unsigned char* buf, unsigned int sz, + const unsigned int* shortOffset); #define WPWRITE(fs,fd,b,s,o) wPwrite((fd),(b),(s),(o)) #define WPREAD(fs,fd,b,s,o) wPread((fd),(b),(s),(o)) diff --git a/wolfssh/ssh.h b/wolfssh/ssh.h index 32143d58f..237377e03 100644 --- a/wolfssh/ssh.h +++ b/wolfssh/ssh.h @@ -61,21 +61,21 @@ WOLFSSH_API void wolfSSH_Debugging_ON(void); WOLFSSH_API void wolfSSH_Debugging_OFF(void); /* context functions */ -WOLFSSH_API WOLFSSH_CTX* wolfSSH_CTX_new(byte, void*); -WOLFSSH_API void wolfSSH_CTX_free(WOLFSSH_CTX*); +WOLFSSH_API WOLFSSH_CTX* wolfSSH_CTX_new(byte side, void* heap); +WOLFSSH_API void wolfSSH_CTX_free(WOLFSSH_CTX* ctx); /* ssh session functions */ -WOLFSSH_API WOLFSSH* wolfSSH_new(WOLFSSH_CTX*); -WOLFSSH_API void wolfSSH_free(WOLFSSH*); +WOLFSSH_API WOLFSSH* wolfSSH_new(WOLFSSH_CTX* ctx); +WOLFSSH_API void wolfSSH_free(WOLFSSH* ssh); -WOLFSSH_API int wolfSSH_worker(WOLFSSH*, word32*); -WOLFSSH_API int wolfSSH_GetLastRxId(WOLFSSH*, word32*); +WOLFSSH_API int wolfSSH_worker(WOLFSSH* ssh, word32* channelId); +WOLFSSH_API int wolfSSH_GetLastRxId(WOLFSSH* ssh, word32* channelId); -WOLFSSH_API int wolfSSH_set_fd(WOLFSSH*, WS_SOCKET_T); -WOLFSSH_API WS_SOCKET_T wolfSSH_get_fd(const WOLFSSH*); +WOLFSSH_API int wolfSSH_set_fd(WOLFSSH* ssh, WS_SOCKET_T fd); +WOLFSSH_API WS_SOCKET_T wolfSSH_get_fd(const WOLFSSH* ssh); -WOLFSSH_API int wolfSSH_SetFilesystemHandle(WOLFSSH*, void*); -WOLFSSH_API void* wolfSSH_GetFilesystemHandle(WOLFSSH*); +WOLFSSH_API int wolfSSH_SetFilesystemHandle(WOLFSSH* ssh, void* handle); +WOLFSSH_API void* wolfSSH_GetFilesystemHandle(WOLFSSH* ssh); /* data high water mark functions (RFC 4253 Sec 9) */ typedef int (*WS_CallbackHighwater)(byte side, void* ctx); @@ -166,11 +166,11 @@ typedef enum WS_Text { WOLFSSH_API size_t wolfSSH_GetText(WOLFSSH *ssh, WS_Text id, char *str, size_t strSz); -typedef void (*WS_CallbackKeyingCompletion)(void *); -WOLFSSH_API void wolfSSH_SetKeyingCompletionCb(WOLFSSH_CTX*, - WS_CallbackKeyingCompletion); -WOLFSSH_API void wolfSSH_SetKeyingCompletionCbCtx(WOLFSSH*, - void*); +typedef void (*WS_CallbackKeyingCompletion)(void* ctx); +WOLFSSH_API void wolfSSH_SetKeyingCompletionCb(WOLFSSH_CTX* ctx, + WS_CallbackKeyingCompletion cb); +WOLFSSH_API void wolfSSH_SetKeyingCompletionCbCtx(WOLFSSH* ssh, + void* ctx); #define WS_CHANNEL_ID_SELF 0 #define WS_CHANNEL_ID_PEER 1 @@ -206,32 +206,44 @@ typedef enum WS_FwdCbError { WS_FWD_PEER_E, } WS_FwdCbError; -typedef int (*WS_CallbackFwd)(WS_FwdCbAction, void*, const char*, word32); -typedef int (*WS_CallbackFwdIO)(WS_FwdIoCbAction, void*, word32, void*); - - -WOLFSSH_API WOLFSSH_CHANNEL* wolfSSH_ChannelFwdNewLocal(WOLFSSH*, - const char*, word32, const char*, word32); -WOLFSSH_API WOLFSSH_CHANNEL* wolfSSH_ChannelFwdNewRemote(WOLFSSH*, - const char*, word32, const char*, word32); -WOLFSSH_API int wolfSSH_CTX_SetFwdCb(WOLFSSH_CTX*, - WS_CallbackFwd, WS_CallbackFwdIO); -WOLFSSH_API int wolfSSH_SetFwdCbCtx(WOLFSSH*, void*); -WOLFSSH_API int wolfSSH_CTX_SetFwdEnable(WOLFSSH_CTX*, byte); -WOLFSSH_API int wolfSSH_SetFwdEnable(WOLFSSH*, byte); -DEPRECATED WOLFSSH_API WOLFSSH_CHANNEL* wolfSSH_ChannelFwdNew(WOLFSSH*, - const char*, word32, const char*, word32); -DEPRECATED WOLFSSH_API int wolfSSH_ChannelSetFwdFd(WOLFSSH_CHANNEL*, int); -DEPRECATED WOLFSSH_API int wolfSSH_ChannelGetFwdFd(const WOLFSSH_CHANNEL*); - -WOLFSSH_API int wolfSSH_ChannelFree(WOLFSSH_CHANNEL*); -WOLFSSH_API int wolfSSH_ChannelGetId(WOLFSSH_CHANNEL*, word32*, byte); -WOLFSSH_API WOLFSSH_CHANNEL* wolfSSH_ChannelFind(WOLFSSH*, word32, byte); -WOLFSSH_API WOLFSSH_CHANNEL* wolfSSH_ChannelNext(WOLFSSH*, WOLFSSH_CHANNEL*); -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*); +typedef int (*WS_CallbackFwd)(WS_FwdCbAction action, void* fwdCbCtx, + const char* address, word32 port); +typedef int (*WS_CallbackFwdIO)(WS_FwdIoCbAction action, void* fwdCbCtx, + word32 bufSz, void* buf); + + +WOLFSSH_API WOLFSSH_CHANNEL* wolfSSH_ChannelFwdNewLocal(WOLFSSH* ssh, + const char* host, word32 hostPort, const char* origin, + word32 originPort); +WOLFSSH_API WOLFSSH_CHANNEL* wolfSSH_ChannelFwdNewRemote(WOLFSSH* ssh, + const char* host, word32 hostPort, const char* origin, + word32 originPort); +WOLFSSH_API int wolfSSH_CTX_SetFwdCb(WOLFSSH_CTX* ctx, + WS_CallbackFwd fwdCb, WS_CallbackFwdIO fwdIoCb); +WOLFSSH_API int wolfSSH_SetFwdCbCtx(WOLFSSH* ssh, void* ctx); +WOLFSSH_API int wolfSSH_CTX_SetFwdEnable(WOLFSSH_CTX* ctx, byte enable); +WOLFSSH_API int wolfSSH_SetFwdEnable(WOLFSSH* ssh, byte enable); +DEPRECATED WOLFSSH_API WOLFSSH_CHANNEL* wolfSSH_ChannelFwdNew(WOLFSSH* ssh, + const char* host, word32 hostPort, const char* origin, + word32 originPort); +DEPRECATED WOLFSSH_API int wolfSSH_ChannelSetFwdFd(WOLFSSH_CHANNEL* channel, + int fwdFd); +DEPRECATED WOLFSSH_API int wolfSSH_ChannelGetFwdFd( + const WOLFSSH_CHANNEL* channel); + +WOLFSSH_API int wolfSSH_ChannelFree(WOLFSSH_CHANNEL* channel); +WOLFSSH_API int wolfSSH_ChannelGetId(WOLFSSH_CHANNEL* channel, word32* id, + byte peer); +WOLFSSH_API WOLFSSH_CHANNEL* wolfSSH_ChannelFind(WOLFSSH* ssh, word32 id, + byte peer); +WOLFSSH_API WOLFSSH_CHANNEL* wolfSSH_ChannelNext(WOLFSSH* ssh, + WOLFSSH_CHANNEL* channel); +WOLFSSH_API int wolfSSH_ChannelRead(WOLFSSH_CHANNEL* channel, byte* buf, + word32 bufSz); +WOLFSSH_API int wolfSSH_ChannelSend(WOLFSSH_CHANNEL* channel, const byte* buf, + word32 bufSz); +WOLFSSH_API int wolfSSH_ChannelExit(WOLFSSH_CHANNEL* channel); +WOLFSSH_API int wolfSSH_ChannelGetEof(WOLFSSH_CHANNEL* channel); WOLFSSH_API const char* wolfSSH_ChannelGetType( const WOLFSSH_CHANNEL* channel); WOLFSSH_API WS_SessionType wolfSSH_ChannelGetSessionType( @@ -271,9 +283,9 @@ WOLFSSH_API int wolfSSH_CTX_SetChannelCloseCb(WOLFSSH_CTX* ctx, 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); +WOLFSSH_API int wolfSSH_get_error(const WOLFSSH* ssh); +WOLFSSH_API const char* wolfSSH_get_error_name(const WOLFSSH* ssh); +WOLFSSH_API const char* wolfSSH_ErrorToName(int err); /* TPM 2.0 integration related functions */ #ifdef WOLFSSH_TPM @@ -284,28 +296,36 @@ WOLFSSH_API void* wolfSSH_GetTpmKey(WOLFSSH* ssh); #endif /* WOLFSSH_TPM */ /* I/O callbacks */ -typedef int (*WS_CallbackIORecv)(WOLFSSH*, void*, word32, void*); -typedef int (*WS_CallbackIOSend)(WOLFSSH*, void*, word32, void*); -WOLFSSH_API void wolfSSH_SetIORecv(WOLFSSH_CTX*, WS_CallbackIORecv); -WOLFSSH_API void wolfSSH_SetIOSend(WOLFSSH_CTX*, WS_CallbackIOSend); -WOLFSSH_API void wolfSSH_SetIOReadCtx(WOLFSSH*, void*); -WOLFSSH_API void wolfSSH_SetIOWriteCtx(WOLFSSH*, void*); -WOLFSSH_API void* wolfSSH_GetIOReadCtx(WOLFSSH*); -WOLFSSH_API void* wolfSSH_GetIOWriteCtx(WOLFSSH*); +typedef int (*WS_CallbackIORecv)(WOLFSSH* ssh, void* buf, word32 sz, + void* ctx); +typedef int (*WS_CallbackIOSend)(WOLFSSH* ssh, void* buf, word32 sz, + void* ctx); +WOLFSSH_API void wolfSSH_SetIORecv(WOLFSSH_CTX* ctx, WS_CallbackIORecv cb); +WOLFSSH_API void wolfSSH_SetIOSend(WOLFSSH_CTX* ctx, WS_CallbackIOSend cb); +WOLFSSH_API void wolfSSH_SetIOReadCtx(WOLFSSH* ssh, void* ctx); +WOLFSSH_API void wolfSSH_SetIOWriteCtx(WOLFSSH* ssh, void* ctx); +WOLFSSH_API void* wolfSSH_GetIOReadCtx(WOLFSSH* ssh); +WOLFSSH_API void* wolfSSH_GetIOWriteCtx(WOLFSSH* ssh); /* Global Request callbacks */ -typedef int (*WS_CallbackGlobalReq)(WOLFSSH*, void*, word32, int, void*); -WOLFSSH_API void wolfSSH_SetGlobalReq(WOLFSSH_CTX*, WS_CallbackGlobalReq); -WOLFSSH_API void wolfSSH_SetGlobalReqCtx(WOLFSSH*, void*); -WOLFSSH_API void *wolfSSH_GetGlobalReqCtx(WOLFSSH*); -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 *); +typedef int (*WS_CallbackGlobalReq)(WOLFSSH* ssh, void* buf, word32 sz, + int reply, void* ctx); +WOLFSSH_API void wolfSSH_SetGlobalReq(WOLFSSH_CTX* ctx, + WS_CallbackGlobalReq cb); +WOLFSSH_API void wolfSSH_SetGlobalReqCtx(WOLFSSH* ssh, void* ctx); +WOLFSSH_API void *wolfSSH_GetGlobalReqCtx(WOLFSSH* ssh); +typedef int (*WS_CallbackReqSuccess)(WOLFSSH* ssh, void* buf, word32 sz, + void* ctx); +WOLFSSH_API void wolfSSH_SetReqSuccess(WOLFSSH_CTX* ctx, + WS_CallbackReqSuccess cb); +WOLFSSH_API void wolfSSH_SetReqSuccessCtx(WOLFSSH* ssh, void * ctx); +WOLFSSH_API void* wolfSSH_GetReqSuccessCtx(WOLFSSH* ssh); +typedef int (*WS_CallbackReqFailure)(WOLFSSH* ssh, void* buf, word32 sz, + void* ctx); +WOLFSSH_API void wolfSSH_SetReqFailure(WOLFSSH_CTX * ctx, + WS_CallbackReqSuccess cb); +WOLFSSH_API void wolfSSH_SetReqFailureCtx(WOLFSSH * ssh, void * ctx); +WOLFSSH_API void *wolfSSH_GetReqFailureCtx(WOLFSSH * ssh); /* User Authentication callback */ typedef struct WS_UserAuthData_Password { @@ -366,13 +386,14 @@ typedef struct WS_UserAuthData { } sf; } WS_UserAuthData; -typedef int (*WS_CallbackUserAuth)(byte, WS_UserAuthData*, void*); -WOLFSSH_API void wolfSSH_SetUserAuth(WOLFSSH_CTX*, WS_CallbackUserAuth); +typedef int (*WS_CallbackUserAuth)(byte authType, WS_UserAuthData* authData, + void* ctx); +WOLFSSH_API void wolfSSH_SetUserAuth(WOLFSSH_CTX* ctx, WS_CallbackUserAuth cb); typedef int (*WS_CallbackUserAuthTypes)(WOLFSSH* ssh, void* ctx); -WOLFSSH_API void wolfSSH_SetUserAuthTypes(WOLFSSH_CTX*, - WS_CallbackUserAuthTypes); -WOLFSSH_API void wolfSSH_SetUserAuthCtx(WOLFSSH*, void*); -WOLFSSH_API void* wolfSSH_GetUserAuthCtx(WOLFSSH*); +WOLFSSH_API void wolfSSH_SetUserAuthTypes(WOLFSSH_CTX* ctx, + WS_CallbackUserAuthTypes cb); +WOLFSSH_API void wolfSSH_SetUserAuthCtx(WOLFSSH* ssh, void* userAuthCtx); +WOLFSSH_API void* wolfSSH_GetUserAuthCtx(WOLFSSH* ssh); typedef int (*WS_CallbackUserAuthResult)(byte result, WS_UserAuthData* authData, void* userAuthResultCtx); @@ -383,63 +404,78 @@ WOLFSSH_API void wolfSSH_SetUserAuthResultCtx(WOLFSSH* ssh, WOLFSSH_API void* wolfSSH_GetUserAuthResultCtx(WOLFSSH* ssh); /* Public Key Check Callback */ -typedef int (*WS_CallbackPublicKeyCheck)(const byte*, word32, void*); -WOLFSSH_API void wolfSSH_CTX_SetPublicKeyCheck(WOLFSSH_CTX*, - WS_CallbackPublicKeyCheck); -WOLFSSH_API void wolfSSH_SetPublicKeyCheckCtx(WOLFSSH*, void*); -WOLFSSH_API void* wolfSSH_GetPublicKeyCheckCtx(WOLFSSH*); - -WOLFSSH_API int wolfSSH_SetUsernameRaw(WOLFSSH*, const byte*, word32); -WOLFSSH_API int wolfSSH_SetUsername(WOLFSSH*, const char*); -WOLFSSH_API char* wolfSSH_GetUsername(WOLFSSH*); - -WOLFSSH_API int wolfSSH_CTX_SetBanner(WOLFSSH_CTX*, const char*); -WOLFSSH_API int wolfSSH_CTX_SetSshProtoIdStr(WOLFSSH_CTX*, const char*); -WOLFSSH_API int wolfSSH_CTX_UsePrivateKey_buffer(WOLFSSH_CTX*, - const byte*, word32, int); +typedef int (*WS_CallbackPublicKeyCheck)(const byte* publicKey, + word32 publicKeySz, void* ctx); +WOLFSSH_API void wolfSSH_CTX_SetPublicKeyCheck(WOLFSSH_CTX* ctx, + WS_CallbackPublicKeyCheck cb); +WOLFSSH_API void wolfSSH_SetPublicKeyCheckCtx(WOLFSSH* ssh, + void* publicKeyCheckCtx); +WOLFSSH_API void* wolfSSH_GetPublicKeyCheckCtx(WOLFSSH* ssh); + +WOLFSSH_API int wolfSSH_SetUsernameRaw(WOLFSSH* ssh, const byte* username, + word32 usernameSz); +WOLFSSH_API int wolfSSH_SetUsername(WOLFSSH* ssh, const char* username); +WOLFSSH_API char* wolfSSH_GetUsername(WOLFSSH* ssh); + +WOLFSSH_API int wolfSSH_CTX_SetBanner(WOLFSSH_CTX* ctx, const char* newBanner); +WOLFSSH_API int wolfSSH_CTX_SetSshProtoIdStr(WOLFSSH_CTX* ctx, + const char* protoIdStr); +WOLFSSH_API int wolfSSH_CTX_UsePrivateKey_buffer(WOLFSSH_CTX* ctx, + const byte* in, word32 inSz, + int format); #ifdef WOLFSSH_CERTS WOLFSSH_API int wolfSSH_CTX_UseCert_buffer(WOLFSSH_CTX* ctx, const byte* cert, word32 certSz, int format); WOLFSSH_API int wolfSSH_CTX_AddRootCert_buffer(WOLFSSH_CTX* ctx, const byte* cert, word32 certSz, int format); #endif /* WOLFSSH_CERTS */ -WOLFSSH_API int wolfSSH_CTX_SetWindowPacketSize(WOLFSSH_CTX*, word32, word32); - -WOLFSSH_API int wolfSSH_accept(WOLFSSH*); -WOLFSSH_API int wolfSSH_connect(WOLFSSH*); -WOLFSSH_API int wolfSSH_shutdown(WOLFSSH*); -WOLFSSH_API int wolfSSH_stream_peek(WOLFSSH*, byte*, word32); -WOLFSSH_API int wolfSSH_stream_read(WOLFSSH*, byte*, word32); -WOLFSSH_API int wolfSSH_stream_send(WOLFSSH*, byte*, word32); -WOLFSSH_API int wolfSSH_stream_exit(WOLFSSH*, int); +WOLFSSH_API int wolfSSH_CTX_SetWindowPacketSize(WOLFSSH_CTX* ctx, + word32 windowSz, word32 maxPacketSz); + +WOLFSSH_API int wolfSSH_accept(WOLFSSH* ssh); +WOLFSSH_API int wolfSSH_connect(WOLFSSH* ssh); +WOLFSSH_API int wolfSSH_shutdown(WOLFSSH* ssh); +WOLFSSH_API int wolfSSH_stream_peek(WOLFSSH* ssh, byte* buf, word32 bufSz); +WOLFSSH_API int wolfSSH_stream_read(WOLFSSH* ssh, byte* buf, word32 bufSz); +WOLFSSH_API int wolfSSH_stream_send(WOLFSSH* ssh, byte* buf, word32 bufSz); +WOLFSSH_API int wolfSSH_stream_exit(WOLFSSH* ssh, int status); WOLFSSH_API int wolfSSH_extended_data_send(WOLFSSH* ssh, byte* buf, word32 bufSz); -WOLFSSH_API int wolfSSH_extended_data_read(WOLFSSH*, byte*, word32); -WOLFSSH_API int wolfSSH_TriggerKeyExchange(WOLFSSH*); -WOLFSSH_API int wolfSSH_SendIgnore(WOLFSSH*, const byte*, word32); -WOLFSSH_API int wolfSSH_SendDisconnect(WOLFSSH*, word32); -WOLFSSH_API int wolfSSH_global_request(WOLFSSH*, const unsigned char*, word32, int); -WOLFSSH_API int wolfSSH_ChannelIdRead(WOLFSSH*, word32, byte*, word32); -WOLFSSH_API int wolfSSH_ChannelIdSend(WOLFSSH*, word32, byte*, word32); - -WOLFSSH_API void wolfSSH_GetStats(WOLFSSH*, - word32*, word32*, word32*, word32*); - -WOLFSSH_API int wolfSSH_KDF(byte, byte, byte*, word32, const byte*, word32, - const byte*, word32, const byte*, word32); +WOLFSSH_API int wolfSSH_extended_data_read(WOLFSSH* ssh, byte* out, + word32 outSz); +WOLFSSH_API int wolfSSH_TriggerKeyExchange(WOLFSSH* ssh); +WOLFSSH_API int wolfSSH_SendIgnore(WOLFSSH* ssh, const byte* buf, word32 bufSz); +WOLFSSH_API int wolfSSH_SendDisconnect(WOLFSSH* ssh, word32 reason); +WOLFSSH_API int wolfSSH_global_request(WOLFSSH* ssh, const unsigned char* data, + word32 dataSz, int reply); +WOLFSSH_API int wolfSSH_ChannelIdRead(WOLFSSH* ssh, word32 channelId, + byte* buf, word32 bufSz); +WOLFSSH_API int wolfSSH_ChannelIdSend(WOLFSSH* ssh, word32 channelId, + byte* buf, word32 bufSz); + +WOLFSSH_API void wolfSSH_GetStats(WOLFSSH* ssh, + word32* txCount, word32* rxCount, + word32* seq, word32* peerSeq); + +WOLFSSH_API int wolfSSH_KDF(byte hashId, byte keyId, byte* key, word32 keySz, + const byte* k, word32 kSz, + const byte* h, word32 hSz, + const byte* sessionId, word32 sessionIdSz); #ifdef USE_WINDOWS_API -WOLFSSH_API int wolfSSH_ConvertConsole(WOLFSSH*, WOLFSSH_HANDLE, byte*, word32); +WOLFSSH_API int wolfSSH_ConvertConsole(WOLFSSH* ssh, WOLFSSH_HANDLE handle, + byte* buf, word32 bufSz); #endif WOLFSSH_API int wolfSSH_DoModes(const byte* modes, word32 modesSz, int fd); -WOLFSSH_API WS_SessionType wolfSSH_GetSessionType(const WOLFSSH*); -WOLFSSH_API const char* wolfSSH_GetSessionCommand(const WOLFSSH*); -WOLFSSH_API int wolfSSH_SetChannelType(WOLFSSH*, byte, byte*, word32); -WOLFSSH_API int wolfSSH_ChangeTerminalSize(WOLFSSH* ssh, word32, word32, - word32, word32); -typedef int (*WS_CallbackTerminalSize)(WOLFSSH*, word32, word32, word32, - word32, void*); +WOLFSSH_API WS_SessionType wolfSSH_GetSessionType(const WOLFSSH* ssh); +WOLFSSH_API const char* wolfSSH_GetSessionCommand(const WOLFSSH* ssh); +WOLFSSH_API int wolfSSH_SetChannelType(WOLFSSH* ssh, byte type, byte* name, + word32 nameSz); +WOLFSSH_API int wolfSSH_ChangeTerminalSize(WOLFSSH* ssh, word32 columns, + word32 rows, word32 widthPixels, word32 heightPixels); +typedef int (*WS_CallbackTerminalSize)(WOLFSSH* ssh, word32 columns, + word32 rows, word32 widthPixels, word32 heightPixels, void* ctx); WOLFSSH_API void wolfSSH_SetTerminalResizeCb(WOLFSSH* ssh, WS_CallbackTerminalSize cb); WOLFSSH_API void wolfSSH_SetTerminalResizeCtx(WOLFSSH* ssh, void* usrCtx); diff --git a/wolfssh/wolfscp.h b/wolfssh/wolfscp.h index d1d6fc78c..e26942fda 100644 --- a/wolfssh/wolfscp.h +++ b/wolfssh/wolfscp.h @@ -116,27 +116,34 @@ enum WS_ScpFileStates { #endif /* NO_FILESYSTEM */ #endif /* WOLFSSH_SCP_USER_CALLBACKS */ -typedef int (*WS_CallbackScpRecv)(WOLFSSH*, int, const char*, const char*, - int, word64, word64, word32, byte*, word32, - word32, void*); -typedef int (*WS_CallbackScpSend)(WOLFSSH*, int, const char*, char*, word32, - word64*, word64*, int*, word32, word32*, - byte*, word32, void*); - -WOLFSSH_API void wolfSSH_SetScpRecv(WOLFSSH_CTX*, WS_CallbackScpRecv); -WOLFSSH_API void wolfSSH_SetScpSend(WOLFSSH_CTX*, WS_CallbackScpSend); - -WOLFSSH_API void wolfSSH_SetScpRecvCtx(WOLFSSH*, void*); -WOLFSSH_API void wolfSSH_SetScpSendCtx(WOLFSSH*, void*); - -WOLFSSH_API void* wolfSSH_GetScpRecvCtx(WOLFSSH*); -WOLFSSH_API void* wolfSSH_GetScpSendCtx(WOLFSSH*); - -WOLFSSH_API int wolfSSH_SetScpErrorMsg(WOLFSSH*, const char*); - -WOLFSSH_API int wolfSSH_SCP_connect(WOLFSSH*, byte*); -WOLFSSH_API int wolfSSH_SCP_to(WOLFSSH*, const char*, const char*); -WOLFSSH_API int wolfSSH_SCP_from(WOLFSSH*, const char*, const char*); +typedef int (*WS_CallbackScpRecv)(WOLFSSH* ssh, int state, + const char* basePath, const char* fileName, + int fileMode, word64 mTime, word64 aTime, + word32 totalFileSz, byte* buf, word32 bufSz, + word32 fileOffset, void* ctx); +typedef int (*WS_CallbackScpSend)(WOLFSSH* ssh, int state, + const char* peerRequest, char* fileName, + word32 fileNameSz, word64* mTime, + word64* aTime, int* fileMode, + word32 fileOffset, word32* totalFileSz, + byte* buf, word32 bufSz, void* ctx); + +WOLFSSH_API void wolfSSH_SetScpRecv(WOLFSSH_CTX* ctx, WS_CallbackScpRecv cb); +WOLFSSH_API void wolfSSH_SetScpSend(WOLFSSH_CTX* ctx, WS_CallbackScpSend cb); + +WOLFSSH_API void wolfSSH_SetScpRecvCtx(WOLFSSH* ssh, void* ctx); +WOLFSSH_API void wolfSSH_SetScpSendCtx(WOLFSSH* ssh, void* ctx); + +WOLFSSH_API void* wolfSSH_GetScpRecvCtx(WOLFSSH* ssh); +WOLFSSH_API void* wolfSSH_GetScpSendCtx(WOLFSSH* ssh); + +WOLFSSH_API int wolfSSH_SetScpErrorMsg(WOLFSSH* ssh, const char* message); + +WOLFSSH_API int wolfSSH_SCP_connect(WOLFSSH* ssh, byte* cmd); +WOLFSSH_API int wolfSSH_SCP_to(WOLFSSH* ssh, const char* src, + const char* dst); +WOLFSSH_API int wolfSSH_SCP_from(WOLFSSH* ssh, const char* src, + const char* dst); #ifdef __cplusplus diff --git a/wolfssh/wolfsftp.h b/wolfssh/wolfsftp.h index 655c87427..ecc34285a 100644 --- a/wolfssh/wolfsftp.h +++ b/wolfssh/wolfsftp.h @@ -222,7 +222,7 @@ WOLFSSH_API int wolfSSH_SFTP_Rename(WOLFSSH* ssh, const char* old, WOLFSSH_API WS_SFTPNAME* wolfSSH_SFTP_LS(WOLFSSH* ssh, char* dir); WOLFSSH_API int wolfSSH_SFTP_CHMOD(WOLFSSH* ssh, char* n, char* oct); -typedef void(WS_STATUS_CB)(WOLFSSH*, word32*, char*); +typedef void(WS_STATUS_CB)(WOLFSSH* ssh, word32* offset, char* fileName); WOLFSSH_API int wolfSSH_SFTP_Get(WOLFSSH* ssh, char* from, char* to, byte resume, WS_STATUS_CB* statusCb); WOLFSSH_API int wolfSSH_SFTP_Put(WOLFSSH* ssh, char* from, char* to, From e8a5f731fc69ff5a3250af5b29e8453f6b7a5eb0 Mon Sep 17 00:00:00 2001 From: John Safranek Date: Thu, 4 Jun 2026 13:36:25 -0700 Subject: [PATCH 2/6] Remove redundant preprocessor guard Cleanup clang-tidy readability-redundant-preprocessor finding. --- src/internal.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/internal.c b/src/internal.c index b50a45721..89931a1d6 100644 --- a/src/internal.c +++ b/src/internal.c @@ -7561,7 +7561,6 @@ static int DoUserAuthRequestRsaCert(WOLFSSH* ssh, WS_UserAuthData_PublicKey* pk, publicKeyTypeSz) == 0) { sigTypeOk = 1; } - #ifdef WOLFSSH_CERTS else if (publicKeyType != NULL && pk->publicKeyTypeSz == 14 && WMEMCMP(pk->publicKeyType, @@ -7579,7 +7578,6 @@ static int DoUserAuthRequestRsaCert(WOLFSSH* ssh, WS_UserAuthData_PublicKey* pk, sigTypeOk = 1; } } - #endif if (!sigTypeOk) { WLOG(WS_LOG_DEBUG, "Signature's type does not match public key type"); From ecfc756765394a3182daf423f75fa89ba876ba75 Mon Sep 17 00:00:00 2001 From: John Safranek Date: Thu, 4 Jun 2026 13:48:31 -0700 Subject: [PATCH 3/6] Move unsafe call out of signal handler Cleanup clang-tidy bugprone-signal-handler findings. - wolfsshd: drop fprintf from interruptCatch; the main accept loop logs "Closing down wolfSSHD" after seeing quit set. - sftpclient: annotate wolfSSH_SFTP_Interrupt call in sig_handler with NOLINT, since the function is only a single byte store and is safe to call from a signal handler. --- apps/wolfsshd/wolfsshd.c | 5 +++-- examples/sftpclient/sftpclient.c | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/apps/wolfsshd/wolfsshd.c b/apps/wolfsshd/wolfsshd.c index 0d1785d08..21ab585f0 100644 --- a/apps/wolfsshd/wolfsshd.c +++ b/apps/wolfsshd/wolfsshd.c @@ -203,8 +203,6 @@ static void ShowUsage(void) static void interruptCatch(int in) { (void)in; - if (logFile) - fprintf(logFile, "Closing down wolfSSHD\n"); quit = 1; } @@ -2753,6 +2751,9 @@ static int StartSSHD(int argc, char** argv) } #endif } + if (quit && logFile) { + fprintf(logFile, "Closing down wolfSSHD\n"); + } } #ifdef _WIN32 diff --git a/examples/sftpclient/sftpclient.c b/examples/sftpclient/sftpclient.c index b73e89244..c3b5cf9a1 100644 --- a/examples/sftpclient/sftpclient.c +++ b/examples/sftpclient/sftpclient.c @@ -268,7 +268,7 @@ static void sig_handler(const int sig) (void)sig; interrupt = 1; - wolfSSH_SFTP_Interrupt(ssh); + wolfSSH_SFTP_Interrupt(ssh); /* NOLINT(bugprone-signal-handler) */ } #endif /* WS_NO_SIGNAL */ From 34a455f4a6e90176f2258dd8f0844a1ce813e23a Mon Sep 17 00:00:00 2001 From: John Safranek Date: Thu, 4 Jun 2026 13:58:24 -0700 Subject: [PATCH 4/6] Use reentrant time conversion in SFTP Cleanup clang-tidy concurrency-mt-unsafe finding. Note, this originally used gmtime which provided UTC based time values. Now, the wolfSFTP server will provide localtimes for file timestamps. The exception is Zephyr, which only provides UTC times. - SFTP_CreateLongName: switch from XGMTIME (gmtime) to WLOCALTIME, which expands to localtime_r/localtime_s per platform. - Note in the Zephyr WLOCALTIME macro that gmtime_r is used because Zephyr's minimal libc does not provide localtime_r. --- src/wolfsftp.c | 23 +++++++++++++---------- wolfssh/port.h | 2 ++ 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/src/wolfsftp.c b/src/wolfsftp.c index e13adaf55..dc47bdd4f 100644 --- a/src/wolfsftp.c +++ b/src/wolfsftp.c @@ -41,7 +41,7 @@ #endif #endif -/* for XGMTIME if defined */ +/* for WLOCALTIME if defined */ #include @@ -2721,7 +2721,7 @@ int wolfSSH_SFTP_RecvOpenDir(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz) #define WS_DATE_SIZE 12 -#if defined(XGMTIME) && defined(XSNPRINTF) +#if defined(XSNPRINTF) /* converts epoch time to recommended calendar time from * draft-ietf-secsh-filexfer-02.txt */ static void getDate(char* buf, int len, struct tm* t) @@ -2762,12 +2762,13 @@ static void getDate(char* buf, int len, struct tm* t) * return WS_SUCCESS on success */ static int SFTP_CreateLongName(WS_SFTPNAME* name) { -#if defined(XGMTIME) && defined(XSNPRINTF) +#if defined(XSNPRINTF) char sizeStr[32]; char perm[11]; int linkCount = 1; /* @TODO set to correct value */ char date[WS_DATE_SIZE + 1]; /* +1 for null terminator */ - struct tm* localTime = NULL; + struct tm localTime; + time_t mtime; int i; WS_SFTP_FILEATRB* atr; #endif @@ -2777,15 +2778,17 @@ static int SFTP_CreateLongName(WS_SFTPNAME* name) return WS_BAD_ARGUMENT; } -#if defined(XGMTIME) && defined(XSNPRINTF) +#if defined(XSNPRINTF) atr = &name->atrb; - /* get date as calendar date */ - localTime = XGMTIME((const time_t*)&atr->mtime, &localTime); - if (localTime == NULL) { + /* get date as calendar date; use the reentrant WLOCALTIME + * wrapper so the shared static buffer behind gmtime() is + * not used. */ + mtime = (time_t)atr->mtime; + if (!WLOCALTIME(&mtime, &localTime)) { return WS_MEMORY_E; } - getDate(date, sizeof(date), localTime); + getDate(date, sizeof(date), &localTime); totalSz += WS_DATE_SIZE; /* set permissions */ @@ -2838,7 +2841,7 @@ static int SFTP_CreateLongName(WS_SFTPNAME* name) name->lSz = totalSz; name->lName[totalSz] = '\0'; -#if defined(XGMTIME) && defined(XSNPRINTF) +#if defined(XSNPRINTF) WSNPRINTF(name->lName, totalSz, "%s %3d %8d %8d %s %s %s", perm, linkCount, atr->uid, atr->gid, sizeStr, date, name->fName); #else diff --git a/wolfssh/port.h b/wolfssh/port.h index 73645ea71..44be5c68f 100644 --- a/wolfssh/port.h +++ b/wolfssh/port.h @@ -622,6 +622,8 @@ extern "C" { #define WOLFSSH_NO_TIMESTAMP /* no strftime() */ #elif defined(WOLFSSH_ZEPHYR) #define WTIME time + /* Zephyr's minimal libc provides gmtime_r but not localtime_r, + * so timestamps are reported in UTC on this platform. */ #define WLOCALTIME(c,r) (gmtime_r((c),(r))!=NULL) #elif defined(WOLFSSL_NUCLEUS) #define WTIME time From 1c46c277cfb2a853c0e520a838ba8aa41692c344 Mon Sep 17 00:00:00 2001 From: John Safranek Date: Thu, 4 Jun 2026 14:02:44 -0700 Subject: [PATCH 5/6] Tighten SCP timestamp bounds check Cleanup clang-tidy bugprone-inc-dec-in-conditions finding. - ParseTimestamp: move ++idx out of the || conditions and tighten the bound from > bufSz to >= bufSz. --- src/wolfscp.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/wolfscp.c b/src/wolfscp.c index 5bdbc4973..d7d219597 100644 --- a/src/wolfscp.c +++ b/src/wolfscp.c @@ -1078,12 +1078,19 @@ static int GetScpTimestamp(WOLFSSH* ssh, byte* buf, word32 bufSz, /* skip '0 ' */ if (ret == WS_SUCCESS) { - if (buf[idx] != '0' || ++idx > bufSz) + if (buf[idx] != '0') { ret = WS_SCP_TIMESTAMP_E; - - if (ret == WS_SUCCESS) { - if (buf[idx] != ' ' || ++idx > bufSz) + } + else { + idx++; + if (idx >= bufSz || buf[idx] != ' ') { ret = WS_SCP_TIMESTAMP_E; + } + else { + idx++; + if (idx >= bufSz) + ret = WS_SCP_TIMESTAMP_E; + } } } From f658e6eec46039c7b1ca5ae40342784e26d762de Mon Sep 17 00:00:00 2001 From: John Safranek Date: Thu, 4 Jun 2026 14:07:56 -0700 Subject: [PATCH 6/6] Bound sshd Include directive recursion Cleanup clang-tidy misc-no-recursion finding. - wolfSSHD_ConfigLoad: track depth on WOLFSSHD_CONFIG and reject loads past WOLFSSHD_MAX_INCLUDE_DEPTH (16). - HandleInclude, HandleConfigOption, ParseConfigLine, wolfSSHD_ConfigLoad: annotate the call cycle with NOLINTNEXTLINE pointing at the bound. - Add a recursive configuration test. --- apps/wolfsshd/configuration.c | 51 +++++++++++---- apps/wolfsshd/configuration.h | 2 +- apps/wolfsshd/test/test_configuration.c | 83 ++++++++++++++++++++++++- 3 files changed, 120 insertions(+), 16 deletions(-) diff --git a/apps/wolfsshd/configuration.c b/apps/wolfsshd/configuration.c index 8e84f95e2..9afc37828 100644 --- a/apps/wolfsshd/configuration.c +++ b/apps/wolfsshd/configuration.c @@ -91,8 +91,16 @@ struct WOLFSSHD_CONFIG { byte authKeysFileSet:1; /* if not set then no explicit authorized keys */ }; -int CountWhitespace(const char* in, int inSz, byte inv); -int SetFileString(char** dst, const char* src, void* heap); +/* Maximum depth of nested Include directives. Bounds the recursion + * through wolfSSHD_ConfigLoad -> ParseConfigLine -> HandleConfigOption + * -> HandleInclude -> wolfSSHD_ConfigLoad. */ +#ifndef WOLFSSHD_MAX_INCLUDE_DEPTH +#define WOLFSSHD_MAX_INCLUDE_DEPTH 16 +#endif +static int ConfigLoad(WOLFSSHD_CONFIG* conf, const char* filename, int depth); + +static int CountWhitespace(const char* in, int inSz, byte inv); +static int SetFileString(char** dst, const char* src, void* heap); /* convert a string into seconds, handles if 'm' for minutes follows the string * number, i.e. 2m @@ -616,7 +624,8 @@ static int HandlePort(WOLFSSHD_CONFIG* conf, const char* value) return ret; } -static int HandleInclude(WOLFSSHD_CONFIG *conf, const char *value) +/* NOLINTNEXTLINE(misc-no-recursion): bounded by WOLFSSHD_MAX_INCLUDE_DEPTH */ +static int HandleInclude(WOLFSSHD_CONFIG *conf, const char *value, int depth) { const char *ptr; const char *ptr2; @@ -802,7 +811,7 @@ static int HandleInclude(WOLFSSHD_CONFIG *conf, const char *value) WSNPRINTF(filepath, PATH_MAX, "%s/%s", path, fileNames[i]); } - ret = wolfSSHD_ConfigLoad(conf, filepath); + ret = ConfigLoad(conf, filepath, depth); if (ret != WS_SUCCESS) { break; } @@ -834,7 +843,7 @@ static int HandleInclude(WOLFSSHD_CONFIG *conf, const char *value) #endif } else { - ret = wolfSSHD_ConfigLoad(conf, value); + ret = ConfigLoad(conf, value, depth); } } return ret; @@ -974,8 +983,9 @@ static int HandleForcedCommand(WOLFSSHD_CONFIG* conf, const char* value, } /* returns WS_SUCCESS on success */ +/* NOLINTNEXTLINE(misc-no-recursion): bounded by WOLFSSHD_MAX_INCLUDE_DEPTH */ static int HandleConfigOption(WOLFSSHD_CONFIG** conf, int opt, - const char* value, const char* full, int fullSz) + const char* value, const char* full, int fullSz, int depth) { int ret = WS_BAD_ARGUMENT; @@ -1043,7 +1053,7 @@ static int HandleConfigOption(WOLFSSHD_CONFIG** conf, int opt, ret = WS_SUCCESS; break; case OPT_INCLUDE: - ret = HandleInclude(*conf, value); + ret = HandleInclude(*conf, value, depth); break; case OPT_CHROOT_DIR: ret = HandleChrootDir(*conf, value); @@ -1074,7 +1084,7 @@ static int HandleConfigOption(WOLFSSHD_CONFIG** conf, int opt, /* helper function to count white spaces, returns the number of white spaces on * success */ -int CountWhitespace(const char* in, int inSz, byte inv) +static int CountWhitespace(const char* in, int inSz, byte inv) { int i = 0; @@ -1100,8 +1110,9 @@ int CountWhitespace(const char* in, int inSz, byte inv) * Fails if any option is found that is unknown/unsupported * Match command will create new configs for specific matching cases */ +/* NOLINTNEXTLINE(misc-no-recursion): bounded by WOLFSSHD_MAX_INCLUDE_DEPTH */ WOLFSSHD_STATIC int ParseConfigLine(WOLFSSHD_CONFIG** conf, const char* l, - int lSz) + int lSz, int depth) { int ret = WS_BAD_ARGUMENT; int sz = 0; @@ -1132,7 +1143,8 @@ WOLFSSHD_STATIC int ParseConfigLine(WOLFSSHD_CONFIG** conf, const char* l, else { WMEMCPY(tmp, l + idx, sz); tmp[sz] = 0; - ret = HandleConfigOption(conf, found->tag, tmp, l + idx, lSz - idx); + ret = HandleConfigOption(conf, + found->tag, tmp, l + idx, lSz - idx, depth); } } else { @@ -1153,6 +1165,13 @@ WOLFSSHD_STATIC int ParseConfigLine(WOLFSSHD_CONFIG** conf, const char* l, * returns WS_SUCCESS on success */ int wolfSSHD_ConfigLoad(WOLFSSHD_CONFIG* conf, const char* filename) +{ + return ConfigLoad(conf, filename, 0); +} + + +/* NOLINTNEXTLINE(misc-no-recursion): bounded by WOLFSSHD_MAX_INCLUDE_DEPTH */ +static int ConfigLoad(WOLFSSHD_CONFIG* conf, const char* filename, int depth) { WFILE *f; WOLFSSHD_CONFIG* currentConfig; @@ -1163,12 +1182,20 @@ int wolfSSHD_ConfigLoad(WOLFSSHD_CONFIG* conf, const char* filename) if (conf == NULL || filename == NULL) return BAD_FUNC_ARG; + if (depth >= WOLFSSHD_MAX_INCLUDE_DEPTH) { + wolfSSH_Log(WS_LOG_ERROR, + "[SSHD] Include depth (%d) exceeded loading %s", + WOLFSSHD_MAX_INCLUDE_DEPTH, filename); + return WS_BAD_ARGUMENT; + } + if (WFOPEN(NULL, &f, filename, "rb") != 0) { wolfSSH_Log(WS_LOG_ERROR, "Unable to open SSHD config file %s", filename); return BAD_FUNC_ARG; } wolfSSH_Log(WS_LOG_INFO, "[SSHD] parsing config file %s", filename); + depth++; currentConfig = conf; while ((current = XFGETS(buf, MAX_LINE_SIZE, f)) != NULL) { @@ -1189,7 +1216,7 @@ int wolfSSHD_ConfigLoad(WOLFSSHD_CONFIG* conf, const char* filename) continue; /* commented out line */ } - ret = ParseConfigLine(¤tConfig, current, currentSz); + ret = ParseConfigLine(¤tConfig, current, currentSz, depth); if (ret != WS_SUCCESS) { fprintf(stderr, "Unable to parse config line : %s\n", current); break; @@ -1358,7 +1385,7 @@ char* wolfSSHD_ConfigGetUserCAKeysFile(const WOLFSSHD_CONFIG* conf) return ret; } -int SetFileString(char** dst, const char* src, void* heap) +static int SetFileString(char** dst, const char* src, void* heap) { int ret = WS_SUCCESS; diff --git a/apps/wolfsshd/configuration.h b/apps/wolfsshd/configuration.h index 064db6bbb..d2b491109 100644 --- a/apps/wolfsshd/configuration.h +++ b/apps/wolfsshd/configuration.h @@ -59,7 +59,7 @@ WOLFSSHD_CONFIG* wolfSSHD_GetUserConf(const WOLFSSHD_CONFIG* conf, void wolfSSHD_ConfigSavePID(const WOLFSSHD_CONFIG* conf); #ifdef WOLFSSHD_UNIT_TEST -int ParseConfigLine(WOLFSSHD_CONFIG** conf, const char* l, int lSz); +int ParseConfigLine(WOLFSSHD_CONFIG** conf, const char* l, int lSz, int depth); #endif #endif /* WOLFSSHD_H */ diff --git a/apps/wolfsshd/test/test_configuration.c b/apps/wolfsshd/test/test_configuration.c index 711bac6bb..67593824e 100644 --- a/apps/wolfsshd/test/test_configuration.c +++ b/apps/wolfsshd/test/test_configuration.c @@ -261,7 +261,7 @@ static int test_ParseConfigLine(void) Log(" Testing scenario: %s.", vectors[i].desc); ret = ParseConfigLine(&conf, vectors[i].line, - (int)WSTRLEN(vectors[i].line)); + (int)WSTRLEN(vectors[i].line), 0); if ((ret == WS_SUCCESS && !vectors[i].shouldFail) || (ret != WS_SUCCESS && vectors[i].shouldFail)) { @@ -293,7 +293,7 @@ static int test_ConfigCopy(void) conf = head; /* string fields via ParseConfigLine */ -#define PCL(s) ParseConfigLine(&conf, s, (int)WSTRLEN(s)) +#define PCL(s) ParseConfigLine(&conf, s, (int)WSTRLEN(s), 0) if (ret == WS_SUCCESS) ret = PCL("Banner /etc/issue"); if (ret == WS_SUCCESS) ret = PCL("ChrootDirectory /var/chroot"); if (ret == WS_SUCCESS) ret = PCL("HostKey /etc/ssh/ssh_host_key"); @@ -406,6 +406,82 @@ static int test_ConfigCopy(void) return ret; } +/* Bounded recursion through Include directives: a self-including config + * must fail with WS_BAD_ARGUMENT once the depth limit is hit, and the + * config object must remain usable so a subsequent load of a normal + * config on the same WOLFSSHD_CONFIG still succeeds. */ +static int test_IncludeRecursionBound(void) +{ + int ret = WS_SUCCESS; + WOLFSSHD_CONFIG* conf = NULL; + WFILE* f = NULL; + const char* loopPath = "./include_loop.conf"; + const char* normalPath = "./include_normal.conf"; + const char* loopContents = "Include ./include_loop.conf\n"; + const char* normalContents = "Port 22\n"; + word32 sz, wr; + + WFOPEN(NULL, &f, loopPath, "w"); + if (f == NULL) { + Log(" Could not create %s.\n", loopPath); + return WS_FATAL_ERROR; + } + sz = (word32)WSTRLEN(loopContents); + wr = (word32)WFWRITE(NULL, loopContents, sizeof(char), sz, f); + WFCLOSE(NULL, f); + if (sz != wr) { + WREMOVE(0, loopPath); + return WS_FATAL_ERROR; + } + + WFOPEN(NULL, &f, normalPath, "w"); + if (f == NULL) { + WREMOVE(0, loopPath); + Log(" Could not create %s.\n", normalPath); + return WS_FATAL_ERROR; + } + sz = (word32)WSTRLEN(normalContents); + wr = (word32)WFWRITE(NULL, normalContents, sizeof(char), sz, f); + WFCLOSE(NULL, f); + if (sz != wr) { + WREMOVE(0, loopPath); + WREMOVE(0, normalPath); + return WS_FATAL_ERROR; + } + + conf = wolfSSHD_ConfigNew(NULL); + if (conf == NULL) { + ret = WS_MEMORY_E; + } + + if (ret == WS_SUCCESS) { + Log(" Testing scenario: self-include hits depth bound."); + if (wolfSSHD_ConfigLoad(conf, loopPath) == WS_BAD_ARGUMENT) { + Log(" PASSED.\n"); + } + else { + Log(" FAILED.\n"); + ret = WS_FATAL_ERROR; + } + } + + if (ret == WS_SUCCESS) { + Log(" Testing scenario: config reusable after failed include."); + if (wolfSSHD_ConfigLoad(conf, normalPath) == WS_SUCCESS) { + Log(" PASSED.\n"); + } + else { + Log(" FAILED.\n"); + ret = WS_FATAL_ERROR; + } + } + + wolfSSHD_ConfigFree(conf); + WREMOVE(0, loopPath); + WREMOVE(0, normalPath); + return ret; +} + /* Verifies ConfigFree releases all string fields - most useful under ASan. */ static int test_ConfigFree(void) { @@ -418,7 +494,7 @@ static int test_ConfigFree(void) ret = WS_MEMORY_E; conf = head; -#define PCL(s) ParseConfigLine(&conf, s, (int)WSTRLEN(s)) +#define PCL(s) ParseConfigLine(&conf, s, (int)WSTRLEN(s), 0) if (ret == WS_SUCCESS) ret = PCL("Banner /etc/issue"); if (ret == WS_SUCCESS) ret = PCL("ChrootDirectory /var/chroot"); if (ret == WS_SUCCESS) ret = PCL("HostKey /etc/ssh/ssh_host_key"); @@ -707,6 +783,7 @@ const TEST_CASE testCases[] = { TEST_DECL(test_ConfigDefaults), TEST_DECL(test_ParseConfigLine), TEST_DECL(test_ConfigCopy), + TEST_DECL(test_IncludeRecursionBound), TEST_DECL(test_ConfigFree), #ifdef WOLFSSL_BASE64_ENCODE TEST_DECL(test_CheckAuthKeysLine),