mirror of https://github.com/wolfSSL/wolfssh.git
304 lines
8.1 KiB
C
304 lines
8.1 KiB
C
/* 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 WOLFSSH_TEST_CLIENT
|
|
|
|
|
|
#include <wolfssh/ssh.h>
|
|
#include <wolfssh/test.h>
|
|
#include "examples/client/client.h"
|
|
#if !defined(USE_WINDOWS_API) && !defined(MICROCHIP_PIC32)
|
|
#include <termios.h>
|
|
#endif
|
|
|
|
const char testString[] = "Hello, wolfSSH!";
|
|
|
|
|
|
static int SetEcho(int on)
|
|
{
|
|
#if !defined(USE_WINDOWS_API) && !defined(MICROCHIP_PIC32)
|
|
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;
|
|
}
|
|
|
|
|
|
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");
|
|
printf(" -x exit after successful connection without doing\n"
|
|
" read/write\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;
|
|
byte imExit = 0;
|
|
|
|
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:x")) != -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 'x':
|
|
/* exit after successful connection without read/write */
|
|
imExit = 1;
|
|
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.");
|
|
|
|
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(&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.");
|
|
|
|
if (!imExit) {
|
|
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;
|
|
args.user_auth = NULL;
|
|
|
|
WSTARTTCP();
|
|
|
|
#ifdef DEBUG_WOLFSSH
|
|
wolfSSH_Debugging_ON();
|
|
#endif
|
|
|
|
wolfSSH_Init();
|
|
|
|
ChangeToWolfSshRoot();
|
|
client_test(&args);
|
|
|
|
wolfSSH_Cleanup();
|
|
|
|
return args.return_code;
|
|
}
|
|
|
|
int myoptind = 0;
|
|
char* myoptarg = NULL;
|
|
|
|
#endif /* NO_MAIN_DRIVER */
|