Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 22 additions & 8 deletions examples/echoserver/echoserver.c
Original file line number Diff line number Diff line change
Expand Up @@ -383,22 +383,24 @@ static int wolfSSH_AGENT_DefaultActions(WS_AgentCbAction action, void* vCtx)
if (action == WOLFSSH_AGENT_LOCAL_SETUP) {
struct sockaddr_un* name = &ctx->name;
size_t size;
int envSet = 0, nameBound = 0;

WMEMSET(name, 0, sizeof(struct sockaddr_un));
ctx->pid = getpid();
name->sun_family = AF_LOCAL;

ret = snprintf(name->sun_path, sizeof(name->sun_path),
"/tmp/wolfserver.%d", ctx->pid);
if (ret >= 0) {
name->sun_path[sizeof(name->sun_path) - 1] = '\0';
size = WSTRLEN(name->sun_path);
ret = (size < WSTRLEN("/tmp/wolfserver."));
}

if (ret == 0) {
name->sun_path[sizeof(name->sun_path) - 1] = '\0';
size = WSTRLEN(name->sun_path) +
offsetof(struct sockaddr_un, sun_path);
size += offsetof(struct sockaddr_un, sun_path);
ctx->listenFd = socket(AF_UNIX, SOCK_STREAM, 0);
if (ctx->listenFd == -1) {
ret = -1;
}
ret = (ctx->listenFd == -1) ? -1 : 0;
}

if (ret == 0) {
Expand All @@ -407,17 +409,29 @@ static int wolfSSH_AGENT_DefaultActions(WS_AgentCbAction action, void* vCtx)
}

if (ret == 0) {
nameBound = 1;
ret = setenv(EnvNameAuthPort, name->sun_path, 1);
}

if (ret == 0) {
envSet = 1;
ret = listen(ctx->listenFd, 5);
}

if (ret == 0) {
ctx->state = AGENT_STATE_LISTEN;
}
else {
if (nameBound) {
unlink(ctx->name.sun_path);
}
if (envSet) {
unsetenv(EnvNameAuthPort);
}
if (ctx->listenFd >= 0) {
close(ctx->listenFd);
ctx->listenFd = -1;
}
ret = WS_AGENT_SETUP_E;
}
}
Expand Down Expand Up @@ -1510,7 +1524,7 @@ static THREAD_RETURN WOLFSSH_THREAD server_worker(void* vArgs)
if (!threadCtx->nonBlock) {
ret = wolfSSH_accept(threadCtx->ssh);
if (wolfSSH_get_error(threadCtx->ssh) == WS_AUTH_PENDING) {
printf("Auth pending error, use -N for non blocking\n");
printf("Auth pending error, use -N for non-blocking\n");
printf("Trying to close down the connection\n");
}
}
Expand Down Expand Up @@ -2749,7 +2763,7 @@ THREAD_RETURN WOLFSSH_THREAD echoserver_test(void* args)

#ifdef WOLFSSH_TEST_BLOCK
if (!nonBlock) {
ES_ERROR("Use -N when testing forced non blocking");
ES_ERROR("Use -N when testing forced non-blocking\n");
}
#endif

Expand Down
26 changes: 25 additions & 1 deletion examples/portfwd/portfwd.c
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,7 @@ THREAD_RETURN WOLFSSH_THREAD portfwd_worker(void* args)
const char* fwdToHost = NULL;
const char* username = NULL;
const char* password = NULL;
const char* readyFile = NULL;
SOCKADDR_IN_T hostAddr;
socklen_t hostAddrSz = sizeof(hostAddr);
SOCKET_T sshFd;
Expand Down Expand Up @@ -266,7 +267,7 @@ THREAD_RETURN WOLFSSH_THREAD portfwd_worker(void* args)

((func_args*)args)->return_code = 0;

