diff --git a/apps/wolfconfig.c b/apps/wolfconfig.c index 25c92117..8c59fd29 100644 --- a/apps/wolfconfig.c +++ b/apps/wolfconfig.c @@ -51,7 +51,7 @@ struct WOLFSSHD_CONFIG { char* kekAlgos; char* listenAddress; char* authKeysFile; - word32 port; + word16 port; byte passwordAuth:1; byte pubKeyAuth:1; byte permitRootLogin:1; @@ -59,7 +59,45 @@ struct WOLFSSHD_CONFIG { byte usePrivilegeSeparation:1; }; -WOLFSSHD_CONFIG* wolfSSH_NewConfig(void* heap) +/* returns WS_SUCCESS on success */ +static int wolfSSHD_CreateString(char** out, const char* in, int inSz, + void* heap) +{ + int ret = WS_SUCCESS; + int idx = 0; + + /* remove white spaces */ + while (idx < inSz && in[idx] == ' ') idx++; + + if (idx == inSz) { + ret = WS_BAD_ARGUMENT; + } + + /* malloc new string and set it */ + if (ret == WS_SUCCESS) { + *out = (char*)WMALLOC((inSz - idx) + 1, heap, DYNTYPE_SSHD); + if (*out == NULL) { + ret = WS_MEMORY_E; + } + else { + XMEMCPY(*out, in + idx, inSz - idx); + *(*out + (inSz - idx)) = '\0'; + } + } + + return ret; +} + +static void wolfSSHD_FreeString(char** in, void* heap) +{ + if (*in != NULL) { + WFREE(*in, heap, DYNTYPE_SSHD); + *in = NULL; + } + (void)heap; +} + +WOLFSSHD_CONFIG* wolfSSHD_NewConfig(void* heap) { WOLFSSHD_CONFIG* ret; @@ -70,24 +108,66 @@ WOLFSSHD_CONFIG* wolfSSH_NewConfig(void* heap) } else { WMEMSET(ret, 0, sizeof(WOLFSSHD_CONFIG)); + + /* default values */ + ret->port = 22; } return ret; } -void wolfSSH_FreeConfig(WOLFSSHD_CONFIG* conf) +void wolfSSHD_FreeConfig(WOLFSSHD_CONFIG* conf) { void* heap; if (conf != NULL) { heap = conf->heap; + wolfSSHD_FreeString(&conf->authKeysFile, heap); + WFREE(conf, heap, DYNTYPE_SSHD); } } #define MAX_LINE_SIZE 160 -int wolfSSH_LoadSSHD(WOLFSSHD_CONFIG* conf, const char* filename) + +/* returns WS_SUCCESS on success + * Fails if any option is found that is unknown/unsupported + */ +static int wolfSSHD_ParseConfigLine(WOLFSSHD_CONFIG* conf, const char* l, + int lSz) +{ + int ret = WS_BAD_ARGUMENT; + int sz; + + /* supported config options */ + const char authKeyFile[] = "AuthorizedKeysFile"; + + sz = (int)XSTRLEN(authKeyFile); + if (lSz > sz && XSTRNCMP(l, authKeyFile, sz) == 0) { + ret = wolfSSHD_CreateString(&conf->authKeysFile, l + sz, lSz - sz, + conf->heap); + } + + if (XSTRNCMP(l, "UsePrivilegeSeparation", 18) == 0) { + ret = WS_SUCCESS; + } + + if (XSTRNCMP(l, "Subsystem", 9) == 0) { + + ret = WS_SUCCESS; + } + + if (ret == WS_BAD_ARGUMENT) { + printf("unknown / unsuported config line\n"); + } + + (void)conf;(void)lSz; + return ret; +} + + +int wolfSSHD_LoadSSHD(WOLFSSHD_CONFIG* conf, const char* filename) { XFILE f; int ret = WS_SUCCESS; @@ -116,11 +196,28 @@ int wolfSSH_LoadSSHD(WOLFSSHD_CONFIG* conf, const char* filename) continue; /* commented out line */ } - printf("read config : %s\n", current); + ret = wolfSSHD_ParseConfigLine(conf, current, currentSz); + if (ret != WS_SUCCESS) { + printf("Unable to parse config line : %s\n", current); + break; + } } XFCLOSE(f); return ret; } +char* wolfSSHD_GetBanner(WOLFSSHD_CONFIG* conf) +{ + if (conf != NULL) + return conf->banner; + return NULL; +} + +word16 wolfSSHD_GetPort(WOLFSSHD_CONFIG* conf) +{ + if (conf != NULL) + return conf->port; + return 0; +} #endif /* WOLFSSH_SSHD */ diff --git a/apps/wolfsshd.c b/apps/wolfsshd.c index 5d0a5e4d..f6c177af 100644 --- a/apps/wolfsshd.c +++ b/apps/wolfsshd.c @@ -26,11 +26,13 @@ #include #include -#include #include #include #include +#define WOLFSSH_TEST_SERVER +#include + #include "wolfsshd.h" #include @@ -44,6 +46,13 @@ /* catch interrupts and close down gracefully */ static volatile byte quit = 0; +static const char defaultBanner[] = "wolfSSHD\n"; + +/* Initial connection information to pass on to threads/forks */ +typedef struct WOLFSSHD_CONNECTION { + WOLFSSH_CTX* ctx; + int fd; +} WOLFSSHD_CONNECTION; static void ShowUsage(void) { @@ -59,18 +68,240 @@ static void interruptCatch(int in) quit = 1; } +static int SetupCTX(WOLFSSHD_CONFIG* conf, WOLFSSH_CTX** ctx) +{ + int ret = WS_SUCCESS; + const char* banner; + + /* create a new WOLFSSH_CTX */ + *ctx = wolfSSH_CTX_new(WOLFSSH_ENDPOINT_SERVER, NULL); + if (ctx == NULL) { + fprintf(stderr, "Couldn't allocate SSH CTX data.\n"); + ret = WS_MEMORY_E; + } + + /* setup authority callback for checking peer connections */ + if (ret == WS_SUCCESS) { +// WMEMSET(&pwMapList, 0, sizeof(pwMapList)); +// if (serverArgs->user_auth == NULL) +// wolfSSH_SetUserAuth(ctx, wsUserAuth); +// else +// wolfSSH_SetUserAuth(ctx, ((func_args*)args)->user_auth); + } + + /* set banner to display on connection */ + if (ret == WS_SUCCESS) { + banner = wolfSSHD_GetBanner(conf); + if (banner == NULL) { + banner = defaultBanner; + } + wolfSSH_CTX_SetBanner(*ctx, banner); + } + +#ifdef WOLFSSH_AGENT + /* check if using an agent is enabled */ + if (ret == WS_SUCCESS) { + wolfSSH_CTX_set_agent_cb(ctx, wolfSSH_AGENT_DefaultActions, NULL); + } +#endif + +#ifdef WOLFSSH_FWD + /* check if port forwarding is enabled */ + if (ret == WS_SUCCESS) { + wolfSSH_CTX_SetFwdCb(ctx, wolfSSH_FwdDefaultActions, NULL); + } +#endif + + /* Load in host private key */ +// { +// const char* bufName = NULL; +// #ifndef WOLFSSH_SMALL_STACK +// byte buf[EXAMPLE_KEYLOAD_BUFFER_SZ]; +// #endif +// byte* keyLoadBuf; +// word32 bufSz; +// +// #ifdef WOLFSSH_SMALL_STACK +// keyLoadBuf = (byte*)WMALLOC(EXAMPLE_KEYLOAD_BUFFER_SZ, +// NULL, 0); +// if (keyLoadBuf == NULL) { +// WEXIT(EXIT_FAILURE); +// } +// #else +// keyLoadBuf = buf; +// #endif +// bufSz = EXAMPLE_KEYLOAD_BUFFER_SZ; +// +// bufSz = load_key(peerEcc, keyLoadBuf, bufSz); +// if (bufSz == 0) { +// fprintf(stderr, "Couldn't load key file.\n"); +// WEXIT(EXIT_FAILURE); +// } +// if (wolfSSH_CTX_UsePrivateKey_buffer(ctx, keyLoadBuf, bufSz, +// WOLFSSH_FORMAT_ASN1) < 0) { +// fprintf(stderr, "Couldn't use key buffer.\n"); +// WEXIT(EXIT_FAILURE); +// } +// +// } + + /* Load in host public key */ +// { +// if (userPubKey) { +// byte* userBuf = NULL; +// word32 userBufSz = 0; +// +// /* get the files size */ +// load_file(userPubKey, NULL, &userBufSz); +// +// /* create temp buffer and load in file */ +// if (userBufSz == 0) { +// fprintf(stderr, "Couldn't find size of file %s.\n", userPubKey); +// WEXIT(EXIT_FAILURE); +// } +// +// userBuf = (byte*)WMALLOC(userBufSz, NULL, 0); +// if (userBuf == NULL) { +// fprintf(stderr, "WMALLOC failed\n"); +// WEXIT(EXIT_FAILURE); +// } +// load_file(userPubKey, userBuf, &userBufSz); +// LoadPublicKeyBuffer(userBuf, userBufSz, &pwMapList); +// } +// +// bufSz = (word32)WSTRLEN(samplePasswordBuffer); +// WMEMCPY(keyLoadBuf, samplePasswordBuffer, bufSz); +// keyLoadBuf[bufSz] = 0; +// LoadPasswordBuffer(keyLoadBuf, bufSz, &pwMapList); +// +// if (userEcc) { +// #ifndef WOLFSSH_NO_ECC +// bufName = samplePublicKeyEccBuffer; +// #endif +// } +// else { +// #ifndef WOLFSSH_NO_RSA +// bufName = samplePublicKeyRsaBuffer; +// #endif +// } +// if (bufName != NULL) { +// bufSz = (word32)WSTRLEN(bufName); +// WMEMCPY(keyLoadBuf, bufName, bufSz); +// keyLoadBuf[bufSz] = 0; +// LoadPublicKeyBuffer(keyLoadBuf, bufSz, &pwMapList); +// } +// +// bufSz = (word32)WSTRLEN(sampleNoneBuffer); +// WMEMCPY(keyLoadBuf, sampleNoneBuffer, bufSz); +// keyLoadBuf[bufSz] = 0; +// LoadNoneBuffer(keyLoadBuf, bufSz, &pwMapList); +// +// #ifdef WOLFSSH_SMALL_STACK +// WFREE(keyLoadBuf, NULL, 0); +// #endif +// } + + /* Load in authorized keys */ + + + /* Set allowed connection type, i.e. public key / password */ + + return ret; +} + + +#if 0 +int SFTP_Subsystem() +{ + +} + +int SCP_Subsystem() +{ + +} +#endif + +//static int SHELL_Subsystem(WOLFSSHD_CONNECTION* conn, WOLFSSH* ssh) +//{ +// (void)conn; +// (void)ssh; +// return WS_SUCCESS; +//} + + +/* handle wolfSSH accept and directing to correct subsystem */ +static void* wolfSSHD_HandleConnection(void* arg) +{ + WOLFSSHD_CONNECTION* conn; + WOLFSSH* ssh; + + conn = (WOLFSSHD_CONNECTION*)arg; + ssh = wolfSSH_new(conn->ctx); + wolfSSH_set_fd(ssh, conn->fd); + return NULL; +} + + +/* returns WS_SUCCESS on success */ +static int wolfSSHD_NewConnection(WOLFSSHD_CONNECTION* conn) +{ + int pd; + int ret = WS_SUCCESS; + + pd = fork(); + if (pd < 0) { + printf("issue spawning new process\n"); + ret = -1; + } + + if (pd == 0) { + /* child process */ + (void)wolfSSHD_HandleConnection((void*)&conn); + } + else { + printf("spawned new process %d\n", pd); + } + + return ret; +} + + int myoptind = 0; char* myoptarg = NULL; int main(int argc, char** argv) { - int ret = WS_SUCCESS; + int ret = WS_SUCCESS; + word16 port = 0; + WS_SOCKET_T listenFd = 0; int ch; WOLFSSHD_CONFIG* conf = NULL; + WOLFSSH_CTX* ctx = NULL; const char* configFile = "/usr/local/etc/ssh/sshd_config"; signal(SIGINT, interruptCatch); + + #ifdef DEBUG_WOLFSSH + wolfSSH_Debugging_ON(); + #endif + #ifdef DEBUG_WOLFSSL + wolfSSL_Debugging_ON(); + #endif + + if (ret == WS_SUCCESS) { + wolfSSH_Init(); + } + + if (ret == WS_SUCCESS) { + conf = wolfSSHD_NewConfig(NULL); + if (conf == NULL) { + ret = WS_MEMORY_E; + } + } + + while ((ch = mygetopt(argc, argv, "?f:")) != -1) { switch (ch) { case 'f': @@ -88,28 +319,47 @@ int main(int argc, char** argv) } if (ret == WS_SUCCESS) { - wolfSSH_Init(); + ret = wolfSSHD_LoadSSHD(conf, configFile); + if (ret != WS_SUCCESS) + printf("Error reading in configure file %s\n", configFile); } - if (ret == WS_SUCCESS) { - conf = wolfSSH_NewConfig(NULL); - if (conf == NULL) { - ret = WS_MEMORY_E; - } - } - - if (wolfSSH_LoadSSHD(conf, configFile) != WS_SUCCESS) { - printf("Error reading in configure file %s\n", configFile); + /* port was not overridden with argument, read from config file */ + if (port == 0) { + port = wolfSSHD_GetPort(conf); } printf("wolfSSH SSHD application\n"); + if (ret == WS_SUCCESS) { + ret = SetupCTX(conf, &ctx); + } + + tcp_listen(&listenFd, &port, 1); + /* wait for incoming connections and fork them off */ - do { + while (ret == WS_SUCCESS && quit == 0) { + WOLFSSHD_CONNECTION conn; + #ifdef WOLFSSL_NUCLEUS + struct addr_struct clientAddr; + #else + SOCKADDR_IN_T clientAddr; + socklen_t clientAddrSz = sizeof(clientAddr); + #endif - } while (ret == WS_SUCCESS && quit == 0); + /* wait for a connection */ + conn.ctx = ctx; + #ifdef WOLFSSL_NUCLEUS + conn.fd = NU_Accept(listenFd, &clientAddr, 0); + #else + conn.fd = accept(listenFd, (struct sockaddr*)&clientAddr, + &clientAddrSz); + #endif - wolfSSH_FreeConfig(conf); + ret = wolfSSHD_NewConnection(&conn); + } + + wolfSSHD_FreeConfig(conf); wolfSSH_Cleanup(); return 0; } diff --git a/apps/wolfsshd.h b/apps/wolfsshd.h index 0a6797a1..3494c3f7 100644 --- a/apps/wolfsshd.h +++ b/apps/wolfsshd.h @@ -23,9 +23,12 @@ typedef struct WOLFSSHD_CONFIG WOLFSSHD_CONFIG; -WOLFSSHD_CONFIG* wolfSSH_NewConfig(void* heap); -void wolfSSH_FreeConfig(WOLFSSHD_CONFIG* conf); -int wolfSSH_LoadSSHD(WOLFSSHD_CONFIG* con, const char* filename); +WOLFSSHD_CONFIG* wolfSSHD_NewConfig(void* heap); +void wolfSSHD_FreeConfig(WOLFSSHD_CONFIG* conf); +int wolfSSHD_LoadSSHD(WOLFSSHD_CONFIG* conf, const char* filename); + +char* wolfSSHD_GetBanner(WOLFSSHD_CONFIG* conf); +word16 wolfSSHD_GetPort(WOLFSSHD_CONFIG* conf); #endif /* WOLFSSHD_H */