Adding code

pull/1/head
John Safranek 2014-07-01 17:27:47 -07:00
parent 997013f210
commit eb82d2bf28
4 changed files with 574 additions and 0 deletions

View File

@ -20,12 +20,234 @@
*/
#include <ctype.h>
#include <string.h>
#include <unistd.h>
#include <netdb.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <stdio.h>
#include <wolfssh/ssh.h>
typedef unsigned short word16;
typedef int SOCKET_T;
#ifdef TEST_IPV6
typedef struct sockaddr_in6 SOCKADDR_IN_T;
#define AF_INET_V AF_INET6
static const char* wolfsshIP = "::1";
#else
typedef struct sockaddr_in SOCKADDR_IN_T;
#define AF_INET_V AF_INET
static const char* wolfsshIP = "127.0.0.1";
#endif
#if defined(__MACH__) || defined(USE_WINDOWS_API)
#ifndef _SOCKLEN_T
typedef int socklen_t;
#endif
#endif
/* HPUX doesn't use socklent_t for third parameter to accept, unless
_XOPEN_SOURCE_EXTENDED is defined */
#if !defined(__hpux__) && !defined(CYASSL_MDK_ARM) && !defined(CYASSL_IAR_ARM)
typedef socklen_t* ACCEPT_THIRD_T;
#else
#if defined _XOPEN_SOURCE_EXTENDED
typedef socklen_t* ACCEPT_THIRD_T;
#else
typedef int* ACCEPT_THIRD_T;
#endif
#endif
static WINLINE void err_sys(const char* msg)
{
printf("server error: %s\n", msg);
if (msg)
exit(EXIT_FAILURE);
}
static WINLINE void build_addr(SOCKADDR_IN_T* addr, const char* peer,
word16 port)
{
int useLookup = 0;
(void)useLookup;
memset(addr, 0, sizeof(SOCKADDR_IN_T));
#ifndef TEST_IPV6
/* peer could be in human readable form */
if ( (peer != INADDR_ANY) && isalpha((int)peer[0])) {
#ifdef CYASSL_MDK_ARM
int err;
struct hostent* entry = gethostbyname(peer, &err);
#else
struct hostent* entry = gethostbyname(peer);
#endif
if (entry) {
memcpy(&addr->sin_addr.s_addr, entry->h_addr_list[0],
entry->h_length);
useLookup = 1;
}
else
err_sys("no entry for host");
}
#endif
#ifndef TEST_IPV6
#if defined(CYASSL_MDK_ARM)
addr->sin_family = PF_INET;
#else
addr->sin_family = AF_INET_V;
#endif
addr->sin_port = htons(port);
if (peer == INADDR_ANY)
addr->sin_addr.s_addr = INADDR_ANY;
else {
if (!useLookup)
addr->sin_addr.s_addr = inet_addr(peer);
}
#else
addr->sin6_family = AF_INET_V;
addr->sin6_port = htons(port);
if (peer == INADDR_ANY)
addr->sin6_addr = in6addr_any;
else {
#ifdef HAVE_GETADDRINFO
struct addrinfo hints;
struct addrinfo* answer = NULL;
int ret;
char strPort[80];
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET_V;
hints.ai_socktype = udp ? SOCK_DGRAM : SOCK_STREAM;
hints.ai_protocol = udp ? IPPROTO_UDP : IPPROTO_TCP;
SNPRINTF(strPort, sizeof(strPort), "%d", port);
strPort[79] = '\0';
ret = getaddrinfo(peer, strPort, &hints, &answer);
if (ret < 0 || answer == NULL)
err_sys("getaddrinfo failed");
memcpy(addr, answer->ai_addr, answer->ai_addrlen);
freeaddrinfo(answer);
#else
printf("no ipv6 getaddrinfo, loopback only tests/examples\n");
addr->sin6_addr = in6addr_loopback;
#endif
}
#endif
}
static WINLINE void tcp_socket(SOCKET_T* sockfd)
{
*sockfd = socket(AF_INET_V, SOCK_STREAM, 0);
#ifdef USE_WINDOWS_API
if (*sockfd == INVALID_SOCKET)
err_sys("socket failed\n");
#else
if (*sockfd < 0)
err_sys("socket failed\n");
#endif
#ifndef USE_WINDOWS_API
#ifdef SO_NOSIGPIPE
{
int on = 1;
socklen_t len = sizeof(on);
int res = setsockopt(*sockfd, SOL_SOCKET, SO_NOSIGPIPE, &on, len);
if (res < 0)
err_sys("setsockopt SO_NOSIGPIPE failed\n");
}
#elif defined(CYASSL_MDK_ARM)
/* nothing to define */
#else /* no S_NOSIGPIPE */
signal(SIGPIPE, SIG_IGN);
#endif /* S_NOSIGPIPE */
#if defined(TCP_NODELAY)
{
int on = 1;
socklen_t len = sizeof(on);
int res = setsockopt(*sockfd, IPPROTO_TCP, TCP_NODELAY, &on, len);
if (res < 0)
err_sys("setsockopt TCP_NODELAY failed\n");
}
#endif
#endif /* USE_WINDOWS_API */
}
static WINLINE void tcp_listen(SOCKET_T* sockfd, word16* port, int useAnyAddr)
{
SOCKADDR_IN_T addr;
/* don't use INADDR_ANY by default, firewall may block, make user switch
on */
build_addr(&addr, (useAnyAddr ? INADDR_ANY : wolfsshIP), *port);
tcp_socket(sockfd);
#if !defined(USE_WINDOWS_API) && !defined(CYASSL_MDK_ARM)
{
int res, on = 1;
socklen_t len = sizeof(on);
res = setsockopt(*sockfd, SOL_SOCKET, SO_REUSEADDR, &on, len);
if (res < 0)
err_sys("setsockopt SO_REUSEADDR failed\n");
}
#endif
if (bind(*sockfd, (const struct sockaddr*)&addr, sizeof(addr)) != 0)
err_sys("tcp bind failed");
if (listen(*sockfd, 5) != 0)
err_sys("tcp listen failed");
#if !defined(USE_WINDOWS_API)
if (*port == 0) {
socklen_t len = sizeof(addr);
if (getsockname(*sockfd, (struct sockaddr*)&addr, &len) == 0) {
#ifndef TEST_IPV6
*port = ntohs(addr.sin_port);
#else
*port = ntohs(addr.sin6_port);
#endif
}
}
#endif
}
static WINLINE void tcp_accept(SOCKET_T* sockfd, SOCKET_T* clientfd, word16 port)
{
SOCKADDR_IN_T client;
socklen_t client_len = sizeof(client);
tcp_listen(sockfd, &port, 1);
*clientfd = accept(*sockfd, (struct sockaddr*)&client,
(ACCEPT_THIRD_T)&client_len);
if (*clientfd == -1)
err_sys("tcp accept failed");
}
int main(void)
{
SOCKET_T sockfd = 0;
SOCKET_T clientfd = 0;
#ifdef DEBUG_WOLFSSH
wolfSSH_Debugging_ON();
#endif
@ -34,9 +256,13 @@ int main(void)
exit(EXIT_FAILURE);
}
tcp_accept(&sockfd, &clientfd, 22222);
if (wolfSSH_Cleanup() != WS_SUCCESS) {
fprintf(stderr, "Couldn't clean up wolfSSH.\n");
exit(EXIT_FAILURE);
}
return 0;
}

