added decode/encode support for base messages

pull/1/head
John Safranek 2014-12-05 12:17:27 -08:00
parent 2d959d7bea
commit bf0133c740
3 changed files with 305 additions and 5 deletions

View File

@ -956,6 +956,154 @@ static int GenerateKeys(WOLFSSH* ssh)
}
static int DoIgnore(WOLFSSH* ssh, uint8_t* buf, uint32_t len, uint32_t* idx)
{
uint32_t dataSz;
uint32_t begin = *idx;
(void)ssh;
(void)len;
ato32(buf + begin, &dataSz);
begin += LENGTH_SZ + dataSz;
*idx = begin;
return WS_SUCCESS;
}
static int DoDebug(WOLFSSH* ssh, uint8_t* buf, uint32_t len, uint32_t* idx)
{
uint8_t alwaysDisplay;
char* msg = NULL;
char* lang = NULL;
uint32_t strSz;
uint32_t begin = *idx;
(void)ssh;
(void)len;
alwaysDisplay = buf[begin++];
ato32(buf + begin, &strSz);
begin += LENGTH_SZ;
if (strSz > 0) {
msg = (char*)WMALLOC(strSz + 1, ssh->ctx->heap, DYNTYPE_STRING);
if (msg != NULL) {
WMEMCPY(msg, buf + begin, strSz);
msg[strSz] = 0;
}
else {
return WS_MEMORY_E;
}
begin += strSz;
}
ato32(buf + begin, &strSz);
begin += LENGTH_SZ;
if (strSz > 0) {
lang = (char*)WMALLOC(strSz + 1, ssh->ctx->heap, DYNTYPE_STRING);
if (lang != NULL) {
WMEMCPY(lang, buf + begin, strSz);
lang[strSz] = 0;
}
else {
WFREE(msg, ssh->ctx->heap, DYNTYPE_STRING);
return WS_MEMORY_E;
}
begin += strSz;
}
if (alwaysDisplay) {
WLOG(WS_LOG_DEBUG, "DEBUG MSG (%s): %s",
(lang == NULL) ? "none" : lang,
(msg == NULL) ? "no message" : msg);
}
*idx = begin;
WFREE(msg, ssh->ctx->heap, DYNTYPE_STRING);
WFREE(lang, ssh->ctx->heap, DYNTYPE_STRING);
return WS_SUCCESS;
}
static int DoUnimplemented(WOLFSSH* ssh, uint8_t* buf, uint32_t len, uint32_t* idx)
{
uint32_t seq;
uint32_t begin = *idx;
(void)ssh;
(void)len;
ato32(buf + begin, &seq);
begin += UINT32_SZ;
WLOG(WS_LOG_DEBUG, "UNIMPLEMENTED: seq %u", seq);
*idx = begin;
return WS_SUCCESS;
}
static int DoDisconnect(WOLFSSH* ssh, uint8_t* buf, uint32_t len, uint32_t* idx)
{
uint32_t reason;
const char* reasonStr;
uint32_t begin = *idx;
(void)ssh;
(void)len;
ato32(buf + begin, &reason);
begin += UINT32_SZ;
switch (reason) {
case WOLFSSH_DISCONNECT_HOST_NOT_ALLOWED_TO_CONNECT:
reasonStr = "host not allowed to connect"; break;
case WOLFSSH_DISCONNECT_PROTOCOL_ERROR:
reasonStr = "protocol error"; break;
case WOLFSSH_DISCONNECT_KEY_EXCHANGE_FAILED:
reasonStr = "key exchange failed"; break;
case WOLFSSH_DISCONNECT_RESERVED:
reasonStr = "reserved"; break;
case WOLFSSH_DISCONNECT_MAC_ERROR:
reasonStr = "mac error"; break;
case WOLFSSH_DISCONNECT_COMPRESSION_ERROR:
reasonStr = "compression error"; break;
case WOLFSSH_DISCONNECT_SERVICE_NOT_AVAILABLE:
reasonStr = "service not available"; break;
case WOLFSSH_DISCONNECT_PROTOCOL_VERSION_NOT_SUPPORTED:
reasonStr = "protocol version not supported"; break;
case WOLFSSH_DISCONNECT_HOST_KEY_NOT_VERIFIABLE:
reasonStr = "host key not verifiable"; break;
case WOLFSSH_DISCONNECT_CONNECTION_LOST:
reasonStr = "connection lost"; break;
case WOLFSSH_DISCONNECT_BY_APPLICATION:
reasonStr = "disconnect by application"; break;
case WOLFSSH_DISCONNECT_TOO_MANY_CONNECTIONS:
reasonStr = "too many connections"; break;
case WOLFSSH_DISCONNECT_AUTH_CANCELLED_BY_USER:
reasonStr = "auth cancelled by user"; break;
case WOLFSSH_DISCONNECT_NO_MORE_AUTH_METHODS_AVAILABLE:
reasonStr = "no more auth methods available"; break;
case WOLFSSH_DISCONNECT_ILLEGAL_USER_NAME:
reasonStr = "illegal user name"; break;
default:
reasonStr = "unknown reason";
}
WLOG(WS_LOG_DEBUG, "DISCONNECT: (%u) %s", reason, reasonStr);
*idx = begin;
return WS_SUCCESS;
}
static int DoPacket(WOLFSSH* ssh)
{
uint8_t* buf = (uint8_t*)ssh->inputBuffer.buffer;
@ -977,18 +1125,22 @@ static int DoPacket(WOLFSSH* ssh)
case MSGID_DISCONNECT:
WLOG(WS_LOG_DEBUG, "Decoding MSGID_KEXDH_INIT (len = %d)", payloadSz - 1);
DoDisconnect(ssh, buf, payloadSz - 1, &idx);
break;
case MSGID_IGNORE:
WLOG(WS_LOG_DEBUG, "Decoding MSGID_KEXDH_INIT (len = %d)", payloadSz - 1);
DoIgnore(ssh, buf, payloadSz - 1, &idx);
break;
case MSGID_UNIMPLEMENTED:
WLOG(WS_LOG_DEBUG, "Decoding MSGID_KEXDH_INIT (len = %d)", payloadSz - 1);
DoUnimplemented(ssh, buf, payloadSz - 1, &idx);
break;
case MSGID_DEBUG:
WLOG(WS_LOG_DEBUG, "Decoding MSGID_KEXDH_INIT (len = %d)", payloadSz - 1);
DoDebug(ssh, buf, payloadSz - 1, &idx);
break;
case MSGID_KEXINIT:
@ -1018,7 +1170,8 @@ static int DoPacket(WOLFSSH* ssh)
break;
default:
WLOG(WS_LOG_DEBUG, "Unsupported message ID (%d)", msg);
WLOG(WS_LOG_DEBUG, "Unimplemented message ID (%d)", msg);
SendUnimplemented(ssh);
break;
}
@ -1089,7 +1242,7 @@ static const char sshIdStr[] = "SSH-2.0-wolfSSHv" LIBWOLFSSH_VERSION_STRING "\r\
int ProcessClientVersion(WOLFSSH* ssh)
{
int error;
size_t protoLen = 7; /* Length of the SSH-2.0 portion of the ID str */
uint32_t protoLen = 7; /* Length of the SSH-2.0 portion of the ID str */
uint8_t scratch[LENGTH_SZ];
if ( (error = GetInputText(ssh)) < 0) {
@ -1528,12 +1681,12 @@ int SendNewKeys(WOLFSSH* ssh)
uint8_t* output;
uint32_t idx = 0;
PreparePacket(ssh, 1);
PreparePacket(ssh, MSG_ID_SZ);
output = ssh->outputBuffer.buffer;
idx = ssh->outputBuffer.length;
output[idx] = MSGID_NEWKEYS;
output[idx++] = MSGID_NEWKEYS;
ssh->outputBuffer.length = idx;
@ -1547,6 +1700,128 @@ int SendNewKeys(WOLFSSH* ssh)
}
int SendUnimplemented(WOLFSSH* ssh)
{
uint8_t* output;
uint32_t idx = 0;
PreparePacket(ssh, MSG_ID_SZ + LENGTH_SZ);
output = ssh->outputBuffer.buffer;
idx = ssh->outputBuffer.length;
output[idx++] = MSGID_UNIMPLEMENTED;
c32toa(ssh->peerSeq, output + idx);
idx += UINT32_SZ;
ssh->outputBuffer.length = idx;
BundlePacket(ssh);
SendBuffered(ssh);
return WS_SUCCESS;
}
int SendDisconnect(WOLFSSH* ssh, uint32_t reason)
{
uint8_t* output;
uint32_t idx = 0;
PreparePacket(ssh, MSG_ID_SZ + UINT32_SZ + (LENGTH_SZ * 2));
output = ssh->outputBuffer.buffer;
idx = ssh->outputBuffer.length;
output[idx++] = MSGID_DISCONNECT;
c32toa(reason, output + idx);
idx += UINT32_SZ;
c32toa(0, output + idx);
idx += LENGTH_SZ;
c32toa(0, output + idx);
idx += LENGTH_SZ;
ssh->outputBuffer.length = idx;
BundlePacket(ssh);
SendBuffered(ssh);
return WS_SUCCESS;
}
int SendIgnore(WOLFSSH* ssh, const unsigned char* data, uint32_t dataSz)
{
uint8_t* output;
uint32_t idx = 0;
if (ssh == NULL || (data == NULL && dataSz > 0))
return WS_BAD_ARGUMENT;
PreparePacket(ssh, MSG_ID_SZ + LENGTH_SZ + dataSz);
output = ssh->outputBuffer.buffer;
idx = ssh->outputBuffer.length;
output[idx++] = MSGID_IGNORE;
c32toa(dataSz, output + idx);
idx += LENGTH_SZ;
if (dataSz > 0) {
WMEMCPY(output + idx, data, dataSz);
idx += dataSz;
}
ssh->outputBuffer.length = idx;
BundlePacket(ssh);
SendBuffered(ssh);
return WS_SUCCESS;
}
static const char cannedLangTag[] = "en-us";
static const uint32_t cannedLangTagSz = sizeof(cannedLangTag) - 1;
int SendDebug(WOLFSSH* ssh, byte alwaysDisplay, const char* msg)
{
uint32_t msgSz;
uint8_t* output;
uint32_t idx = 0;
if (ssh == NULL)
return WS_BAD_ARGUMENT;
msgSz = (msg != NULL) ? (uint32_t)WSTRLEN(msg) : 0;
PreparePacket(ssh, MSG_ID_SZ + BOOLEAN_SZ + (LENGTH_SZ * 2) + msgSz + cannedLangTagSz);
output = ssh->outputBuffer.buffer;
idx = ssh->outputBuffer.length;
output[idx++] = MSGID_DEBUG;
output[idx++] = (alwaysDisplay != 0);
c32toa(msgSz, output + idx);
idx += LENGTH_SZ;
if (msgSz > 0) {
WMEMCPY(output + idx, msg, msgSz);
idx += msgSz;
}
c32toa(cannedLangTagSz, output + idx);
idx += LENGTH_SZ;
WMEMCPY(output + idx, cannedLangTag, cannedLangTagSz);
idx += cannedLangTagSz;
ssh->outputBuffer.length = idx;
BundlePacket(ssh);
SendBuffered(ssh);
return WS_SUCCESS;
}
#define LINE_WIDTH 16
void DumpOctetString(const uint8_t* input, uint32_t inputSz)
{

View File

@ -91,6 +91,7 @@ enum {
#define BOOLEAN_SZ 1
#define MSG_ID_SZ 1
#define SHA1_96_SZ (96/8)
#define UINT32_SZ 4
WOLFSSH_LOCAL uint8_t NameToId(const char*, uint32_t);
@ -221,6 +222,10 @@ WOLFSSH_LOCAL int SendServerVersion(WOLFSSH*);
WOLFSSH_LOCAL int SendKexInit(WOLFSSH*);
WOLFSSH_LOCAL int SendKexDhReply(WOLFSSH*);
WOLFSSH_LOCAL int SendNewKeys(WOLFSSH*);
WOLFSSH_LOCAL int SendUnimplemented(WOLFSSH*);
WOLFSSH_LOCAL int SendDisconnect(WOLFSSH*, uint32_t);
WOLFSSH_LOCAL int SendIgnore(WOLFSSH*, const unsigned char*, uint32_t);
WOLFSSH_LOCAL int SendDebug(WOLFSSH*, byte, const char*);
enum AcceptStates {
@ -276,7 +281,8 @@ enum WS_DynamicTypes {
DYNTYPE_CERT,
DYNTYPE_KEY,
DYNTYPE_DH,
DYNTYPE_RNG
DYNTYPE_RNG,
DYNTYPE_STRING
};

View File

@ -99,6 +99,25 @@ enum WS_FormatTypes {
};
enum WS_DisconnectReasonCodes {
WOLFSSH_DISCONNECT_HOST_NOT_ALLOWED_TO_CONNECT = 1,
WOLFSSH_DISCONNECT_PROTOCOL_ERROR = 2,
WOLFSSH_DISCONNECT_KEY_EXCHANGE_FAILED = 3,
WOLFSSH_DISCONNECT_RESERVED = 4,
WOLFSSH_DISCONNECT_MAC_ERROR = 5,
WOLFSSH_DISCONNECT_COMPRESSION_ERROR = 6,
WOLFSSH_DISCONNECT_SERVICE_NOT_AVAILABLE = 7,
WOLFSSH_DISCONNECT_PROTOCOL_VERSION_NOT_SUPPORTED = 8,
WOLFSSH_DISCONNECT_HOST_KEY_NOT_VERIFIABLE = 9,
WOLFSSH_DISCONNECT_CONNECTION_LOST = 10,
WOLFSSH_DISCONNECT_BY_APPLICATION = 11,
WOLFSSH_DISCONNECT_TOO_MANY_CONNECTIONS = 12,
WOLFSSH_DISCONNECT_AUTH_CANCELLED_BY_USER = 13,
WOLFSSH_DISCONNECT_NO_MORE_AUTH_METHODS_AVAILABLE = 14,
WOLFSSH_DISCONNECT_ILLEGAL_USER_NAME = 15
};
#ifdef __cplusplus
}
#endif