Merge pull request #445 from ejohnstown/wildcard

pull/447/head
Hayden Roche 2022-08-29 17:44:45 -07:00 committed by GitHub
commit 8cda0c4cc9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 278 additions and 114 deletions

1
.gitignore vendored
View File

@ -58,6 +58,7 @@ examples/scpclient/wolfscp
# applications
apps/wolfsshd/wolfsshd
apps/wolfsshd/test/test_configuration
# test output
tests/*.test

View File

@ -35,6 +35,7 @@
#include <wolfssh/ssh.h>
#include <wolfssh/internal.h>
#include <wolfssh/log.h>
#include <wolfssh/port.h>
#include <wolfssl/wolfcrypt/wc_port.h>
#include <wolfssl/wolfcrypt/error-crypt.h>
@ -59,7 +60,7 @@ struct WOLFSSHD_CONFIG {
char* authKeysFile;
long loginTimer;
word16 port;
byte usePrivilegeSeparation;
byte usePrivilegeSeparation:2;
byte passwordAuth:1;
byte pubKeyAuth:1;
byte permitRootLogin:1;
@ -436,135 +437,204 @@ static int HandleInclude(WOLFSSHD_CONFIG *conf, const char *value)
const char *prefix = NULL;
int prefixLen = 0;
int found = 0;
int ret = WS_SUCCESS;
/* No value, nothing to do */
if (!value || value[0] == '\0') {
return WS_BAD_ARGUMENT;
ret = WS_BAD_ARGUMENT;
}
/* Ignore trailing whitespace */
ptr = value + WSTRLEN(value) - 1;
while (ptr != value) {
if (!WISSPACE(*ptr)) {
ptr--;
}
else {
break;
}
}
/* Find wildcards */
ptr2 = ptr;
while (ptr2 != value) {
if (*ptr2 == '*') {
/* Wildcard found */
found = 1;
if (ptr != ptr2) {
postfix = ptr2 + 1;
if (ret == WS_SUCCESS) {
/* Ignore trailing whitespace */
ptr = value + WSTRLEN(value) - 1;
while (ptr != value) {
if (WISSPACE(*ptr)) {
ptr--;
}
else {
break;
}
break;
}
if (*ptr2 == '/') {
/* Found slash before wildcard directory-wildcards not supported */
break;
}
ptr2--;
}
ptr = ptr2;
/* Use wildcard */
if (found) {
#ifdef __unix__
int ret;
struct dirent *dir;
DIR *d;
char *path;
char *filepath = (char*)WMALLOC(PATH_MAX, NULL, 0);
/* Back find the full path */
/* Find wildcards */
ptr2 = ptr;
while (ptr2 != value) {
if (*ptr2 == '*') {
/* Wildcard found */
found = 1;
if (ptr != ptr2) {
postfix = ptr2 + 1;
}
break;
}
if (*ptr2 == '/') {
/* Found slash before wildcard directory-wildcards
* not supported */
break;
}
ptr2--;
}
ptr = ptr2;
if (ptr2 != value) {
path = (char*)WMALLOC(ptr2 - value + 1, NULL, 0);
memcpy(path, value, ptr2 - value);
path[ptr2 - value] = '\0';
prefix = ptr2 + 1;
prefixLen = (int)(ptr - ptr2 - 1);
} else {
path = (char*)WMALLOC(2, NULL, 0);
memcpy(path, ".", 1);
path[1] = '\0';
prefix = value;
prefixLen = (int)(ptr - value);
}
/* Use wildcard */
if (found) {
#if defined(__unix__) || defined(__unix) || \
(defined(__APPLE__) && defined(__MACH__))
struct dirent *dir;
WDIR d;
char *path = NULL;
char *filepath = (char*)WMALLOC(PATH_MAX, conf->heap, DYNTYPE_PATH);
d = opendir(path);
if (d) {
while ((dir = readdir(d)) != NULL) {
if (dir->d_type == DT_DIR) {
/* Skip sub-directories */
continue;
}
else {
/* Check if filename prefix matches */
if (prefixLen > 0) {
if ((int)WSTRLEN(dir->d_name) <= prefixLen) {
continue;
}
if (WSTRNCMP(dir->d_name, prefix, prefixLen) != 0) {
continue;
}
if (filepath == NULL) {
ret = WS_MEMORY_E;
}
if (ret == WS_SUCCESS) {
/* Back find the full path */
while (ptr2 != value) {
if (*ptr2 == '/') {
break;
}
if (postfix) {
/* Skip if file is too short */
if (WSTRLEN(dir->d_name) <= WSTRLEN(postfix)) {
continue;
}
if (WSTRNCMP(dir->d_name + WSTRLEN(dir->d_name) -
WSTRLEN(postfix), postfix, WSTRLEN(postfix))
== 0) {
snprintf(filepath, PATH_MAX, "%s/%s", path,
dir->d_name);
}
else {
/* Not a match */
continue;
}
ptr2--;
}
if (ptr2 != value) {
path = (char*)WMALLOC(ptr2 - value + 1,
conf->heap, DYNTYPE_PATH);
if (path == NULL) {
ret = WS_MEMORY_E;
}
else {
snprintf(filepath, PATH_MAX, "%s/%s", path,
dir->d_name);
WMEMCPY(path, value, ptr2 - value);
path[ptr2 - value] = '\0';
prefix = ptr2 + 1;
prefixLen = (int)(ptr - ptr2 - 1);
}
ret = wolfSSHD_ConfigLoad(conf, filepath);
if (ret != WS_SUCCESS) {
return ret;
}
else {
path = (char*)WMALLOC(2, conf->heap, DYNTYPE_PATH);
if (path == NULL) {
ret = WS_MEMORY_E;
}
else {
WMEMCPY(path, ".", 1);
path[1] = '\0';
prefix = value;
prefixLen = (int)(ptr - value);
}
}
}
if (ret == WS_SUCCESS) {
if (!WOPENDIR(NULL, conf->heap, &d, path)) {
word32 fileCount = 0, i, j;
char** fileNames = NULL;
/* Count up the number of files */
while ((dir = WREADDIR(&d)) != NULL) {
/* Skip sub-directories */
if (dir->d_type != DT_DIR) {
fileCount++;
}
}
WREWINDDIR(&d);
if (fileCount > 0) {
fileNames = (char**)WMALLOC(fileCount * sizeof(char*),
conf->heap, DYNTYPE_PATH);
if (fileNames == NULL) {
ret = WS_MEMORY_E;
}
}
if (ret == WS_SUCCESS) {
i = 0;
while (i < fileCount && (dir = WREADDIR(&d)) != NULL) {
/* Skip sub-directories */
if (dir->d_type != DT_DIR) {
/* Insert in string order */
for (j = 0; j < i; j++) {
if (WSTRCMP(dir->d_name, fileNames[j])
< 0) {
WMEMMOVE(fileNames+j+1, fileNames+j,
(i - j)*sizeof(char*));
break;
}
}
fileNames[j] = dir->d_name;
i++;
}
}
for (i = 0; i < fileCount; i++) {
/* Check if filename prefix matches */
if (prefixLen > 0) {
if ((int)WSTRLEN(fileNames[i]) <= prefixLen) {
continue;
}
if (WSTRNCMP(fileNames[i], prefix, prefixLen)
!= 0) {
continue;
}
}
if (postfix) {
/* Skip if file is too short */
if (WSTRLEN(fileNames[i]) <= WSTRLEN(postfix)) {
continue;
}
if (WSTRNCMP(fileNames[i] +
WSTRLEN(fileNames[i]) -
WSTRLEN(postfix),
postfix, WSTRLEN(postfix))
== 0) {
WSNPRINTF(filepath, PATH_MAX, "%s/%s", path,
fileNames[i]);
}
else {
/* Not a match */
continue;
}
}
else {
WSNPRINTF(filepath, PATH_MAX, "%s/%s", path,
fileNames[i]);
}
ret = wolfSSHD_ConfigLoad(conf, filepath);
if (ret != WS_SUCCESS) {
break;
}
}
if (fileNames != NULL) {
WFREE(fileNames, conf->heap, DYNTYPE_PATH);
}
}
WCLOSEDIR(&d);
}
else {
/* Bad directory */
ret = WS_INVALID_PATH_E;
}
}
if (path != NULL) {
WFREE(path, conf->heap, DYNTYPE_PATH);
}
if (filepath != NULL) {
WFREE(filepath, conf->heap, DYNTYPE_PATH);
}
#else
(void)postfix;
(void)prefixLen;
(void)prefix;
/* Don't support wildcards here */
ret = WS_BAD_ARGUMENT;
#endif
}
else {
/* Bad directory */
WFREE(filepath, NULL, 0);
return WS_BAD_ARGUMENT;
ret = wolfSSHD_ConfigLoad(conf, value);
}
WFREE(filepath, NULL, 0);
#else
(void)postfix;
(void)prefixLen;
(void)prefix;
/* Don't support wildcards here */
return WS_BAD_ARGUMENT;
#endif
}
else {
return wolfSSHD_ConfigLoad(conf, value);
}
return WS_SUCCESS;
return ret;
}
/* returns WS_SUCCESS on success */
@ -726,7 +796,7 @@ int wolfSSHD_ConfigLoad(WOLFSSHD_CONFIG* conf, const char* filename)
f = XFOPEN(filename, "rb");
if (f == XBADFILE) {
wolfSSH_Log(WS_LOG_ERROR, "Unable to open SSHD config file %s\n",
wolfSSH_Log(WS_LOG_ERROR, "Unable to open SSHD config file %s",
filename);
return BAD_FUNC_ARG;
}

View File

@ -15,7 +15,7 @@ apps_wolfsshd_test_test_configuration_SOURCES = apps/wolfsshd/test/test_configur
apps/wolfsshd/auth.c
apps_wolfsshd_test_test_configuration_LDADD = src/libwolfssh.la
apps_wolfsshd_test_test_configuration_DEPENDENCIES = src/libwolfssh.la
apps_wolfsshd_test_test_configuration_CPPFLAGS = -DWOLFSSH_SSHD -DWOLFSSHD_UNIT_TEST -Iapps/wolfsshd/
apps_wolfsshd_test_test_configuration_CPPFLAGS = $(AM_CPPFLAGS) -DWOLFSSH_SSHD -DWOLFSSHD_UNIT_TEST -Iapps/wolfsshd/
DISTCLEANFILES+= apps/wolfsshd/.libs/wolfsshd \
apps/wolfsshd/test/.libs/test_configuration

View File

@ -26,6 +26,77 @@ void Log(const char *const fmt, ...)
va_end(vlist);
}
static void CleanupWildcardTest(void)
{
WDIR dir;
struct dirent* d;
char filepath[MAX_PATH*2]; /* d_name is max_path long */
if (!WOPENDIR(NULL, NULL, &dir, "./sshd_config.d/")) {
while ((d = WREADDIR(&dir)) != NULL) {
if (d->d_type != DT_DIR) {
WSNPRINTF(filepath, sizeof filepath, "%s%s",
"./sshd_config.d/", d->d_name);
WREMOVE(0, filepath);
}
}
WCLOSEDIR(&dir);
WRMDIR(0, "./sshd_config.d/");
}
}
static int SetupWildcardTest(void)
{
WFILE* f;
const byte fileIds[] = { 0, 1, 50, 59, 99 };
word32 fileIdsSz = (word32)(sizeof(fileIds) / sizeof(byte));
word32 i;
int ret;
char filepath[MAX_PATH];
ret = WMKDIR(0, "./sshd_config.d/", 0755);
if (ret == 0) {
for (i = 0; i < fileIdsSz; i++) {
if (fileIds[i] != 0) {
WSNPRINTF(filepath, sizeof filepath, "%s%02u-test.conf",
"./sshd_config.d/", fileIds[i]);
}
else {
WSNPRINTF(filepath, sizeof filepath, "%stest.bad",
"./sshd_config.d/");
}
WFOPEN(&f, filepath, "w");
if (f) {
word32 sz, wr;
char contents[20];
WSNPRINTF(contents, sizeof contents, "LoginGraceTime %02u",
fileIds[i]);
sz = (word32)WSTRLEN(contents);
wr = (word32)WFWRITE(contents, sizeof(char), sz, f);
WFCLOSE(f);
if (sz != wr) {
Log("Couldn't write the contents of file %s\n", filepath);
ret = WS_FATAL_ERROR;
break;
}
}
else {
Log("Couldn't create the file %s\n", filepath);
ret = WS_FATAL_ERROR;
break;
}
}
}
else {
Log("Couldn't make the test config directory\n");
ret = WS_FATAL_ERROR;
}
return ret;
}
typedef int (*TEST_FUNC)(void);
typedef struct {
const char *name;
@ -110,6 +181,13 @@ static int test_ParseConfigLine(void)
{"Password auth no", "PasswordAuthentication no", 0},
{"Password auth yes", "PasswordAuthentication yes", 0},
{"Password auth invalid", "PasswordAuthentication wolfsshd", 1},
/* Include files tests. */
{"Include file bad", "Include sshd_config.d/test.bad", 1},
{"Include file exists", "Include sshd_config.d/01-test.conf", 0},
{"Include file DNE", "Include sshd_config.d/test-dne.conf", 1},
{"Include wildcard exists", "Include sshd_config.d/*.conf", 0},
{"Include wildcard NDE", "Include sshd_config.d/*.dne", 0},
};
const int numVectors = (int)(sizeof(vectors) / sizeof(*vectors));
@ -136,6 +214,7 @@ static int test_ParseConfigLine(void)
break;
}
}
wolfSSHD_ConfigFree(conf);
}
return ret;
@ -153,12 +232,19 @@ int main(int argc, char** argv)
(void)argc;
(void)argv;
for (i = 0; i < TEST_CASE_CNT; ++i) {
ret = RunTest(&testCases[i]);
if (ret != WS_SUCCESS) {
break;
CleanupWildcardTest();
ret = SetupWildcardTest();
if (ret == 0) {
for (i = 0; i < TEST_CASE_CNT; ++i) {
ret = RunTest(&testCases[i]);
if (ret != WS_SUCCESS) {
break;
}
}
}
CleanupWildcardTest();
return ret;
}

View File

@ -267,6 +267,8 @@ THREAD_RETURN WOLFSSH_THREAD portfwd_worker(void* args)
break;
case 'f':
if (myoptarg == NULL)
err_sys("null argument found");
fwdFromPort = (word16)atoi(myoptarg);
break;
@ -281,6 +283,8 @@ THREAD_RETURN WOLFSSH_THREAD portfwd_worker(void* args)
break;
case 't':
if (myoptarg == NULL)
err_sys("null argument found");
fwdToPort = (word16)atoi(myoptarg);
break;

View File

@ -342,7 +342,8 @@ extern "C" {
#define WCHMOD(fs,f,m) _chmod((f),(m))
#endif
#if (defined(WOLFSSH_SCP) || defined(WOLFSSH_SFTP)) && \
#if (defined(WOLFSSH_SCP) || \
defined(WOLFSSH_SFTP) || defined(WOLFSSH_SSHD)) && \
!defined(WOLFSSH_SCP_USER_CALLBACKS)
#ifdef USE_WINDOWS_API
@ -476,8 +477,9 @@ extern "C" {
#define WLOCALTIME(c,r) (localtime_r((c),(r))!=NULL)
#endif
#if (defined(WOLFSSH_SFTP) || defined(WOLFSSH_SCP)) && \
!defined(NO_WOLFSSH_SERVER) && !defined(NO_FILESYSTEM)
#if (defined(WOLFSSH_SFTP) || \
defined(WOLFSSH_SCP) || defined(WOLFSSH_SSHD)) && \
!defined(NO_WOLFSSH_SERVER) && !defined(NO_FILESYSTEM)
#ifndef SIZEOF_OFF_T
/* if not using autoconf then make a guess on off_t size based on sizeof
@ -1219,8 +1221,9 @@ extern "C" {
/* returns 0 on success */
#define WOPENDIR(fs,h,c,d) ((*(c) = opendir((d))) == NULL)
#define WCLOSEDIR(d) closedir(*(d))
#define WREADDIR(d) readdir(*(d))
#define WCLOSEDIR(d) closedir(*(d))
#define WREADDIR(d) readdir(*(d))
#define WREWINDDIR(d) rewinddir(*(d))
#endif /* NO_WOLFSSH_DIR */
#endif
#endif /* WOLFSSH_SFTP or WOLFSSH_SCP */