PR review: Fix potential memory leak when failing to parse a key of any type.

pull/604/head
John Safranek 2023-11-02 15:57:11 -07:00
parent 9bbfcf1a96
commit 8049606f2e
1 changed files with 99 additions and 53 deletions

152
src/ssh.c
View File

@ -1497,12 +1497,13 @@ static int DoSshPubKey(const byte* in, word32 inSz, byte** out,
word32* outSz, const byte** outType, word32* outTypeSz, word32* outSz, const byte** outType, word32* outTypeSz,
void* heap) void* heap)
{ {
int ret = WS_SUCCESS;
byte* newKey = NULL; byte* newKey = NULL;
char* c; char* c;
char* last; char* last;
char* type = NULL; char* type = NULL;
char* key = NULL; char* key = NULL;
int ret = WS_SUCCESS;
word32 newKeySz, typeSz;
WOLFSSH_UNUSED(inSz); WOLFSSH_UNUSED(inSz);
WOLFSSH_UNUSED(heap); WOLFSSH_UNUSED(heap);
@ -1512,38 +1513,60 @@ static int DoSshPubKey(const byte* in, word32 inSz, byte** out,
type AAAABASE64ENCODEDKEYDATA comment type AAAABASE64ENCODEDKEYDATA comment
*/ */
c = WSTRDUP((const char*)in, heap, DYNTYPE_STRING); c = WSTRDUP((const char*)in, heap, DYNTYPE_STRING);
type = WSTRTOK(c, " \n", &last); if (c != NULL) {
key = WSTRTOK(NULL, " \n", &last); type = WSTRTOK(c, " \n", &last);
key = WSTRTOK(NULL, " \n", &last);
if (type != NULL && key != NULL) { }
const char* name; else {
word32 typeSz; ret = WS_MEMORY_E;
byte nameId;
typeSz = (word32)WSTRLEN(type);
nameId = NameToId(type, typeSz);
name = IdToName(nameId);
*outType = (const byte*)name;
*outTypeSz = typeSz;
if (*out == NULL) {
/* set size based on sanity check in wolfSSL base64 decode
* function */
*outSz = ((word32)WSTRLEN(key) * 3 + 3) / 4;
newKey = (byte*)WMALLOC(*outSz, heap, DYNTYPE_PRIVKEY);
if (newKey == NULL) {
return WS_MEMORY_E;
}
*out = newKey;
}
ret = Base64_Decode((byte*)key, (word32)WSTRLEN(key), *out, outSz);
} }
if (ret != 0) { if (ret == WS_SUCCESS) {
WLOG(WS_LOG_DEBUG, "Base64 decode of public key failed."); if (type == NULL || key == NULL) {
ret = WS_PARSE_E; ret = WS_PARSE_E;
}
}
if (ret == WS_SUCCESS) {
typeSz = (word32)WSTRLEN(type);
/* set size based on sanity check in wolfSSL base64 decode
* function */
newKeySz = ((word32)WSTRLEN(key) * 3 + 3) / 4;
if (*out == NULL) {
newKey = (byte*)WMALLOC(*outSz, heap, DYNTYPE_PRIVKEY);
if (newKey == NULL) {
ret = WS_MEMORY_E;
}
}
else {
if (*outSz < newKeySz) {
WLOG(WS_LOG_DEBUG, "PEM private key output size too small");
ret = WS_BUFFER_E;
}
else {
newKey = *out;
}
}
}
if (ret == WS_SUCCESS) {
ret = Base64_Decode((byte*)key, (word32)WSTRLEN(key),
newKey, &newKeySz);
if (ret == 0) {
*out = newKey;
*outSz = newKeySz;
*outType = (const byte *)IdToName(NameToId(type, typeSz));
*outTypeSz = (word32)WSTRLEN((const char*)*outType);
ret = WS_SUCCESS;
}
else {
WLOG(WS_LOG_DEBUG, "Base64 decode of public key failed.");
if (*out == NULL) {
WFREE(newKey, heap, DYNTYPE_PRIVKEY);
}
ret = WS_PARSE_E;
}
} }
WFREE(c, heap, DYNTYPE_STRING); WFREE(c, heap, DYNTYPE_STRING);
@ -1565,7 +1588,6 @@ static int DoAsn1Key(const byte* in, word32 inSz, byte** out,
if (newKey == NULL) { if (newKey == NULL) {
return WS_MEMORY_E; return WS_MEMORY_E;
} }
*out = newKey;
} }
else { else {
if (*outSz < inSz) { if (*outSz < inSz) {
@ -1574,15 +1596,23 @@ static int DoAsn1Key(const byte* in, word32 inSz, byte** out,
} }
newKey = *out; newKey = *out;
} }
*outSz = inSz;
WMEMCPY(newKey, in, inSz);
ret = IdentifyAsn1Key(in, inSz, 1, heap); ret = IdentifyAsn1Key(in, inSz, 1, heap);
if (ret > 0) { if (ret > 0) {
*out = newKey;
*outSz = inSz;
WMEMCPY(newKey, in, inSz);
*outType = (const byte*)IdToName(ret); *outType = (const byte*)IdToName(ret);
*outTypeSz = (word32)WSTRLEN((const char*)*outType); *outTypeSz = (word32)WSTRLEN((const char*)*outType);
ret = WS_SUCCESS; ret = WS_SUCCESS;
} }
else {
WLOG(WS_LOG_DEBUG, "unable to identify key");
if (*out == NULL) {
WFREE(newKey, heap, DYNTYPE_PRIVKEY);
}
}
return ret; return ret;
} }
@ -1599,11 +1629,10 @@ static int DoPemKey(const byte* in, word32 inSz, byte** out,
WOLFSSH_UNUSED(heap); WOLFSSH_UNUSED(heap);
if (*out == NULL) { if (*out == NULL) {
newKey = (byte*)WMALLOC(newKeySz, heap, DYNTYPE_PRIVKEY); newKey = (byte*)WMALLOC(inSz, heap, DYNTYPE_PRIVKEY);
if (newKey == NULL) { if (newKey == NULL) {
return WS_MEMORY_E; return WS_MEMORY_E;
} }
*out = newKey;
} }
else { else {
if (*outSz < inSz) { if (*outSz < inSz) {
@ -1626,14 +1655,19 @@ static int DoPemKey(const byte* in, word32 inSz, byte** out,
if (ret == WS_SUCCESS) { if (ret == WS_SUCCESS) {
ret = IdentifyAsn1Key(newKey, newKeySz, 1, heap); ret = IdentifyAsn1Key(newKey, newKeySz, 1, heap);
if (ret > 0) { }
*outSz = newKeySz;
*outType = (const byte*)IdToName(ret); if (ret > 0) {
*outTypeSz = (word32)WSTRLEN((const char*)*outType); *out = newKey;
ret = WS_SUCCESS; *outSz = newKeySz;
} *outType = (const byte*)IdToName(ret);
else { *outTypeSz = (word32)WSTRLEN((const char*)*outType);
WLOG(WS_LOG_DEBUG, "unable to identify key"); ret = WS_SUCCESS;
}
else {
WLOG(WS_LOG_DEBUG, "unable to identify key");
if (*out == NULL) {
WFREE(newKey, heap, DYNTYPE_PRIVKEY);
} }
} }
@ -1654,7 +1688,6 @@ static int DoOpenSshKey(const byte* in, word32 inSz, byte** out,
if (newKey == NULL) { if (newKey == NULL) {
return WS_MEMORY_E; return WS_MEMORY_E;
} }
*out = newKey;
} }
else { else {
if (*outSz < inSz) { if (*outSz < inSz) {
@ -1669,15 +1702,28 @@ static int DoOpenSshKey(const byte* in, word32 inSz, byte** out,
ret = Base64_Decode((byte*)in, inSz, newKey, &newKeySz); ret = Base64_Decode((byte*)in, inSz, newKey, &newKeySz);
if (ret == 0) { if (ret == 0) {
ret = WS_SUCCESS;
}
else {
WLOG(WS_LOG_DEBUG, "Base64 decode of public key failed.");
ret = WS_PARSE_E;
}
if (ret == WS_SUCCESS) {
ret = IdentifyOpenSshKey(newKey, newKeySz, heap); ret = IdentifyOpenSshKey(newKey, newKeySz, heap);
if (ret > 0) { }
*outSz = newKeySz;
*outType = (const byte*)IdToName(ret); if (ret > 0) {
*outTypeSz = (word32)WSTRLEN((const char*)*outType); *out = newKey;
ret = WS_SUCCESS; *outSz = newKeySz;
} *outType = (const byte*)IdToName(ret);
else { *outTypeSz = (word32)WSTRLEN((const char*)*outType);
WLOG(WS_LOG_DEBUG, "unable to identify key"); ret = WS_SUCCESS;
}
else {
WLOG(WS_LOG_DEBUG, "unable to identify key");
if (*out == NULL) {
WFREE(newKey, heap, DYNTYPE_PRIVKEY);
} }
} }