From a008275f37553a8cf6fd72ec817a613f42c74bc6 Mon Sep 17 00:00:00 2001 From: Michael Zillgith Date: Wed, 27 Sep 2017 23:32:23 +0200 Subject: [PATCH] - MMS client: parse reject PDU - MMS: improved BER decoder stability --- src/mms/asn1/ber_decode.c | 6 + src/mms/inc_private/mms_common_internal.h | 2 + .../iso_mms/client/mms_client_connection.c | 116 ++++++++++++++++-- .../iso_mms/server/mms_server_connection.c | 9 +- 4 files changed, 124 insertions(+), 9 deletions(-) diff --git a/src/mms/asn1/ber_decode.c b/src/mms/asn1/ber_decode.c index 4acc260..3818899 100644 --- a/src/mms/asn1/ber_decode.c +++ b/src/mms/asn1/ber_decode.c @@ -56,6 +56,12 @@ BerDecoder_decodeLength(uint8_t* buffer, int* length, int bufPos, int maxBufPos) *length = len1; } + if (*length < 0) + return -1; + + if (bufPos + (*length) > maxBufPos) + return -1; + return bufPos; } diff --git a/src/mms/inc_private/mms_common_internal.h b/src/mms/inc_private/mms_common_internal.h index e987fd1..6bb2848 100644 --- a/src/mms/inc_private/mms_common_internal.h +++ b/src/mms/inc_private/mms_common_internal.h @@ -90,6 +90,8 @@ mmsMsg_createMmsRejectPdu(uint32_t* invokeId, int reason, ByteBuffer* response); int mmsMsg_parseConfirmedErrorPDU(uint8_t* buffer, int bufPos, int maxBufPos, uint32_t* invokeId, MmsServiceError* serviceError); +int +mmsMsg_parseRejectPDU(uint8_t* buffer, int bufPos, int maxBufPos, uint32_t* invokeId, int* rejectType, int* rejectReason); MmsValue* mmsMsg_parseDataElement(Data_t* dataElement); diff --git a/src/mms/iso_mms/client/mms_client_connection.c b/src/mms/iso_mms/client/mms_client_connection.c index 041748a..7111b65 100644 --- a/src/mms/iso_mms/client/mms_client_connection.c +++ b/src/mms/iso_mms/client/mms_client_connection.c @@ -389,6 +389,21 @@ waitUntilLastResponseHasBeenProcessed(MmsConnection self) } } +static MmsError +convertRejectCodesToMmsError(int rejectType, int rejectReason) +{ + if ((rejectType == 1) && (rejectReason == 1)) + return MMS_ERROR_REJECT_UNRECOGNIZED_SERVICE; + else if ((rejectType == 5) && (rejectReason == 0)) + return MMS_ERROR_REJECT_UNKNOWN_PDU_TYPE; + else if ((rejectType == 1) && (rejectReason == 4)) + return MMS_ERROR_REJECT_REQUEST_INVALID_ARGUMENT; + else if ((rejectType == 5) && (rejectReason == 1)) + return MMS_ERROR_REJECT_INVALID_PDU; + else + return MMS_ERROR_REJECT_OTHER; +} + static MmsError convertServiceErrorToMmsError(MmsServiceError serviceError) { @@ -569,11 +584,8 @@ mmsMsg_parseConfirmedErrorPDU(uint8_t* buffer, int bufPos, int maxBufPos, uint32 int endPos = bufPos + length; - if (endPos > maxBufPos) { - if (DEBUG_MMS_CLIENT) - printf("parseConfirmedErrorPDU: message to short!\n"); + if (endPos > maxBufPos) goto exit_error; - } while (bufPos < endPos) { tag = buffer[bufPos++]; @@ -605,6 +617,63 @@ mmsMsg_parseConfirmedErrorPDU(uint8_t* buffer, int bufPos, int maxBufPos, uint32 return bufPos; exit_error: + if (DEBUG_MMS_CLIENT) + printf("MMS_CLIENT: error parsing confirmed error PDU\n"); + + return -1; +} + +int +mmsMsg_parseRejectPDU(uint8_t* buffer, int bufPos, int maxBufPos, uint32_t* invokeId, int* rejectType, int* rejectReason) +{ + int length; + + uint8_t tag = buffer[bufPos++]; + + if (tag != 0xa4) + goto exit_error; + + bufPos = BerDecoder_decodeLength(buffer, &length, bufPos, maxBufPos); + if (bufPos < 0) + goto exit_error; + + if (bufPos + length > maxBufPos) + goto exit_error; + + int endPos = bufPos + length; + + if (endPos > maxBufPos) + goto exit_error; + + while (bufPos < endPos) { + tag = buffer[bufPos++]; + bufPos = BerDecoder_decodeLength(buffer, &length, bufPos, maxBufPos); + + if (bufPos < 0) + goto exit_error; + + + if (tag == 0x80) { /* invoke id */ + if (invokeId != NULL) + *invokeId = BerDecoder_decodeUint32(buffer, length, bufPos); + } + else if (tag > 0x80 && tag < 0x8c) { + *rejectType = tag - 0x80; + *rejectReason = BerDecoder_decodeInt32(buffer, length, bufPos); + } + else { + /* unknown - ignore */ + } + + bufPos += length; + } + + return bufPos; + +exit_error: + if (DEBUG_MMS_CLIENT) + printf("MMS_CLIENT: error parsing reject PDU\n"); + return -1; } @@ -710,6 +779,8 @@ mmsIsoCallback(IsoIndication indication, void* parameter, ByteBuffer* payload) if (mmsMsg_parseConfirmedErrorPDU(payload->buffer, 0, payload->size, &invokeId, &serviceError) < 0) { if (DEBUG_MMS_CLIENT) printf("MMS_CLIENT: Error parsing confirmedErrorPDU!\n"); + + goto exit_with_error; } else { if (checkForOutstandingCall(self, invokeId)) { @@ -730,6 +801,37 @@ mmsIsoCallback(IsoIndication indication, void* parameter, ByteBuffer* payload) } } } + else if (tag == 0xa4) { /* reject PDU */ + if (DEBUG_MMS_CLIENT) + printf("MMS_CLIENT: reject PDU!\n"); + + uint32_t invokeId; + int rejectType; + int rejectReason; + + if (mmsMsg_parseRejectPDU(payload->buffer, 0, payload->size, &invokeId, &rejectType, &rejectReason) >= 0) { + + if (DEBUG_MMS_CLIENT) + printf("MMS_CLIENT: reject PDU invokeID: %i type: %i reason: %i\n", (int) invokeId, rejectType, rejectReason); + + if (checkForOutstandingCall(self, invokeId)) { + + /* wait for application thread to handle last received response */ + waitUntilLastResponseHasBeenProcessed(self); + + Semaphore_wait(self->lastResponseLock); + self->lastResponseError = convertRejectCodesToMmsError(rejectType, rejectReason); + self->responseInvokeId = invokeId; + Semaphore_post(self->lastResponseLock); + } + else { + IsoClientConnection_releaseReceiveBuffer(self->isoClient); + return; + } + } + else + goto exit_with_error; + } else if (tag == 0xa1) { /* confirmed response PDU */ int length; @@ -897,16 +999,16 @@ mmsIsoCallback(IsoIndication indication, void* parameter, ByteBuffer* payload) return; - exit_with_error: +exit_with_error: if (DEBUG_MMS_CLIENT) - printf("received malformed message from server!\n"); + printf("MMS_CLIENT: received malformed message from server!\n"); IsoClientConnection_releaseReceiveBuffer(self->isoClient); if (DEBUG_MMS_CLIENT) - printf("LEAVE mmsIsoCallback - NOT OK!\n"); + printf("MMS_CLIENT: LEAVE mmsIsoCallback - NOT OK!\n"); return; } diff --git a/src/mms/iso_mms/server/mms_server_connection.c b/src/mms/iso_mms/server/mms_server_connection.c index 6764457..c80b068 100644 --- a/src/mms/iso_mms/server/mms_server_connection.c +++ b/src/mms/iso_mms/server/mms_server_connection.c @@ -156,9 +156,14 @@ handleConfirmedRequestPdu( bufPos = BerDecoder_decodeLength(buffer, &length, bufPos, maxBufPos); if (bufPos < 0) { - mmsMsg_createMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_UNRECOGNIZED_SERVICE, response); + mmsMsg_createMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_INVALID_PDU, response); return; - } + } + + if (bufPos + length > maxBufPos) { + mmsMsg_createMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_INVALID_PDU, response); + return; + } if (extendedTag) { switch(tag) {