TCP/IP Forwarding

1. Removed some unused macros in the configure.ac script.
2. Added option for enabling TCP/IP Forwarding.
3. Coalesced the option enable checks to one location in the configure script.
4. Removed redundant compile flags from the wolfSSH automake include.
5. Added a check of the BUILD_SCP option to leave out the wolfcsp file as needed.
6. Removed the redundant debug flags from the ax_harden macro since we add them at the configure level.
7. Modified the ax_harden macro to add the flags to AM_CFLAGS rather than CFLAGS.
8. Removed redundant AM_CFLAGS from the include.am that are adding them to their build's CFLAGS.
9. Replaced the have-wolfssl macro with AC_CHECK_LIB.
10. When adding per-target CPPFLAGS, add the AM_CPPFLAGS back in.
11. remove redundant call to wolfSSH_Init() from echoserver
12. Add runtime configuration of the session window size and max packet size.
13. Parse the TCP/IP direct connect flavor of the Channel Open message.
14. Save and release the host and origin addresses.
15. Added an example forwarding tool.
16. Move and rename the FIND_SELF and FIND_PEER constants.
17. Add planned functions ChannelSend, ChannelRead, ChannelExit, worker.
18. Add new function ChannelNext, which returns the next channel in the list.
19. Changed SendBuffered() from static to local so it could be used by the worker.
20. Separated creating a channel and sending an channel open request.
21. Added status code for pending open channel and for received data.
pull/98/head
John Safranek 2018-08-31 11:16:28 -07:00
parent d7cd20bdb9
commit a42075d823
16 changed files with 1240 additions and 181 deletions

1
.gitignore vendored
View File

@ -51,6 +51,7 @@ diff
examples/client/client
examples/echoserver/echoserver
examples/server/server
examples/wolffwd/wolffwd
wolfsftp/client/wolfsftp
# test output

View File

