1. added in the stream send function

2. example uses the new send function
3. added in window size update receipt
4. tweaked the accept state machine to actually finish
pull/1/head
John Safranek 2015-01-07 13:49:01 -08:00
parent 6975448d1b
commit b548720a9a
7 changed files with 183 additions and 56 deletions

View File

@ -245,13 +245,13 @@ static THREAD_RETURN CYASSL_THREAD server_worker(void* vArgs)
{
WOLFSSH* ssh = (WOLFSSH*)vArgs;
SOCKET_T clientFd = wolfSSH_get_fd(ssh);
const char* msgA = "Who's there?!\n";
const char* msgB = "Go away!\n";
const char* msgA = "Who's there?!\r\n";
const char* msgB = "Go away!\r\n";
if (wolfSSH_accept(ssh) == WS_SUCCESS) {
send(clientFd, msgA, strlen(msgA), 0);
wolfSSH_stream_send(ssh, (uint8_t*)msgA, (uint32_t)strlen(msgA));
sleep(1);
send(clientFd, msgB, strlen(msgB), 0);
wolfSSH_stream_send(ssh, (uint8_t*)msgB, (uint32_t)strlen(msgB));
}
close(clientFd);
wolfSSH_free(ssh);

View File

@ -136,6 +136,9 @@ const char* GetErrorString(int err)
case WS_CREATE_MAC_E:
return "verify mac error";
case WS_RESOURCE_E:
return "insufficient resources for new channel";
default:
return "Unknown error code";
}
@ -169,7 +172,10 @@ static const NameIdPair NameIdMap[] = {
{ ID_SSH_RSA, "ssh-rsa" },
/* UserAuth IDs */
{ ID_USERAUTH_PASSWORD, "password" }
{ ID_USERAUTH_PASSWORD, "password" },
/* Channel Type IDs */
{ ID_CHANTYPE_SESSION, "session" }
};
@ -207,6 +213,33 @@ const char* IdToName(uint8_t id)
}
static Channel* ChannelNew(WOLFSSH* ssh, uint8_t channelType,
uint32_t peerChannel,
uint32_t peerInitialWindowSz,
uint32_t peerMaxPacketSz)
{
Channel *newChannel = NULL;
WLOG(WS_LOG_DEBUG, "Entering ChannelNew()");
if (!ssh->channel.inUse) {
newChannel = &ssh->channel;
newChannel->inUse = 1;
newChannel->channelType = channelType;
newChannel->channel = ssh->nextChannel++;
newChannel->windowSz = DEFAULT_WINDOW_SZ;
newChannel->maxPacketSz = DEFAULT_MAX_PACKET_SZ;
newChannel->peerChannel = peerChannel;
newChannel->peerWindowSz = peerInitialWindowSz;
newChannel->peerMaxPacketSz = peerMaxPacketSz;
}
WLOG(WS_LOG_INFO, "Leaving ChannelNew(), ret = %p", newChannel);
return newChannel;
}
int BufferInit(Buffer* buffer, uint32_t size, void* heap)
{
if (buffer == NULL)
@ -1273,40 +1306,51 @@ static int DoChannelOpen(WOLFSSH* ssh,
uint32_t begin = *idx;
uint32_t typeSz;
char type[32];
uint32_t channel;
uint32_t initialWindowSz;
uint32_t maxPacketSz;
uint8_t typeId;
uint32_t peerChannel;
uint32_t peerInitialWindowSz;
uint32_t peerMaxPacketSz;
int ret;
Channel* newChannel;
WLOG(WS_LOG_DEBUG, "Entering DoChannelOpen()");
(void)ssh;
(void)len;
ret = GetString(type, &typeSz, buf, len, &begin);
if (ret == WS_SUCCESS)
ret = GetUint32(&channel, buf, len, &begin);
ret = GetUint32(&peerChannel, buf, len, &begin);
if (ret == WS_SUCCESS)
ret = GetUint32(&initialWindowSz, buf, len, &begin);
ret = GetUint32(&peerInitialWindowSz, buf, len, &begin);
if (ret == WS_SUCCESS)
ret = GetUint32(&maxPacketSz, buf, len, &begin);
ret = GetUint32(&peerMaxPacketSz, buf, len, &begin);
if (ret != WS_SUCCESS) {
WLOG(WS_LOG_DEBUG, "Leaving DoChannelOpen(), ret = %d", ret);
return ret;
}
WLOG(WS_LOG_DEBUG, " type = %s", type);
WLOG(WS_LOG_DEBUG, " channel = %u", channel);
WLOG(WS_LOG_DEBUG, " initialWindowSz = %u", initialWindowSz);
WLOG(WS_LOG_DEBUG, " maxPacketSz = %u", maxPacketSz);
WLOG(WS_LOG_INFO, " type = %s", type);
WLOG(WS_LOG_INFO, " peerChannel = %u", peerChannel);
WLOG(WS_LOG_INFO, " peerInitialWindowSz = %u", peerInitialWindowSz);
WLOG(WS_LOG_INFO, " peerMaxPacketSz = %u", peerMaxPacketSz);
*idx = begin;
ssh->clientState = CLIENT_CHANNEL_REQUEST_DONE;
typeId = NameToId(type, typeSz);
if (typeId != ID_CHANTYPE_SESSION)
return WS_INVALID_CHANTYPE;
newChannel = ChannelNew(ssh, typeId,
peerChannel, peerInitialWindowSz, peerMaxPacketSz);
if (newChannel == NULL)
return WS_RESOURCE_E;
ssh->clientState = CLIENT_DONE;
newChannel->peerChannel = peerChannel;
newChannel->peerWindowSz = peerInitialWindowSz;
newChannel->peerMaxPacketSz = peerMaxPacketSz;
return WS_SUCCESS;
}
@ -1398,6 +1442,36 @@ static int DoChannelRequest(WOLFSSH* ssh,
}
static int DoChannelWindowAdjust(WOLFSSH* ssh,
uint8_t* buf, uint32_t len, uint32_t* idx)
{
uint32_t begin = *idx;
uint32_t channel, bytesToAdd;
int ret;
WLOG(WS_LOG_DEBUG, "Entering DoChannelWindowAdjust()");
ret = GetUint32(&channel, buf, len, &begin);
if (ret == WS_SUCCESS)
ret = GetUint32(&bytesToAdd, buf, len, &begin);
if (ret != WS_SUCCESS) {
WLOG(WS_LOG_DEBUG, "Leaving DoChannelWindowAdjust(), ret = %d", ret);
return ret;
}
WLOG(WS_LOG_INFO, " channel = %u", channel);
WLOG(WS_LOG_INFO, " bytesToAdd = %u", bytesToAdd);
WLOG(WS_LOG_INFO, " peerWindowSz = %u", ssh->channel.peerWindowSz);
ssh->channel.peerWindowSz += bytesToAdd;
WLOG(WS_LOG_INFO, " update peerWindowSz = %u", ssh->channel.peerWindowSz);
WLOG(WS_LOG_DEBUG, "Leaving DoChannelWindowAdjust()");
return WS_SUCCESS;
}
static int DoChannelData(WOLFSSH* ssh,
uint8_t* buf, uint32_t len, uint32_t* idx)
{
@ -1416,7 +1490,7 @@ static int DoChannelData(WOLFSSH* ssh,
return ret;
}
SendChannelData(ssh, channel, buf + begin, dataSz);
SendChannelData(ssh, ssh->channel.peerChannel, buf + begin, dataSz);
*idx = begin + dataSz;
@ -1505,6 +1579,12 @@ static int DoPacket(WOLFSSH* ssh)
idx += payloadIdx;
break;
case MSGID_CHANNEL_WINDOW_ADJUST:
WLOG(WS_LOG_DEBUG, "Decoding MSGID_CHANNEL_WINDOW_ADJUST");
DoChannelWindowAdjust(ssh, buf + idx, payloadSz, &payloadIdx);
idx += payloadIdx;
break;
case MSGID_CHANNEL_DATA:
WLOG(WS_LOG_DEBUG, "Decoding MSGID_CHANNEL_DATA");
DoChannelData(ssh, buf + idx, payloadSz, &payloadIdx);
@ -2197,7 +2277,7 @@ int SendNewKeys(WOLFSSH* ssh)
idx = ssh->outputBuffer.length;
output[idx++] = MSGID_NEWKEYS;
ssh->outputBuffer.length = idx;
BundlePacket(ssh);
@ -2470,11 +2550,17 @@ int SendChannelOpenConf(WOLFSSH* ssh)
{
uint8_t* output;
uint32_t idx;
Channel* channel;
WLOG(WS_LOG_DEBUG, "Entering SendChannelOpenConf()");
if (ssh == NULL)
if (ssh == NULL) {
WLOG(WS_LOG_DEBUG, "Leaving SendChannelOpenConf(), ret = %d",
WS_BAD_ARGUMENT);
return WS_BAD_ARGUMENT;
}
channel = &ssh->channel;
PreparePacket(ssh, MSG_ID_SZ + (UINT32_SZ * 4));
@ -2482,13 +2568,13 @@ int SendChannelOpenConf(WOLFSSH* ssh)
idx = ssh->outputBuffer.length;
output[idx++] = MSGID_CHANNEL_OPEN_CONF;
c32toa(0, output + idx); /* recipient channel */
c32toa(channel->peerChannel, output + idx);
idx += UINT32_SZ;
c32toa(0, output + idx); /* sender channel */
c32toa(channel->channel, output + idx);
idx += UINT32_SZ;
c32toa(DEFAULT_WINDOW_SZ, output + idx);
c32toa(channel->windowSz, output + idx);
idx += UINT32_SZ;
c32toa(DEFAULT_MAX_PACKET_SZ, output + idx);
c32toa(channel->maxPacketSz, output + idx);
idx += UINT32_SZ;
ssh->outputBuffer.length = idx;
@ -2496,20 +2582,31 @@ int SendChannelOpenConf(WOLFSSH* ssh)
BundlePacket(ssh);
SendBuffered(ssh);
WLOG(WS_LOG_DEBUG, "Leaving SendChannelOpenConf()");
return WS_SUCCESS;
}
int SendChannelData(WOLFSSH* ssh, uint32_t channel,
int SendChannelData(WOLFSSH* ssh, uint32_t peerChannel,
uint8_t* data, uint32_t dataSz)
{
uint8_t* output;
uint32_t idx;
Channel* channel;
WLOG(WS_LOG_DEBUG, "Entering SendChannelData()");
if (ssh == NULL)
return WS_BAD_ARGUMENT;
channel = &ssh->channel;
if (channel->peerChannel != peerChannel) {
WLOG(WS_LOG_DEBUG, "Invalid peer channel");
}
if (channel->peerWindowSz < dataSz) {
WLOG(WS_LOG_DEBUG, "Peer window too small");
}
PreparePacket(ssh, MSG_ID_SZ + UINT32_SZ + LENGTH_SZ + dataSz);
@ -2517,7 +2614,7 @@ int SendChannelData(WOLFSSH* ssh, uint32_t channel,
idx = ssh->outputBuffer.length;
output[idx++] = MSGID_CHANNEL_DATA;
c32toa(channel, output + idx);
c32toa(channel->peerChannel, output + idx);
idx += UINT32_SZ;
c32toa(dataSz, output + idx);
idx += LENGTH_SZ;
@ -2529,6 +2626,11 @@ int SendChannelData(WOLFSSH* ssh, uint32_t channel,
BundlePacket(ssh);
SendBuffered(ssh);
WLOG(WS_LOG_INFO, " dataSz = %u", dataSz);
WLOG(WS_LOG_INFO, " peerWindowSz = %u", channel->peerWindowSz);
channel->peerWindowSz -= dataSz;
WLOG(WS_LOG_INFO, " update peerWindowSz = %u", channel->peerWindowSz);
WLOG(WS_LOG_DEBUG, "Leaving SendChannelData()");
return WS_SUCCESS;
}

View File

@ -158,7 +158,7 @@ void WLOG(enum wolfSSH_LogLevel level, const char *const fmt, ...)
if (logFunction)
logFunction(level, msgStr);
else
fprintf(stderr, "%s: [%s] %s\n", timeStr, GetLogStr(level), msgStr);
fprintf(stdout, "%s: [%s] %s\n", timeStr, GetLogStr(level), msgStr);
}
#endif /* DEBUG_WOLFSSH */

View File

@ -151,6 +151,7 @@ static WOLFSSH* SshInit(WOLFSSH* ssh, WOLFSSH_CTX* ctx)
ssh->ioWriteCtx = &ssh->wfd; /* set */
ssh->acceptState = ACCEPT_BEGIN;
ssh->clientState = CLIENT_BEGIN;
ssh->nextChannel = DEFAULT_NEXT_CHANNEL;
ssh->blockSz = MIN_BLOCK_SZ;
ssh->encryptId = ID_NONE;
ssh->macId = ID_NONE;
@ -401,7 +402,7 @@ int wolfSSH_accept(WOLFSSH* ssh)
WLOG(WS_LOG_DEBUG, acceptState, "SERVER_USERAUTH_SENT");
case ACCEPT_SERVER_USERAUTH_SENT:
while (ssh->clientState < CLIENT_CHANNEL_REQUEST_DONE) {
while (ssh->clientState < CLIENT_DONE) {
if ( (ssh->error = ProcessReply(ssh)) < 0) {
WLOG(WS_LOG_DEBUG, acceptError,
"SERVER_USERAUTH_SENT", ssh->error);
@ -419,18 +420,31 @@ int wolfSSH_accept(WOLFSSH* ssh)
}
ssh->acceptState = ACCEPT_SERVER_CHANNEL_ACCEPT_SENT;
WLOG(WS_LOG_DEBUG, acceptState, "SERVER_CHANNEL_ACCEPT_SENT");
case ACCEPT_SERVER_CHANNEL_ACCEPT_SENT:
while (ssh->clientState < CLIENT_DONE) {
if ( (ssh->error = ProcessReply(ssh)) < 0) {
WLOG(WS_LOG_DEBUG, acceptError,
"SERVER_CHANNEL_ACCEPT_SENT", ssh->error);
return WS_FATAL_ERROR;
}
}
}
return WS_FATAL_ERROR;
return WS_SUCCESS;
}
int wolfSSH_stream_read(WOLFSSH* ssh, uint8_t* buf, uint32_t bufSz)
{
int bytesRxd = 0;
(void)ssh;
(void)buf;
(void)bufSz;
return bytesRxd;
}
int wolfSSH_stream_send(WOLFSSH* ssh, uint8_t* buf, uint32_t bufSz)
{
int bytesTxd = 0;
bytesTxd = SendChannelData(ssh, ssh->channel.peerChannel, buf, bufSz);
return bytesTxd;
}

View File

@ -39,20 +39,20 @@ extern "C" {
/* main public return values */
enum WS_ErrorCodes {
WS_SUCCESS = 0, /* function success */
WS_FATAL_ERROR = -1, /* general function failure */
WS_BAD_ARGUMENT = -2, /* bad function argument */
WS_MEMORY_E = -3, /* memory allocation failure */
WS_BUFFER_E = -4, /* input/output buffer size error */
WS_PARSE_E = -5, /* general parsing error */
WS_NOT_COMPILED = -6, /* feature not compiled in */
WS_OVERFLOW_E = -7, /* would overflow if continued */
WS_BAD_USAGE = -8, /* bad example usage */
WS_SUCCESS = 0, /* function success */
WS_FATAL_ERROR = -1, /* general function failure */
WS_BAD_ARGUMENT = -2, /* bad function argument */
WS_MEMORY_E = -3, /* memory allocation failure */
WS_BUFFER_E = -4, /* input/output buffer size error */
WS_PARSE_E = -5, /* general parsing error */
WS_NOT_COMPILED = -6, /* feature not compiled in */
WS_OVERFLOW_E = -7, /* would overflow if continued */
WS_BAD_USAGE = -8, /* bad example usage */
WS_SOCKET_ERROR_E = -9,
WS_WANT_READ = -10,
WS_WANT_WRITE = -11,
WS_RECV_OVERFLOW_E = -12,
WS_VERSION_E = -13, /* Peer using wrong version of SSH */
WS_VERSION_E = -13, /* Peer using wrong version of SSH */
WS_SEND_OOB_READ_E = -14,
WS_INPUT_CASE_E = -15,
WS_BAD_FILETYPE_E = -16,
@ -63,7 +63,9 @@ enum WS_ErrorCodes {
WS_DECRYPT_E = -21,
WS_ENCRYPT_E = -22,
WS_VERIFY_MAC_E = -23,
WS_CREATE_MAC_E = -24
WS_CREATE_MAC_E = -24,
WS_RESOURCE_E = -25, /* insufficient resources for new channel */
WS_INVALID_CHANTYPE = -26, /* invalid channel type */
};

View File

@ -81,6 +81,9 @@ enum {
/* UserAuth IDs */
ID_USERAUTH_PASSWORD,
/* Channel Type IDs */
ID_CHANTYPE_SESSION,
ID_UNKNOWN
};
@ -99,6 +102,7 @@ enum {
#define UINT32_SZ 4
#define DEFAULT_WINDOW_SZ (1024 * 1024)
#define DEFAULT_MAX_PACKET_SZ (16 * 1024)
#define DEFAULT_NEXT_CHANNEL 13013
WOLFSSH_LOCAL uint8_t NameToId(const char*, uint32_t);
@ -163,13 +167,14 @@ typedef struct HandshakeInfo {
typedef struct Channel {
uint8_t inUse;
uint8_t channelType;
uint32_t channel;
uint32_t windowSz;
uint32_t maxPacketSz;
uint32_t peerChannel;
uint32_t peerWindowSz;
uint32_t peerMaxPacketSz;
uint32_t channel;
uint32_t peerChannel;
} Channel;
@ -210,6 +215,9 @@ struct WOLFSSH {
Ciphers encryptCipher;
Ciphers decryptCipher;
uint32_t nextChannel;
Channel channel;
Buffer inputBuffer;
Buffer outputBuffer;
RNG* rng;
@ -291,8 +299,6 @@ enum ClientStates {
CLIENT_USING_KEYS,
CLIENT_USERAUTH_REQUEST_DONE,
CLIENT_USERAUTH_DONE,
CLIENT_CHANNEL_REQUEST_DONE,
CLIENT_CHANNEL_PTY_OPEN,
CLIENT_DONE
};
@ -326,6 +332,7 @@ enum WS_MessageIds {
MSGID_CHANNEL_OPEN = 90,
MSGID_CHANNEL_OPEN_CONF = 91,
MSGID_CHANNEL_WINDOW_ADJUST = 93,
MSGID_CHANNEL_DATA = 94,
MSGID_CHANNEL_REQUEST = 98
};

View File

@ -83,7 +83,9 @@ WOLFSSH_API int wolfSSH_CTX_UseCert_buffer(WOLFSSH_CTX*,
WOLFSSH_API int wolfSSH_CTX_UseCaCert_buffer(WOLFSSH_CTX*,
const uint8_t*, uint32_t, int);
WOLFSSH_API int wolfSSH_accept(WOLFSSH* ssh);
WOLFSSH_API int wolfSSH_accept(WOLFSSH*);
WOLFSSH_API int wolfSSH_stream_read(WOLFSSH*, uint8_t*, uint32_t);
WOLFSSH_API int wolfSSH_stream_send(WOLFSSH*, uint8_t*, uint32_t);
enum WS_EndpointTypes {