From f98c1a956dfc02a2ed3c4f97e1e3efb404256f49 Mon Sep 17 00:00:00 2001 From: Michael Zillgith Date: Fri, 28 Jan 2022 19:30:14 +0100 Subject: [PATCH] - handle presentation layer data messages with transfer-syntax-name --- src/mms/iso_presentation/iso_presentation.c | 99 +++++++++++++++------ 1 file changed, 73 insertions(+), 26 deletions(-) diff --git a/src/mms/iso_presentation/iso_presentation.c b/src/mms/iso_presentation/iso_presentation.c index c48c4a87..96fd8a37 100644 --- a/src/mms/iso_presentation/iso_presentation.c +++ b/src/mms/iso_presentation/iso_presentation.c @@ -1,7 +1,7 @@ /* * iso_presentation.c * - * Copyright 2013-2019 Michael Zillgith + * Copyright 2013-2022 Michael Zillgith * * This file is part of libIEC61850. * @@ -234,6 +234,10 @@ parseFullyEncodedData(IsoPresentation* self, uint8_t* buffer, int len, int bufPo } break; + case 0x06: /* transfer-syntax-name */ + bufPos += length; + break; + case 0xa0: if (DEBUG_PRES) printf("PRES: fully-encoded-data\n"); @@ -451,12 +455,27 @@ parseNormalModeParameters(IsoPresentation* self, uint8_t* buffer, int totalLengt bufPos += len; break; + case 0x83: /* responding-presentation-selector */ + + if (len > 16) { + if (DEBUG_PRES) + printf("PRES: responding-presentation-sel too large\n"); + } + + bufPos += len; + break; + case 0xa4: /* presentation-context-definition list */ if (DEBUG_PRES) printf("PRES: pcd list\n"); bufPos = parsePresentationContextDefinitionList(self, buffer, len, bufPos); break; + case 0xa5: /* context-definition-result-list */ + + bufPos += len; + break; + case 0x61: /* user data */ if (DEBUG_PRES) printf("PRES: user-data\n"); @@ -625,12 +644,13 @@ IsoPresentation_createUserDataACSE(IsoPresentation* self, BufferChain writeBuffe int IsoPresentation_parseUserData(IsoPresentation* self, ByteBuffer* readBuffer) { - int length = readBuffer->size; uint8_t* buffer = readBuffer->buffer; + int maxBufPos = readBuffer->size; + bool hasAbstractSyntaxName = false; int bufPos = 0; - if (length < 9) + if (maxBufPos < 9) return 0; if (buffer[bufPos++] != 0x61) @@ -638,7 +658,7 @@ IsoPresentation_parseUserData(IsoPresentation* self, ByteBuffer* readBuffer) int len; - bufPos = BerDecoder_decodeLength(buffer, &len, bufPos, length); + bufPos = BerDecoder_decodeLength(buffer, &len, bufPos, maxBufPos); if (bufPos < 0) { if (DEBUG_PRES) @@ -649,7 +669,7 @@ IsoPresentation_parseUserData(IsoPresentation* self, ByteBuffer* readBuffer) if (buffer[bufPos++] != 0x30) return 0; - bufPos = BerDecoder_decodeLength(buffer, &len, bufPos, length); + bufPos = BerDecoder_decodeLength(buffer, &len, bufPos, maxBufPos); if (bufPos < 0) { if (DEBUG_PRES) @@ -657,37 +677,64 @@ IsoPresentation_parseUserData(IsoPresentation* self, ByteBuffer* readBuffer) return 0; } - if (buffer[bufPos++] != 0x02) - return 0; + while (bufPos < maxBufPos) { + uint8_t tag = buffer[bufPos++]; + uint8_t lenField = buffer[bufPos]; - if (buffer[bufPos++] != 0x01) - return 0; + bufPos = BerDecoder_decodeLength(buffer, &len, bufPos, maxBufPos); - self->nextContextId = buffer[bufPos++]; + if (bufPos < 0) { + if (DEBUG_PRES) + printf("PRES: wrong parameter length\n"); + return 0; + } - if (buffer[bufPos++] != 0xa0) - return 0; + switch (tag) { + case 0x02: /* abstract-syntax-name */ + self->nextContextId = buffer[bufPos]; + hasAbstractSyntaxName = true; + bufPos += len; + break; - int userDataLength; + case 0x06: /* transfer-syntax-name */ + { + /* check if basic-encoding (2.1.1 - 51 01) */ + if ((buffer[bufPos] != 0x51) || (buffer[bufPos + 1] != 0x01)) { + if (DEBUG_PRES) { + printf("PRES: unknown transfer-syntax-name\n"); + } - uint8_t lengthByte = buffer[bufPos]; + return 0; + } - bufPos = BerDecoder_decodeLength(buffer, &userDataLength, bufPos, length); + bufPos += len; + } + break; - if (bufPos < 0) { - if (DEBUG_PRES) - printf("PRES: invalid message!\n"); - return 0; - } - if (lengthByte == 0x80) { - /* remove end element from user data length when indefinite length encoded */ - userDataLength = userDataLength - 2; - } + case 0xa0: /* presentation data */ + { + if (hasAbstractSyntaxName == false) { + if (DEBUG_PRES) + printf("PRES: abstract-syntax-name missing!\n"); - ByteBuffer_wrap(&(self->nextPayload), buffer + bufPos, userDataLength, userDataLength); + return 0; + } - return 1; + int userDataLength = len; + + if (lenField == 0x80) + userDataLength = userDataLength - 2; + + ByteBuffer_wrap(&(self->nextPayload), buffer + bufPos, userDataLength, userDataLength); + + return 1; + } + break; + } + } + + return 0; } int