271
src/ssh.c
View File

@ -44,3 +44,274 @@ int wolfSSH_Cleanup(void)
return WS_SUCCESS;
}
static WOLFSSH_CTX* CtxInit(WOLFSSH_CTX* ctx, void* heap)
{
WLOG(WS_LOG_DEBUG, "Enter CtxInit()");
if (ctx == NULL)
return ctx;
WMEMSET(ctx, 0, sizeof(WOLFSSH_CTX));
if (heap)
ctx->heap = heap;
#ifndef WOLFSSH_USER_IO
ctx->ioRecvCb = wsEmbedRecv;
ctx->ioSendCb = wsEmbedSend;
#endif /* WOLFSSH_USER_IO */
return ctx;
}
WOLFSSH_CTX* wolfSSH_CTX_new(void* heap)
{
WOLFSSH_CTX* ctx;
WLOG(WS_LOG_DEBUG, "Enter wolfSSH_CTX_new()");
ctx = (WOLFSSH_CTX*)WMALLOC(sizeof(WOLFSSH_CTX), heap, WOLFSSH_CTX_TYPE);
ctx = CtxInit(ctx, heap);
WLOG(WS_LOG_DEBUG, "Leaving wolfSSH_CTX_new(), ctx = %p", ctx);
return ctx;
}
static void CtxResourceFree(WOLFSSH_CTX* ctx)
{
/* when context holds resources, free here */
(void)ctx;
WLOG(WS_LOG_DEBUG, "Enter CtxResourceFree()");
}
void wolfSSH_CTX_free(WOLFSSH_CTX* ctx)
{
WLOG(WS_LOG_DEBUG, "Enter wolfSSH_CTX_free()");
if (ctx) {
CtxResourceFree(ctx);
WFREE(ctx, ctx->heap, WOLFSSH_CTX_TYPE);
}
}
static WOLFSSH* SshInit(WOLFSSH* ssh, WOLFSSH_CTX* ctx)
{
WLOG(WS_LOG_DEBUG, "Enter SshInit()");
if (ssh == NULL)
return ssh;
WMEMSET(ssh, 0, sizeof(WOLFSSH)); /* default init to zeros */
if (ctx)
ssh->ctx = ctx;
else {
WLOG(WS_LOG_ERROR, "Trying to init a wolfSSH w/o wolfSSH_CTX");
wolfSSH_free(ssh);
return NULL;
}
ssh->rfd = -1; /* set to invalid */
ssh->wfd = -1; /* set to invalid */
ssh->ioReadCtx = &ssh->rfd; /* prevent invalid access if not correctly */
ssh->ioWriteCtx = &ssh->wfd; /* set */
return ssh;
}
WOLFSSH* wolfSSH_new(WOLFSSH_CTX* ctx)
{
WOLFSSH* ssh;
void* heap = NULL;
if (ctx)
heap = ctx->heap;
WLOG(WS_LOG_DEBUG, "Enter wolfSSH_new()");
ssh = (WOLFSSH*)WMALLOC(sizeof(WOLFSSH), heap, WOLFSSH_TYPE);
ssh = SshInit(ssh, ctx);
WLOG(WS_LOG_DEBUG, "Leaving wolfSSH_new(), ssh = %p", ssh);
return ssh;
}
static void SshResourceFree(WOLFSSH* ssh)
{
/* when ssh holds resources, free here */
(void)ssh;
WLOG(WS_LOG_DEBUG, "Enter sshResourceFree()");
}
void wolfSSH_free(WOLFSSH* ssh)
{
WLOG(WS_LOG_DEBUG, "Enter wolfSSH_free()");
if (ssh) {
SshResourceFree(ssh);
WFREE(ssh, ssh->ctx ? ssh->ctx->heap : NULL, WOLFSSH_TYPE);
}
}
static WOLFSSH_CHAN* SshChanInit(WOLFSSH_CHAN* chan, WOLFSSH* ssh)
{
WLOG(WS_LOG_DEBUG, "Enter SshChanInit()");
if (chan == NULL)
return chan;
WMEMSET(chan, 0, sizeof(WOLFSSH_CHAN)); /* default init to zeros */
if (ssh) {
chan->ssh = ssh;
chan->ctx = ssh->ctx;
}
else {
WLOG(WS_LOG_ERROR, "Trying to init a wolfSSH_CHAN w/o wolfSSH");
wolfSSH_CHAN_free(chan);
return NULL;
}
return chan;
}
WOLFSSH_CHAN* wolfSSH_CHAN_new(WOLFSSH* ssh)
{
WOLFSSH_CHAN* chan;
void* heap = NULL;
WLOG(WS_LOG_DEBUG, "Enter wolfSSH_CHAN_new()");
if (ssh != NULL && ssh->ctx != NULL)
heap = ssh->ctx->heap;
chan = (WOLFSSH_CHAN*)WMALLOC(sizeof(WOLFSSH_CHAN),
heap, WOLFSSH_CHAN_TYPE);
chan = SshChanInit(chan, ssh);
WLOG(WS_LOG_DEBUG, "Leaving wolfSSH_CHAN_new(), chan = %p", chan);
return chan;
}
static void SshChanResourceFree(WOLFSSH_CHAN* chan)
{
/* when ssh channel holds resources, free here */
(void)chan;
WLOG(WS_LOG_DEBUG, "Enter SshChanResourceFree()");
}
void wolfSSH_CHAN_free(WOLFSSH_CHAN* chan)
{
WLOG(WS_LOG_DEBUG, "Enter wolfSCEP_free()");
if (chan) {
SshChanResourceFree(chan);
WFREE(chan, chan->ctx ? chan->ctx->heap : NULL, WOLFSCEP_TYPE);
}
}
int wolfSSH_set_fd(WOLFSSH* ssh, int fd)
{
WLOG(WS_LOG_DEBUG, "Enter wolfSSH_set_fd()");
if (ssh) {
ssh->rfd = fd;
ssh->wfd = fd;
ssh->ioReadCtx = &ssh->rfd;
ssh->ioWriteCtx = &ssh->wfd;
return WS_SUCCESS;
}
return WS_BAD_ARGUMENT;
}
int wolfSSH_get_fd(const WOLFSSH* ssh)
{
WLOG(WS_LOG_DEBUG, "Enter wolfSSH_get_fd()");
if (ssh)
return ssh->rfd;
return WS_BAD_ARGUMENT;
}
enum {
doProcessInit
};
int ProcessReply(WOLFSSH* ssh)
{
int ret = WS_FATAL_ERROR;
int readSz;
(void)readSz;
for (;;) {
switch (ssh->processReply) {
case doProcessInit:
readSz = ssh->blockSz;
}
}
return ret;
}
int wolfSSH_accept(WOLFSSH* ssh)
{
switch (ssh->acceptState) {
case ACCEPT_BEGIN:
if ( (ssh->error = ProcessReply(ssh)) < 0) {
WLOG(WS_LOG_DEBUG, "accept reply error: %d", ssh->error);
return WS_FATAL_ERROR;
}
ssh->acceptState = CLIENT_VERSION_DONE;
WLOG(WS_LOG_DEBUG, "accept state CLIENT_VERSION_DONE");
case CLIENT_VERSION_DONE:
break;
case SERVER_VERSION_SENT:
break;
}
return WS_FATAL_ERROR;
}
int SendServerVersion(WOLFSSH* ssh)
{
(void)ssh;
return WS_FATAL_ERROR;
}
int DoClientVersion(WOLFSSH* ssh)
{
(void)ssh;
return WS_FATAL_ERROR;
}

