aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/llmessage
diff options
context:
space:
mode:
authorJacek Antonelli2008-10-08 00:59:21 -0500
committerJacek Antonelli2008-10-08 00:59:26 -0500
commitf6276d08ec2d6a7ce1ac568c77771162bd8cece5 (patch)
treebf90071e73ded161624c5c1cd77fc1a57a79de4d /linden/indra/llmessage
parentSecond Life viewer sources 1.21.4-RC (diff)
downloadmeta-impy-f6276d08ec2d6a7ce1ac568c77771162bd8cece5.zip
meta-impy-f6276d08ec2d6a7ce1ac568c77771162bd8cece5.tar.gz
meta-impy-f6276d08ec2d6a7ce1ac568c77771162bd8cece5.tar.bz2
meta-impy-f6276d08ec2d6a7ce1ac568c77771162bd8cece5.tar.xz
Second Life viewer sources 1.21.5-RC
Diffstat (limited to 'linden/indra/llmessage')
-rw-r--r--linden/indra/llmessage/llurlrequest.cpp42
-rw-r--r--linden/indra/llmessage/llxfermanager.cpp119
-rw-r--r--linden/indra/llmessage/llxfermanager.h16
3 files changed, 150 insertions, 27 deletions
diff --git a/linden/indra/llmessage/llurlrequest.cpp b/linden/indra/llmessage/llurlrequest.cpp
index fbd002b..ee62798 100644
--- a/linden/indra/llmessage/llurlrequest.cpp
+++ b/linden/indra/llmessage/llurlrequest.cpp
@@ -484,27 +484,29 @@ static size_t headerCallback(void* data, size_t size, size_t nmemb, void* user)
484 // Per HTTP spec the first header line must be the status line. 484 // Per HTTP spec the first header line must be the status line.
485 if (!complete->haveHTTPStatus()) 485 if (!complete->haveHTTPStatus())
486 { 486 {
487 std::string::iterator end = header.end(); 487 if (header.substr(0,5) == "HTTP/")
488 std::string::iterator pos1 = std::find(header.begin(), end, ' ');
489 if (pos1 != end) ++pos1;
490 std::string::iterator pos2 = std::find(pos1, end, ' ');
491 if (pos2 != end) ++pos2;
492 std::string::iterator pos3 = std::find(pos2, end, '\r');
493
494 std::string version(header.begin(), pos1);
495 std::string status(pos1, pos2);
496 std::string reason(pos2, pos3);
497
498 int statusCode = atoi(status.c_str());
499 if (statusCode > 0)
500 { 488 {
501 complete->httpStatus((U32)statusCode, reason); 489 std::string::iterator end = header.end();
502 } 490 std::string::iterator pos1 = std::find(header.begin(), end, ' ');
503 else 491 if (pos1 != end) ++pos1;
504 { 492 std::string::iterator pos2 = std::find(pos1, end, ' ');
505 llwarns << "Unable to parse http response status line: " 493 if (pos2 != end) ++pos2;
506 << header << llendl; 494 std::string::iterator pos3 = std::find(pos2, end, '\r');
507 complete->httpStatus(499,"Unable to parse status line."); 495
496 std::string version(header.begin(), pos1);
497 std::string status(pos1, pos2);
498 std::string reason(pos2, pos3);
499
500 int statusCode = atoi(status.c_str());
501 if (statusCode >= 300 && statusCode < 400)
502 {
503 // This is a redirect, ignore it and all headers
504 // until we find a normal status code.
505 }
506 else if (statusCode > 0)
507 {
508 complete->httpStatus((U32)statusCode, reason);
509 }
508 } 510 }
509 return header_len; 511 return header_len;
510 } 512 }
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
716static 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
729void LLXferManager::expectFileForRequest(const std::string& filename)
730{
731 mExpectedRequests.insert(filename);
732}
733
734bool LLXferManager::validateFileForRequest(const std::string& filename)
735{
736 return find_and_remove(mExpectedRequests, filename);
737}
738
739void LLXferManager::expectFileForTransfer(const std::string& filename)
740{
741 mExpectedTransfers.insert(filename);
742}
743
744bool LLXferManager::validateFileForTransfer(const std::string& filename)
745{
746 return find_and_remove(mExpectedTransfers, filename);
747}
748
749static 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
759static 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
716void LLXferManager::processFileRequest (LLMessageSystem *mesgsys, void ** /*user_data*/) 788void 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
866void LLXferManager::processConfirmation (LLMessageSystem *mesgsys, void ** /*user_data*/) 971void LLXferManager::processConfirmation (LLMessageSystem *mesgsys, void ** /*user_data*/)
diff --git a/linden/indra/llmessage/llxfermanager.h b/linden/indra/llmessage/llxfermanager.h
index 77f3f60..4bcf5de 100644
--- a/linden/indra/llmessage/llxfermanager.h
+++ b/linden/indra/llmessage/llxfermanager.h
@@ -108,6 +108,8 @@ class LLXferManager
108 // implementation methods 108 // implementation methods
109 virtual void startPendingDownloads(); 109 virtual void startPendingDownloads();
110 virtual void addToList(LLXfer* xferp, LLXfer*& head, BOOL is_priority); 110 virtual void addToList(LLXfer* xferp, LLXfer*& head, BOOL is_priority);
111 std::multiset<std::string> mExpectedTransfers; // files that are authorized to transfer out
112 std::multiset<std::string> mExpectedRequests; // files that are authorized to be downloaded on top of
111 113
112 public: 114 public:
113 LLXferManager(LLVFS *vfs); 115 LLXferManager(LLVFS *vfs);
@@ -168,6 +170,20 @@ class LLXferManager
168 const LLHost& remote_host, 170 const LLHost& remote_host,
169 void (*callback)(void**,S32,LLExtStat), void** user_data, 171 void (*callback)(void**,S32,LLExtStat), void** user_data,
170 BOOL is_priority = FALSE); 172 BOOL is_priority = FALSE);
173 /**
174 When arbitrary files are requested to be transfered (by giving a dir of LL_PATH_NONE)
175 they must be "expected", but having something pre-authorize them. This pair of functions
176 maintains a pre-authorized list. The first function adds something to the list, the second
177 checks if is authorized, removing it if so. In this way, a file is only authorized for
178 a single use.
179 */
180 virtual void expectFileForTransfer(const std::string& filename);
181 virtual bool validateFileForTransfer(const std::string& filename);
182 /**
183 Same idea, but for the viewer about to call InitiateDownload to track what it requested.
184 */
185 virtual void expectFileForRequest(const std::string& filename);
186 virtual bool validateFileForRequest(const std::string& filename);
171 187
172/* 188/*
173// xfer request (may be memory or file) 189// xfer request (may be memory or file)