mirror of https://github.com/wolfSSL/wolfssh.git
367 lines
9.1 KiB
C
367 lines
9.1 KiB
C
/* wolfsshd.c
|
|
*
|
|
* Copyright (C) 2014-2021 wolfSSL Inc.
|
|
*
|
|
* This file is part of wolfSSH.
|
|
*
|
|
* wolfSSH is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* wolfSSH is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with wolfSSH. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include <config.h>
|
|
#endif
|
|
|
|
#ifdef WOLFSSH_SSHD
|
|
|
|
#include <wolfssh/ssh.h>
|
|
#include <wolfssh/internal.h>
|
|
#include <wolfssh/log.h>
|
|
#include <wolfssl/wolfcrypt/wc_port.h>
|
|
#include <wolfssl/wolfcrypt/error-crypt.h>
|
|
|
|
#define WOLFSSH_TEST_SERVER
|
|
#include <wolfssh/test.h>
|
|
|
|
#include "wolfsshd.h"
|
|
|
|
#include <signal.h>
|
|
|
|
#ifdef NO_INLINE
|
|
#include <wolfssh/misc.h>
|
|
#else
|
|
#define WOLFSSH_MISC_INCLUDED
|
|
#include "src/misc.c"
|
|
#endif
|
|
|
|
/* 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)
|
|
{
|
|
printf("wolfsshd %s\n", LIBWOLFSSH_VERSION_STRING);
|
|
printf(" -? display this help and exit\n");
|
|
printf(" -f <file name> Configuration file to use, default is /usr/locacl/etc/ssh/sshd_config\n");
|
|
}
|
|
|
|
static void interruptCatch(int in)
|
|
{
|
|
(void)in;
|
|
printf("Closing down wolfSSHD\n");
|
|
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;
|
|
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':
|
|
configFile = myoptarg;
|
|
break;
|
|
|
|
case '?':
|
|
ShowUsage();
|
|
return WS_SUCCESS;
|
|
|
|
default:
|
|
ShowUsage();
|
|
return WS_SUCCESS;
|
|
}
|
|
}
|
|
|
|
if (ret == WS_SUCCESS) {
|
|
ret = wolfSSHD_LoadSSHD(conf, configFile);
|
|
if (ret != 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 */
|
|
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
|
|
|
|
/* 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
|
|
|
|
ret = wolfSSHD_NewConnection(&conn);
|
|
}
|
|
|
|
wolfSSHD_FreeConfig(conf);
|
|
wolfSSH_Cleanup();
|
|
return 0;
|
|
}
|
|
#endif /* WOLFSSH_SSHD */
|