mirror of https://github.com/wolfSSL/wolfssh.git
Merge pull request #445 from ejohnstown/wildcard
commit
8cda0c4cc9
|
@ -58,6 +58,7 @@ examples/scpclient/wolfscp
|
|||
|
||||
# applications
|
||||
apps/wolfsshd/wolfsshd
|
||||
apps/wolfsshd/test/test_configuration
|
||||
|
||||
# test output
|
||||
tests/*.test
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
Loading…
Reference in New Issue