while ((ch = mygetopt(argc, argv, "?f:h:p:t:u:F:P:T:")) != -1) {
while ((ch = mygetopt(argc, argv, "?f:h:p:t:u:F:P:R:T:")) != -1) {
switch (ch) {
case 'h':
host = myoptarg;
Expand Down Expand Up @@ -306,6 +307,10 @@ THREAD_RETURN WOLFSSH_THREAD portfwd_worker(void* args)
password = myoptarg;
break;

case 'R':
readyFile = myoptarg;
break;

case 'T':
fwdToHost = myoptarg;
break;
Expand Down Expand Up @@ -404,6 +409,25 @@ THREAD_RETURN WOLFSSH_THREAD portfwd_worker(void* args)
if (ret != WS_SUCCESS)
err_sys("Couldn't connect SFTP");

if (readyFile != NULL) {
#ifndef NO_FILESYSTEM
WFILE* f = NULL;
ret = WFOPEN(NULL, &f, readyFile, "w");
if (f != NULL && ret == 0) {
char portStr[10];
int l;

l = WSNPRINTF(portStr, sizeof(portStr), "%d\n", (int)fwdFromPort);
if (l > 0) {
WFWRITE(NULL, portStr, MIN((size_t)l, sizeof(portStr)), 1, f);
WFCLOSE(NULL, f);
}
}
#else
err_sys("cannot create readyFile with no file system.\r\n");
#endif
}

FD_ZERO(&templateFds);
FD_SET(sshFd, &templateFds);
FD_SET(listenFd, &templateFds);
Expand Down
49 changes: 49 additions & 0 deletions scripts/fwd.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#!/usr/bin/env sh

# Prerequisite checking

if [ ! -x "$(which expect)" ]
then
echo "skipping: missing expect"
exit 77
fi

if [ ! -x ./scripts/fwd.test.expect ]
then
echo "fail: missing expect script"
exit 1
fi

if [ ! -x "$(which nc)" ]
then
echo "skipping: missing netcat"
exit 77
fi

## libtool can leave behind a script that runs the actual executable.
if [ ! -x ./examples/echoserver/echoserver ] || \
./examples/echoserver/echoserver "-?" 2>&1 | grep -q "does not exist"
then
echo "fail: missing echoserver"
exit 1
fi

## libtool can leave behind a script that runs the actual executable.
if [ ! -x ./examples/portfwd/portfwd ] || \
./examples/portfwd/portfwd "-?" 2>&1 | grep -q "does not exist"
then
echo "skipping: missing forwarding"
exit 77
fi

## test for nonblocking only
if ./examples/client/client "-?" 2>&1 | grep WOLFSSH_TEST_BLOCK >/dev/null 2>&1
then
echo "skipping: non-blocking test"
exit 77
fi


# Run the expect script

./scripts/fwd.test.expect
154 changes: 154 additions & 0 deletions scripts/fwd.test.expect
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
#!/usr/bin/env expect -f
#
# SSH Tunnel Test Script
#
# Tests an SSH tunnel using wolfSSH and netcat (nc).
#
# Architecture:
#
# [nc client] --plain--> :12345 [wolfssh client]
# |
# SSH
# |
# [wolfssh server] :ephem --plain--> :11111 [nc server]
#
# The nc client sends each line of a Lorem Ipsum paragraph through the tunnel
# to the nc server one at a time. The server echoes each line back. Both sides
# verify receipt of every line.
#
# Ports used:
# 11111 - nc server (plain text backend)
# 12345 - wolfssh client listener (plain text, nc connects here)
# 22222 - wolfSSH rendezvous (SSH, internal use only)
#
# Requirements: nc (netcat), expect

set timeout 30

set lorem_lines {
{Lorem ipsum dolor sit amet, consectetur adipiscing elit,}
{sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.}
{Ut enim ad minim veniam, quis nostrud exercitation ullamco}
{laboris nisi ut aliquip ex ea commodo consequat.}
{Duis aute irure dolor in reprehenderit in voluptate velit esse}
{cillum dolore eu fugiat nulla pariatur.}
{Excepteur sint occaecat cupidatat non proident, sunt in culpa qui}
{officia deserunt mollit anim id est laborum.}
}

# PIDs for cleanup
set nc_server_pid ""
set wolfssh_srv_pid ""
set wolfssh_clt_pid ""
set nc_client_pid ""

# --- Cleanup -----------------------------------------------------------------
proc cleanup {} {
global nc_client_pid wolfssh_clt_pid wolfssh_srv_pid nc_server_pid

puts "\n--- Cleaning up ---"
foreach pid [list $nc_client_pid $wolfssh_clt_pid $wolfssh_srv_pid $nc_server_pid] {
if {$pid ne ""} {
catch {exec kill $pid}
}
}
puts "Done."
}

# --- Fail helper -------------------------------------------------------------
proc fail {msg} {
puts "\n\[FAIL\] $msg"
cleanup
exit 1
}

# --- Check prerequisites -----------------------------------------------------
foreach tool {nc} {
if {[catch {exec which $tool}]} {
puts "ERROR: '$tool' not found in PATH"
exit 1
}
}

# --- [1] Start nc server -----------------------------------------------------
puts "\n\[1\] Starting nc server: nc -l 11111"
spawn nc -l 11111
set nc_server_id $spawn_id
set nc_server_pid [exp_pid]
puts " PID $nc_server_pid — waiting for a connection..."

# --- [2] Start wolfssh server ------------------------------------------------
puts "\n\[2\] Starting wolfssh server..."
spawn ./examples/echoserver/echoserver -1 -f
set wolfssh_srv_id $spawn_id
set wolfssh_srv_pid [exp_pid]
puts " PID $wolfssh_srv_pid — waiting for a connection..."

# --- [3] Start wolfssh client ------------------------------------------------
puts "\n\[3\] Starting wolfssh client (plain:12345 -> 11111)..."
spawn ./examples/portfwd/portfwd -u jill -P upthehill -f 12345 -t 11111
set wolfssh_clt_id $spawn_id
set wolfssh_clt_pid [exp_pid]

expect {
-i $wolfssh_clt_id
-re {sampled} {
puts " wolfssh client ready (PID $wolfssh_clt_pid)."
}
-re {(?i)(error|fatal)} {
fail "wolfssh client failed to start"
}
timeout {
fail "Timed out waiting for wolfssh client to start"
}
}

# Brief pause to let the wolfssh tunnels fully bind their listening ports
sleep 1

# --- [4] Start nc client -----------------------------------------------------
puts "\n\[4\] Starting nc client: nc localhost 12345"
spawn nc localhost 12345
set nc_client_id $spawn_id
set nc_client_pid [exp_pid]
puts " PID $nc_client_pid"

# Allow the TCP handshake and SSH negotiation to complete
sleep 1

# --- [5] Send each line, verify receipt, echo back, verify echo --------------
set n [llength $lorem_lines]
set i 0
foreach line $lorem_lines {
incr i
puts "\n\[5.$i/$n\] Client sending: \"$line\""
send -i $nc_client_id "$line\n"

expect {
-i $nc_server_id
-ex $line {
puts " \[PASS\] Server received line $i."
}
timeout {
fail "Server did not receive line $i within ${timeout}s"
}
}

send -i $nc_server_id "$line\n"

expect {
-i $nc_client_id
-ex $line {
puts " \[PASS\] Client received echo of line $i."
}
timeout {
fail "Client did not receive echo of line $i within ${timeout}s"
}
}
}

# --- Done --------------------------------------------------------------------
puts "\n=== TEST PASSED ===\n"

cleanup
exit 0
3 changes: 2 additions & 1 deletion scripts/include.am
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@ if BUILD_SCP
dist_noinst_SCRIPTS+= scripts/scp.test
endif

dist_noinst_SCRIPTS+= scripts/external.test
dist_noinst_SCRIPTS+= scripts/external.test scripts/fwd.test
EXTRA_DIST += scripts/fwd.test.expect
2 changes: 2 additions & 0 deletions src/agent.c
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,7 @@ static int PostLock(WOLFSSH_AGENT_CTX* agent,
word32 ppSz;

WLOG(WS_LOG_AGENT, "Posting lock to agent %p", agent);
WOLFSSH_UNUSED(agent);

ppSz = sizeof(pp) - 1;
if (passphraseSz < ppSz)
Expand All @@ -395,6 +396,7 @@ static int PostUnlock(WOLFSSH_AGENT_CTX* agent,
word32 ppSz;

WLOG(WS_LOG_AGENT, "Posting unlock to agent %p", agent);
WOLFSSH_UNUSED(agent);

ppSz = sizeof(pp) - 1;
if (passphraseSz < ppSz)
Expand Down
2 changes: 1 addition & 1 deletion src/ssh.c
Original file line number Diff line number Diff line change
Expand Up @@ -2607,7 +2607,7 @@ int wolfSSH_worker(WOLFSSH* ssh, word32* channelId)
}
#endif /* WOLFSSH_TEST_BLOCK */

if (ret == WS_SUCCESS) {
if (ret == WS_SUCCESS || ret == WS_CHAN_RXD) {
if (channelId != NULL) {
*channelId = ssh->lastRxId;
}
Expand Down