View File

@ -29,21 +29,65 @@ extern "C" {
#endif
enum {
/* Any of the items can be none. */
ID_NONE,
/* Encryption IDs */
ID_AES128_CBC,
ID_AES128_CTR,
ID_AES128_GCM_WOLF,
/* Integrity IDs */
ID_HMAC_SHA1,
ID_HMAC_SHA1_96,
/* Key Exchange IDs */
ID_DH_GROUP1_SHA1,
ID_DH_GROUP14_SHA1,
/* Public Key IDs */
ID_SSH_RSA,
ID_UNKNOWN
};
WOLFSSH_LOCAL uint8_t NameToId(const char*);
WOLFSSH_LOCAL const char* IdToName(uint8_t);
/* our wolfSSH Context */
struct WOLFSSH_CTX {
void* heap; /* heap hint */
WS_CallbackIORecv ioRecvCb; /* I/O Receive Callback */
WS_CallbackIOSend ioSendCb; /* I/O Send Callback */
uint8_t compression;
};
/* our wolfSSH session */
struct WOLFSSH {
WOLFSSH_CTX* ctx; /* owner context */
int error;
int rfd;
int wfd;
void* ioReadCtx; /* I/O Read Context handle */
void* ioWriteCtx; /* I/O Write Context handle */
int rflags; /* optional read flags */
int wflags; /* optional write flags */
WOLFSSH_CHAN *channel; /* single data channel */
uint8_t blockSz;
uint8_t acceptState;
uint8_t processReply;
};
/* wolfSSH channel */
struct WOLFSSH_CHAN {
WOLFSSH_CTX* ctx;
WOLFSSH* ssh;
int id;
};
@ -55,6 +99,19 @@ WOLFSSH_LOCAL int wsEmbedSend(WOLFSSH* ssh, void*, uint32_t sz, void* ctx);
#endif /* WOLFSSH_USER_IO */
WOLFSSH_LOCAL int ProcessReply(WOLFSSH*);
WOLFSSH_LOCAL int SendServerVersion(WOLFSSH*);
WOLFSSH_LOCAL int DoClientVersion(WOLFSSH*);
enum {
ACCEPT_BEGIN = 0,
CLIENT_VERSION_DONE,
SERVER_VERSION_SENT,
};
#ifdef __cplusplus
}
#endif

