more return code checking

pull/13/head
John Safranek 2016-07-21 20:07:29 -07:00
parent f865ad2487
commit 2e1744265b
1 changed files with 202 additions and 128 deletions

View File

@ -411,16 +411,16 @@ int GrowBuffer(Buffer* buf, uint32_t sz, uint32_t usedSz)
void ShrinkBuffer(Buffer* buf, int forcedFree) void ShrinkBuffer(Buffer* buf, int forcedFree)
{ {
WLOG(WS_LOG_DEBUG, "Entering %s", __func__); WLOG(WS_LOG_DEBUG, "Entering ShrinkBuffer()");
if (buf != NULL) { if (buf != NULL) {
uint32_t usedSz = buf->length - buf->idx; uint32_t usedSz = buf->length - buf->idx;
WLOG(WS_LOG_DEBUG, "SB: usedSz = %u, forcedFree = %u", usedSz, forcedFree); WLOG(WS_LOG_DEBUG, "SB: usedSz = %u, forcedFree = %u",
if (!forcedFree && usedSz > STATIC_BUFFER_LEN) { usedSz, forcedFree);
WLOG(WS_LOG_DEBUG, "SB: shifting down");
if (!forcedFree && usedSz > STATIC_BUFFER_LEN)
return; return;
}
if (!forcedFree && usedSz) { if (!forcedFree && usedSz) {
WLOG(WS_LOG_DEBUG, "SB: shifting down"); WLOG(WS_LOG_DEBUG, "SB: shifting down");
@ -437,7 +437,8 @@ void ShrinkBuffer(Buffer* buf, int forcedFree)
buf->length = forcedFree ? 0 : usedSz; buf->length = forcedFree ? 0 : usedSz;
buf->idx = 0; buf->idx = 0;
} }
WLOG(WS_LOG_DEBUG, "Leaving %s", __func__);
WLOG(WS_LOG_DEBUG, "Leaving ShrinkBuffer()");
} }
@ -667,6 +668,7 @@ static int GetBoolean(uint8_t* v, uint8_t* buf, uint32_t len, uint32_t* idx)
*idx += BOOLEAN_SZ; *idx += BOOLEAN_SZ;
result = WS_SUCCESS; result = WS_SUCCESS;
} }
return result; return result;
} }
@ -711,62 +713,76 @@ static int DoNameList(uint8_t* idList, uint32_t* idListSz,
{ {
uint8_t idListIdx; uint8_t idListIdx;
uint32_t nameListSz, nameListIdx; uint32_t nameListSz, nameListIdx;
uint32_t begin = *idx; uint32_t begin;
uint8_t* name; uint8_t* name;
uint32_t nameSz; uint32_t nameSz;
int ret = WS_SUCCESS;
WLOG(WS_LOG_DEBUG, "Entering DoNameList()");
if (idList == NULL || idListSz == NULL ||
buf == NULL || len == 0 || idx == NULL) {
ret = WS_BAD_ARGUMENT;
}
/* /*
* This iterates across a name list and finds names that end in either the * This iterates across a name list and finds names that end in either the
* comma delimeter or with the end of the list. * comma delimeter or with the end of the list.
*/ */
if (begin >= len || begin + 4 >= len) if (ret == WS_SUCCESS) {
return WS_FATAL_ERROR; begin = *idx;
if (begin >= len || begin + 4 >= len)
ret = WS_BUFFER_E;
}
ato32(buf + begin, &nameListSz); if (ret == WS_SUCCESS)
begin += 4; ret = GetUint32(&nameListSz, buf, len, &begin);
if (begin + nameListSz > len)
return WS_FATAL_ERROR;
/* The strings we want are now in the bounds of the message, and the /* The strings we want are now in the bounds of the message, and the
* length of the list. Find the commas, or end of list, and then decode * length of the list. Find the commas, or end of list, and then decode
* the values. */ * the values. */
name = buf + begin; if (ret == WS_SUCCESS) {
nameSz = 0; name = buf + begin;
nameListIdx = 0; nameSz = 0;
idListIdx = 0; nameListIdx = 0;
idListIdx = 0;
while (nameListIdx < nameListSz) { while (nameListIdx < nameListSz) {
nameListIdx++; nameListIdx++;
if (nameListIdx == nameListSz) if (nameListIdx == nameListSz)
nameSz++; nameSz++;
if (nameListIdx == nameListSz || name[nameSz] == ',') { if (nameListIdx == nameListSz || name[nameSz] == ',') {
uint8_t id; uint8_t id;
id = NameToId((char*)name, nameSz); id = NameToId((char*)name, nameSz);
{ {
const char* displayName = IdToName(id); const char* displayName = IdToName(id);
if (displayName) { if (displayName) {
/*WLOG(WS_LOG_DEBUG, "DNL: name ID = %s", displayName);*/ /*WLOG(WS_LOG_DEBUG,
"DNL: name ID = %s", displayName);*/
}
} }
} if (id != ID_UNKNOWN)
if (id != ID_UNKNOWN) idList[idListIdx++] = id;
idList[idListIdx++] = id;
name += 1 + nameSz; name += 1 + nameSz;
nameSz = 0; nameSz = 0;
}
else
nameSz++;
} }
else
nameSz++; begin += nameListSz;
*idListSz = idListIdx;
*idx = begin;
} }
begin += nameListSz; WLOG(WS_LOG_DEBUG, "Leaving DoNameList(), ret = %d", ret);
*idListSz = idListIdx; return ret;
*idx = begin;
return WS_SUCCESS;
} }
@ -855,7 +871,9 @@ static int DoKexInit(WOLFSSH* ssh, uint8_t* buf, uint32_t len, uint32_t* idx)
uint8_t list[3]; uint8_t list[3];
uint32_t listSz; uint32_t listSz;
uint32_t skipSz; uint32_t skipSz;
uint32_t begin = *idx; uint32_t begin;
WLOG(WS_LOG_DEBUG, "Entering DoKexInit()");
if (ssh == NULL || buf == NULL || len == 0 || idx == NULL) if (ssh == NULL || buf == NULL || len == 0 || idx == NULL)
ret = WS_BAD_ARGUMENT; ret = WS_BAD_ARGUMENT;
@ -867,126 +885,182 @@ static int DoKexInit(WOLFSSH* ssh, uint8_t* buf, uint32_t len, uint32_t* idx)
* is save the actual values. * is save the actual values.
*/ */
/* Check that the cookie exists inside the message */ if (ret == WS_SUCCESS) {
if (begin + COOKIE_SZ > len) { begin = *idx;
/* error, out of bounds */
return WS_FATAL_ERROR; /* Check that the cookie exists inside the message */
if (begin + COOKIE_SZ > len) {
/* error, out of bounds */
ret = WS_PARSE_E;
}
else {
/* Move past the cookie. */
begin += COOKIE_SZ;
}
} }
/* Move past the cookie. */
begin += COOKIE_SZ;
/* KEX Algorithms */ /* KEX Algorithms */
WLOG(WS_LOG_DEBUG, "DKI: KEX Algorithms"); if (ret == WS_SUCCESS) {
listSz = 2; WLOG(WS_LOG_DEBUG, "DKI: KEX Algorithms");
DoNameList(list, &listSz, buf, len, &begin); listSz = 2;
algoId = MatchIdLists(list, listSz, cannedKexAlgo, cannedKexAlgoSz); ret = DoNameList(list, &listSz, buf, len, &begin);
if (algoId == ID_UNKNOWN) { if (ret == WS_SUCCESS) {
WLOG(WS_LOG_DEBUG, "Unable to negotiate KEX Algo"); algoId = MatchIdLists(list, listSz, cannedKexAlgo, cannedKexAlgoSz);
return WS_INVALID_ALGO_ID; if (algoId == ID_UNKNOWN) {
WLOG(WS_LOG_DEBUG, "Unable to negotiate KEX Algo");
ret = WS_INVALID_ALGO_ID;
}
else
ssh->handshake->kexId = algoId;
}
} }
ssh->handshake->kexId = algoId;
/* Server Host Key Algorithms */ /* Server Host Key Algorithms */
WLOG(WS_LOG_DEBUG, "DKI: Server Host Key Algorithms"); if (ret == WS_SUCCESS) {
listSz = 1; WLOG(WS_LOG_DEBUG, "DKI: Server Host Key Algorithms");
DoNameList(list, &listSz, buf, len, &begin); listSz = 1;
algoId = MatchIdLists(list, listSz, cannedKeyAlgo, cannedKeyAlgoSz); ret = DoNameList(list, &listSz, buf, len, &begin);
if (algoId == ID_UNKNOWN) { if (ret == WS_SUCCESS) {
WLOG(WS_LOG_DEBUG, "Unable to negotiate Server Host Key Algo"); algoId = MatchIdLists(list, listSz, cannedKeyAlgo, cannedKeyAlgoSz);
return WS_INVALID_ALGO_ID; if (algoId == ID_UNKNOWN) {
WLOG(WS_LOG_DEBUG, "Unable to negotiate Server Host Key Algo");
return WS_INVALID_ALGO_ID;
}
else
ssh->handshake->pubKeyId = algoId;
}
} }
ssh->handshake->pubKeyId = algoId;
/* Enc Algorithms - Client to Server */ /* Enc Algorithms - Client to Server */
WLOG(WS_LOG_DEBUG, "DKI: Enc Algorithms - Client to Server"); if (ret == WS_SUCCESS) {
listSz = 3; WLOG(WS_LOG_DEBUG, "DKI: Enc Algorithms - Client to Server");
DoNameList(list, &listSz, buf, len, &begin); listSz = 3;
algoId = MatchIdLists(list, listSz, cannedEncAlgo, cannedEncAlgoSz); ret = DoNameList(list, &listSz, buf, len, &begin);
if (algoId == ID_UNKNOWN) { if (ret == WS_SUCCESS) {
WLOG(WS_LOG_DEBUG, "Unable to negotiate Encryption Algo C2S"); algoId = MatchIdLists(list, listSz, cannedEncAlgo, cannedEncAlgoSz);
return WS_INVALID_ALGO_ID; if (algoId == ID_UNKNOWN) {
WLOG(WS_LOG_DEBUG, "Unable to negotiate Encryption Algo C2S");
ret = WS_INVALID_ALGO_ID;
}
}
} }
/* Enc Algorithms - Server to Client */ /* Enc Algorithms - Server to Client */
WLOG(WS_LOG_DEBUG, "DKI: Enc Algorithms - Server to Client"); if (ret == WS_SUCCESS) {
listSz = 3; WLOG(WS_LOG_DEBUG, "DKI: Enc Algorithms - Server to Client");
DoNameList(list, &listSz, buf, len, &begin); listSz = 3;
if (MatchIdLists(list, listSz, &algoId, 1) == ID_UNKNOWN) { ret = DoNameList(list, &listSz, buf, len, &begin);
WLOG(WS_LOG_DEBUG, "Unable to negotiate Encryption Algo S2C"); if (MatchIdLists(list, listSz, &algoId, 1) == ID_UNKNOWN) {
return WS_INVALID_ALGO_ID; WLOG(WS_LOG_DEBUG, "Unable to negotiate Encryption Algo S2C");
ret = WS_INVALID_ALGO_ID;
}
else {
ssh->handshake->encryptId = algoId;
ssh->handshake->blockSz = ssh->ivClientSz = ssh->ivServerSz
= BlockSzForId(algoId);
ssh->encKeyClientSz = ssh->encKeyServerSz = KeySzForId(algoId);
}
} }
ssh->handshake->encryptId = algoId;
ssh->handshake->blockSz = ssh->ivClientSz = ssh->ivServerSz
= BlockSzForId(algoId);
ssh->encKeyClientSz = ssh->encKeyServerSz = KeySzForId(algoId);
/* MAC Algorithms - Client to Server */ /* MAC Algorithms - Client to Server */
WLOG(WS_LOG_DEBUG, "DKI: MAC Algorithms - Client to Server"); if (ret == WS_SUCCESS) {
listSz = 2; WLOG(WS_LOG_DEBUG, "DKI: MAC Algorithms - Client to Server");
DoNameList(list, &listSz, buf, len, &begin); listSz = 2;
algoId = MatchIdLists(list, listSz, cannedMacAlgo, cannedMacAlgoSz); ret = DoNameList(list, &listSz, buf, len, &begin);
if (algoId == ID_UNKNOWN) { if (ret == WS_SUCCESS) {
WLOG(WS_LOG_DEBUG, "Unable to negotiate MAC Algo C2S"); algoId = MatchIdLists(list, listSz, cannedMacAlgo, cannedMacAlgoSz);
return WS_INVALID_ALGO_ID; if (algoId == ID_UNKNOWN) {
WLOG(WS_LOG_DEBUG, "Unable to negotiate MAC Algo C2S");
ret = WS_INVALID_ALGO_ID;
}
}
} }
/* MAC Algorithms - Server to Client */ /* MAC Algorithms - Server to Client */
WLOG(WS_LOG_DEBUG, "DKI: MAC Algorithms - Server to Client"); if (ret == WS_SUCCESS) {
listSz = 2; WLOG(WS_LOG_DEBUG, "DKI: MAC Algorithms - Server to Client");
DoNameList(list, &listSz, buf, len, &begin); listSz = 2;
if (MatchIdLists(list, listSz, &algoId, 1) == ID_UNKNOWN) { ret = DoNameList(list, &listSz, buf, len, &begin);
WLOG(WS_LOG_DEBUG, "Unable to negotiate MAC Algo S2C"); if (ret == WS_SUCCESS) {
return WS_INVALID_ALGO_ID; if (MatchIdLists(list, listSz, &algoId, 1) == ID_UNKNOWN) {
WLOG(WS_LOG_DEBUG, "Unable to negotiate MAC Algo S2C");
ret = WS_INVALID_ALGO_ID;
}
else {
ssh->handshake->macId = algoId;
ssh->handshake->macSz = MacSzForId(algoId);
ssh->macKeyClientSz = ssh->macKeyServerSz = KeySzForId(algoId);
}
}
} }
ssh->handshake->macId = algoId;
ssh->handshake->macSz = MacSzForId(algoId);
ssh->macKeyClientSz = ssh->macKeyServerSz = KeySzForId(algoId);
/* The compression algorithm lists should have none as a value. */
algoId = ID_NONE;
/* Compression Algorithms - Client to Server */ /* Compression Algorithms - Client to Server */
WLOG(WS_LOG_DEBUG, "DKI: Compression Algorithms - Client to Server"); if (ret == WS_SUCCESS) {
listSz = 1; /* The compression algorithm lists should have none as a value. */
DoNameList(list, &listSz, buf, len, &begin); algoId = ID_NONE;
if (MatchIdLists(list, listSz, &algoId, 1) == ID_UNKNOWN) {
WLOG(WS_LOG_DEBUG, "Unable to negotiate Compression Algo C2S"); WLOG(WS_LOG_DEBUG, "DKI: Compression Algorithms - Client to Server");
return WS_INVALID_ALGO_ID; listSz = 1;
ret = DoNameList(list, &listSz, buf, len, &begin);
if (ret == WS_SUCCESS) {
if (MatchIdLists(list, listSz, &algoId, 1) == ID_UNKNOWN) {
WLOG(WS_LOG_DEBUG, "Unable to negotiate Compression Algo C2S");
ret = WS_INVALID_ALGO_ID;
}
}
} }
/* Compression Algorithms - Server to Client */ /* Compression Algorithms - Server to Client */
WLOG(WS_LOG_DEBUG, "DKI: Compression Algorithms - Server to Client"); if (ret == WS_SUCCESS) {
listSz = 1; WLOG(WS_LOG_DEBUG, "DKI: Compression Algorithms - Server to Client");
DoNameList(list, &listSz, buf, len, &begin); listSz = 1;
if (MatchIdLists(list, listSz, &algoId, 1) == ID_UNKNOWN) { ret = DoNameList(list, &listSz, buf, len, &begin);
WLOG(WS_LOG_DEBUG, "Unable to negotiate Compression Algo S2C"); if (ret == WS_SUCCESS) {
return WS_INVALID_ALGO_ID; if (MatchIdLists(list, listSz, &algoId, 1) == ID_UNKNOWN) {
WLOG(WS_LOG_DEBUG, "Unable to negotiate Compression Algo S2C");
ret = WS_INVALID_ALGO_ID;
}
}
} }
/* Languages - Client to Server, skip */ /* Languages - Client to Server, skip */
ato32(buf + begin, &skipSz); if (ret == WS_SUCCESS) {
begin += 4 + skipSz; WLOG(WS_LOG_DEBUG, "DKI: Languages - Client to Server");
ret = GetUint32(&skipSz, buf, len, &begin);
if (ret == WS_SUCCESS)
begin += skipSz;
}
/* Languages - Server to Client, skip */ /* Languages - Server to Client, skip */
ato32(buf + begin, &skipSz); if (ret == WS_SUCCESS) {
begin += 4 + skipSz; WLOG(WS_LOG_DEBUG, "DKI: Languages - Server to Client");
ret = GetUint32(&skipSz, buf, len, &begin);
if (ret == WS_SUCCESS)
begin += skipSz;
}
/* First KEX Packet Follows */ /* First KEX Packet Follows */
ssh->handshake->kexPacketFollows = buf[begin]; if (ret == WS_SUCCESS) {
begin += 1; WLOG(WS_LOG_DEBUG, "DKI: KEX Packet Follows");
ret = GetBoolean(&ssh->handshake->kexPacketFollows, buf, len, &begin);
}
/* Skip the "for future use" length. */ /* Skip the "for future use" length. */
ato32(buf + begin, &skipSz); if (ret == WS_SUCCESS) {
begin += 4 + skipSz; WLOG(WS_LOG_DEBUG, "DKI: For Future Use");
ret = GetUint32(&skipSz, buf, len, &begin);
if (ret == WS_SUCCESS)
begin += skipSz;
}
*idx = begin; if (ret == WS_SUCCESS) {
*idx = begin;
ssh->clientState = CLIENT_KEXINIT_DONE;
}
ssh->clientState = CLIENT_KEXINIT_DONE; WLOG(WS_LOG_DEBUG, "Leaving DoKexInit(), ret = %d", ret);
return WS_SUCCESS; return ret;
} }
@ -2080,11 +2154,11 @@ static int DoPacket(WOLFSSH* ssh)
case MSGID_KEXINIT: case MSGID_KEXINIT:
{ {
uint8_t scratchLen[LENGTH_SZ]; uint8_t szFlat[LENGTH_SZ];
WLOG(WS_LOG_DEBUG, "Decoding MSGID_KEXINIT"); WLOG(WS_LOG_DEBUG, "Decoding MSGID_KEXINIT");
c32toa(payloadSz + sizeof(msg), scratchLen); c32toa(payloadSz + sizeof(msg), szFlat);
wc_ShaUpdate(&ssh->handshake->hash, scratchLen, LENGTH_SZ); wc_ShaUpdate(&ssh->handshake->hash, szFlat, LENGTH_SZ);
wc_ShaUpdate(&ssh->handshake->hash, &msg, sizeof(msg)); wc_ShaUpdate(&ssh->handshake->hash, &msg, sizeof(msg));
wc_ShaUpdate(&ssh->handshake->hash, buf + idx, payloadSz); wc_ShaUpdate(&ssh->handshake->hash, buf + idx, payloadSz);
ret = DoKexInit(ssh, buf + idx, payloadSz, &payloadIdx); ret = DoKexInit(ssh, buf + idx, payloadSz, &payloadIdx);