From de6886c6f30ade97c5718bce8fcf652755321830 Mon Sep 17 00:00:00 2001 From: Michael Zillgith Date: Tue, 7 Jul 2020 12:09:26 +0200 Subject: [PATCH] - MMS: fixed problem in handling of indefinite length encoded BER elements --- src/mms/asn1/ber_decode.c | 36 ++++++++++++++++++- src/mms/iso_acse/acse.c | 8 +++++ .../iso_mms/client/mms_client_connection.c | 6 +++- src/mms/iso_mms/client/mms_client_files.c | 16 +++++++++ src/mms/iso_mms/client/mms_client_identify.c | 2 ++ src/mms/iso_mms/client/mms_client_initiate.c | 6 ++++ src/mms/iso_mms/client/mms_client_journals.c | 21 +++++++++++ src/mms/iso_mms/client/mms_client_status.c | 2 ++ src/mms/iso_mms/server/mms_access_result.c | 5 +++ .../iso_mms/server/mms_association_service.c | 3 ++ src/mms/iso_mms/server/mms_file_service.c | 11 ++++++ .../iso_mms/server/mms_get_namelist_service.c | 6 ++++ .../iso_mms/server/mms_server_connection.c | 6 ++++ src/mms/iso_presentation/iso_presentation.c | 27 ++++++++++++++ 14 files changed, 153 insertions(+), 2 deletions(-) diff --git a/src/mms/asn1/ber_decode.c b/src/mms/asn1/ber_decode.c index db6c8d91..bcc4352c 100644 --- a/src/mms/asn1/ber_decode.c +++ b/src/mms/asn1/ber_decode.c @@ -24,6 +24,40 @@ #include "libiec61850_platform_includes.h" #include "ber_decode.h" +static int +getIndefiniteLength(uint8_t* buffer, int bufPos, int maxBufPos) +{ + int length = 0; + + while (bufPos < maxBufPos) { + if ((buffer[bufPos] == 0) && (buffer[bufPos+1] == 0)) { + return length + 2; + } + else { + length++; + + if ((buffer[bufPos++] & 0x1f) == 0x1f) { + /* handle extended tags */ + bufPos++; + length++; + } + + int subLength = -1; + + int newBufPos = BerDecoder_decodeLength(buffer, &subLength, bufPos, maxBufPos); + + if (newBufPos == -1) + return -1; + + length += subLength + newBufPos - bufPos; + + bufPos = newBufPos + subLength; + } + } + + return -1; +} + int BerDecoder_decodeLength(uint8_t* buffer, int* length, int bufPos, int maxBufPos) { @@ -36,7 +70,7 @@ BerDecoder_decodeLength(uint8_t* buffer, int* length, int bufPos, int maxBufPos) int lenLength = len1 & 0x7f; if (lenLength == 0) { /* indefinite length form */ - *length = -1; + *length = getIndefiniteLength(buffer, bufPos, maxBufPos); } else { *length = 0; diff --git a/src/mms/iso_acse/acse.c b/src/mms/iso_acse/acse.c index 8ff5b335..dc892e46 100644 --- a/src/mms/iso_acse/acse.c +++ b/src/mms/iso_acse/acse.c @@ -230,6 +230,9 @@ parseAarePdu(AcseConnection* self, uint8_t* buffer, int bufPos, int maxBufPos) } break; + case 0x00: /* indefinite length end tag -> ignore */ + break; + default: /* ignore unknown tag */ if (DEBUG_ACSE) printf("ACSE: parseAarePdu: unknown tag %02x\n", tag); @@ -363,6 +366,9 @@ parseAarqPdu(AcseConnection* self, uint8_t* buffer, int bufPos, int maxBufPos) } break; + case 0x00: /* indefinite length end tag -> ignore */ + break; + default: /* ignore unknown tag */ if (DEBUG_ACSE) printf("ACSE: parseAarqPdu: unknown tag %02x\n", tag); @@ -454,6 +460,8 @@ AcseConnection_parseMessage(AcseConnection* self, ByteBuffer* message) case 0x64: /* A_ABORT */ indication = ACSE_ABORT; break; + case 0x00: /* indefinite length end tag -> ignore */ + break; default: if (DEBUG_ACSE) printf("ACSE: Unknown ACSE message\n"); diff --git a/src/mms/iso_mms/client/mms_client_connection.c b/src/mms/iso_mms/client/mms_client_connection.c index 63ebfd38..698b8f71 100644 --- a/src/mms/iso_mms/client/mms_client_connection.c +++ b/src/mms/iso_mms/client/mms_client_connection.c @@ -553,6 +553,8 @@ parseServiceError(uint8_t* buffer, int bufPos, int maxLength, MmsServiceError* e case 0xa3: /* serviceSpecificInfo */ bufPos += length; /* ignore */ break; + case 0x00: /* indefinite length end tag -> ignore */ + break; default: bufPos += length; /* ignore */ break; @@ -605,6 +607,8 @@ mmsMsg_parseConfirmedErrorPDU(uint8_t* buffer, int bufPos, int maxBufPos, uint32 if (bufPos < 0) goto exit_error; break; + case 0x00: /* indefinite length end tag -> ignore */ + break; default: bufPos += length; /* ignore */ break; @@ -673,7 +677,7 @@ exit_error: return -1; } -static void +void handleAsyncResponse(MmsConnection self, ByteBuffer* response, uint32_t bufPos, MmsOutstandingCall outstandingCall, MmsError err) { diff --git a/src/mms/iso_mms/client/mms_client_files.c b/src/mms/iso_mms/client/mms_client_files.c index c21bc0a4..d9215abc 100644 --- a/src/mms/iso_mms/client/mms_client_files.c +++ b/src/mms/iso_mms/client/mms_client_files.c @@ -114,6 +114,9 @@ mmsClient_handleFileOpenRequest( bufPos += length; break; + case 0x00: /* indefinite length end tag -> ignore */ + break; + default: /* unrecognized parameter */ bufPos += length; goto exit_reject_invalid_pdu; @@ -470,6 +473,8 @@ parseFileAttributes(uint8_t* buffer, int bufPos, int maxBufPos, uint32_t* fileSi } } break; + case 0x00: /* indefinite length end tag -> ignore */ + break; default: return false; } @@ -523,6 +528,8 @@ parseDirectoryEntry(uint8_t* buffer, int bufPos, int maxBufPos, uint32_t invokeI return false; bufPos += length; break; + case 0x00: /* indefinite length end tag -> ignore */ + break; default: bufPos += length; if (DEBUG_MMS_CLIENT) @@ -568,6 +575,8 @@ parseListOfDirectoryEntries(uint8_t* buffer, int bufPos, int maxBufPos, uint32_t parseDirectoryEntry(buffer, bufPos, bufPos + length, invokeId, handler, parameter); bufPos += length; break; + case 0x00: /* indefinite length end tag -> ignore */ + break; default: bufPos += length; if (DEBUG_MMS_CLIENT) @@ -626,6 +635,8 @@ mmsClient_parseFileDirectoryResponse(ByteBuffer* response, int bufPos, uint32_t moreFollows = BerDecoder_decodeBoolean(buffer, bufPos); bufPos += length; break; + case 0x00: /* indefinite length end tag -> ignore */ + break; default: bufPos += length; if (DEBUG_MMS_CLIENT) @@ -684,6 +695,8 @@ mmsMsg_parseFileOpenResponse(uint8_t* buffer, int bufPos, int maxBufPos, int32_t return false; bufPos += length; break; + case 0x00: /* indefinite length end tag -> ignore */ + break; default: bufPos += length; if (DEBUG_MMS_CLIENT) @@ -748,6 +761,9 @@ mmsMsg_parseFileReadResponse(uint8_t* buffer, int bufPos, int maxBufPos, uint32_ bufPos += length; break; + case 0x00: /* indefinite length end tag -> ignore */ + break; + default: bufPos += length; if (DEBUG_MMS_CLIENT) diff --git a/src/mms/iso_mms/client/mms_client_identify.c b/src/mms/iso_mms/client/mms_client_identify.c index c065a754..e7fa754e 100644 --- a/src/mms/iso_mms/client/mms_client_identify.c +++ b/src/mms/iso_mms/client/mms_client_identify.c @@ -96,6 +96,8 @@ mmsClient_parseIdentifyResponse(MmsConnection self, ByteBuffer* response, uint32 case 0x83: /* list of abstract syntaxes */ bufPos += length; break; + case 0x00: /* indefinite length end tag -> ignore */ + break; default: /* ignore unknown tags */ bufPos += length; break; diff --git a/src/mms/iso_mms/client/mms_client_initiate.c b/src/mms/iso_mms/client/mms_client_initiate.c index 57288551..f79f163e 100644 --- a/src/mms/iso_mms/client/mms_client_initiate.c +++ b/src/mms/iso_mms/client/mms_client_initiate.c @@ -149,6 +149,9 @@ parseInitResponseDetail(MmsConnection self, uint8_t* buffer, int bufPos, int max } break; + case 0x00: /* indefinite length end tag -> ignore */ + break; + default: break; } @@ -221,6 +224,9 @@ mmsClient_parseInitiateResponse(MmsConnection self, ByteBuffer* response) } break; + case 0x00: /* indefinite length end tag -> ignore */ + break; + default: break; /* Ignore unknown tags */ } diff --git a/src/mms/iso_mms/client/mms_client_journals.c b/src/mms/iso_mms/client/mms_client_journals.c index 4d80c613..7dfd741b 100644 --- a/src/mms/iso_mms/client/mms_client_journals.c +++ b/src/mms/iso_mms/client/mms_client_journals.c @@ -72,6 +72,9 @@ parseJournalVariable(uint8_t* buffer, int bufPos, int maxLength, MmsJournalVaria break; + case 0x00: /* indefinite length end tag -> ignore */ + break; + default: break; @@ -115,6 +118,9 @@ parseJournalVariables(uint8_t* buffer, int bufPos, int maxLength, MmsJournalEntr break; + case 0x00: /* indefinite length end tag -> ignore */ + break; + default: break; } @@ -152,6 +158,9 @@ parseData(uint8_t* buffer, int bufPos, int maxLength, MmsJournalEntry journalEnt break; + case 0x00: /* indefinite length end tag -> ignore */ + break; + default: break; @@ -200,6 +209,9 @@ parseEntryContent(uint8_t* buffer, int bufPos, int maxLength, MmsJournalEntry jo break; + case 0x00: /* indefinite length end tag -> ignore */ + break; + default: if (DEBUG_MMS_CLIENT) printf("MMS_CLIENT: parseReadJournalResponse: ignore unknown tag %02x\n", tag); @@ -250,6 +262,9 @@ parseJournalEntry(uint8_t* buffer, int bufPos, int maxLength, LinkedList journal break; + case 0x00: /* indefinite length end tag -> ignore */ + break; + default: if (DEBUG_MMS_CLIENT) printf("MMS_CLIENT: parseReadJournalResponse: unknown tag %02x\n", tag); @@ -288,6 +303,9 @@ parseListOfJournalEntries(uint8_t* buffer, int bufPos, int maxLength, LinkedList return false; break; + case 0x00: /* indefinite length end tag -> ignore */ + break; + default: if (DEBUG_MMS_CLIENT) printf("MMS_CLIENT: parseReadJournalResponse: unknown tag %02x\n", tag); @@ -353,6 +371,9 @@ mmsClient_parseReadJournalResponse(MmsConnection self, ByteBuffer* response, int *moreFollows = BerDecoder_decodeBoolean(buffer, bufPos); break; + case 0x00: /* indefinite length end tag -> ignore */ + break; + default: if (DEBUG_MMS_CLIENT) printf("MMS_CLIENT: mmsClient_parseReadJournalResponse: message contains unknown tag %02x!\n", tag); diff --git a/src/mms/iso_mms/client/mms_client_status.c b/src/mms/iso_mms/client/mms_client_status.c index 0e19823c..a7c291b8 100644 --- a/src/mms/iso_mms/client/mms_client_status.c +++ b/src/mms/iso_mms/client/mms_client_status.c @@ -95,6 +95,8 @@ mmsClient_parseStatusResponse(MmsConnection self, ByteBuffer* response, int bufP case 0x82: /* localDetail */ bufPos += length; break; + case 0x00: /* indefinite length end tag -> ignore */ + break; default: return false; } diff --git a/src/mms/iso_mms/server/mms_access_result.c b/src/mms/iso_mms/server/mms_access_result.c index bb53312e..4671211f 100644 --- a/src/mms/iso_mms/server/mms_access_result.c +++ b/src/mms/iso_mms/server/mms_access_result.c @@ -135,6 +135,8 @@ getNumberOfElements(uint8_t* buffer, int bufPos, int elementLength) break; case 0x91: /* Utctime */ break; + case 0x00: /* indefinite length end tag -> ignore */ + break; default: goto exit_with_error; } @@ -304,6 +306,9 @@ MmsValue_decodeMmsData(uint8_t* buffer, int bufPos, int bufferLength, int* endBu break; + case 0x00: /* indefinite length end tag -> ignore */ + break; + default: /* unknown tag -> decoding error */ goto exit_with_error; } diff --git a/src/mms/iso_mms/server/mms_association_service.c b/src/mms/iso_mms/server/mms_association_service.c index 22b24a50..afa5d07a 100644 --- a/src/mms/iso_mms/server/mms_association_service.c +++ b/src/mms/iso_mms/server/mms_association_service.c @@ -308,6 +308,9 @@ parseInitiateRequestPdu(MmsServerConnection self, uint8_t* buffer, int bufPos, i /* we ignore this */ break; + case 0x00: /* indefinite length end tag -> ignore */ + break; + default: break; /* Ignore unknown tags */ } diff --git a/src/mms/iso_mms/server/mms_file_service.c b/src/mms/iso_mms/server/mms_file_service.c index e73eb271..2c1831f1 100644 --- a/src/mms/iso_mms/server/mms_file_service.c +++ b/src/mms/iso_mms/server/mms_file_service.c @@ -333,6 +333,9 @@ mmsServer_handleFileOpenRequest( bufPos += length; break; + case 0x00: /* indefinite length end tag -> ignore */ + break; + default: /* unrecognized parameter */ bufPos += length; goto exit_reject_invalid_pdu; @@ -672,6 +675,9 @@ mmsServer_handleObtainFileRequest( break; + case 0x00: /* indefinite length end tag -> ignore */ + break; + default: /* unrecognized parameter */ bufPos += length; goto exit_reject_invalid_pdu; @@ -1095,6 +1101,8 @@ mmsServer_handleFileRenameRequest( if (DEBUG_MMS_SERVER) printf("MMS_SERVER: newFileName: (%s)\n", newFileName); + break; + case 0x00: /* indefinite length end tag -> ignore */ break; default: /* ignore unknown tag */ if (DEBUG_MMS_SERVER) @@ -1181,6 +1189,9 @@ mmsServer_handleFileDirectoryRequest( break; + case 0x00: /* indefinite length end tag -> ignore */ + break; + default: /* unrecognized parameter */ if (DEBUG_MMS_SERVER) printf("MMS_SERVER: handleFileDirectoryRequest: unrecognized parameter\n"); diff --git a/src/mms/iso_mms/server/mms_get_namelist_service.c b/src/mms/iso_mms/server/mms_get_namelist_service.c index 0b1e3185..7e7e187b 100644 --- a/src/mms/iso_mms/server/mms_get_namelist_service.c +++ b/src/mms/iso_mms/server/mms_get_namelist_service.c @@ -486,6 +486,8 @@ mmsServer_handleGetNameListRequest( case 0x82: /* association-specific */ objectScope = OBJECT_SCOPE_ASSOCIATION; break; + case 0x00: /* indefinite length end tag -> ignore */ + break; default: mmsMsg_createMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_UNRECOGNIZED_MODIFIER, response); return; @@ -497,6 +499,10 @@ mmsServer_handleGetNameListRequest( continueAfter = (char*) (buffer + bufPos); continueAfterLength = length; break; + + case 0x00: /* indefinite length end tag -> ignore */ + break; + default: /* ignore unknown tag */ break; diff --git a/src/mms/iso_mms/server/mms_server_connection.c b/src/mms/iso_mms/server/mms_server_connection.c index 2db82867..4834bd38 100644 --- a/src/mms/iso_mms/server/mms_server_connection.c +++ b/src/mms/iso_mms/server/mms_server_connection.c @@ -387,6 +387,9 @@ handleConfirmedRequestPdu( break; #endif /* (MMS_GET_DATA_SET_ATTRIBUTES == 1) */ + case 0x00: /* indefinite length end tag -> ignore */ + break; + default: mmsMsg_createMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_UNRECOGNIZED_SERVICE, response); return; @@ -682,6 +685,9 @@ MmsServerConnection_parseMessage(MmsServerConnection self, ByteBuffer* message, printf("MMS_SERVER: received reject PDU!\n"); break; + case 0x00: /* indefinite length end tag -> ignore */ + break; + default: mmsMsg_createMmsRejectPdu(NULL, MMS_ERROR_REJECT_UNKNOWN_PDU_TYPE, response); break; diff --git a/src/mms/iso_presentation/iso_presentation.c b/src/mms/iso_presentation/iso_presentation.c index c29f1baf..6818e260 100644 --- a/src/mms/iso_presentation/iso_presentation.c +++ b/src/mms/iso_presentation/iso_presentation.c @@ -245,6 +245,10 @@ parseFullyEncodedData(IsoPresentation* self, uint8_t* buffer, int len, int bufPo bufPos += length; break; + + case 0x00: /* indefinite length end tag -> ignore */ + break; + default: if (DEBUG_PRES) printf("PRES: fed: unknown tag %02x\n", tag); @@ -289,6 +293,7 @@ parsePCDLEntry(IsoPresentation* self, uint8_t* buffer, int totalLength, int bufP contextId = BerDecoder_decodeUint32(buffer, len, bufPos); bufPos += len; break; + case 0x06: /* abstract-syntax-name */ if (DEBUG_PRES) printf("PRES: abstract-syntax-name with len %i\n", len); @@ -305,12 +310,17 @@ parsePCDLEntry(IsoPresentation* self, uint8_t* buffer, int totalLength, int bufP bufPos += len; break; + case 0x30: /* transfer-syntax-name */ if (DEBUG_PRES) printf("PRES: ignore transfer-syntax-name\n"); bufPos += len; break; + + case 0x00: /* indefinite length end tag -> ignore */ + break; + default: if (DEBUG_PRES) printf("PRES: unknown tag in presentation-context-definition-list-entry\n"); @@ -367,6 +377,8 @@ parsePresentationContextDefinitionList(IsoPresentation* self, uint8_t* buffer, i if (bufPos < 0) return -1; break; + case 0x00: /* indefinite length end tag -> ignore */ + break; default: if (DEBUG_PRES) printf("PRES: unknown tag in presentation-context-definition-list\n"); @@ -436,6 +448,7 @@ parseNormalModeParameters(IsoPresentation* self, uint8_t* buffer, int totalLengt printf("PRES: pcd list\n"); bufPos = parsePresentationContextDefinitionList(self, buffer, len, bufPos); break; + case 0x61: /* user data */ if (DEBUG_PRES) printf("PRES: user-data\n"); @@ -447,6 +460,9 @@ parseNormalModeParameters(IsoPresentation* self, uint8_t* buffer, int totalLengt break; + case 0x00: /* indefinite length end tag -> ignore */ + break; + default: if (DEBUG_PRES) printf("PRES: unknown tag in normal-mode\n"); @@ -508,6 +524,8 @@ IsoPresentation_parseAcceptMessage(IsoPresentation* self, ByteBuffer* byteBuffer return 0; } + break; + case 0x00: /* indefinite length end tag -> ignore */ break; default: if (DEBUG_PRES) @@ -634,6 +652,8 @@ IsoPresentation_parseUserData(IsoPresentation* self, ByteBuffer* readBuffer) int userDataLength; + uint8_t lengthByte = buffer[bufPos]; + bufPos = BerDecoder_decodeLength(buffer, &userDataLength, bufPos, length); if (bufPos < 0) { @@ -642,6 +662,11 @@ IsoPresentation_parseUserData(IsoPresentation* self, ByteBuffer* readBuffer) return 0; } + if (lengthByte == 0x80) { + /* remove end element from user data length when indefinite length encoded */ + userDataLength = userDataLength - 2; + } + ByteBuffer_wrap(&(self->nextPayload), buffer + bufPos, userDataLength, userDataLength); return 1; @@ -721,6 +746,8 @@ IsoPresentation_parseConnect(IsoPresentation* self, ByteBuffer* byteBuffer) return 0; } + break; + case 0x00: /* indefinite length end tag -> ignore */ break; default: /* unsupported element */ if (DEBUG_PRES)