View File

@ -42,12 +42,31 @@ WOLFSSH_API int wolfSSH_Cleanup(void);
WOLFSSH_API int wolfSSH_Debugging_ON(void);
WOLFSSH_API void wolfSSH_Debugging_OFF(void);
/* context functions */
WOLFSSH_API WOLFSSH_CTX* wolfSSH_CTX_new(void*);
WOLFSSH_API void wolfSSH_CTX_free(WOLFSSH_CTX*);
/* ssh session functions */
WOLFSSH_API WOLFSSH* wolfSSH_new(WOLFSSH_CTX*);
WOLFSSH_API void wolfSSH_free(WOLFSSH*);
/* ssh channel functions */
WOLFSSH_API WOLFSSH_CHAN* wolfSSH_CHAN_new(WOLFSSH*);
WOLFSSH_API void wolfSSH_CHAN_free(WOLFSSH_CHAN*);
WOLFSSH_API int wolfSSH_set_fd(WOLFSSH*, int);
WOLFSSH_API int wolfSSH_get_fd(const WOLFSSH*);
WOLFSSH_API const char* wolfSSH_get_error(int);
/* I/O callbacks */
typedef int (*WS_CallbackIORecv)(WOLFSSH*, void* buf, uint32_t sz, void* ctx);
typedef int (*WS_CallbackIOSend)(WOLFSSH*, void* buf, uint32_t sz, void* ctx);
/* Channel I/O callbacks */
typedef int (*WSH_CallbackChanRecv)();
typedef int (*WSH_CallbackChanSend)();
WOLFSSH_API void wolfSSH_SetIORecv(WOLFSSH_CTX*, WS_CallbackIORecv);
WOLFSSH_API void wolfSSH_SetIOSend(WOLFSSH_CTX*, WS_CallbackIOSend);
@ -57,6 +76,7 @@ WOLFSSH_API void wolfSSH_SetIOWriteCtx(WOLFSSH* ssh, void *ctx);
WOLFSSH_API void* wolfSSH_GetIOReadCtx(WOLFSSH* ssh);
WOLFSSH_API void* wolfSSH_GetIOWriteCtx(WOLFSSH* ssh);
WOLFSSH_API int wolfSSH_accept(WOLFSSH* ssh);
/* dynamic memory types */