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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions apps/wolfsshd/configuration.c
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,16 @@ struct WOLFSSHD_CONFIG {
byte permitRootLogin:1;
byte permitEmptyPasswords:1;
byte authKeysFileSet:1; /* if not set then no explicit authorized keys */
byte includeDepth; /* current Include recursion depth */
};

/* 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

int CountWhitespace(const char* in, int inSz, byte inv);
int SetFileString(char** dst, const char* src, void* heap);

Expand Down Expand Up @@ -616,6 +624,7 @@ static int HandlePort(WOLFSSHD_CONFIG* conf, const char* value)
return ret;
}

/* NOLINTNEXTLINE(misc-no-recursion): bounded by WOLFSSHD_MAX_INCLUDE_DEPTH */
static int HandleInclude(WOLFSSHD_CONFIG *conf, const char *value)
{
const char *ptr;
Expand Down Expand Up @@ -974,6 +983,7 @@ 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)
{
Expand Down Expand Up @@ -1100,6 +1110,7 @@ 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)
{
Expand Down Expand Up @@ -1152,6 +1163,7 @@ WOLFSSHD_STATIC int ParseConfigLine(WOLFSSHD_CONFIG** conf, const char* l,
/* parses and loads in the given configuration file 'filename'
* returns WS_SUCCESS on success
*/
/* NOLINTNEXTLINE(misc-no-recursion): bounded by WOLFSSHD_MAX_INCLUDE_DEPTH */
int wolfSSHD_ConfigLoad(WOLFSSHD_CONFIG* conf, const char* filename)
{
WFILE *f;
Expand All @@ -1163,12 +1175,20 @@ int wolfSSHD_ConfigLoad(WOLFSSHD_CONFIG* conf, const char* filename)
if (conf == NULL || filename == NULL)
return BAD_FUNC_ARG;

if (conf->includeDepth >= 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;
}
Comment thread
ejohnstown marked this conversation as resolved.

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);
conf->includeDepth++;

currentConfig = conf;
while ((current = XFGETS(buf, MAX_LINE_SIZE, f)) != NULL) {
Expand Down Expand Up @@ -1196,6 +1216,7 @@ int wolfSSHD_ConfigLoad(WOLFSSHD_CONFIG* conf, const char* filename)
}
}
WFCLOSE(NULL, f);
conf->includeDepth--;

SetAuthKeysPattern(conf->authKeysFile);

Expand Down
79 changes: 78 additions & 1 deletion apps/wolfsshd/test/test_configuration.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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
* per-config depth counter must be restored so a subsequent load of a
* normal 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: depth counter restored after failure.");
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)
{
Expand Down Expand Up @@ -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),
Expand Down
5 changes: 3 additions & 2 deletions apps/wolfsshd/wolfsshd.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down Expand Up @@ -2753,6 +2751,9 @@ static int StartSSHD(int argc, char** argv)
}
#endif
}
if (quit && logFile) {
fprintf(logFile, "Closing down wolfSSHD\n");
}
}

#ifdef _WIN32
Expand Down
2 changes: 1 addition & 1 deletion examples/scpclient/scpclient.h
Original file line number Diff line number Diff line change
Expand Up @@ -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_ */
4 changes: 2 additions & 2 deletions examples/sftpclient/sftpclient.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 <time.h>
#define WIN32_LEAN_AND_MEAN
Expand Down Expand Up @@ -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 */

Expand Down
2 changes: 0 additions & 2 deletions src/internal.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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");
Expand Down
3 changes: 2 additions & 1 deletion src/log.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
15 changes: 11 additions & 4 deletions src/wolfscp.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}
}

Expand Down
21 changes: 12 additions & 9 deletions src/wolfsftp.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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
Expand All @@ -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. */
Comment thread
ejohnstown marked this conversation as resolved.
mtime = (time_t)atr->mtime;
if (!WLOCALTIME(&mtime, &localTime)) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This switches from UTC time to local time in all platforms except Zephyr which uses gmtime_r (in port.h). Is this ok?

return WS_MEMORY_E;
}
getDate(date, sizeof(date), localTime);
getDate(date, sizeof(date), &localTime);
totalSz += WS_DATE_SIZE;

/* set permissions */
Expand Down Expand Up @@ -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
Expand Down
33 changes: 18 additions & 15 deletions wolfssh/agent.h
Original file line number Diff line number Diff line change
Expand Up @@ -169,21 +169,24 @@ 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);
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
Expand Down
Loading
Loading