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; WOLFSSH* ssh = (WOLFSSH*)vArgs;
SOCKET_T clientFd = wolfSSH_get_fd(ssh); SOCKET_T clientFd = wolfSSH_get_fd(ssh);
const char* msgA = "Who's there?!\n"; const char* msgA = "Who's there?!\r\n";
const char* msgB = "Go away!\n"; const char* msgB = "Go away!\r\n";
if (wolfSSH_accept(ssh) == WS_SUCCESS) { 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); sleep(1);
send(clientFd, msgB, strlen(msgB), 0); wolfSSH_stream_send(ssh, (uint8_t*)msgB, (uint32_t)strlen(msgB));
} }
close(clientFd); close(clientFd);
wolfSSH_free(ssh); wolfSSH_free(ssh);

View File

@ -136,6 +136,9 @@ const char* GetErrorString(int err)
case WS_CREATE_MAC_E: case WS_CREATE_MAC_E:
return "verify mac error"; return "verify mac error";
case WS_RESOURCE_E:
return "insufficient resources for new channel";
default: default:
return "Unknown error code"; return "Unknown error code";
} }
@ -169,7 +172,10 @@ static const NameIdPair NameIdMap[] = {
{ ID_SSH_RSA, "ssh-rsa" }, { ID_SSH_RSA, "ssh-rsa" },
/* UserAuth IDs */ /* 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) int BufferInit(Buffer* buffer, uint32_t size, void* heap)
{ {
if (buffer == NULL) if (buffer == NULL)
@ -1273,40 +1306,51 @@ static int DoChannelOpen(WOLFSSH* ssh,
uint32_t begin = *idx; uint32_t begin = *idx;
uint32_t typeSz; uint32_t typeSz;
char type[32]; char type[32];
uint32_t channel; uint8_t typeId;
uint32_t initialWindowSz; uint32_t peerChannel;
uint32_t maxPacketSz; uint32_t peerInitialWindowSz;
uint32_t peerMaxPacketSz;
int ret; int ret;
Channel* newChannel;
WLOG(WS_LOG_DEBUG, "Entering DoChannelOpen()"); WLOG(WS_LOG_DEBUG, "Entering DoChannelOpen()");
(void)ssh;
(void)len;
ret = GetString(type, &typeSz, buf, len, &begin); ret = GetString(type, &typeSz, buf, len, &begin);
if (ret == WS_SUCCESS) if (ret == WS_SUCCESS)
ret = GetUint32(&channel, buf, len, &begin); ret = GetUint32(&peerChannel, buf, len, &begin);
if (ret == WS_SUCCESS) if (ret == WS_SUCCESS)
ret = GetUint32(&initialWindowSz, buf, len, &begin); ret = GetUint32(&peerInitialWindowSz, buf, len, &begin);
if (ret == WS_SUCCESS) if (ret == WS_SUCCESS)
ret = GetUint32(&maxPacketSz, buf, len, &begin); ret = GetUint32(&peerMaxPacketSz, buf, len, &begin);
if (ret != WS_SUCCESS) { if (ret != WS_SUCCESS) {
WLOG(WS_LOG_DEBUG, "Leaving DoChannelOpen(), ret = %d", ret); WLOG(WS_LOG_DEBUG, "Leaving DoChannelOpen(), ret = %d", ret);
return ret; return ret;
} }
WLOG(WS_LOG_DEBUG, " type = %s", type); WLOG(WS_LOG_INFO, " type = %s", type);
WLOG(WS_LOG_DEBUG, " channel = %u", channel); WLOG(WS_LOG_INFO, " peerChannel = %u", peerChannel);
WLOG(WS_LOG_DEBUG, " initialWindowSz = %u", initialWindowSz); WLOG(WS_LOG_INFO, " peerInitialWindowSz = %u", peerInitialWindowSz);
WLOG(WS_LOG_DEBUG, " maxPacketSz = %u", maxPacketSz); WLOG(WS_LOG_INFO, " peerMaxPacketSz = %u", peerMaxPacketSz);
*idx = begin; *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; 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, static int DoChannelData(WOLFSSH* ssh,
uint8_t* buf, uint32_t len, uint32_t* idx) uint8_t* buf, uint32_t len, uint32_t* idx)
{ {
@ -1416,7 +1490,7 @@ static int DoChannelData(WOLFSSH* ssh,
return ret; return ret;
} }
SendChannelData(ssh, channel, buf + begin, dataSz); SendChannelData(ssh, ssh->channel.peerChannel, buf + begin, dataSz);
*idx = begin + dataSz; *idx = begin + dataSz;
@ -1505,6 +1579,12 @@ static int DoPacket(WOLFSSH* ssh)
idx += payloadIdx; idx += payloadIdx;
break; 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: case MSGID_CHANNEL_DATA:
WLOG(WS_LOG_DEBUG, "Decoding MSGID_CHANNEL_DATA"); WLOG(WS_LOG_DEBUG, "Decoding MSGID_CHANNEL_DATA");
DoChannelData(ssh, buf + idx, payloadSz, &payloadIdx); DoChannelData(ssh, buf + idx, payloadSz, &payloadIdx);
@ -2470,11 +2550,17 @@ int SendChannelOpenConf(WOLFSSH* ssh)
{ {
uint8_t* output; uint8_t* output;
uint32_t idx; uint32_t idx;
Channel* channel;
WLOG(WS_LOG_DEBUG, "Entering SendChannelOpenConf()"); 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; return WS_BAD_ARGUMENT;
}
channel = &ssh->channel;
PreparePacket(ssh, MSG_ID_SZ + (UINT32_SZ * 4)); PreparePacket(ssh, MSG_ID_SZ + (UINT32_SZ * 4));
@ -2482,13 +2568,13 @@ int SendChannelOpenConf(WOLFSSH* ssh)
idx = ssh->outputBuffer.length; idx = ssh->outputBuffer.length;
output[idx++] = MSGID_CHANNEL_OPEN_CONF; output[idx++] = MSGID_CHANNEL_OPEN_CONF;
c32toa(0, output + idx); /* recipient channel */ c32toa(channel->peerChannel, output + idx);
idx += UINT32_SZ; idx += UINT32_SZ;
c32toa(0, output + idx); /* sender channel */ c32toa(channel->channel, output + idx);
idx += UINT32_SZ; idx += UINT32_SZ;
c32toa(DEFAULT_WINDOW_SZ, output + idx); c32toa(channel->windowSz, output + idx);
idx += UINT32_SZ; idx += UINT32_SZ;
c32toa(DEFAULT_MAX_PACKET_SZ, output + idx); c32toa(channel->maxPacketSz, output + idx);
idx += UINT32_SZ; idx += UINT32_SZ;
ssh->outputBuffer.length = idx; ssh->outputBuffer.length = idx;
@ -2496,20 +2582,31 @@ int SendChannelOpenConf(WOLFSSH* ssh)
BundlePacket(ssh); BundlePacket(ssh);
SendBuffered(ssh); SendBuffered(ssh);
WLOG(WS_LOG_DEBUG, "Leaving SendChannelOpenConf()");
return WS_SUCCESS; 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* data, uint32_t dataSz)
{ {
uint8_t* output; uint8_t* output;
uint32_t idx; uint32_t idx;
Channel* channel;
WLOG(WS_LOG_DEBUG, "Entering SendChannelData()"); WLOG(WS_LOG_DEBUG, "Entering SendChannelData()");
if (ssh == NULL) if (ssh == NULL)
return WS_BAD_ARGUMENT; 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); 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; idx = ssh->outputBuffer.length;
output[idx++] = MSGID_CHANNEL_DATA; output[idx++] = MSGID_CHANNEL_DATA;
c32toa(channel, output + idx); c32toa(channel->peerChannel, output + idx);
idx += UINT32_SZ; idx += UINT32_SZ;
c32toa(dataSz, output + idx); c32toa(dataSz, output + idx);
idx += LENGTH_SZ; idx += LENGTH_SZ;
@ -2529,6 +2626,11 @@ int SendChannelData(WOLFSSH* ssh, uint32_t channel,
BundlePacket(ssh); BundlePacket(ssh);
SendBuffered(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()"); WLOG(WS_LOG_DEBUG, "Leaving SendChannelData()");
return WS_SUCCESS; return WS_SUCCESS;
} }

View File

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

View File

@ -151,6 +151,7 @@ static WOLFSSH* SshInit(WOLFSSH* ssh, WOLFSSH_CTX* ctx)
ssh->ioWriteCtx = &ssh->wfd; /* set */ ssh->ioWriteCtx = &ssh->wfd; /* set */
ssh->acceptState = ACCEPT_BEGIN; ssh->acceptState = ACCEPT_BEGIN;
ssh->clientState = CLIENT_BEGIN; ssh->clientState = CLIENT_BEGIN;
ssh->nextChannel = DEFAULT_NEXT_CHANNEL;
ssh->blockSz = MIN_BLOCK_SZ; ssh->blockSz = MIN_BLOCK_SZ;
ssh->encryptId = ID_NONE; ssh->encryptId = ID_NONE;
ssh->macId = ID_NONE; ssh->macId = ID_NONE;
@ -401,7 +402,7 @@ int wolfSSH_accept(WOLFSSH* ssh)
WLOG(WS_LOG_DEBUG, acceptState, "SERVER_USERAUTH_SENT"); WLOG(WS_LOG_DEBUG, acceptState, "SERVER_USERAUTH_SENT");
case ACCEPT_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) { if ( (ssh->error = ProcessReply(ssh)) < 0) {
WLOG(WS_LOG_DEBUG, acceptError, WLOG(WS_LOG_DEBUG, acceptError,
"SERVER_USERAUTH_SENT", ssh->error); "SERVER_USERAUTH_SENT", ssh->error);
@ -419,18 +420,31 @@ int wolfSSH_accept(WOLFSSH* ssh)
} }
ssh->acceptState = ACCEPT_SERVER_CHANNEL_ACCEPT_SENT; ssh->acceptState = ACCEPT_SERVER_CHANNEL_ACCEPT_SENT;
WLOG(WS_LOG_DEBUG, acceptState, "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

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