mirror of https://github.com/wolfSSL/wolfssh.git
Add a test program, test_configuration.c, for testing sshd config.
I wanted to be able to test ParseConfigLine directly, so I added some preprocessor logic to expose this function (i.e. make it non-static) when building test_configuration. I fixed a couple bugs discovered by this new testing.pull/435/head
parent
f7fad8b8d0
commit
90769af1f8
|
@ -26,6 +26,12 @@
|
|||
/* functions for parsing out options from a config file and for handling loading
|
||||
* key/certs using the env. filesystem */
|
||||
|
||||
#ifdef WOLFSSHD_UNIT_TEST
|
||||
#define WOLFSSHD_STATIC
|
||||
#else
|
||||
#define WOLFSSHD_STATIC static
|
||||
#endif
|
||||
|
||||
#include <wolfssh/ssh.h>
|
||||
#include <wolfssh/internal.h>
|
||||
#include <wolfssh/log.h>
|
||||
|
@ -91,7 +97,10 @@ static long GetConfigInt(const char* in, int inSz, int isTime, void* heap)
|
|||
WMEMCPY(num, in, sz);
|
||||
num[sz] = '\0';
|
||||
ret = atol(num);
|
||||
if (ret > 0) {
|
||||
if (ret == 0 && WSTRCMP(in, "0") != 0) {
|
||||
ret = WS_BAD_ARGUMENT;
|
||||
}
|
||||
else if (ret > 0) {
|
||||
ret = ret * mult;
|
||||
}
|
||||
WFREE(num, heap, DYNTYPE_SSHD);
|
||||
|
@ -228,17 +237,14 @@ static int HandlePrivSep(WOLFSSHD_CONFIG* conf, const char* value)
|
|||
if (WSTRCMP(value, "sandbox") == 0) {
|
||||
wolfSSH_Log(WS_LOG_INFO, "[SSHD] Sandbox privilege separation");
|
||||
}
|
||||
|
||||
if (WSTRCMP(value, "yes") == 0) {
|
||||
else if (WSTRCMP(value, "yes") == 0) {
|
||||
wolfSSH_Log(WS_LOG_INFO, "[SSHD] Privilege separation enabled");
|
||||
}
|
||||
|
||||
if (WSTRCMP(value, "no") == 0) {
|
||||
else if (WSTRCMP(value, "no") == 0) {
|
||||
wolfSSH_Log(WS_LOG_INFO,
|
||||
"[SSHD] Turning off privilege separation!");
|
||||
}
|
||||
|
||||
if (ret != WS_SUCCESS) {
|
||||
else {
|
||||
wolfSSH_Log(WS_LOG_ERROR,
|
||||
"[SSHD] Unknown/supported privilege separation!");
|
||||
ret = WS_BAD_ARGUMENT;
|
||||
|
@ -331,7 +337,7 @@ static int HandlePort(WOLFSSHD_CONFIG* conf, const char* value)
|
|||
|
||||
if (ret == WS_SUCCESS) {
|
||||
portInt = XATOI(value);
|
||||
if (portInt < 0) {
|
||||
if (portInt <= 0) {
|
||||
wolfSSH_Log(WS_LOG_ERROR, "[SSHD] Unable to parse port number: %s.",
|
||||
value);
|
||||
ret = WS_BAD_ARGUMENT;
|
||||
|
@ -437,7 +443,8 @@ static int CountWhitespace(const char* in, int inSz, byte inv)
|
|||
/* returns WS_SUCCESS on success
|
||||
* Fails if any option is found that is unknown/unsupported
|
||||
*/
|
||||
static int ParseConfigLine(WOLFSSHD_CONFIG* conf, const char* l, int lSz)
|
||||
WOLFSSHD_STATIC int ParseConfigLine(WOLFSSHD_CONFIG* conf, const char* l,
|
||||
int lSz)
|
||||
{
|
||||
int ret = WS_BAD_ARGUMENT;
|
||||
int sz;
|
||||
|
|
|
@ -25,7 +25,6 @@ typedef struct WOLFSSHD_CONFIG WOLFSSHD_CONFIG;
|
|||
|
||||
#include "auth.h"
|
||||
|
||||
|
||||
#define WOLFSSHD_PRIV_SEPARAT 0
|
||||
#define WOLFSSHD_PRIV_SANDBOX 1
|
||||
#define WOLFSSHD_PRIV_OFF 2
|
||||
|
@ -44,5 +43,9 @@ byte wolfSSHD_ConfigGetPermitEmptyPw(const WOLFSSHD_CONFIG* conf);
|
|||
long wolfSSHD_ConfigGetGraceTime(const WOLFSSHD_CONFIG* conf);
|
||||
byte wolfSSHD_ConfigGetPwAuth(const WOLFSSHD_CONFIG* conf);
|
||||
|
||||
#ifdef WOLFSSHD_UNIT_TEST
|
||||
int ParseConfigLine(WOLFSSHD_CONFIG* conf, const char* l, int lSz);
|
||||
#endif
|
||||
|
||||
#endif /* WOLFSSHD_H */
|
||||
|
||||
|
|
|
@ -9,6 +9,15 @@ apps_wolfsshd_wolfsshd_SOURCES = apps/wolfsshd/wolfsshd.c \
|
|||
apps_wolfsshd_wolfsshd_LDADD = src/libwolfssh.la
|
||||
apps_wolfsshd_wolfsshd_DEPENDENCIES = src/libwolfssh.la
|
||||
|
||||
DISTCLEANFILES+= apps/wolfsshd/.libs/wolfsshd
|
||||
noinst_PROGRAMS += apps/wolfsshd/test/test_configuration
|
||||
apps_wolfsshd_test_test_configuration_SOURCES = apps/wolfsshd/test/test_configuration.c \
|
||||
apps/wolfsshd/configuration.c \
|
||||
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/
|
||||
|
||||
DISTCLEANFILES+= apps/wolfsshd/.libs/wolfsshd \
|
||||
apps/wolfsshd/test/.libs/test_configuration
|
||||
|
||||
endif BUILD_SSHD
|
||||
|
|
|
@ -0,0 +1,149 @@
|
|||
#include <stdarg.h>
|
||||
|
||||
#include <wolfssh/ssh.h>
|
||||
#include <configuration.h>
|
||||
|
||||
static void Log(const char* fmt, ...)
|
||||
{
|
||||
va_list vlist;
|
||||
|
||||
va_start(vlist, fmt);
|
||||
vfprintf(stderr, fmt, vlist);
|
||||
va_end(vlist);
|
||||
}
|
||||
|
||||
typedef int (*TEST_FUNC)(void);
|
||||
typedef struct {
|
||||
const char *name;
|
||||
TEST_FUNC func;
|
||||
} TEST_CASE;
|
||||
|
||||
#define TEST_DECL(func) { #func, func }
|
||||
|
||||
#define TEST_CASE_CNT (int)(sizeof(testCases) / sizeof(*testCases))
|
||||
|
||||
static void TestSetup(const TEST_CASE* tc)
|
||||
{
|
||||
Log("Running %s.\n", tc->name);
|
||||
}
|
||||
|
||||
static void TestCleanup(void)
|
||||
{
|
||||
}
|
||||
|
||||
static int RunTest(const TEST_CASE* tc)
|
||||
{
|
||||
int ret;
|
||||
|
||||
TestSetup(tc);
|
||||
|
||||
ret = tc->func();
|
||||
if (ret != 0) {
|
||||
Log("%s FAILED.\n", tc->name);
|
||||
}
|
||||
else {
|
||||
Log("%s PASSED.\n", tc->name);
|
||||
}
|
||||
|
||||
TestCleanup();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
const char* desc;
|
||||
const char* line;
|
||||
int shouldFail;
|
||||
} CONFIG_LINE_VECTOR;
|
||||
|
||||
static int test_ParseConfigLine(void)
|
||||
{
|
||||
int ret = WS_SUCCESS;
|
||||
int i;
|
||||
WOLFSSHD_CONFIG* conf;
|
||||
|
||||
static CONFIG_LINE_VECTOR vectors[] = {
|
||||
/* Port tests. */
|
||||
{"Valid port", "Port 22", 0},
|
||||
{"Port too big", "Port 65536", 1},
|
||||
{"Negative port", "Port -99", 1},
|
||||
{"Port NaN", "Port wolfsshd", 1},
|
||||
{"Port no value", "Port \n", 1},
|
||||
|
||||
/* Whitespace tests. */
|
||||
{"Extra leading whitespace", "Port 22", 0},
|
||||
{"Extra trailing whitespace", "Port 22 \n", 0},
|
||||
|
||||
/* Privilege separation tests. */
|
||||
{"Privilege separation yes", "UsePrivilegeSeparation yes", 0},
|
||||
{"Privilege separation no", "UsePrivilegeSeparation no", 0},
|
||||
{"Privilege separation sandbox", "UsePrivilegeSeparation sandbox", 0},
|
||||
{"Privilege separation invalid", "UsePrivilegeSeparation wolfsshd", 1},
|
||||
|
||||
/* Login grace time tests. */
|
||||
{"Valid login grace time seconds", "LoginGraceTime 60", 0},
|
||||
{"Valid login grace time minutes", "LoginGraceTime 1m", 0},
|
||||
{"Valid login grace time hours", "LoginGraceTime 1h", 0},
|
||||
{"Invalid login grace time", "LoginGraceTime wolfsshd", 1},
|
||||
|
||||
/* Permit empty password tests. */
|
||||
{"Permit empty password no", "PermitEmptyPasswords no", 0},
|
||||
{"Permit empty password yes", "PermitEmptyPasswords yes", 0},
|
||||
{"Permit empty password invalid", "PermitEmptyPasswords wolfsshd", 1},
|
||||
|
||||
/* Password auth tests. */
|
||||
{"Password auth no", "PasswordAuthentication no", 0},
|
||||
{"Password auth yes", "PasswordAuthentication yes", 0},
|
||||
{"Password auth invalid", "PasswordAuthentication wolfsshd", 1},
|
||||
};
|
||||
const int numVectors = (int)(sizeof(vectors) / sizeof(*vectors));
|
||||
|
||||
conf = wolfSSHD_NewConfig(NULL);
|
||||
if (conf == NULL) {
|
||||
ret = WS_MEMORY_E;
|
||||
}
|
||||
|
||||
if (ret == WS_SUCCESS) {
|
||||
for (i = 0; i < numVectors; ++i) {
|
||||
Log(" Testing scenario: %s.", vectors[i].desc);
|
||||
|
||||
ret = ParseConfigLine(conf, vectors[i].line,
|
||||
WSTRLEN(vectors[i].line));
|
||||
|
||||
if ((ret == WS_SUCCESS && !vectors[i].shouldFail) ||
|
||||
(ret != WS_SUCCESS && vectors[i].shouldFail)) {
|
||||
Log(" PASSED.\n");
|
||||
ret = WS_SUCCESS;
|
||||
}
|
||||
else {
|
||||
Log(" FAILED.\n");
|
||||
ret = WS_FATAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
const TEST_CASE testCases[] = {
|
||||
TEST_DECL(test_ParseConfigLine)
|
||||
};
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
int i;
|
||||
int ret = WS_SUCCESS;
|
||||
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
|
||||
for (i = 0; i < TEST_CASE_CNT; ++i) {
|
||||
ret = RunTest(&testCases[i]);
|
||||
if (ret != WS_SUCCESS) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
Loading…
Reference in New Issue