- MMS client/server: added missing length field checks to increase decoder stability

pull/143/head
Michael Zillgith 8 years ago
parent 11f0fa9e2a
commit d45e729ecf

@ -22,6 +22,7 @@ model: $(PROJECT_ICD_FILE)
$(PROJECT_BINARY_NAME): $(PROJECT_SOURCES) $(LIB_NAME)
$(CC) $(CFLAGS) $(LDFLAGS) -o $(PROJECT_BINARY_NAME) $(PROJECT_SOURCES) $(INCLUDES) $(LIB_NAME) $(LDLIBS)
mkdir -p vmd-filestore
$(CP) $(PROJECT_BINARY_NAME) vmd-filestore/IEDSERVER.BIN
clean:

@ -126,6 +126,11 @@ parseUserInformation(AcseConnection* self, uint8_t* buffer, int bufPos, int maxB
bufPos = BerDecoder_decodeLength(buffer, &len, bufPos, maxBufPos);
if (bufPos < 0) {
*userInfoValid = false;
return -1;
}
switch (tag) {
case 0x02: /* indirect-reference */
@ -178,6 +183,8 @@ parseAarePdu(AcseConnection* self, uint8_t* buffer, int bufPos, int maxBufPos)
int len;
bufPos = BerDecoder_decodeLength(buffer, &len, bufPos, maxBufPos);
if (bufPos < 0)
return ACSE_ERROR;
switch (tag) {
case 0xa1: /* application context name */
@ -188,6 +195,9 @@ parseAarePdu(AcseConnection* self, uint8_t* buffer, int bufPos, int maxBufPos)
bufPos++;
bufPos = BerDecoder_decodeLength(buffer, &len, bufPos, maxBufPos);
if (bufPos < 0)
return ACSE_ERROR;
result = BerDecoder_decodeUint32(buffer, len, bufPos);
bufPos += len;
@ -206,8 +216,12 @@ parseAarePdu(AcseConnection* self, uint8_t* buffer, int bufPos, int maxBufPos)
bufPos++;
bufPos = BerDecoder_decodeLength(buffer, &len, bufPos, maxBufPos);
if (bufPos < 0)
return ACSE_ERROR;
bufPos = parseUserInformation(self, buffer, bufPos, bufPos + len, &userInfoValid);
if (bufPos < 0)
return ACSE_ERROR;
}
break;
@ -247,8 +261,7 @@ parseAarqPdu(AcseConnection* self, uint8_t* buffer, int bufPos, int maxBufPos)
bufPos = BerDecoder_decodeLength(buffer, &len, bufPos, maxBufPos);
if (bufPos < 0) {
if (DEBUG_ACSE)
printf("ACSE: parseAarqPdu: user info invalid!\n");
if (DEBUG_ACSE) printf("ACSE: Invalid PDU!\n");
return ACSE_ASSOCIATE_FAILED;
}
@ -302,7 +315,13 @@ parseAarqPdu(AcseConnection* self, uint8_t* buffer, int bufPos, int maxBufPos)
case 0xac: /* authentication value */
bufPos++;
bufPos = BerDecoder_decodeLength(buffer, &len, bufPos, maxBufPos);
if (bufPos < 0) {
if (DEBUG_ACSE) printf("ACSE: Invalid PDU!\n");
return ACSE_ASSOCIATE_FAILED;
}
authValueLen = len;
authValue = buffer + bufPos;
bufPos += len;
@ -318,7 +337,17 @@ parseAarqPdu(AcseConnection* self, uint8_t* buffer, int bufPos, int maxBufPos)
bufPos = BerDecoder_decodeLength(buffer, &len, bufPos, maxBufPos);
if (bufPos < 0) {
if (DEBUG_ACSE) printf("ACSE: Invalid PDU!\n");
return ACSE_ASSOCIATE_FAILED;
}
bufPos = parseUserInformation(self, buffer, bufPos, bufPos + len, &userInfoValid);
if (bufPos < 0) {
if (DEBUG_ACSE) printf("ACSE: Invalid PDU!\n");
return ACSE_ASSOCIATE_FAILED;
}
}
break;

@ -651,8 +651,8 @@ mmsMsg_parseConfirmedErrorPDU(uint8_t* buffer, int bufPos, int maxBufPos, uint32
while (bufPos < endPos) {
tag = buffer[bufPos++];
bufPos = BerDecoder_decodeLength(buffer, &length, bufPos, maxBufPos);
bufPos = BerDecoder_decodeLength(buffer, &length, bufPos, maxBufPos);
if (bufPos < 0)
goto exit_error;
@ -709,8 +709,8 @@ mmsMsg_parseRejectPDU(uint8_t* buffer, int bufPos, int maxBufPos, uint32_t* invo
while (bufPos < endPos) {
tag = buffer[bufPos++];
bufPos = BerDecoder_decodeLength(buffer, &length, bufPos, maxBufPos);
bufPos = BerDecoder_decodeLength(buffer, &length, bufPos, maxBufPos);
if (bufPos < 0)
goto exit_error;
@ -949,7 +949,10 @@ mmsIsoCallback(IsoIndication indication, void* parameter, ByteBuffer* payload)
int bufPos = 1;
int length;
bufPos = BerDecoder_decodeLength(buf, &length, bufPos, payload->size);
if (bufPos == -1)
goto exit_with_error;
uint32_t invokeId;
@ -965,6 +968,8 @@ mmsIsoCallback(IsoIndication indication, void* parameter, ByteBuffer* payload)
}
bufPos = BerDecoder_decodeLength(buf, &length, bufPos, payload->size);
if (bufPos == -1)
goto exit_with_error;
if (extendedTag) {
switch(nestedTag) {

@ -463,7 +463,13 @@ parseDirectoryEntry(uint8_t* buffer, int bufPos, int maxBufPos, MmsFileDirectory
while (bufPos < maxBufPos) {
uint8_t tag = buffer[bufPos++];
int length;
bufPos = BerDecoder_decodeLength(buffer, &length, bufPos, maxBufPos);
if (bufPos < 0) {
if (DEBUG_MMS_CLIENT)
printf("MMS_CLIENT: message contains unknown tag!\n");
return false;
}
switch (tag) {
case 0xa0: /* file-name */
@ -471,7 +477,14 @@ parseDirectoryEntry(uint8_t* buffer, int bufPos, int maxBufPos, MmsFileDirectory
filename = fileNameMemory;
tag = buffer[bufPos++];
bufPos = BerDecoder_decodeLength(buffer, &length, bufPos, maxBufPos);
if (bufPos < 0) {
if (DEBUG_MMS_CLIENT)
printf("MMS_CLIENT: message contains unknown tag!\n");
return false;
}
memcpy(filename, buffer + bufPos, length);
filename[length] = 0;
@ -485,7 +498,7 @@ parseDirectoryEntry(uint8_t* buffer, int bufPos, int maxBufPos, MmsFileDirectory
default:
bufPos += length;
if (DEBUG_MMS_CLIENT)
printf("mmsClient_parseFileDirectoryResponse: message contains unknown tag!\n");
printf("MMS_CLIENT: message contains unknown tag!\n");
return false;
}
@ -511,7 +524,6 @@ parseListOfDirectoryEntries(uint8_t* buffer, int bufPos, int maxBufPos,
int length;
bufPos = BerDecoder_decodeLength(buffer, &length, bufPos, maxBufPos);
if (bufPos < 0) return false;
int endPos = bufPos + length;
@ -524,7 +536,9 @@ parseListOfDirectoryEntries(uint8_t* buffer, int bufPos, int maxBufPos,
while (bufPos < endPos) {
tag = buffer[bufPos++];
bufPos = BerDecoder_decodeLength(buffer, &length, bufPos, maxBufPos);
if (bufPos < 0) return false;
switch (tag) {
case 0x30: /* Sequence */
@ -583,7 +597,9 @@ mmsClient_parseFileDirectoryResponse(MmsConnection self, MmsFileDirectoryHandler
while (bufPos < endPos) {
tag = buffer[bufPos++];
bufPos = BerDecoder_decodeLength(buffer, &length, bufPos, maxBufPos);
if (bufPos < 0) return false;
switch (tag) {
case 0xa0: /* listOfDirectoryEntries */
@ -641,7 +657,10 @@ mmsMsg_parseFileOpenResponse(uint8_t* buffer, int bufPos, int maxBufPos, int32_t
while (bufPos < endPos) {
tag = buffer[bufPos++];
bufPos = BerDecoder_decodeLength(buffer, &length, bufPos, maxBufPos);
if (bufPos < 0)
return false;
switch (tag) {
case 0x80: /* frsmId */
@ -704,6 +723,8 @@ mmsMsg_parseFileReadResponse(uint8_t* buffer, int bufPos, int maxBufPos, int frs
while (bufPos < endPos) {
tag = buffer[bufPos++];
bufPos = BerDecoder_decodeLength(buffer, &length, bufPos, maxBufPos);
if (bufPos < 0)
return false;
switch (tag) {
case 0x80: /* fileData */

@ -81,6 +81,7 @@ mmsClient_parseIdentifyResponse(MmsConnection self)
tag = buffer[bufPos++];
bufPos = BerDecoder_decodeLength(buffer, &length, bufPos, maxBufPos);
if (bufPos < 0) goto exit_error;
switch (tag) {
case 0x80: /* vendorName */

@ -42,11 +42,13 @@ parseJournalVariable(uint8_t* buffer, int bufPos, int maxLength, MmsJournalVaria
while (bufPos < maxBufPos) {
int length;
uint8_t tag = buffer[bufPos++];
int length;
bufPos = BerDecoder_decodeLength(buffer, &length, bufPos, maxBufPos);
if ((bufPos + length) > maxBufPos) { /* check length field for validity */
if ((bufPos < 0) || ((bufPos + length) > maxBufPos)) { /* check length field for validity */
if (DEBUG_MMS_CLIENT)
printf("MMS_CLIENT: parseReadJournalResponse: invalid length field\n");
@ -94,7 +96,7 @@ parseJournalVariables(uint8_t* buffer, int bufPos, int maxLength, MmsJournalEntr
uint8_t tag = buffer[bufPos++];
bufPos = BerDecoder_decodeLength(buffer, &length, bufPos, maxBufPos);
if ((bufPos + length) > maxBufPos) { /* check length field for validity */
if ((bufPos < 0) || ((bufPos + length) > maxBufPos)) { /* check length field for validity */
if (DEBUG_MMS_CLIENT)
printf("MMS_CLIENT: parseReadJournalResponse: invalid length field\n");
@ -137,7 +139,7 @@ parseData(uint8_t* buffer, int bufPos, int maxLength, MmsJournalEntry journalEnt
uint8_t tag = buffer[bufPos++];
bufPos = BerDecoder_decodeLength(buffer, &length, bufPos, maxBufPos);
if ((bufPos + length) > maxBufPos) { /* check length field for validity */
if ((bufPos < 0) || ((bufPos + length) > maxBufPos)) { /* check length field for validity */
if (DEBUG_MMS_CLIENT)
printf("MMS_CLIENT: parseReadJournalResponse: invalid length field\n");
@ -175,7 +177,7 @@ parseEntryContent(uint8_t* buffer, int bufPos, int maxLength, MmsJournalEntry jo
uint8_t tag = buffer[bufPos++];
bufPos = BerDecoder_decodeLength(buffer, &length, bufPos, maxBufPos);
if ((bufPos + length) > maxBufPos) { /* check length field for validity */
if ((bufPos < 0) ||((bufPos + length) > maxBufPos)) { /* check length field for validity */
if (DEBUG_MMS_CLIENT)
printf("MMS_CLIENT: parseReadJournalResponse: invalid length field\n");
@ -276,7 +278,7 @@ parseListOfJournalEntries(uint8_t* buffer, int bufPos, int maxLength, LinkedList
uint8_t tag = buffer[bufPos++];
bufPos = BerDecoder_decodeLength(buffer, &length, bufPos, maxBufPos);
if ((bufPos + length) > maxBufPos) { /* check length field for validity */
if ((bufPos < 0) || ((bufPos + length) > maxBufPos)) { /* check length field for validity */
if (DEBUG_MMS_CLIENT)
printf("MMS_CLIENT: parseReadJournalResponse: invalid length field\n");
@ -330,8 +332,7 @@ mmsClient_parseReadJournalResponse(MmsConnection self, bool* moreFollows, Linked
}
bufPos = BerDecoder_decodeLength(buffer, &length, bufPos, maxBufPos);
if (bufPos < 0)
return false;
if (bufPos < 0) return false;
int endPos = bufPos + length;
@ -346,6 +347,7 @@ mmsClient_parseReadJournalResponse(MmsConnection self, bool* moreFollows, Linked
while (bufPos < endPos) {
tag = buffer[bufPos++];
bufPos = BerDecoder_decodeLength(buffer, &length, bufPos, maxBufPos);
if (bufPos < 0) return false;
switch (tag) {
case 0xa0: /* listOfJournalEntry */

@ -82,6 +82,7 @@ mmsClient_parseStatusResponse(MmsConnection self, int* vmdLogicalStatus, int* vm
while (bufPos < endPos) {
tag = buffer[bufPos++];
bufPos = BerDecoder_decodeLength(buffer, &length, bufPos, maxBufPos);
if (bufPos < 0) goto exit_error;
switch (tag) {
case 0x80: /* vmdLogicalStatus */

@ -169,6 +169,12 @@ mmsClient_parseWriteResponse(ByteBuffer* message, int32_t bufPos, MmsError* mmsE
if (tag == 0x80) {
bufPos = BerDecoder_decodeLength(buf, &length, bufPos, size);
if (bufPos == -1) {
*mmsError = MMS_ERROR_PARSING_RESPONSE;
retVal = DATA_ACCESS_ERROR_UNKNOWN;
goto exit_function;
}
uint32_t dataAccessErrorCode =
BerDecoder_decodeUint32(buf, length, bufPos);

@ -107,7 +107,7 @@ getNumberOfElements(uint8_t* buffer, int bufPos, int elementLength)
bufPos = BerDecoder_decodeLength(buffer, &elementLength, bufPos, elementEndBufPos);
if (bufPos + elementLength > elementEndBufPos) {
if ((bufPos < 0) || (bufPos + elementLength > elementEndBufPos)) {
goto exit_with_error;
}

@ -250,6 +250,8 @@ mmsServer_handleFileDeleteRequest(
int length;
bufPos = BerDecoder_decodeLength(buffer, &length, bufPos, maxBufPos);
if (bufPos == -1)
goto exit_reject_invalid_pdu;
if (length > 255) {
mmsMsg_createMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_REQUEST_INVALID_ARGUMENT, response);

@ -472,6 +472,11 @@ mmsServer_handleGetNameListRequest(
uint8_t objectScopeTag = buffer[bufPos++];
bufPos = BerDecoder_decodeLength(buffer, &length, bufPos, maxBufPos);
if (bufPos < 0) {
mmsMsg_createMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_INVALID_PDU, response);
return;
}
switch (objectScopeTag) {
case 0x80: /* vmd-specific */
objectScope = OBJECT_SCOPE_VMD;

@ -271,6 +271,11 @@ mmsServer_handleReadJournalRequest(
uint8_t objectIdTag = requestBuffer[bufPos++];
bufPos = BerDecoder_decodeLength(requestBuffer, &length, bufPos, maxBufPos);
if (bufPos < 0) {
mmsMsg_createMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_INVALID_PDU, response);
return;
}
switch (objectIdTag) {
case 0xa1: /* domain-specific */
@ -298,13 +303,18 @@ mmsServer_handleReadJournalRequest(
case 0xa1: /* rangeStartSpecification */
{
uint8_t subTag = requestBuffer[bufPos++];
bufPos = BerDecoder_decodeLength(requestBuffer, &length, bufPos, maxBufPos);
if (subTag != 0x80) {
mmsMsg_createMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_UNRECOGNIZED_MODIFIER, response);
return;
}
bufPos = BerDecoder_decodeLength(requestBuffer, &length, bufPos, maxBufPos);
if (bufPos < 0) {
mmsMsg_createMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_INVALID_PDU, response);
return;
}
if ((length == 4) || (length == 6)) {
@ -328,13 +338,19 @@ mmsServer_handleReadJournalRequest(
case 0xa2: /* rangeStopSpecification */
{
uint8_t subTag = requestBuffer[bufPos++];
bufPos = BerDecoder_decodeLength(requestBuffer, &length, bufPos, maxBufPos);
if (subTag != 0x80) {
mmsMsg_createMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_UNRECOGNIZED_MODIFIER, response);
return;
}
bufPos = BerDecoder_decodeLength(requestBuffer, &length, bufPos, maxBufPos);
if (bufPos < 0) {
mmsMsg_createMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_INVALID_PDU, response);
return;
}
if ((length == 4) || (length == 6)) {
rangeStop.type = MMS_BINARY_TIME;
rangeStop.value.binaryTime.size = length;
@ -359,8 +375,14 @@ mmsServer_handleReadJournalRequest(
while (bufPos < maxSubBufPos) {
uint8_t subTag = requestBuffer[bufPos++];
bufPos = BerDecoder_decodeLength(requestBuffer, &length, bufPos, maxBufPos);
if (bufPos < 0) {
mmsMsg_createMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_INVALID_PDU, response);
return;
}
switch (subTag) {
case 0x80: /* timeSpecification */

@ -210,14 +210,14 @@ parseFullyEncodedData(IsoPresentation* self, uint8_t* buffer, int len, int bufPo
bufPos = BerDecoder_decodeLength(buffer, &len, bufPos, endPos);
endPos = bufPos + len;
if (bufPos < 0) {
if (DEBUG_PRES)
printf("PRES: wrong parameter length\n");
return -1;
}
endPos = bufPos + len;
while (bufPos < endPos) {
uint8_t tag = buffer[bufPos++];
int length;
@ -285,6 +285,12 @@ parsePCDLEntry(IsoPresentation* self, uint8_t* buffer, int totalLength, int bufP
bufPos = BerDecoder_decodeLength(buffer, &len, bufPos, endPos);
if (bufPos < 0) {
if (DEBUG_PRES)
printf("PRES: Invalid PDU\n");
return -1;
}
switch (tag) {
case 0x02: /* presentation-context-identifier */
contextId = BerDecoder_decodeUint32(buffer, len, bufPos);
@ -357,6 +363,8 @@ parsePresentationContextDefinitionList(IsoPresentation* self, uint8_t* buffer, i
int len;
bufPos = BerDecoder_decodeLength(buffer, &len, bufPos, endPos);
if (bufPos < 0)
return -1;
switch (tag) {
case 0x30:
@ -452,6 +460,12 @@ IsoPresentation_parseAcceptMessage(IsoPresentation* self, ByteBuffer* byteBuffer
bufPos = BerDecoder_decodeLength(buffer, &len, bufPos, maxBufPos);
if (bufPos < 0) {
if (DEBUG_PRES)
printf("PRES: Invalid message\n");
return 0;
}
while (bufPos < maxBufPos) {
uint8_t tag = buffer[bufPos++];
@ -572,11 +586,23 @@ IsoPresentation_parseUserData(IsoPresentation* self, ByteBuffer* readBuffer)
bufPos = BerDecoder_decodeLength(buffer, &len, bufPos, length);
if (bufPos < 0) {
if (DEBUG_PRES)
printf("PRES: invalid message!\n");
return 0;
}
if (buffer[bufPos++] != 0x30)
return 0;
bufPos = BerDecoder_decodeLength(buffer, &len, bufPos, length);
if (bufPos < 0) {
if (DEBUG_PRES)
printf("PRES: invalid message!\n");
return 0;
}
if (buffer[bufPos++] != 0x02)
return 0;
@ -592,6 +618,12 @@ IsoPresentation_parseUserData(IsoPresentation* self, ByteBuffer* readBuffer)
bufPos = BerDecoder_decodeLength(buffer, &userDataLength, bufPos, length);
if (bufPos < 0) {
if (DEBUG_PRES)
printf("PRES: invalid message!\n");
return 0;
}
ByteBuffer_wrap(&(self->nextPayload), buffer + bufPos, userDataLength, userDataLength);
return 1;
@ -617,6 +649,12 @@ IsoPresentation_parseConnect(IsoPresentation* self, ByteBuffer* byteBuffer)
bufPos = BerDecoder_decodeLength(buffer, &len, bufPos, maxBufPos);
if (bufPos < 0) {
if (DEBUG_PRES)
printf("PRES: invalid message!\n");
return 0;
}
if (DEBUG_PRES)
printf("PRES: CPType with len %i\n", len);
@ -627,7 +665,7 @@ IsoPresentation_parseConnect(IsoPresentation* self, ByteBuffer* byteBuffer)
if (bufPos < 0) {
if (DEBUG_PRES)
printf("PRES: wrong parameter length\n");
printf("PRES: invalid message!\n");
return 0;
}
@ -639,10 +677,20 @@ IsoPresentation_parseConnect(IsoPresentation* self, ByteBuffer* byteBuffer)
printf("PRES: mode-value of wrong type!\n");
return 0;
}
bufPos = BerDecoder_decodeLength(buffer, &len, bufPos, maxBufPos);
if (bufPos < 0) {
if (DEBUG_PRES)
printf("PRES: invalid message!\n");
return 0;
}
uint32_t modeSelector = BerDecoder_decodeUint32(buffer, len, bufPos);
if (DEBUG_PRES)
printf("PRES: modesel %ui\n", modeSelector);
bufPos += len;
}
break;

Loading…
Cancel
Save