diff options
Diffstat (limited to 'linden/indra/llmessage/llxfermanager.cpp')
-rw-r--r-- | linden/indra/llmessage/llxfermanager.cpp | 119 |
1 files changed, 112 insertions, 7 deletions
diff --git a/linden/indra/llmessage/llxfermanager.cpp b/linden/indra/llmessage/llxfermanager.cpp index f40612c..8173b7c 100644 --- a/linden/indra/llmessage/llxfermanager.cpp +++ b/linden/indra/llmessage/llxfermanager.cpp | |||
@@ -713,6 +713,78 @@ void LLXferManager::sendConfirmPacket (LLMessageSystem *mesgsys, U64 id, S32 pac | |||
713 | 713 | ||
714 | /////////////////////////////////////////////////////////// | 714 | /////////////////////////////////////////////////////////// |
715 | 715 | ||
716 | static bool find_and_remove(std::multiset<std::string>& files, | ||
717 | const std::string& filename) | ||
718 | { | ||
719 | std::multiset<std::string>::iterator ptr; | ||
720 | if ( (ptr = files.find(filename)) != files.end()) | ||
721 | { | ||
722 | //erase(filename) erases *all* entries with that key | ||
723 | files.erase(ptr); | ||
724 | return true; | ||
725 | } | ||
726 | return false; | ||
727 | } | ||
728 | |||
729 | void LLXferManager::expectFileForRequest(const std::string& filename) | ||
730 | { | ||
731 | mExpectedRequests.insert(filename); | ||
732 | } | ||
733 | |||
734 | bool LLXferManager::validateFileForRequest(const std::string& filename) | ||
735 | { | ||
736 | return find_and_remove(mExpectedRequests, filename); | ||
737 | } | ||
738 | |||
739 | void LLXferManager::expectFileForTransfer(const std::string& filename) | ||
740 | { | ||
741 | mExpectedTransfers.insert(filename); | ||
742 | } | ||
743 | |||
744 | bool LLXferManager::validateFileForTransfer(const std::string& filename) | ||
745 | { | ||
746 | return find_and_remove(mExpectedTransfers, filename); | ||
747 | } | ||
748 | |||
749 | static bool remove_prefix(std::string& filename, const std::string& prefix) | ||
750 | { | ||
751 | if (std::equal(prefix.begin(), prefix.end(), filename.begin())) | ||
752 | { | ||
753 | filename = filename.substr(prefix.length()); | ||
754 | return true; | ||
755 | } | ||
756 | return false; | ||
757 | } | ||
758 | |||
759 | static bool verify_cache_filename(const std::string& filename) | ||
760 | { | ||
761 | //NOTE: This routine is only used to check file names that our own | ||
762 | // code places in the cache directory. As such, it can be limited | ||
763 | // to this very restrictive file name pattern. It does not need to | ||
764 | // handle other characters. | ||
765 | |||
766 | size_t len = filename.size(); | ||
767 | //const boost::regex expr("[a-zA-Z0-9][-_.a-zA-Z0-9]<0,49>"); | ||
768 | if (len < 1 || len > 50) | ||
769 | { | ||
770 | return false; | ||
771 | } | ||
772 | for(unsigned i=0; i<len; ++i) | ||
773 | { | ||
774 | char c = filename[i]; | ||
775 | bool ok = isalnum(c); | ||
776 | if (!ok && i > 0) | ||
777 | { | ||
778 | ok = '_'==c || '-'==c || '.'==c; | ||
779 | } | ||
780 | if (!ok) | ||
781 | { | ||
782 | return false; | ||
783 | } | ||
784 | } | ||
785 | return true; | ||
786 | } | ||
787 | |||
716 | void LLXferManager::processFileRequest (LLMessageSystem *mesgsys, void ** /*user_data*/) | 788 | void LLXferManager::processFileRequest (LLMessageSystem *mesgsys, void ** /*user_data*/) |
717 | { | 789 | { |
718 | 790 | ||
@@ -734,16 +806,11 @@ void LLXferManager::processFileRequest (LLMessageSystem *mesgsys, void ** /*user | |||
734 | 806 | ||
735 | mesgsys->getStringFast(_PREHASH_XferID, _PREHASH_Filename, local_filename); | 807 | mesgsys->getStringFast(_PREHASH_XferID, _PREHASH_Filename, local_filename); |
736 | 808 | ||
737 | U8 local_path_u8; | ||
738 | mesgsys->getU8("XferID", "FilePath", local_path_u8); | ||
739 | if( local_path_u8 < (U8)LL_PATH_LAST ) | ||
740 | { | 809 | { |
810 | U8 local_path_u8; | ||
811 | mesgsys->getU8("XferID", "FilePath", local_path_u8); | ||
741 | local_path = (ELLPath)local_path_u8; | 812 | local_path = (ELLPath)local_path_u8; |
742 | } | 813 | } |
743 | else | ||
744 | { | ||
745 | llwarns << "Invalid file path in LLXferManager::processFileRequest() " << (U32)local_path_u8 << llendl; | ||
746 | } | ||
747 | 814 | ||
748 | mesgsys->getUUIDFast(_PREHASH_XferID, _PREHASH_VFileID, uuid); | 815 | mesgsys->getUUIDFast(_PREHASH_XferID, _PREHASH_VFileID, uuid); |
749 | mesgsys->getS16Fast(_PREHASH_XferID, _PREHASH_VFileType, type_s16); | 816 | mesgsys->getS16Fast(_PREHASH_XferID, _PREHASH_VFileType, type_s16); |
@@ -782,6 +849,43 @@ void LLXferManager::processFileRequest (LLMessageSystem *mesgsys, void ** /*user | |||
782 | } | 849 | } |
783 | else if (!local_filename.empty()) | 850 | else if (!local_filename.empty()) |
784 | { | 851 | { |
852 | // See DEV-21775 for detailed security issues | ||
853 | |||
854 | if (local_path == LL_PATH_NONE) | ||
855 | { | ||
856 | // this handles legacy simulators that are passing objects | ||
857 | // by giving a filename that explicitly names the cache directory | ||
858 | static const std::string legacy_cache_prefix = "data/"; | ||
859 | if (remove_prefix(local_filename, legacy_cache_prefix)) | ||
860 | { | ||
861 | local_path = LL_PATH_CACHE; | ||
862 | } | ||
863 | } | ||
864 | |||
865 | switch (local_path) | ||
866 | { | ||
867 | case LL_PATH_NONE: | ||
868 | if(!validateFileForTransfer(local_filename)) | ||
869 | { | ||
870 | llwarns << "SECURITY: Unapproved filename '" << local_filename << llendl; | ||
871 | return; | ||
872 | } | ||
873 | break; | ||
874 | |||
875 | case LL_PATH_CACHE: | ||
876 | if(!verify_cache_filename(local_filename)) | ||
877 | { | ||
878 | llwarns << "SECURITY: Illegal cache filename '" << local_filename << llendl; | ||
879 | return; | ||
880 | } | ||
881 | break; | ||
882 | |||
883 | default: | ||
884 | llwarns << "SECURITY: Restricted file dir enum: " << (U32)local_path << llendl; | ||
885 | return; | ||
886 | } | ||
887 | |||
888 | |||
785 | std::string expanded_filename = gDirUtilp->getExpandedFilename( local_path, local_filename ); | 889 | std::string expanded_filename = gDirUtilp->getExpandedFilename( local_path, local_filename ); |
786 | llinfos << "starting file transfer: " << expanded_filename << " to " << mesgsys->getSender() << llendl; | 890 | llinfos << "starting file transfer: " << expanded_filename << " to " << mesgsys->getSender() << llendl; |
787 | 891 | ||
@@ -861,6 +965,7 @@ void LLXferManager::processFileRequest (LLMessageSystem *mesgsys, void ** /*user | |||
861 | } | 965 | } |
862 | } | 966 | } |
863 | 967 | ||
968 | |||
864 | /////////////////////////////////////////////////////////// | 969 | /////////////////////////////////////////////////////////// |
865 | 970 | ||
866 | void LLXferManager::processConfirmation (LLMessageSystem *mesgsys, void ** /*user_data*/) | 971 | void LLXferManager::processConfirmation (LLMessageSystem *mesgsys, void ** /*user_data*/) |