@ -20,7 +20,7 @@ AC_ARG_PROGRAM
AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_HEADERS([src/config.h])
WOLFSSH_LIBRARY_VERSION=4:0:3
WOLFSSH_LIBRARY_VERSION=5:0:1
# | | |
# +------+ | +---+
# | | |
@ -56,12 +56,7 @@ AC_CHECK_SIZEOF([long])
# Check headers/libs
AC_CHECK_FUNCS([gethostbyname getaddrinfo gettimeofday inet_ntoa memset socket])
AC_CHECK_LIB([network],[socket])
# Requirements
TAO_REQUIRE_LIBWOLFSSL
# since we have autoconf available, we can use cyassl options header
AM_CPPFLAGS="$AM_CPPFLAGS -DHAVE_CYASSL_OPTIONS"
AC_CHECK_LIB([wolfssl],[wolfCrypt_Init],,[AC_MSG_ERROR([libwolfssl is required for ${PACKAGE}, It can be obtained from https://www.wolfssl.com/download.html/])])
# DEBUG
DEBUG_CFLAGS="-g -O0"
@ -81,10 +76,9 @@ AX_PTHREAD([
AS_CASE([$PTHREAD_CFLAGS],[-Qunused-arguments*],[PTHREAD_CFLAGS="-Xcompiler $PTHREAD_CFLAGS"])
AM_CFLAGS="$AM_CFLAGS $PTHREAD_CFLAGS"])
# Inline Build
AC_ARG_ENABLE([inline],
[AS_HELP_STRING([--enable-inline],[Enable inline functions (default: enabled)])],
[AS_HELP_STRING([--disable-inline],[Enable inline functions (default: enabled)])],
[ENABLED_INLINE=$enableval],[ENABLED_INLINE=yes])
if test "$ENABLED_INLINE" = "no"
@ -99,31 +93,37 @@ AC_ARG_ENABLE([keygen],
[AS_HELP_STRING([--enable-keygen],[Enable key generation (default: disabled)])],
[ENABLED_KEYGEN=$enableval],[ENABLED_KEYGEN=no])
AS_IF([test "x$ENABLED_KEYGEN" = "xyes"],
[AM_CPPFLAGS="$AM_CPPFLAGS -DWOLFSSH_KEYGEN"])
AM_CONDITIONAL([BUILD_KEYGEN], [test "x$ENABLED_KEYGEN" = "xyes"])
# SCP
AC_ARG_ENABLE([scp],
[AS_HELP_STRING([--enable-scp],[Enable scp support (default: disabled)])],
[ENABLED_SCP=$enableval],[ENABLED_SCP=no])
AS_IF([test "x$ENABLED_SCP" = "xyes"],
[AM_CPPFLAGS="$AM_CPPFLAGS -DWOLFSSH_SCP"])
AM_CONDITIONAL([BUILD_SCP], [test "x$ENABLED_SCP" = "xyes"])
# SFTP
AC_ARG_ENABLE([sftp],
[AS_HELP_STRING([--enable-sftp],[Enable SFTP support (default: disabled)])],
[ENABLED_SFTP=$enableval],[ENABLED_SFTP=no])
# TCP/IP Forwarding
AC_ARG_ENABLE([fwd],
[AS_HELP_STRING([--enable-fwd],[Enable TCP/IP Forwarding support (default: disabled)])],
[ENABLED_FWD=$enableval],[ENABLED_FWD=no])
AS_IF([test "x$ENABLED_INLINE" = "xno"],
[AM_CPPFLAGS="$AM_CPPFLAGS -DNO_INLINE"])
AS_IF([test "x$ENABLED_KEYGEN" = "xyes"],
[AM_CPPFLAGS="$AM_CPPFLAGS -DWOLFSSH_KEYGEN"])
AS_IF([test "x$ENABLED_SCP" = "xyes"],
[AM_CPPFLAGS="$AM_CPPFLAGS -DWOLFSSH_SCP"])
AS_IF([test "x$ENABLED_SFTP" = "xyes"],
[AM_CPPFLAGS="$AM_CPPFLAGS -DWOLFSSH_SFTP"])
AS_IF([test "x$ENABLED_FWD" = "xyes"],
[AM_CPPFLAGS="$AM_CPPFLAGS -DWOLFSSH_FWD"])
AM_CONDITIONAL([BUILD_SFTP], [test "x$ENABLED_SFTP" = "xyes"])
AM_CONDITIONAL([BUILD_INLINE],[test "x$ENABLED_INLINE" = "xyes"])
AM_CONDITIONAL([BUILD_KEYGEN],[test "x$ENABLED_KEYGEN" = "xyes"])
AM_CONDITIONAL([BUILD_SCP],[test "x$ENABLED_SCP" = "xyes"])
AM_CONDITIONAL([BUILD_SFTP],[test "x$ENABLED_SFTP" = "xyes"])
AM_CONDITIONAL([BUILD_FWD],[test "x$ENABLED_FWD" = "xyes"])
# Checks for typedefs, structures, and compiler characteristics.
if test "$ac_cv_sizeof_long" = "8"; then
@ -154,7 +154,6 @@ AC_OUTPUT
echo "---"
echo "Running make clean..."
make clean >/dev/null 2>&1
echo
# output config summary
echo "---"
@ -167,10 +166,10 @@ echo " * C Compiler: $CC"
echo " * C Flags: $CFLAGS"
echo " * CPP Flags: $CPPFLAGS"
echo " * Linker Flags: $LDFLAGS"
echo " * LIB Flags: $LIB"
echo
echo " Features "
echo " Features"
echo " * keygen: $ENABLED_KEYGEN"
echo " * scp: $ENABLED_SCP"
echo " * sftp: $ENABLED_SFTP"
echo " * TCP/IP Forwarding: $ENABLED_FWD"

View File

@ -827,8 +827,6 @@ THREAD_RETURN WOLFSSH_THREAD echoserver_test(void* args)
wolfSSH_Debugging_ON();
#endif
wolfSSH_Init();
#ifndef WOLFSSL_NUCLEUS
ChangeToWolfSshRoot();
#endif

View File

@ -5,3 +5,4 @@
include examples/client/include.am
include examples/server/include.am
include examples/echoserver/include.am
include examples/wolffwd/include.am

View File

@ -0,0 +1,12 @@
# vim:ft=automake
# All paths should be given relative to the root
if BUILD_FWD
noinst_PROGRAMS += examples/wolffwd/wolffwd
noinst_HEADERS += examples/wolffwd/wolffwd.h
examples_wolffwd_wolffwd_SOURCES = examples/wolffwd/wolffwd.c
examples_wolffwd_wolffwd_LDADD = src/libwolfssh.la
examples_wolffwd_wolffwd_DEPENDENCIES = src/libwolfssh.la
endif
DISTCLEANFILES+= examples/wolffwd/.libs/wolffwd

View File

@ -0,0 +1,439 @@
#include <stdio.h>
#include <termios.h>
#include <errno.h>
#include <sys/select.h>
#include <wolfssh/ssh.h>
#include <wolfssh/test.h>
#include <wolfssh/port.h>
#include "examples/wolffwd/wolffwd.h"
/* The wolffwd tool will be a client or server in the port forwarding
* interaction.
*
* The wolffwd client will connect to an SSH server and request a tunnel.
* The client acts like a server for the local user application. It forwards
* the packets received to the SSH server who will then forward the packet
* to its local application server.
*
* The wolffwd server will listen for SSH connections, and when it receives
* one will only accept forward requests from the connection. All data for
* the forwarding channel are sent to the local application server and
* data from the server is forwarded to the client.
*/
static inline int max(int a, int b)
{
return (a > b) ? a : b;
}
static void ShowUsage(void)
{
printf("wolffwd %s\n"
" -? display this help and exit\n"
" -h <host> host to connect to, default %s\n"
" -p <num> port to connect on, default %u\n"
" -u <username> username to authenticate as (REQUIRED)\n"
" -P <password> password for username, prompted if omitted\n"
" -F <host> host to forward from, default 0.0.0.0\n"
" -f <num> host port to forward from (REQUIRED)\n"
" -T <host> host to forward to, default to host\n"
" -t <num> port to forward to (REQUIRED)\n"
" -d server mode\n",
LIBWOLFSSH_VERSION_STRING, wolfSshIp, wolfSshPort);
}
static int SetEcho(int on)
{
#ifndef USE_WINDOWS_API
static int echoInit = 0;
static struct termios originalTerm;
if (!echoInit) {
if (tcgetattr(STDIN_FILENO, &originalTerm) != 0) {
printf("Couldn't get the original terminal settings.\n");
return -1;
}
echoInit = 1;
}
if (on) {
if (tcsetattr(STDIN_FILENO, TCSANOW, &originalTerm) != 0) {
printf("Couldn't restore the terminal settings.\n");
return -1;
}
}
else {
struct termios newTerm;
memcpy(&newTerm, &originalTerm, sizeof(struct termios));
newTerm.c_lflag &= ~ECHO;
newTerm.c_lflag |= (ICANON | ECHONL);
if (tcsetattr(STDIN_FILENO, TCSANOW, &newTerm) != 0) {
printf("Couldn't turn off echo.\n");
return -1;
}
}
#else
static int echoInit = 0;
static DWORD originalTerm;
HANDLE stdinHandle = GetStdHandle(STD_INPUT_HANDLE);
if (!echoInit) {
if (GetConsoleMode(stdinHandle, &originalTerm) == 0) {
printf("Couldn't get the original terminal settings.\n");
return -1;
}
echoInit = 1;
}
if (on) {
if (SetConsoleMode(stdinHandle, originalTerm) == 0) {
printf("Couldn't restore the terminal settings.\n");
return -1;
}
}
else {
DWORD newTerm = originalTerm;
newTerm &= ~ENABLE_ECHO_INPUT;
if (SetConsoleMode(stdinHandle, newTerm) == 0) {
printf("Couldn't turn off echo.\n");
return -1;
}
}
#endif
return 0;
}
byte userPassword[256];
static int wsUserAuth(byte authType,
WS_UserAuthData* authData,
void* ctx)
{
const char* defaultPassword = (const char*)ctx;
word32 passwordSz;
int ret = WOLFSSH_USERAUTH_SUCCESS;
(void)authType;
if (defaultPassword != NULL) {
passwordSz = (word32)strlen(defaultPassword);
memcpy(userPassword, defaultPassword, passwordSz);
}
else {
printf("Password: ");
SetEcho(0);
if (WFGETS((char*)userPassword, sizeof(userPassword), stdin) == NULL) {
printf("Getting password failed.\n");
ret = WOLFSSH_USERAUTH_FAILURE;
}
else {
char* c = strpbrk((char*)userPassword, "\r\n");;
if (c != NULL)
*c = '\0';
passwordSz = (word32)strlen((const char*)userPassword);
}
SetEcho(1);
#ifdef USE_WINDOWS_API
printf("\r\n");
#endif
}
if (ret == WOLFSSH_USERAUTH_SUCCESS) {
authData->sf.password.password = userPassword;
authData->sf.password.passwordSz = passwordSz;
}
return ret;
}
#define INVALID_FWD_PORT 0
static const char defaultFwdFromHost[] = "0.0.0.0";
/*
* fwdFromHost - address to bind the local listener socket to (default: any)
* fwdFromHostPort - port number to bind the local listener socket to
* fwdToHost - address to tell the remote peer to connect to on behalf of the
* client (actual server address)
* fwdToHostPort - port number to tell the remote peer to connect to on behalf
* of the client (actual server port)
* host - peer SSH server address to connect to
* hostPort - peer SSH server port number to connect to
*/
THREAD_RETURN WOLFSSH_THREAD wolffwd_worker(void* args)
{
WOLFSSH* ssh;
WOLFSSH_CTX* ctx;
char* host = (char*)wolfSshIp;
word16 port = wolfSshPort;
word16 fwdFromPort = INVALID_FWD_PORT;
word16 fwdToPort = INVALID_FWD_PORT;
const char* fwdFromHost = defaultFwdFromHost;
const char* fwdToHost = NULL;
const char* username = NULL;
const char* password = NULL;
SOCKADDR_IN_T hostAddr;
socklen_t hostAddrSz = sizeof(hostAddr);
SOCKET_T sshFd;
SOCKADDR_IN_T fwdFromHostAddr;
socklen_t fwdFromHostAddrSz = sizeof(fwdFromHostAddr);
SOCKET_T listenFd;
SOCKET_T appFd;
int argc = ((func_args*)args)->argc;
char** argv = ((func_args*)args)->argv;
int serverMode = 0;
fd_set templateFds;
fd_set rxFds;
fd_set errFds;
int nFds;
int ret;
char ch;
int done = 0;
int appFdSet = 0;
struct timeval to;
WOLFSSH_CHANNEL* fwdChannel = NULL;
byte buffer[4096];
word32 bufferSz = sizeof(buffer);
word32 bufferUsed = 0;
((func_args*)args)->return_code = 0;
while ((ch = mygetopt(argc, argv, "?df:h:p:t:u:F:P:T:")) != -1) {
switch (ch) {
case 'd':
serverMode = 1;
break;
case 'h':
host = myoptarg;
break;
case 'f':
fwdFromPort = (word16)atoi(myoptarg);
break;
case 'p':
port = (word16)atoi(myoptarg);
#if !defined(NO_MAIN_DRIVER) || defined(USE_WINDOWS_API)
if (port == 0)
err_sys("port number cannot be 0");
#endif
break;
case 't':
fwdToPort = (word16)atoi(myoptarg);
break;
case 'u':
username = myoptarg;
break;
case 'F':
fwdFromHost = myoptarg;
break;
case 'P':
password = myoptarg;
break;
case 'T':
fwdToHost = myoptarg;
break;
case '?':
ShowUsage();
exit(EXIT_SUCCESS);
default:
ShowUsage();
exit(MY_EX_USAGE);
}
}
myoptind = 0;
if (username == NULL)
err_sys("client requires a username parameter.");
if (fwdToPort == INVALID_FWD_PORT)
err_sys("requires a port to forward to");
if (fwdFromPort == INVALID_FWD_PORT)
err_sys("requires a port to forward from");
if (fwdToHost == NULL)
fwdToHost = host;
printf("wolffwd options\n"
" * ssh host: %s:%u\n"
" * username: %s\n"
" * password: %s\n"
" * forward from: %s:%u\n"
" * forward to: %s:%u\n"
" * server mode: %s\n",
host, port, username, password,
fwdFromHost, fwdFromPort,
fwdToHost, fwdToPort,
serverMode ? "yes" : "no");
ctx = wolfSSH_CTX_new(WOLFSSH_ENDPOINT_CLIENT, NULL);
if (ctx == NULL)
err_sys("couldn't create the ssh client");
if (((func_args*)args)->user_auth == NULL)
wolfSSH_SetUserAuth(ctx, wsUserAuth);
else
wolfSSH_SetUserAuth(ctx, ((func_args*)args)->user_auth);
ssh = wolfSSH_new(ctx);
if (ssh == NULL)
err_sys("Couldn't create wolfSSH session.");
if (password != NULL)
wolfSSH_SetUserAuthCtx(ssh, (void*)password);
ret = wolfSSH_SetUsername(ssh, username);
if (ret != WS_SUCCESS)
err_sys("Couldn't set the username.");
build_addr(&hostAddr, host, port);
build_addr(&fwdFromHostAddr, fwdFromHost, fwdFromPort);
tcp_socket(&sshFd); /* Socket to SSH peer. */
tcp_socket(&listenFd); /* Either receive from client application or connect
to server application. */
tcp_listen(&listenFd, &fwdFromPort, 1);
printf("Connecting to the SSH server...\n");
ret = connect(sshFd, (const struct sockaddr *)&hostAddr, hostAddrSz);
if (ret != 0)
err_sys("Couldn't connect to server.");
ret = wolfSSH_set_fd(ssh, (int)sshFd);
if (ret != WS_SUCCESS)
err_sys("Couldn't set the session's socket.");
ret = wolfSSH_connect(ssh);
if (ret != WS_SUCCESS)
err_sys("Couldn't connect SFTP");
FD_ZERO(&templateFds);
FD_SET(sshFd, &templateFds);
FD_SET(listenFd, &templateFds);
nFds = max(sshFd, listenFd) + 1;
printf("Entering the run loop...\n");
while (!done) {
FD_COPY(&templateFds, &rxFds);
to.tv_sec = 1;
to.tv_usec = 0;
ret = select(nFds, &rxFds, NULL, &errFds, &to);
if (ret == 0) {
printf("select timed out\n");
ret = wolfSSH_SendIgnore(ssh, NULL, 0);
if (ret != WS_SUCCESS)
printf("Couldn't send an ignore message.\n");
continue;
}
else if (ret < 0) {
printf("select failed\n");
break;
}
else
printf("select returned something: %d\n", ret);
if (appFdSet && FD_ISSET(appFd, &rxFds)) {
int rxd;
printf("application packet received\n");
rxd = (int)recv(appFd, buffer + bufferUsed, bufferSz - bufferUsed, 0);
if (rxd > 0)
bufferUsed += rxd;
else
break;
}
if (FD_ISSET(sshFd, &rxFds)) {
word32 channelId = 0;
ret = wolfSSH_worker(ssh, &channelId);
if (ret == WS_CHAN_RXD) {
WOLFSSH_CHANNEL* readChannel;
bufferSz = sizeof(buffer);
readChannel = wolfSSH_ChannelFind(ssh,
channelId, WS_CHANNEL_ID_SELF);
ret = (readChannel == NULL) ? WS_INVALID_CHANID : WS_SUCCESS;
if (ret == WS_SUCCESS)
ret = wolfSSH_ChannelRead(readChannel, buffer, bufferSz);
if (ret > 0) {
bufferSz = (word32)ret;
ret = (int)send(appFd, buffer, bufferSz, 0);
}
ret = (ret != (int)bufferSz) ? -1 : WS_SUCCESS;
}
}
if (!appFdSet && FD_ISSET(listenFd, &rxFds)) {
appFd = accept(listenFd,
(struct sockaddr*)&fwdFromHostAddr, &fwdFromHostAddrSz);
FD_SET(appFd, &templateFds);
nFds = appFd + 1;
appFdSet = 1;
fwdChannel = wolfSSH_ChannelFwdNew(ssh, fwdToHost, fwdToPort,
fwdFromHost, fwdFromPort);
}
if (bufferUsed > 0) {
ret = wolfSSH_ChannelSend(fwdChannel, buffer, bufferUsed);
if (ret > 0)
bufferUsed -= ret;
}
}
ret = wolfSSH_shutdown(ssh);
if (ret != WS_SUCCESS)
err_sys("Closing stream failed.");
WCLOSESOCKET(sshFd);
WCLOSESOCKET(listenFd);
WCLOSESOCKET(appFd);
wolfSSH_free(ssh);
wolfSSH_CTX_free(ctx);
return 0;
}
#ifndef NO_MAIN_DRIVER
int main(int argc, char** argv)
{
func_args args;
args.argc = argc;
args.argv = argv;
args.return_code = 0;
args.user_auth = NULL;
WSTARTTCP();
#ifdef DEBUG_WOLFSSH
wolfSSH_Debugging_ON();
#endif
wolfSSH_Init();
ChangeToWolfSshRoot();
wolffwd_worker(&args);
wolfSSH_Cleanup();
return args.return_code;
}
int myoptind = 0;
char* myoptarg = NULL;
#endif /* NO_MAIN_DRIVER */

View File

@ -0,0 +1,8 @@
#pragma once
#ifndef _WOLFSSH_CLIENT_H_
#define _WOLFSSH_CLIENT_H_
THREAD_RETURN WOLFSSH_THREAD wolffwd_worker(void* args);
#endif /* _WOLFSSH_CLIENT_H_ */

View File

@ -105,10 +105,12 @@
[AX_APPEND_COMPILE_FLAGS([-Werror],[AM_CFLAGS])
ac_cv_warnings_as_errors="yes"])
AS_IF([test "$ax_enable_debug" = "yes"],
[AX_APPEND_COMPILE_FLAGS([-g],[AM_CFLAGS])
AX_APPEND_COMPILE_FLAGS([-ggdb],[AM_CFLAGS],[$ax_append_compile_cflags_extra])
AX_APPEND_COMPILE_FLAGS([-O0],[AM_CFLAGS],[$ax_append_compile_cflags_extra])])
dnl The main configure script handles setting the debugging flags.
dnl AS_IF([test "$ax_enable_debug" = "yes"], [
dnl AX_APPEND_COMPILE_FLAGS([-g],[AM_CFLAGS])
dnl AX_APPEND_COMPILE_FLAGS([-ggdb],[AM_CFLAGS],[$ax_append_compile_cflags_extra])
dnl AX_APPEND_COMPILE_FLAGS([-O0],[AM_CFLAGS],[$ax_append_compile_cflags_extra])
dnl ],[])
AX_APPEND_COMPILE_FLAGS([-Wno-pragmas],[AM_CFLAGS],[$ax_append_compile_cflags_extra])

View File

@ -1,57 +0,0 @@
#--------------------------------------------------------------------
# Check for libwolfssl
#--------------------------------------------------------------------
AC_DEFUN([_TAO_SEARCH_LIBWOLFSSL],[
AC_REQUIRE([AC_LIB_PREFIX])
LDFLAGS="$LDFLAGS -L/usr/local/lib"
LIBS="$LIBS -lwolfssl"
AC_LIB_HAVE_LINKFLAGS(wolfssl,,
[
#include <wolfssl/wolfcrypt/wc_port.h>
],[
wolfCrypt_Init();
])
AM_CONDITIONAL(HAVE_LIBWOLFSSL, [test "x${ac_cv_libwolfssl}" = "xyes"])
AS_IF([test "x${ac_cv_libwolfssl}" = "xyes"],[
save_LIBS="${LIBS}"
LIBS="${LIBS} ${LTLIBWOLFSSL}"
AC_CHECK_FUNCS(wolfSSL_Cleanup)
LIBS="$save_LIBS"
])
])
AC_DEFUN([_TAO_HAVE_LIBWOLFSSL],[
AC_ARG_ENABLE([libwolfssl],
[AS_HELP_STRING([--disable-libwolfssl],
[Build with libwolfssl support @<:@default=on@:>@])],
[ac_enable_libwolfssl="$enableval"],
[ac_enable_libwolfssl="yes"])
_TAO_SEARCH_LIBWOLFSSL
])
AC_DEFUN([TAO_HAVE_LIBWOLFSSL],[
AC_REQUIRE([_TAO_HAVE_LIBWOLFSSL])
])
AC_DEFUN([_TAO_REQUIRE_LIBWOLFSSL],[
ac_enable_libwolfssl="yes"
_TAO_SEARCH_LIBWOLFSSL
AS_IF([test x$ac_cv_libwolfssl = xno],[
AC_MSG_ERROR([libwolfssl is required for ${PACKAGE}, It can be obtained from http://www.wolfssl.com/download.html/])
])
])
AC_DEFUN([TAO_REQUIRE_LIBWOLFSSL],[
AC_REQUIRE([_TAO_REQUIRE_LIBWOLFSSL])
])

View File

@ -2,20 +2,15 @@
# included from Top Level Makefile.am
# All paths should be given relative to the root
lib_LTLIBRARIES+= src/libwolfssh.la
lib_LTLIBRARIES += src/libwolfssh.la
src_libwolfssh_la_SOURCES = src/ssh.c \
src/internal.c \
src/memory.c \
src/log.c \
src/io.c \
src/port.c \
src/wolfscp.c
src_libwolfssh_la_CFLAGS = -DBUILDING_WOLFSSH $(AM_CFLAGS)
src_libwolfssh_la_CPPFLAGS = -DBUILDING_WOLFSSH $(AM_CPPFLAGS)
src_libwolfssh_la_LDFLAGS = ${AM_LDFLAGS} -no-undefined -version-info ${WOLFSSH_LIBRARY_VERSION}
src_libwolfssh_la_DEPENDENCIES =
EXTRA_DIST +=
src/port.c
src_libwolfssh_la_CPPFLAGS = -DBUILDING_WOLFSSH ${AM_CPPFLAGS}
src_libwolfssh_la_LDFLAGS = -no-undefined -version-info ${WOLFSSH_LIBRARY_VERSION}
if !BUILD_INLINE
src_libwolfssh_la_SOURCES += src/misc.c
@ -25,6 +20,10 @@ if BUILD_KEYGEN
src_libwolfssh_la_SOURCES += src/keygen.c
endif
if BUILD_SCP
src_libwolfssh_la_SOURCES += src/wolfscp.c
endif
if BUILD_SFTP
src_libwolfssh_la_SOURCES += src/wolfsftp.c
endif

View File

@ -239,6 +239,15 @@ const char* GetErrorString(int err)
case WS_NEXT_ERROR:
return "Getting next value/state results in error";
case WS_CHAN_RXD:
return "Channel data received";
case WS_INVALID_EXTDATA:
return "invalid extended data type";
case WS_CHAN_PENDING:
return "channel open pending";
default:
return "Unknown error code";
}
@ -363,6 +372,8 @@ WOLFSSH_CTX* CtxInit(WOLFSSH_CTX* ctx, byte side, void* heap)
ctx->banner = cannedBanner;
ctx->bannerSz = cannedBannerSz;
#endif /* DEBUG_WOLFSSH */
ctx->windowSz = DEFAULT_WINDOW_SZ;
ctx->maxPacketSz = DEFAULT_MAX_PACKET_SZ;
return ctx;
}
@ -849,7 +860,11 @@ static const NameIdPair NameIdMap[] = {
{ ID_USERAUTH_PUBLICKEY, "publickey" },
/* Channel Type IDs */
{ ID_CHANTYPE_SESSION, "session" }
{ ID_CHANTYPE_SESSION, "session" },
#ifdef WOLFSSH_FWD
{ ID_CHANTYPE_TCPIP_FORWARD, "forwarded-tcpip" },
{ ID_CHANTYPE_TCPIP_DIRECT, "direct-tcpip" },
#endif /* WOLFSSH_FWD */
};
@ -908,6 +923,7 @@ WOLFSSH_CHANNEL* ChannelNew(WOLFSSH* ssh, byte channelType,
buffer = (byte*)WMALLOC(initialWindowSz, heap, DYNTYPE_BUFFER);
if (buffer != NULL) {
WMEMSET(newChannel, 0, sizeof(WOLFSSH_CHANNEL));
newChannel->ssh = ssh;
newChannel->channelType = channelType;
newChannel->channel = ssh->nextChannel++;
newChannel->windowSz = initialWindowSz;
@ -945,6 +961,12 @@ void ChannelDelete(WOLFSSH_CHANNEL* channel, void* heap)
(void)heap;
if (channel) {
#ifdef WOLFSSH_FWD
if (channel->host)
WFREE(channel->host, heap, DYNTYPE_STRING);
if (channel->origin)
WFREE(channel->origin, heap, DYNTYPE_STRING);
#endif /* WOLFSSH_FWD */
WFREE(channel->inputBuffer.buffer,
channel->inputBuffer.heap, DYNTYPE_BUFFER);
if (channel->command)
@ -954,9 +976,6 @@ void ChannelDelete(WOLFSSH_CHANNEL* channel, void* heap)
}
#define FIND_SELF 0
#define FIND_PEER 1
WOLFSSH_CHANNEL* ChannelFind(WOLFSSH* ssh, word32 channel, byte peer)
{
WOLFSSH_CHANNEL* findChannel = NULL;
@ -972,7 +991,7 @@ WOLFSSH_CHANNEL* ChannelFind(WOLFSSH* ssh, word32 channel, byte peer)
word32 listSz = ssh->channelListSz;
while (list && listSz) {
if (channel == ((peer == FIND_PEER) ?
if (channel == ((peer == WS_CHANNEL_ID_PEER) ?
list->peerChannel : list->channel)) {
findChannel = list;
break;
@ -988,7 +1007,7 @@ WOLFSSH_CHANNEL* ChannelFind(WOLFSSH* ssh, word32 channel, byte peer)
}
int ChannelUpdate(WOLFSSH_CHANNEL* channel, word32 peerChannelId,
int ChannelUpdatePeer(WOLFSSH_CHANNEL* channel, word32 peerChannelId,
word32 peerInitialWindowSz, word32 peerMaxPacketSz)
{
int ret = WS_SUCCESS;
@ -999,13 +1018,49 @@ int ChannelUpdate(WOLFSSH_CHANNEL* channel, word32 peerChannelId,
channel->peerChannel = peerChannelId;
channel->peerWindowSz = peerInitialWindowSz;
channel->peerMaxPacketSz = peerMaxPacketSz;
channel->openConfirmed = 1;
}
return ret;
}
static int ChannelAppend(WOLFSSH* ssh, WOLFSSH_CHANNEL* channel)
#ifdef WOLFSSH_FWD
int ChannelUpdateForward(WOLFSSH_CHANNEL* channel,
const char* host, word32 hostPort,
const char* origin, word32 originPort)
{
int ret = WS_SUCCESS;
char* hostCopy = NULL;
char* originCopy = NULL;
if (channel == NULL || host == NULL || origin == NULL)
ret = WS_BAD_ARGUMENT;
else {
void* heap = channel->ssh->ctx->heap;
hostCopy = (char*)WMALLOC(WSTRLEN(host) + 1, heap, DYNTYPE_STRING);
originCopy = (char*)WMALLOC(WSTRLEN(origin) + 1, heap, DYNTYPE_STRING);
if (hostCopy == NULL || originCopy == NULL) {
WFREE(hostCopy, heap, DYNTYPE_STRING);
WFREE(originCopy, heap, DYNTYPE_STRING);
ret = WS_MEMORY_E;
}
}
if (ret == WS_SUCCESS) {
channel->host = hostCopy;
channel->hostPort = hostPort;
channel->origin = originCopy;
channel->originPort = originPort;
}
return ret;
}
#endif /* WOLFSSH_FWD */
int ChannelAppend(WOLFSSH* ssh, WOLFSSH_CHANNEL* channel)
{
int ret = WS_SUCCESS;
@ -1052,7 +1107,7 @@ int ChannelRemove(WOLFSSH* ssh, word32 channel, byte peer)
word32 listSz = ssh->channelListSz;
while (list && listSz) {
if (channel == ((peer == FIND_PEER) ?
if (channel == ((peer == WS_CHANNEL_ID_PEER) ?
list->peerChannel : list->channel)) {
if (prev == NULL)
ssh->channelList = list->next;
@ -1287,7 +1342,7 @@ static int GetInputText(WOLFSSH* ssh, byte** pEol)
}
static int SendBuffered(WOLFSSH* ssh)
int SendBuffered(WOLFSSH* ssh)
{
WLOG(WS_LOG_DEBUG, "Entering SendBuffered()");
@ -2628,7 +2683,7 @@ static int DoKexDhGexGroup(WOLFSSH* ssh,
byte* generator = NULL;
word32 generatorSz;
word32 begin;
int ret = WS_UNIMPLEMENTED_E;
int ret = WS_SUCCESS;
if (ssh == NULL || buf == NULL || len == 0 || idx == NULL)
ret = WS_BAD_ARGUMENT;
@ -3110,7 +3165,7 @@ static int DoUserAuthRequestEcc(WOLFSSH* ssh, WS_UserAuthData_PublicKey* pk,
(void)hashId;
WLOG(WS_LOG_DEBUG, "Entering DoUserAuthRequestRsa()");
WLOG(WS_LOG_DEBUG, "Entering DoUserAuthRequestEcc()");
if (ssh == NULL || pk == NULL || digest == NULL || digestSz == 0)
ret = WS_BAD_ARGUMENT;
@ -3544,6 +3599,19 @@ static int DoGlobalRequest(WOLFSSH* ssh,
ret = GetBoolean(&wantReply, buf, len, &begin);
}
#ifdef WOLFSSH_FWD
if (ret == WS_SUCCESS) {
if (WSTRNCMP(name, "tcpip-forward", nameSz) == 0) {
fprintf(stderr, "tcpip-forward requested\n");
fflush(stderr);
}
else if (WSTRNCMP(name, "cancel-tcpip-forward", nameSz) == 0) {
fprintf(stderr, "cancel-tcpip-forward requested\n");
fflush(stderr);
}
}
#endif /* WOLFSSH_FWD */
if (ret == WS_SUCCESS) {
*idx += len;
@ -3556,23 +3624,81 @@ static int DoGlobalRequest(WOLFSSH* ssh,
}
#ifdef WOLFSSH_FWD
static int DoChannelOpenForward(WOLFSSH* ssh,
char** host, word32* hostPort,
char** origin, word32* originPort,
byte* buf, word32 len, word32* idx)
{
word32 begin;
int ret = WS_SUCCESS;
WLOG(WS_LOG_DEBUG, "Entering DoChannelOpenForward()");
if (idx == NULL)
ret = WS_BAD_ARGUMENT;
if (ret == WS_SUCCESS) {
begin = *idx;
ret = GetStringAlloc(ssh, host, buf, len, &begin);
}
if (ret == WS_SUCCESS)
ret = GetUint32(hostPort, buf, len, &begin);
if (ret == WS_SUCCESS)
ret = GetStringAlloc(ssh, origin, buf, len, &begin);
if (ret == WS_SUCCESS)
ret = GetUint32(originPort, buf, len, &begin);
if (ret == WS_SUCCESS) {
*idx = begin;
WLOG(WS_LOG_INFO, " host = %s:%u", *host, *hostPort);
WLOG(WS_LOG_INFO, " origin = %s:%u", *origin, *originPort);
}
else {
*idx += len;
WFREE(*host, ssh->ctx->heap, DYNTYPE_STRING);
WFREE(*origin, ssh->ctx->heap, DYNTYPE_STRING);
*host = NULL;
*origin = NULL;
}
WLOG(WS_LOG_DEBUG, "Leaving DoChannelOpenForward(), ret = %d", ret);
return ret;
}
#endif /* WOLFSSH_FWD */
static int DoChannelOpen(WOLFSSH* ssh,
byte* buf, word32 len, word32* idx)
{
word32 begin = *idx;
word32 begin;
word32 typeSz;
char type[32];
byte typeId = ID_UNKNOWN;
word32 peerChannelId;
word32 peerInitialWindowSz;
word32 peerMaxPacketSz;
int ret;
#ifdef WOLFSSH_FWD
char* host = NULL;
char* origin = NULL;
word32 hostPort, originPort;
#endif /* WOLFSSH_FWD */
WOLFSSH_CHANNEL* newChannel;
int ret = WS_SUCCESS;
WLOG(WS_LOG_DEBUG, "Entering DoChannelOpen()");
typeSz = sizeof(type);
ret = GetString(type, &typeSz, buf, len, &begin);
if (idx == NULL)
ret = WS_BAD_ARGUMENT;
if (ret == WS_SUCCESS) {
begin = *idx;
typeSz = sizeof(type);
ret = GetString(type, &typeSz, buf, len, &begin);
}
if (ret == WS_SUCCESS)
ret = GetUint32(&peerChannelId, buf, len, &begin);
@ -3584,34 +3710,63 @@ static int DoChannelOpen(WOLFSSH* ssh,
ret = GetUint32(&peerMaxPacketSz, buf, len, &begin);
if (ret == WS_SUCCESS) {
*idx = begin;
WLOG(WS_LOG_INFO, " type = %s", type);
WLOG(WS_LOG_INFO, " peerChannelId = %u", peerChannelId);
WLOG(WS_LOG_INFO, " peerInitialWindowSz = %u", peerInitialWindowSz);
WLOG(WS_LOG_INFO, " peerMaxPacketSz = %u", peerMaxPacketSz);
typeId = NameToId(type, typeSz);
if (typeId != ID_CHANTYPE_SESSION)
ret = WS_INVALID_CHANTYPE;
switch (typeId) {
case ID_CHANTYPE_SESSION:
break;
#ifdef WOLFSSH_FWD
/*case ID_CHANTYPE_TCPIP_FORWARD:*/
case ID_CHANTYPE_TCPIP_DIRECT:
ret = DoChannelOpenForward(ssh,
&host, &hostPort, &origin, &originPort,
buf, len, &begin);
break;
#endif /* WOLFSSH_FWD */
default:
ret = WS_INVALID_CHANTYPE;
}
}
if (ret == WS_SUCCESS) {
*idx = begin;
newChannel = ChannelNew(ssh, typeId,
DEFAULT_WINDOW_SZ, DEFAULT_MAX_PACKET_SZ);
ssh->ctx->windowSz, ssh->ctx->maxPacketSz);
if (newChannel == NULL)
ret = WS_RESOURCE_E;
else {
ChannelUpdate(newChannel, peerChannelId,
ChannelUpdatePeer(newChannel, peerChannelId,
peerInitialWindowSz, peerMaxPacketSz);
if (ssh->channelListSz == 0)
ssh->defaultPeerChannelId = peerChannelId;
#ifdef WOLFSSH_FWD
switch (typeId) {
/*case ID_CHANTYPE_TCPIP_FORWARD:*/
case ID_CHANTYPE_TCPIP_DIRECT:
ChannelUpdateForward(newChannel,
host, hostPort, origin, originPort);
break;
}
#endif /* WOLFSSH_FWD */
ChannelAppend(ssh, newChannel);
ssh->clientState = CLIENT_CHANNEL_OPEN_DONE;
}
}
#ifdef WOLFSSH_FWD
if (ret != WS_SUCCESS) {
WFREE(host, ssh->ctx->heap, DYNTYPE_STRING);
WFREE(origin, ssh->ctx->heap, DYNTYPE_STRING);
}
#endif /* WOLFSSH_FWD */
WLOG(WS_LOG_DEBUG, "Leaving DoChannelOpen(), ret = %d", ret);
return ret;
}
@ -3650,13 +3805,13 @@ static int DoChannelOpenConf(WOLFSSH* ssh,
WLOG(WS_LOG_INFO, " peerInitialWindowSz = %u", peerInitialWindowSz);
WLOG(WS_LOG_INFO, " peerMaxPacketSz = %u", peerMaxPacketSz);
channel = ChannelFind(ssh, channelId, FIND_SELF);
channel = ChannelFind(ssh, channelId, WS_CHANNEL_ID_SELF);
if (channel == NULL)
ret = WS_INVALID_CHANID;
}
if (ret == WS_SUCCESS)
ret = ChannelUpdate(channel, peerChannelId,
ret = ChannelUpdatePeer(channel, peerChannelId,
peerInitialWindowSz, peerMaxPacketSz);
if (ret == WS_SUCCESS)
@ -3703,7 +3858,7 @@ static int DoChannelOpenFail(WOLFSSH* ssh,
WLOG(WS_LOG_INFO, "description: %s", desc);
}
ret = ChannelRemove(ssh, channelId, FIND_SELF);
ret = ChannelRemove(ssh, channelId, WS_CHANNEL_ID_SELF);
}
if (ret == WS_SUCCESS)
@ -3729,7 +3884,7 @@ static int DoChannelEof(WOLFSSH* ssh,
if (ret == WS_SUCCESS) {
*idx = begin;
channel = ChannelFind(ssh, channelId, FIND_SELF);
channel = ChannelFind(ssh, channelId, WS_CHANNEL_ID_SELF);
if (channel == NULL)
ret = WS_INVALID_CHANID;
}
@ -3757,7 +3912,7 @@ static int DoChannelClose(WOLFSSH* ssh,
if (ret == WS_SUCCESS) {
*idx = begin;
channel = ChannelFind(ssh, channelId, FIND_SELF);
channel = ChannelFind(ssh, channelId, WS_CHANNEL_ID_SELF);
if (channel == NULL)
ret = WS_INVALID_CHANID;
}
@ -3767,7 +3922,7 @@ static int DoChannelClose(WOLFSSH* ssh,
}
if (ret == WS_SUCCESS) {
ret = ChannelRemove(ssh, channelId, FIND_SELF);
ret = ChannelRemove(ssh, channelId, WS_CHANNEL_ID_SELF);
}
if (ret == WS_SUCCESS) {
@ -3807,7 +3962,7 @@ static int DoChannelRequest(WOLFSSH* ssh,
}
if (ret == WS_SUCCESS) {
channel = ChannelFind(ssh, channelId, FIND_SELF);
channel = ChannelFind(ssh, channelId, WS_CHANNEL_ID_SELF);
if (channel == NULL)
ret = WS_INVALID_CHANID;
}
@ -3944,7 +4099,7 @@ static int DoChannelWindowAdjust(WOLFSSH* ssh,
if (ret == WS_SUCCESS) {
*idx = begin;
channel = ChannelFind(ssh, channelId, FIND_SELF);
channel = ChannelFind(ssh, channelId, WS_CHANNEL_ID_SELF);
if (channel == NULL)
ret = WS_INVALID_CHANID;
else {
@ -3984,18 +4139,66 @@ static int DoChannelData(WOLFSSH* ssh,
if (ret == WS_SUCCESS) {
*idx = begin + dataSz;
channel = ChannelFind(ssh, channelId, FIND_SELF);
channel = ChannelFind(ssh, channelId, WS_CHANNEL_ID_SELF);
if (channel == NULL)
ret = WS_INVALID_CHANID;
else
ret = ChannelPutData(channel, buf + begin, dataSz);
}
if (ret == WS_SUCCESS) {
ssh->lastRxId = channelId;
ret = WS_CHAN_RXD;
}
WLOG(WS_LOG_DEBUG, "Leaving DoChannelData(), ret = %d", ret);
return ret;
}
static int DoChannelExtendedData(WOLFSSH* ssh,
byte* buf, word32 len, word32* idx)
{
WOLFSSH_CHANNEL* channel = NULL;
word32 begin = *idx;
word32 dataSz = 0;
word32 channelId;
word32 dataTypeCode;
int ret;
WLOG(WS_LOG_DEBUG, "Entering DoChannelExtendedData()");
ret = GetUint32(&channelId, buf, len, &begin);
if (ret == WS_SUCCESS)
ret = GetUint32(&dataTypeCode, buf, len, &begin);
if (ret == WS_SUCCESS)
ret = (dataTypeCode == CHANNEL_EXTENDED_DATA_STDERR) ?
WS_SUCCESS : WS_INVALID_EXTDATA;
if (ret == WS_SUCCESS)
ret = GetUint32(&dataSz, buf, len, &begin);
if (ret == WS_SUCCESS) {
channel = ChannelFind(ssh, channelId, WS_CHANNEL_ID_SELF);
if (channel == NULL)
ret = WS_INVALID_CHANID;
else {
#ifdef DEBUG_WOLFSSH
DumpOctetString(buf + begin, dataSz);
#endif
ret = SendChannelWindowAdjust(ssh, channel->peerChannel, dataSz);
}
*idx = begin + dataSz;
}
if (ret == WS_SUCCESS) {
ssh->lastRxId = channelId;
}
WLOG(WS_LOG_DEBUG, "Leaving DoChannelExtendedData(), ret = %d", ret);
return ret;
}
static int DoPacket(WOLFSSH* ssh)
{
byte* buf = (byte*)ssh->inputBuffer.buffer;
@ -4158,6 +4361,11 @@ static int DoPacket(WOLFSSH* ssh)
ret = DoChannelData(ssh, buf + idx, payloadSz, &payloadIdx);
break;
case MSGID_CHANNEL_EXTENDED_DATA:
WLOG(WS_LOG_DEBUG, "Decoding MSGID_CHANNEL_EXTENDED_DATA");
ret = DoChannelExtendedData(ssh, buf + idx, payloadSz, &payloadIdx);
break;
case MSGID_CHANNEL_EOF:
WLOG(WS_LOG_DEBUG, "Decoding MSGID_CHANNEL_EOF");
ret = DoChannelEof(ssh, buf + idx, payloadSz, &payloadIdx);
@ -4191,7 +4399,7 @@ static int DoPacket(WOLFSSH* ssh)
ret = SendUnimplemented(ssh);
}
if (ret == WS_SUCCESS) {
if (ret == WS_SUCCESS || ret == WS_CHAN_RXD) {
idx += payloadIdx;
if (idx + padSz > len) {
@ -4200,7 +4408,7 @@ static int DoPacket(WOLFSSH* ssh)
}
}
if (ret == WS_SUCCESS) {
if (ret == WS_SUCCESS || ret == WS_CHAN_RXD) {
idx += padSz;
ssh->inputBuffer.idx = idx;
ssh->peerSeq++;
@ -4477,7 +4685,7 @@ static INLINE int DecryptAead(WOLFSSH* ssh, byte* plain,
int DoReceive(WOLFSSH* ssh)
{
int ret = WS_FATAL_ERROR;
int ret = WS_SUCCESS;
int verifyResult;
word32 readSz;
byte peerBlockSz = ssh->peerBlockSz;
@ -4589,7 +4797,8 @@ int DoReceive(WOLFSSH* ssh)
FALL_THROUGH /* no break */
case PROCESS_PACKET:
if ( (ret = DoPacket(ssh)) < 0) {
ret = DoPacket(ssh);
if (ret < 0 && ret != WS_CHAN_RXD) {
return ret;
}
WLOG(WS_LOG_DEBUG, "PR3: peerMacSz = %u", peerMacSz);
@ -4607,9 +4816,9 @@ int DoReceive(WOLFSSH* ssh)
WLOG(WS_LOG_DEBUG, "PR5: txCount = %u, rxCount = %u",
ssh->txCount, ssh->rxCount);
return WS_SUCCESS;
return ret;
}
return ret;
return WS_FATAL_ERROR;
}
@ -6433,37 +6642,27 @@ int SendRequestSuccess(WOLFSSH* ssh, int success)
}
int SendChannelOpenSession(WOLFSSH* ssh,
word32 initialWindowSz, word32 maxPacketSz)
static int SendChannelOpen(WOLFSSH* ssh, WOLFSSH_CHANNEL* channel,
byte* channelData, word32 channelDataSz)
{
WOLFSSH_CHANNEL* newChannel;
byte* output;
const char* channelType;
word32 channelTypeSz, channelId, idx;
word32 channelTypeSz, idx;
int ret = WS_SUCCESS;
WLOG(WS_LOG_DEBUG, "Entering SendChannelOpenSession()");
WLOG(WS_LOG_DEBUG, "Entering SendChannelOpen()");
if (ssh == NULL)
if (ssh == NULL || channel == NULL)
ret = WS_BAD_ARGUMENT;
if (channelDataSz > 0 && channelData == NULL)
ret = WS_BAD_ARGUMENT;
if (ret == WS_SUCCESS) {
channelId = ssh->nextChannel;
newChannel = ChannelNew(ssh, ID_CHANTYPE_SESSION,
initialWindowSz, maxPacketSz);
if (newChannel == NULL)
ret = WS_MEMORY_E;
if (ret == WS_SUCCESS)
ret = ChannelAppend(ssh, newChannel);
}
if (ret == WS_SUCCESS) {
channelType = IdToName(ID_CHANTYPE_SESSION);
channelType = IdToName(channel->channelType);
channelTypeSz = (word32)WSTRLEN(channelType);
ret = PreparePacket(ssh, MSG_ID_SZ + LENGTH_SZ + channelTypeSz +
(UINT32_SZ * 3));
(UINT32_SZ * 3) + channelDataSz);
}
if (ret == WS_SUCCESS) {
@ -6475,12 +6674,15 @@ int SendChannelOpenSession(WOLFSSH* ssh,
idx += LENGTH_SZ;
WMEMCPY(output + idx, channelType, channelTypeSz);
idx += channelTypeSz;
c32toa(channelId, output + idx);
c32toa(channel->channel, output + idx);
idx += UINT32_SZ;
c32toa(initialWindowSz, output + idx);
c32toa(channel->windowSz, output + idx);
idx += UINT32_SZ;
c32toa(maxPacketSz, output + idx);
c32toa(channel->maxPacketSz, output + idx);
idx += UINT32_SZ;
if (channelDataSz > 0)
WMEMCPY(output + idx, channelData, channelDataSz);
idx += channelDataSz;
ssh->outputBuffer.length = idx;
@ -6490,11 +6692,71 @@ int SendChannelOpenSession(WOLFSSH* ssh,
if (ret == WS_SUCCESS)
ret = SendBuffered(ssh);
WLOG(WS_LOG_DEBUG, "Leaving SendChannelOpen(), ret = %d", ret);
return ret;
}
int SendChannelOpenSession(WOLFSSH* ssh, WOLFSSH_CHANNEL* channel)
{
int ret = WS_SUCCESS;
WLOG(WS_LOG_DEBUG, "Entering SendChannelOpenSession()");
ret = SendChannelOpen(ssh, channel, NULL, 0);
WLOG(WS_LOG_DEBUG, "Leaving SendChannelOpenSession(), ret = %d", ret);
return ret;
}
#ifdef WOLFSSH_FWD
int SendChannelOpenForward(WOLFSSH* ssh, WOLFSSH_CHANNEL* channel)
{
int ret = WS_SUCCESS;
byte* forwardData = NULL;
word32 hostSz, originSz, forwardDataSz, idx;
WLOG(WS_LOG_DEBUG, "Entering SendChannelOpenForward()");
if (ssh == NULL || channel->host == NULL || channel->origin == NULL)
ret = WS_BAD_ARGUMENT;
if (ret == WS_SUCCESS) {
hostSz = (word32)WSTRLEN(channel->host);
originSz = (word32)WSTRLEN(channel->origin);
forwardDataSz = UINT32_SZ * 2 + LENGTH_SZ * 2 + hostSz + originSz;
forwardData = (byte*)WMALLOC(forwardDataSz,
ssh->ctx->heap, DYNTYPE_TEMP);
if (forwardData == NULL)
ret = WS_MEMORY_E;
}
if (ret == WS_SUCCESS) {
c32toa(hostSz, forwardData);
idx = LENGTH_SZ;
WMEMCPY(forwardData + idx, channel->host, hostSz);
idx += hostSz;
c32toa(channel->hostPort, forwardData + idx);
idx += UINT32_SZ;
c32toa(originSz, forwardData);
idx += LENGTH_SZ;
WMEMCPY(forwardData + idx, channel->origin, originSz);
idx += originSz;
c32toa(channel->originPort, forwardData + idx);
ret = SendChannelOpen(ssh, channel, forwardData, forwardDataSz);
}
if (forwardData)
WFREE(forwardData, ssh->ctx->heap, DYNTYPE_TEMP);
WLOG(WS_LOG_DEBUG, "Leaving SendChannelOpenForward(), ret = %d", ret);
return ret;
}
#endif /* WOLFSSH_FWD */
int SendChannelOpenConf(WOLFSSH* ssh)
{
byte* output;
@ -6508,7 +6770,8 @@ int SendChannelOpenConf(WOLFSSH* ssh)
ret = WS_BAD_ARGUMENT;
if (ret == WS_SUCCESS) {
channel = ChannelFind(ssh, ssh->defaultPeerChannelId, FIND_PEER);
channel = ChannelFind(ssh,
ssh->defaultPeerChannelId, WS_CHANNEL_ID_PEER);
if (channel == NULL)
ret = WS_INVALID_CHANID;
}
@ -6556,7 +6819,7 @@ int SendChannelEof(WOLFSSH* ssh, word32 peerChannelId)
ret = WS_BAD_ARGUMENT;
if (ret == WS_SUCCESS) {
channel = ChannelFind(ssh, peerChannelId, FIND_PEER);
channel = ChannelFind(ssh, peerChannelId, WS_CHANNEL_ID_PEER);
if (channel == NULL)
ret = WS_INVALID_CHANID;
}
@ -6604,7 +6867,7 @@ int SendChannelEow(WOLFSSH* ssh, word32 peerChannelId)
}
if (ret == WS_SUCCESS) {
channel = ChannelFind(ssh, peerChannelId, FIND_PEER);
channel = ChannelFind(ssh, peerChannelId, WS_CHANNEL_ID_PEER);
if (channel == NULL)
ret = WS_INVALID_CHANID;
}
@ -6653,7 +6916,7 @@ int SendChannelExit(WOLFSSH* ssh, word32 peerChannelId, int status)
ret = WS_BAD_ARGUMENT;
if (ret == WS_SUCCESS) {
channel = ChannelFind(ssh, peerChannelId, FIND_PEER);
channel = ChannelFind(ssh, peerChannelId, WS_CHANNEL_ID_PEER);
if (channel == NULL)
ret = WS_INVALID_CHANID;
}
@ -6703,7 +6966,7 @@ int SendChannelClose(WOLFSSH* ssh, word32 peerChannelId)
ret = WS_BAD_ARGUMENT;
if (ret == WS_SUCCESS) {
channel = ChannelFind(ssh, peerChannelId, FIND_PEER);
channel = ChannelFind(ssh, peerChannelId, WS_CHANNEL_ID_PEER);
if (channel == NULL)
ret = WS_INVALID_CHANID;
else if (channel->closeSent) {
@ -6757,7 +7020,7 @@ int SendChannelData(WOLFSSH* ssh, word32 peerChannel,
}
if (ret == WS_SUCCESS) {
channel = ChannelFind(ssh, peerChannel, FIND_PEER);
channel = ChannelFind(ssh, peerChannel, WS_CHANNEL_ID_PEER);
if (channel == NULL) {
WLOG(WS_LOG_DEBUG, "Invalid peer channel");
ret = WS_INVALID_CHANID;
@ -6823,7 +7086,7 @@ int SendChannelWindowAdjust(WOLFSSH* ssh, word32 peerChannel,
if (ssh == NULL)
ret = WS_BAD_ARGUMENT;
channel = ChannelFind(ssh, peerChannel, FIND_PEER);
channel = ChannelFind(ssh, peerChannel, WS_CHANNEL_ID_PEER);
if (channel == NULL) {
WLOG(WS_LOG_DEBUG, "Invalid peer channel");
ret = WS_INVALID_CHANID;
@ -6880,7 +7143,8 @@ int SendChannelRequest(WOLFSSH* ssh, byte* name, word32 nameSz)
ret = WS_BAD_ARGUMENT;
if (ret == WS_SUCCESS) {
channel = ChannelFind(ssh, ssh->defaultPeerChannelId, FIND_PEER);
channel = ChannelFind(ssh,
ssh->defaultPeerChannelId, WS_CHANNEL_ID_PEER);
if (channel == NULL)
ret = WS_INVALID_CHANID;
}
@ -6981,7 +7245,7 @@ int SendChannelSuccess(WOLFSSH* ssh, word32 channelId, int success)
ret = WS_BAD_ARGUMENT;
if (ret == WS_SUCCESS) {
channel = ChannelFind(ssh, channelId, FIND_SELF);
channel = ChannelFind(ssh, channelId, WS_CHANNEL_ID_SELF);
if (channel == NULL) {
WLOG(WS_LOG_DEBUG, "Invalid channel");
ret = WS_INVALID_CHANID;

355
src/ssh.c
View File

@ -553,11 +553,26 @@ int wolfSSH_connect(WOLFSSH* ssh)
FALL_THROUGH /* no break */
case CONNECT_SERVER_USERAUTH_ACCEPT_DONE:
if ( (ssh->error = SendChannelOpenSession(ssh, DEFAULT_WINDOW_SZ,
DEFAULT_MAX_PACKET_SZ)) < WS_SUCCESS) {
WLOG(WS_LOG_DEBUG, connectError,
"SERVER_USERAUTH_ACCEPT_DONE", ssh->error);
return WS_FATAL_ERROR;
{
WOLFSSH_CHANNEL* newChannel;
newChannel = ChannelNew(ssh, ID_CHANTYPE_SESSION,
ssh->ctx->windowSz, ssh->ctx->maxPacketSz);
if (newChannel == NULL) {
ssh->error = WS_MEMORY_E;
WLOG(WS_LOG_DEBUG, connectError,
"SERVER_USERAUTH_ACCEPT_DONE", ssh->error);
return WS_FATAL_ERROR;
}
if ( (ssh->error =
SendChannelOpenSession(ssh, newChannel)) < WS_SUCCESS) {
ChannelDelete(newChannel, ssh->ctx->heap);
WLOG(WS_LOG_DEBUG, connectError,
"SERVER_USERAUTH_ACCEPT_DONE", ssh->error);
return WS_FATAL_ERROR;
}
ChannelAppend(ssh, newChannel);
}
ssh->connectState = CONNECT_CLIENT_CHANNEL_OPEN_SESSION_SENT;
WLOG(WS_LOG_DEBUG, connectState,
@ -661,7 +676,7 @@ int wolfSSH_stream_read(WOLFSSH* ssh, byte* buf, word32 bufSz)
int ret = DoReceive(ssh);
if (ssh->channelList == NULL || ssh->channelList->receivedEof)
ret = WS_EOF;
if (ret < 0) {
if (ret < 0 && ret != WS_CHAN_RXD) {
WLOG(WS_LOG_DEBUG, "Leaving wolfSSH_stream_read(), ret = %d", ret);
return ret;
}
@ -744,6 +759,38 @@ int wolfSSH_stream_exit(WOLFSSH* ssh, int status)
}
int wolfSSH_SendIgnore(WOLFSSH* ssh, const byte* buf, word32 bufSz)
{
byte scratch[128];
(void)buf;
(void)bufSz;
WMEMSET(scratch, 0, sizeof(scratch));
return SendIgnore(ssh, scratch, sizeof(scratch));
}
/* Sets up a timeout wrapper. */
WOLFSSH_TIMEOUT wolfSSH_SetTimeout(int sec, int usec)
{
WOLFSSH_TIMEOUT to = {sec, usec};
return to;
}
int wolfSSH_Select(WOLFSSH* ssh, WOLFSSH_TIMEOUT to)
{
(void)ssh;
(void)to;
WLOG(WS_LOG_INFO, "Entering wolfSSH_Select()");
WLOG(WS_LOG_INFO, "Entering wolfSSH_Select(), ret = %d", WS_SUCCESS);
return WS_SUCCESS;
}
void wolfSSH_SetUserAuth(WOLFSSH_CTX* ctx, WS_CallbackUserAuth cb)
{
if (ctx != NULL) {
@ -810,7 +857,7 @@ int wolfSSH_SetChannelType(WOLFSSH* ssh, byte type, byte* name, word32 nameSz)
}
return WS_SUCCESS;
}
}
int wolfSSH_SetUsername(WOLFSSH* ssh, const char* username)
{
@ -873,7 +920,27 @@ int wolfSSH_CTX_UsePrivateKey_buffer(WOLFSSH_CTX* ctx,
const byte* in, word32 inSz, int format)
{
WLOG(WS_LOG_DEBUG, "Entering wolfSSH_CTX_UsePrivateKey_buffer()");
return wolfSSH_ProcessBuffer(ctx, in, inSz, format, BUFTYPE_PRIVKEY);
return wolfSSH_ProcessBuffer(ctx, in, inSz, format, BUFTYPE_PRIVKEY);
}
int wolfSSH_CTX_SetWindowPacketSize(WOLFSSH_CTX* ctx,
word32 windowSz, word32 maxPacketSz)
{
WLOG(WS_LOG_DEBUG, "Entering wolfSSH_CTX_SetWindowPacketSize()");
if (ctx == NULL)
return WS_BAD_ARGUMENT;
if (windowSz == 0)
windowSz = DEFAULT_WINDOW_SZ;
if (maxPacketSz == 0)
maxPacketSz = DEFAULT_MAX_PACKET_SZ;
ctx->windowSz = windowSz;
ctx->maxPacketSz = maxPacketSz;
return WS_SUCCESS;
}
@ -935,3 +1002,275 @@ const char* wolfSSH_GetSessionCommand(const WOLFSSH* ssh)
return NULL;
}
int wolfSSH_worker(WOLFSSH* ssh, word32* channelId)
{
int ret = WS_SUCCESS;
printf("Entering wolfSSH_worker()\n");
WLOG(WS_LOG_DEBUG, "Entering wolfSSH_worker()");
if (ssh == NULL)
ret = WS_BAD_ARGUMENT;
/* Attempt to send any data pending in the outputBuffer. */
if (ret == WS_SUCCESS) {
if (ssh->outputBuffer.length != 0)
ret = SendBuffered(ssh);
}
/* Attempt to receive data from the peer. */
if (ret == WS_SUCCESS)
ret = DoReceive(ssh);
if (ret == WS_CHAN_RXD) {
if (channelId != NULL)
*channelId = ssh->lastRxId;
}
if (ret == WS_CHAN_RXD) {
printf("Leaving wolfSSH_worker(), "
"data received on channel %u\n", ssh->lastRxId);
WLOG(WS_LOG_DEBUG, "Leaving wolfSSH_worker(), "
"data received on channel %u", ssh->lastRxId);
}
else {
printf("Leaving wolfSSH_worker(), ret = %d\n", ret);
WLOG(WS_LOG_DEBUG, "Leaving wolfSSH_worker(), ret = %d", ret);
}
return ret;
}
#ifdef WOLFSSH_FWD
WOLFSSH_CHANNEL* wolfSSH_ChannelFwdNew(WOLFSSH* ssh,
const char* host, word32 hostPort,
const char* origin, word32 originPort)
{
WOLFSSH_CHANNEL* newChannel = NULL;
int ret = WS_SUCCESS;
WLOG(WS_LOG_DEBUG, "Entering wolfSSH_ChannelFwdNew()");
if (ssh == NULL || host == NULL || origin == NULL)
ret = WS_BAD_ARGUMENT;
if (ret == WS_SUCCESS)
newChannel = ChannelNew(ssh, ID_CHANTYPE_TCPIP_DIRECT,
ssh->ctx->windowSz, ssh->ctx->maxPacketSz);
if (ret == WS_SUCCESS)
ret = ChannelUpdateForward(newChannel,
host, hostPort, origin, originPort);
if (ret == WS_SUCCESS)
ret = SendChannelOpenForward(ssh, newChannel);
if (ret != WS_SUCCESS) {
ChannelDelete(newChannel, ssh->ctx->heap);
newChannel = NULL;
}
if (newChannel != NULL)
ChannelAppend(ssh, newChannel);
WLOG(WS_LOG_DEBUG, "Leaving wolfSSH_ChannelFwdNew(), newChannel = %p",
newChannel);
return newChannel;
}
#endif /* WOLFSSH_FWD */
int wolfSSH_ChannelFree(WOLFSSH_CHANNEL* channel)
{
int ret;
WLOG(WS_LOG_DEBUG, "Entering wolfSSH_ChannelFree()");
if (channel != NULL) {
ret = ChannelRemove(channel->ssh,
channel->channel, WS_CHANNEL_ID_SELF);
}
else
ret = WS_BAD_ARGUMENT;
WLOG(WS_LOG_DEBUG, "Leaving wolfSSH_ChannelFree(), ret = %d", ret);
return ret;
}
int wolfSSH_ChannelGetId(WOLFSSH_CHANNEL* channel, word32* id, byte peer)
{
int ret = WS_SUCCESS;
WLOG(WS_LOG_DEBUG, "Entering wolfSSH_ChannelGetId()");
if (channel == NULL || id == NULL)
ret = WS_BAD_ARGUMENT;
else {
*id = (peer == WS_CHANNEL_ID_SELF) ?
channel->channel : channel->peerChannel;
}
WLOG(WS_LOG_DEBUG, "Leaving wolfSSH_ChannelGetId(), ret = %d", ret);
return ret;
}
WOLFSSH_CHANNEL* wolfSSH_ChannelFind(WOLFSSH* ssh, word32 id, byte peer)
{
return ChannelFind(ssh, id, peer);
}
#ifdef WOLFSSH_FWD
int wolfSSH_ChannelSetFwdFd(WOLFSSH_CHANNEL* channel, int fwdFd)
{
int ret = WS_SUCCESS;
WLOG(WS_LOG_DEBUG, "Entering wolfSSH_ChannelSetFwdFd()");
if (channel != NULL)
channel->fwdFd = fwdFd;
else
ret = WS_BAD_ARGUMENT;
WLOG(WS_LOG_DEBUG, "Leaving wolfSSH_ChannelSetFwdFd(), ret = %d", ret);
return ret;
}
int wolfSSH_ChannelGetFwdFd(const WOLFSSH_CHANNEL* channel)
{
int fwdFd = -1;
WLOG(WS_LOG_DEBUG, "Entering wolfSSH_ChannelGetFwdFd()");
if (channel != NULL)
fwdFd = channel->fwdFd;
WLOG(WS_LOG_DEBUG, "Leaving wolfSSH_ChannelGetFwdFd(), ret = %d", fwdFd);
return fwdFd;
}
#endif /* WOLFSSH_FWD */
int wolfSSH_ChannelRead(WOLFSSH_CHANNEL* channel, byte* buf, word32 bufSz)
{
Buffer* inputBuffer;
WLOG(WS_LOG_DEBUG, "Entering wolfSSH_ChannelRead()");
if (channel == NULL || buf == NULL || bufSz == 0)
return WS_BAD_ARGUMENT;
inputBuffer = &channel->inputBuffer;
bufSz = min(bufSz, inputBuffer->length - inputBuffer->idx);
WMEMCPY(buf, inputBuffer->buffer + inputBuffer->idx, bufSz);
inputBuffer->idx += bufSz;
if (!channel->ssh->isKeying &&
(inputBuffer->length > inputBuffer->bufferSz / 2)) {
word32 usedSz = inputBuffer->length - inputBuffer->idx;
word32 bytesToAdd = inputBuffer->idx;
int sendResult;
WLOG(WS_LOG_DEBUG, "Making more room: %u", usedSz);
if (usedSz) {
WLOG(WS_LOG_DEBUG, " ...moving data down");
WMEMMOVE(inputBuffer->buffer,
inputBuffer->buffer + bytesToAdd, usedSz);
}
sendResult = SendChannelWindowAdjust(channel->ssh,
channel->peerChannel,
bytesToAdd);
if (sendResult != WS_SUCCESS)
bufSz = sendResult;
WLOG(WS_LOG_INFO, " bytesToAdd = %u", bytesToAdd);
WLOG(WS_LOG_INFO, " windowSz = %u", channel->windowSz);
channel->windowSz += bytesToAdd;
WLOG(WS_LOG_INFO, " update windowSz = %u", channel->windowSz);
inputBuffer->length = usedSz;
inputBuffer->idx = 0;
}
WLOG(WS_LOG_DEBUG, "Leaving wolfSSH_ChannelRead(), bytesRxd = %d",
bufSz);
return bufSz;
}
int wolfSSH_ChannelSend(WOLFSSH_CHANNEL* channel,
const byte* buf, word32 bufSz)
{
int bytesTxd = 0;
WLOG(WS_LOG_DEBUG, "Entering wolfSSH_ChannelSend(), ID = %d, peerID = %d", channel->channel, channel->peerChannel);
#ifdef DEBUG_WOLFSSH
DumpOctetString(buf, bufSz);
#endif
if (channel == NULL || buf == NULL)
bytesTxd = WS_BAD_ARGUMENT;
else if (!channel->openConfirmed) {
WLOG(WS_LOG_DEBUG, "Channel not confirmed yet.");
return -666;
}
else {
WLOG(WS_LOG_DEBUG, "Sending data.");
bytesTxd = SendChannelData(channel->ssh, channel->peerChannel,
(byte*)buf, bufSz);
}
WLOG(WS_LOG_DEBUG, "Leaving wolfSSH_ChannelSend(), bytesTxd = %d",
bytesTxd);
return bytesTxd;
}
int wolfSSH_ChannelExit(WOLFSSH_CHANNEL* channel)
{
int ret = WS_SUCCESS;
WLOG(WS_LOG_DEBUG, "Entering wolfSSH_ChannelExit()");
if (channel == NULL)
ret = WS_BAD_ARGUMENT;
if (ret == WS_SUCCESS)
ret = SendChannelEof(channel->ssh, channel->peerChannel);
if (ret == WS_SUCCESS)
ret = SendChannelClose(channel->ssh, channel->peerChannel);
if (ret == WS_SUCCESS)
ret = ChannelRemove(channel->ssh,
channel->peerChannel, WS_CHANNEL_ID_PEER);
WLOG(WS_LOG_DEBUG, "Leaving wolfSSH_ChannelExit(), ret = %d", ret);
return ret;
}
WOLFSSH_CHANNEL* wolfSSH_ChannelNext(WOLFSSH* ssh, WOLFSSH_CHANNEL* channel)
{
WOLFSSH_CHANNEL* nextChannel = NULL;
WLOG(WS_LOG_DEBUG, "Entering wolfSSH_ChannelNext()");
if (ssh != NULL && channel == NULL)
nextChannel = ssh->channelList;
else if (channel != NULL)
nextChannel = channel->next;
WLOG(WS_LOG_DEBUG, "Leaving wolfSSH_ChannelNext(), %s",
nextChannel == NULL ? "none" : "NEXT!");
return nextChannel;
}

View File

@ -8,20 +8,20 @@ noinst_PROGRAMS += tests/unit.test tests/api.test \
tests/testsuite.test
tests_unit_test_SOURCES = tests/unit.c
tests_unit_test_CFLAGS = -DNO_MAIN_DRIVER $(AM_CFLAGS)
tests_unit_test_LDADD = src/libwolfssh.la $(LIB_STATIC_ADD)
tests_unit_test_CPPFLAGS = -DNO_MAIN_DRIVER
tests_unit_test_LDADD = src/libwolfssh.la
tests_unit_test_DEPENDENCIES = src/libwolfssh.la
tests_api_test_SOURCES = tests/api.c
tests_api_test_CFLAGS = -DNO_MAIN_DRIVER $(AM_CFLAGS)
tests_api_test_LDADD = src/libwolfssh.la $(LIB_STATIC_ADD)
tests_api_test_CPPFLAGS = -DNO_MAIN_DRIVER
tests_api_test_LDADD = src/libwolfssh.la
tests_api_test_DEPENDENCIES = src/libwolfssh.la
tests_testsuite_test_SOURCES = tests/testsuite.c \
examples/echoserver/echoserver.c \
examples/client/client.c
tests_testsuite_test_CFLAGS = -DNO_MAIN_DRIVER $(AM_CFLAGS)
tests_testsuite_test_LDADD = src/libwolfssh.la $(LIB_STATIC_ADD)
tests_testsuite_test_CPPFLAGS = -DNO_MAIN_DRIVER
tests_testsuite_test_LDADD = src/libwolfssh.la
tests_testsuite_test_DEPENDENCIES = src/libwolfssh.la
DISTCLEANFILES+= tests/.libs/unit.test tests/.libs/api.test \

View File

@ -94,8 +94,11 @@ enum WS_ErrorCodes {
WS_PERMISSIONS = -54,
WS_SFTP_COMPLETE = -55, /* SFTP connection established */
WS_NEXT_ERROR = -56, /* Getting next value/state results in error */
WS_CHAN_RXD = -57, /* Status that channel data received. */
WS_INVALID_EXTDATA = -58, /* invalid Channel Extended Data Type */
WS_CHAN_PENDING = -59, /* peer hasn't confirmed channel open */
WS_LAST_E = -56 /* Update this to indicate last error */
WS_LAST_E = -59 /* Update this to indicate last error */
};

View File

@ -98,6 +98,8 @@ enum {
/* Channel Type IDs */
ID_CHANTYPE_SESSION,
ID_CHANTYPE_TCPIP_FORWARD,
ID_CHANTYPE_TCPIP_DIRECT,
ID_UNKNOWN
};
@ -185,6 +187,8 @@ struct WOLFSSH_CTX {
word32 highwaterMark;
const char* banner;
word32 bannerSz;
word32 windowSz;
word32 maxPacketSz;
byte side; /* client or server */
byte showBanner;
};
@ -339,6 +343,7 @@ struct WOLFSSH {
word32 connectChannelId;
byte channelName[WOLFSSH_MAX_CHN_NAMESZ];
byte channelNameSz;
word32 lastRxId;
Buffer inputBuffer;
Buffer outputBuffer;
@ -382,12 +387,20 @@ struct WOLFSSH_CHANNEL {
byte sessionType;
byte closeSent;
byte receivedEof;
byte openConfirmed;
word32 channel;
word32 windowSz;
word32 maxPacketSz;
word32 peerChannel;
word32 peerWindowSz;
word32 peerMaxPacketSz;
#ifdef WOLFSSH_FWD
char* host;
word32 hostPort;
char* origin;
word32 originPort;
int fwdFd;
#endif /* WOLFSSH_FWD */
Buffer inputBuffer;
char* command;
struct WOLFSSH* ssh;
@ -401,7 +414,10 @@ WOLFSSH_LOCAL WOLFSSH* SshInit(WOLFSSH*, WOLFSSH_CTX*);
WOLFSSH_LOCAL void SshResourceFree(WOLFSSH*, void*);
WOLFSSH_LOCAL WOLFSSH_CHANNEL* ChannelNew(WOLFSSH*, byte, word32, word32);
WOLFSSH_LOCAL int ChannelUpdate(WOLFSSH_CHANNEL*, word32, word32, word32);
WOLFSSH_LOCAL int ChannelUpdatePeer(WOLFSSH_CHANNEL*, word32, word32, word32);
WOLFSSH_LOCAL int ChannelUpdateForward(WOLFSSH_CHANNEL*,
const char*, word32, const char*, word32);
WOLFSSH_LOCAL int ChannelAppend(WOLFSSH* ssh, WOLFSSH_CHANNEL* channel);
WOLFSSH_LOCAL void ChannelDelete(WOLFSSH_CHANNEL*, void*);
WOLFSSH_LOCAL WOLFSSH_CHANNEL* ChannelFind(WOLFSSH*, word32, byte);
WOLFSSH_LOCAL int ChannelRemove(WOLFSSH*, word32, byte);
@ -422,6 +438,7 @@ WOLFSSH_LOCAL int wsEmbedSend(WOLFSSH*, void*, word32, void*);
WOLFSSH_LOCAL int DoReceive(WOLFSSH*);
WOLFSSH_LOCAL int DoProtoId(WOLFSSH*);
WOLFSSH_LOCAL int SendBuffered(WOLFSSH*);
WOLFSSH_LOCAL int SendProtoId(WOLFSSH*);
WOLFSSH_LOCAL int SendKexInit(WOLFSSH*);
WOLFSSH_LOCAL int SendKexDhInit(WOLFSSH*);
@ -442,7 +459,8 @@ WOLFSSH_LOCAL int SendUserAuthBanner(WOLFSSH*);
WOLFSSH_LOCAL int SendUserAuthPkOk(WOLFSSH*, const byte*, word32,
const byte*, word32);
WOLFSSH_LOCAL int SendRequestSuccess(WOLFSSH*, int);
WOLFSSH_LOCAL int SendChannelOpenSession(WOLFSSH*, word32, word32);
WOLFSSH_LOCAL int SendChannelOpenSession(WOLFSSH*, WOLFSSH_CHANNEL*);
WOLFSSH_LOCAL int SendChannelOpenForward(WOLFSSH*, WOLFSSH_CHANNEL*);
WOLFSSH_LOCAL int SendChannelOpenConf(WOLFSSH*);
WOLFSSH_LOCAL int SendChannelEof(WOLFSSH*, word32);
WOLFSSH_LOCAL int SendChannelEow(WOLFSSH*, word32);
@ -562,6 +580,7 @@ enum WS_MessageIds {
MSGID_CHANNEL_OPEN_FAIL = 92,
MSGID_CHANNEL_WINDOW_ADJUST = 93,
MSGID_CHANNEL_DATA = 94,
MSGID_CHANNEL_EXTENDED_DATA = 95,
MSGID_CHANNEL_EOF = 96,
MSGID_CHANNEL_CLOSE = 97,
MSGID_CHANNEL_REQUEST = 98,
@ -570,6 +589,9 @@ enum WS_MessageIds {
};
#define CHANNEL_EXTENDED_DATA_STDERR 1
/* dynamic memory types */
enum WS_DynamicTypes {
DYNTYPE_CTX,
@ -588,7 +610,8 @@ enum WS_DynamicTypes {
DYNTYPE_MPINT,
DYNTYPE_SCPCTX,
DYNTYPE_SCPDIR,
DYNTYPE_SFTP
DYNTYPE_SFTP,
DYNTYPE_TEMP
};

View File

@ -62,6 +62,8 @@ WOLFSSH_API void wolfSSH_CTX_free(WOLFSSH_CTX*);
WOLFSSH_API WOLFSSH* wolfSSH_new(WOLFSSH_CTX*);
WOLFSSH_API void wolfSSH_free(WOLFSSH*);
WOLFSSH_API int wolfSSH_worker(WOLFSSH*, word32*);
WOLFSSH_API int wolfSSH_set_fd(WOLFSSH*, int);
WOLFSSH_API int wolfSSH_get_fd(const WOLFSSH*);
@ -76,6 +78,22 @@ WOLFSSH_API void wolfSSH_SetHighwaterCtx(WOLFSSH*, void*);
WOLFSSH_API void* wolfSSH_GetHighwaterCtx(WOLFSSH*);
#define WS_CHANNEL_ID_SELF 0
#define WS_CHANNEL_ID_PEER 1
WOLFSSH_API WOLFSSH_CHANNEL* wolfSSH_ChannelFwdNew(WOLFSSH*,
const char*, word32, const char*, word32);
WOLFSSH_API int wolfSSH_ChannelFree(WOLFSSH_CHANNEL*);
WOLFSSH_API int wolfSSH_ChannelGetId(WOLFSSH_CHANNEL*, word32*, byte);
WOLFSSH_API WOLFSSH_CHANNEL* wolfSSH_ChannelFind(WOLFSSH*, word32, byte);
WOLFSSH_API WOLFSSH_CHANNEL* wolfSSH_ChannelNext(WOLFSSH*, WOLFSSH_CHANNEL*);
WOLFSSH_API int wolfSSH_ChannelSetFwdFd(WOLFSSH_CHANNEL*, int);
WOLFSSH_API int wolfSSH_ChannelGetFwdFd(const WOLFSSH_CHANNEL*);
WOLFSSH_API int wolfSSH_ChannelRead(WOLFSSH_CHANNEL*, byte*, word32);
WOLFSSH_API int wolfSSH_ChannelSend(WOLFSSH_CHANNEL*, const byte*, word32);
WOLFSSH_API int wolfSSH_ChannelExit(WOLFSSH_CHANNEL*);
WOLFSSH_API int wolfSSH_get_error(const WOLFSSH*);
WOLFSSH_API const char* wolfSSH_get_error_name(const WOLFSSH*);
WOLFSSH_API const char* wolfSSH_ErrorToName(int);
@ -135,6 +153,7 @@ WOLFSSH_API int wolfSSH_SetUsername(WOLFSSH*, const char*);
WOLFSSH_API int wolfSSH_CTX_SetBanner(WOLFSSH_CTX*, const char*);
WOLFSSH_API int wolfSSH_CTX_UsePrivateKey_buffer(WOLFSSH_CTX*,
const byte*, word32, int);
WOLFSSH_API int wolfSSH_CTX_SetWindowPacketSize(WOLFSSH_CTX*, word32, word32);
WOLFSSH_API int wolfSSH_accept(WOLFSSH*);
WOLFSSH_API int wolfSSH_connect(WOLFSSH*);
@ -143,6 +162,15 @@ WOLFSSH_API int wolfSSH_stream_read(WOLFSSH*, byte*, word32);
WOLFSSH_API int wolfSSH_stream_send(WOLFSSH*, byte*, word32);
WOLFSSH_API int wolfSSH_stream_exit(WOLFSSH*, int);
WOLFSSH_API int wolfSSH_TriggerKeyExchange(WOLFSSH*);
WOLFSSH_API int wolfSSH_SendIgnore(WOLFSSH*, const byte*, word32);
typedef struct WOLFSSH_TIMEOUT {
int sec;
int usec;
} WOLFSSH_TIMEOUT;
WOLFSSH_API WOLFSSH_TIMEOUT wolfSSH_SetTimeout(int, int);
WOLFSSH_API int wolfSSH_Select(WOLFSSH*, WOLFSSH_TIMEOUT);
WOLFSSH_API void wolfSSH_GetStats(WOLFSSH*,
word32*, word32*, word32*, word32*);