diff --git a/hal/filesystem/linux/file_provider_linux.c b/hal/filesystem/linux/file_provider_linux.c index dc869d96..7b501f00 100644 --- a/hal/filesystem/linux/file_provider_linux.c +++ b/hal/filesystem/linux/file_provider_linux.c @@ -37,7 +37,6 @@ struct sDirectoryHandle { DIR* handle; }; - FileHandle FileSystem_openFile(char* fileName, bool readWrite) { diff --git a/src/mms/inc_private/mms_common_internal.h b/src/mms/inc_private/mms_common_internal.h index 6ce05aeb..f096e7bc 100644 --- a/src/mms/inc_private/mms_common_internal.h +++ b/src/mms/inc_private/mms_common_internal.h @@ -82,6 +82,9 @@ mmsMsg_createExtendedFilename(const char* basepath, int bufSize, char* extendedF LIB61850_INTERNAL FileHandle mmsMsg_openFile(const char* basepath, char* fileName, bool readWrite); +LIB61850_INTERNAL bool +mmsMsg_isFilenameSave(const char* filename); + #endif /* (MMS_FILE_SERVICE == 1) */ typedef struct sMmsServiceError diff --git a/src/mms/iso_mms/client/mms_client_files.c b/src/mms/iso_mms/client/mms_client_files.c index eda9bb1f..4fca418e 100644 --- a/src/mms/iso_mms/client/mms_client_files.c +++ b/src/mms/iso_mms/client/mms_client_files.c @@ -71,7 +71,6 @@ getFrsm(MmsConnection connection, int32_t frsmId) return frsm; } - static int32_t getNextFrsmId(MmsConnection connection) { @@ -125,38 +124,48 @@ mmsClient_handleFileOpenRequest( if (hasFileName) { - MmsFileReadStateMachine* frsm = getFreeFrsm(connection); + if (mmsMsg_isFilenameSave(filename) == false) { + /* potential attack */ - if (frsm != NULL) { + if (DEBUG_MMS_CLIENT) + printf("MMS_CLIENT: client provided unsave filename -> rejected\n"); - MmsOutstandingCall obtainFileCall = mmsClient_getMatchingObtainFileRequest(connection, filename); + mmsMsg_createServiceErrorPdu(invokeId, response, MMS_ERROR_FILE_FILE_NON_EXISTENT); + } + else { + MmsFileReadStateMachine* frsm = getFreeFrsm(connection); - if (obtainFileCall) { + if (frsm != NULL) { - if (DEBUG_MMS_CLIENT) - printf("MMS_CLIENT: file open is matching obtain file request for file %s\n", filename); + MmsOutstandingCall obtainFileCall = mmsClient_getMatchingObtainFileRequest(connection, filename); - obtainFileCall->timeout = Hal_getTimeInMs() + connection->requestTimeout; - } + if (obtainFileCall) { - FileHandle fileHandle = mmsMsg_openFile(MmsConnection_getFilestoreBasepath(connection), filename, false); + if (DEBUG_MMS_CLIENT) + printf("MMS_CLIENT: file open is matching obtain file request for file %s\n", filename); - if (fileHandle != NULL) { + obtainFileCall->timeout = Hal_getTimeInMs() + connection->requestTimeout; + } - frsm->fileHandle = fileHandle; - frsm->readPosition = filePosition; - frsm->frsmId = getNextFrsmId(connection); - frsm->obtainRequest = obtainFileCall; + FileHandle fileHandle = mmsMsg_openFile(MmsConnection_getFilestoreBasepath(connection), filename, false); + + if (fileHandle != NULL) { + + frsm->fileHandle = fileHandle; + frsm->readPosition = filePosition; + frsm->frsmId = getNextFrsmId(connection); + frsm->obtainRequest = obtainFileCall; + + mmsMsg_createFileOpenResponse(MmsConnection_getFilestoreBasepath(connection), + invokeId, response, filename, frsm); + } + else + mmsMsg_createServiceErrorPdu(invokeId, response, MMS_ERROR_FILE_FILE_NON_EXISTENT); - mmsMsg_createFileOpenResponse(MmsConnection_getFilestoreBasepath(connection), - invokeId, response, filename, frsm); } else - mmsMsg_createServiceErrorPdu(invokeId, response, MMS_ERROR_FILE_FILE_NON_EXISTENT); - + mmsMsg_createServiceErrorPdu(invokeId, response, MMS_ERROR_RESOURCE_OTHER); } - else - mmsMsg_createServiceErrorPdu(invokeId, response, MMS_ERROR_RESOURCE_OTHER); } else goto exit_invalid_parameter; diff --git a/src/mms/iso_mms/common/mms_common_msg.c b/src/mms/iso_mms/common/mms_common_msg.c index 7555f0c0..76657334 100644 --- a/src/mms/iso_mms/common/mms_common_msg.c +++ b/src/mms/iso_mms/common/mms_common_msg.c @@ -570,6 +570,24 @@ mmsMsg_createExtendedFilename(const char* basepath, int bufSize, char* extendedF #endif } +bool +mmsMsg_isFilenameSave(const char* filename) +{ + if (filename) + { + if (strstr(filename, "..")) + return false; + + if (strstr(filename, "./")) + return false; + + return true; + } + else { + return false; + } +} + FileHandle mmsMsg_openFile(const char* basepath, char* fileName, bool readWrite) { @@ -620,7 +638,7 @@ mmsMsg_parseFileName(char* filename, uint8_t* buffer, int* bufPos, int maxBufPos * characters. */ if (strstr(filename, "..") != NULL) { - mmsMsg_createServiceErrorPdu(invokeId, response, MMS_ERROR_FILE_FILENAME_SYNTAX_ERROR); + mmsMsg_createServiceErrorPdu(invokeId, response, MMS_ERROR_FILE_FILE_NON_EXISTENT); return false; } diff --git a/src/mms/iso_mms/server/mms_file_service.c b/src/mms/iso_mms/server/mms_file_service.c index 2a0b18ad..e4ae154b 100644 --- a/src/mms/iso_mms/server/mms_file_service.c +++ b/src/mms/iso_mms/server/mms_file_service.c @@ -235,8 +235,6 @@ mmsMsg_createFileOpenResponse(const char* basepath, uint32_t invokeId, ByteBuffe response->size = bufPos; } - - void mmsServer_handleFileDeleteRequest( MmsServerConnection connection, @@ -266,6 +264,16 @@ mmsServer_handleFileDeleteRequest( if (DEBUG_MMS_SERVER) printf("MMS_SERVER: mms_file_service.c: Delete file (%s)\n", filename); + if (mmsMsg_isFilenameSave(filename) == false) + { + if (DEBUG_MMS_SERVER) + printf("MMS_SERVER: remote provided unsave filename -> rejected\n"); + + mmsMsg_createServiceErrorPdu(invokeId, response, MMS_ERROR_FILE_FILE_NON_EXISTENT); + + return; + } + if (connection->server->fileAccessHandler != NULL) { MmsError access = connection->server->fileAccessHandler(connection->server->fileAccessHandlerParameter, connection, MMS_FILE_ACCESS_TYPE_DELETE, filename, NULL); @@ -344,6 +352,17 @@ mmsServer_handleFileOpenRequest( if (hasFileName) { + if (mmsMsg_isFilenameSave(filename) == false) { + /* potential attack */ + + if (DEBUG_MMS_CLIENT) + printf("MMS_SERVER: remote provided unsave filename -> rejected\n"); + + mmsMsg_createServiceErrorPdu(invokeId, response, MMS_ERROR_FILE_FILE_NON_EXISTENT); + + return; + } + if (connection->server->fileAccessHandler != NULL) { MmsError access = connection->server->fileAccessHandler(connection->server->fileAccessHandlerParameter, connection, MMS_FILE_ACCESS_TYPE_OPEN, filename, NULL); @@ -690,6 +709,15 @@ mmsServer_handleObtainFileRequest( if (hasSourceFileName && hasDestinationFilename) { + if (mmsMsg_isFilenameSave(destinationFilename) == false) { + /* potential attack */ + + if (DEBUG_MMS_SERVER) + printf("MMS_SERVER: remote provided unsave filename -> rejected\n"); + + goto exit_invalid_parameter; + } + /* Call user to check if access is allowed */ if (connection->server->fileAccessHandler != NULL) { MmsError access = connection->server->fileAccessHandler(connection->server->fileAccessHandlerParameter, @@ -1023,6 +1051,17 @@ createFileDirectoryResponse(const char* basepath, uint32_t invokeId, ByteBuffer* continueAfterFileName = NULL; } + if ((directoryName && mmsMsg_isFilenameSave(directoryName) == false) || + (continueAfterFileName && mmsMsg_isFilenameSave(continueAfterFileName) == false)) + { + if (DEBUG_MMS_SERVER) + printf("MMS_SERVER: remote provided unsave filename -> rejected\n"); + + mmsMsg_createServiceErrorPdu(invokeId, response, MMS_ERROR_FILE_FILE_NON_EXISTENT); + + return; + } + tempCurPos = addFileEntriesToResponse(basepath, buffer, tempCurPos, maxSize, directoryName, &continueAfterFileName, &moreFollows); if (tempCurPos < 0) { @@ -1128,6 +1167,16 @@ mmsServer_handleFileRenameRequest( if ((strlen(currentFileName) != 0) && (strlen(newFileName) != 0)) { + if ((mmsMsg_isFilenameSave(currentFileName) == false) || (mmsMsg_isFilenameSave(newFileName) == false)) + { + if (DEBUG_MMS_SERVER) + printf("MMS_SERVER: remote provided unsave filename -> rejected\n"); + + mmsMsg_createServiceErrorPdu(invokeId, response, MMS_ERROR_FILE_FILE_NON_EXISTENT); + + return; + } + /* Call user to check if access is allowed */ if (connection->server->fileAccessHandler != NULL) { MmsError access = connection->server->fileAccessHandler(connection->server->fileAccessHandlerParameter,