Skip to content

Commit

Permalink
Merge pull request #38 from ejohnstown/client
Browse files Browse the repository at this point in the history
Client
  • Loading branch information
dgarske authored Sep 26, 2017
2 parents 8e2d105 + 65fb16d commit 524e56e
Show file tree
Hide file tree
Showing 26 changed files with 1,834 additions and 494 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ diff
.vimrc

# examples
examples/client/client
examples/echoserver/echoserver
examples/server/server

Expand Down
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ wolfSSH is dependent on wolfCrypt. The simplest configuration of wolfSSL
required for wolfSSH is the default build.

$ cd wolfssl
$ ./configure [OPTIONS]
$ ./configure [OPTIONS] CPPFLAGS=-DWOLFSSL_PUBLIC_MP
$ make check
$ sudo make install

Expand Down Expand Up @@ -95,6 +95,8 @@ release notes
- Added ECDH Group Exchange with SHA2 hashing and curves nistp256,
nistp384, and nistp521.
- Added ECDSA with SHA2 hashing and curves nistp256, nistp384, and nistp521.
- Added client support.
- Added an example client.
- Changed the echoserver to allow only one connection, but multiple
connections are allowed with a command line option.
- Added option to echoserver to offer an ECC public key.
Expand Down
3 changes: 0 additions & 3 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,6 @@ TAO_REQUIRE_LIBWOLFSSL
#REQUIRE_CYASSL([scep])
#REQUIRE_WOLFCRYPT([aes rsa dh])

# Disable any client code. For size, as nothing calls it.
AM_CPPFLAGS="$AM_CPPFLAGS -DWOLFSSL_NO_CLIENT"

# since we have autoconf available, we can use cyassl options header
AM_CPPFLAGS="$AM_CPPFLAGS -DHAVE_CYASSL_OPTIONS"

Expand Down
295 changes: 295 additions & 0 deletions examples/client/client.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,295 @@
/* client.c
*
* Copyright (C) 2014-2017 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/>.
*/


#define SINGLE_THREADED
/* The client doesn't use threading. */

#include <wolfssh/ssh.h>
#include <wolfssh/test.h>
#include "examples/client/client.h"
#ifndef USE_WINDOWS_API
#include <termios.h>
#endif


const char testString[] = "Hello, wolfSSH!";


#ifndef USE_WINDOWS_API
static struct termios originalTerm;
#else
static DWORD originalTerm;
#endif

static int InitEcho(void)
{
#ifndef USE_WINDOWS_API
return tcgetattr(STDIN_FILENO, &originalTerm);
#else
HANDLE stdinHandle = GetStdHandle(STD_INPUT_HANDLE);
return (GetConsoleMode(stdinHandle, &originalTerm) == 0);
#endif
}


static int SetEcho(int on)
{
#ifndef USE_WINDOWS_API
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
HANDLE stdinHandle = GetStdHandle(STD_INPUT_HANDLE);
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;
}


static void ShowUsage(void)
{
printf("client %s\n", LIBWOLFSSH_VERSION_STRING);
printf(" -? display this help and exit\n");
printf(" -h <host> host to connect to, default %s\n", wolfSshIp);
printf(" -p <num> port to connect on, default %d\n", wolfSshPort);
printf(" -u <username> username to authenticate as (REQUIRED)\n");
printf(" -P <password> password for username, prompted if omitted\n");
}


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 (fgets((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;
}


THREAD_RETURN WOLFSSH_THREAD client_test(void* args)
{
WOLFSSH_CTX* ctx = NULL;
WOLFSSH* ssh = NULL;
SOCKET_T sockFd = WOLFSSH_SOCKET_INVALID;
SOCKADDR_IN_T clientAddr;
socklen_t clientAddrSz = sizeof(clientAddr);
char rxBuf[80];
int ret;
char ch;
word16 port = wolfSshPort;
char* host = (char*)wolfSshIp;
const char* username = NULL;
const char* password = NULL;

int argc = ((func_args*)args)->argc;
char** argv = ((func_args*)args)->argv;
((func_args*)args)->return_code = 0;

while ((ch = mygetopt(argc, argv, "?h:p:u:P:")) != -1) {
switch (ch) {
case 'h':
host = 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 'u':
username = myoptarg;
break;

case 'P':
password = myoptarg;
break;

case '?':
ShowUsage();
exit(EXIT_SUCCESS);

default:
ShowUsage();
exit(MY_EX_USAGE);
}
}
myoptind = 0; /* reset for test cases */

if (username == NULL)
err_sys("client requires a username parameter.");

ctx = wolfSSH_CTX_new(WOLFSSH_ENDPOINT_CLIENT, NULL);
if (ctx == NULL)
err_sys("Couldn't create wolfSSH client context.");

wolfSSH_SetUserAuth(ctx, wsUserAuth);

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(&clientAddr, host, port);
tcp_socket(&sockFd);
ret = connect(sockFd, (const struct sockaddr *)&clientAddr, clientAddrSz);
if (ret != 0)
err_sys("Couldn't connect to server.");

ret = wolfSSH_set_fd(ssh, (int)sockFd);
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 SSH stream.");

ret = wolfSSH_stream_send(ssh, (byte*)testString,
(word32)strlen(testString));
if (ret <= 0)
err_sys("Couldn't send test string.");

ret = wolfSSH_stream_read(ssh, (byte*)rxBuf, sizeof(rxBuf) - 1);
if (ret <= 0)
err_sys("Stream read failed.");
rxBuf[ret] = '\0';
printf("Server said: %s\n", rxBuf);

ret = wolfSSH_shutdown(ssh);
if (ret != WS_SUCCESS)
err_sys("Closing stream failed.");

WCLOSESOCKET(sockFd);
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;

WSTARTTCP();

if (InitEcho() != 0)
err_sys("Couldn't initialize terminal.");

#ifdef DEBUG_WOLFSSH
wolfSSH_Debugging_ON();
#endif

wolfSSH_Init();

ChangeToWolfSshRoot();
#ifndef NO_WOLFSSH_CLIENT
client_test(&args);
#endif /* NO_WOLFSSH_CLIENT */

wolfSSH_Cleanup();

return args.return_code;
}

int myoptind = 0;
char* myoptarg = NULL;

#endif /* NO_MAIN_DRIVER */
31 changes: 31 additions & 0 deletions examples/client/client.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/* client.h
*
* Copyright (C) 2014-2017 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/>.
*/


#pragma once

#ifndef _WOLFSSH_CLIENT_H_
#define _WOLFSSH_CLIENT_H_


THREAD_RETURN WOLFSSH_THREAD client_test(void* args);


#endif /* _WOLFSSH_CLIENT_H_ */
11 changes: 11 additions & 0 deletions examples/client/include.am
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# vim:ft=automake
# All paths should be given relative to the root

noinst_PROGRAMS += examples/client/client
noinst_HEADERS += examples/client/client.h
examples_client_client_SOURCES = examples/client/client.c
examples_client_client_LDADD = src/libwolfssh.la
examples_client_client_DEPENDENCIES = src/libwolfssh.la

dist_example_DATA+= examples/client/client.c
DISTCLEANFILES+= examples/client/.libs/client
Empty file modified examples/echoserver/echoserver.h
100755 → 100644
Empty file.
1 change: 1 addition & 0 deletions examples/include.am
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@
# included from Top Level Makefile.am
# All paths should be given relative to the root

include examples/client/include.am
include examples/echoserver/include.am
Loading

0 comments on commit 524e56e

Please sign in to comment.