1
0
Эх сурвалжийг харах

Bug fix: Some operations with relative paths (notably creating and deleting a subdirectory) were failing on encrypted session

(cherry picked from commit 9a215447f90a0482a01dd7b8ea5749cb1bb301da)

Source commit: 7cdbfda710aafc30087c43a13b4ded9c262ab808
Martin Prikryl 4 жил өмнө
parent
commit
5b5a56f675

+ 16 - 11
source/core/SftpFileSystem.cpp

@@ -2731,7 +2731,7 @@ int __fastcall TSFTPFileSystem::SendPacketAndReceiveResponse(
   return Result;
 }
 //---------------------------------------------------------------------------
-UnicodeString __fastcall TSFTPFileSystem::RealPath(const UnicodeString Path)
+UnicodeString __fastcall TSFTPFileSystem::RealPath(const UnicodeString & Path)
 {
   if (FTerminal->SessionData->SFTPRealPath == asOff)
   {
@@ -2785,7 +2785,10 @@ UnicodeString __fastcall TSFTPFileSystem::RealPath(const UnicodeString Path)
       }
 
       UnicodeString RealDir = UnixExcludeTrailingBackslash(Packet.GetPathString(FUtfStrings));
-      RealDir = FTerminal->DecryptFileName(RealDir);
+      // do not cache, as particularly when called from CreateDirectory > Canonify,
+      // we would cache an unencrypted path to a directory we want to create encrypted,
+      // what would prevent the encryption later.
+      RealDir = FTerminal->DecryptFileName(RealDir, true, true);
       // ignore rest of SSH_FXP_NAME packet
 
       FTerminal->LogEvent(0, FORMAT(L"Real path is '%s'", (RealDir)));
@@ -2806,8 +2809,7 @@ UnicodeString __fastcall TSFTPFileSystem::RealPath(const UnicodeString Path)
   }
 }
 //---------------------------------------------------------------------------
-UnicodeString __fastcall TSFTPFileSystem::RealPath(const UnicodeString Path,
-  const UnicodeString BaseDir)
+UnicodeString __fastcall TSFTPFileSystem::RealPath(const UnicodeString & Path, const UnicodeString & BaseDir)
 {
   UnicodeString APath;
 
@@ -2846,12 +2848,12 @@ UnicodeString __fastcall TSFTPFileSystem::LocalCanonify(const UnicodeString & Pa
   }
 }
 //---------------------------------------------------------------------------
-UnicodeString __fastcall TSFTPFileSystem::Canonify(UnicodeString Path)
+UnicodeString __fastcall TSFTPFileSystem::Canonify(const UnicodeString & AAPath)
 {
   // inspired by canonify() from PSFTP.C
   UnicodeString Result;
-  FTerminal->LogEvent(FORMAT(L"Canonifying: \"%s\"", (Path)));
-  Path = LocalCanonify(Path);
+  FTerminal->LogEvent(FORMAT(L"Canonifying: \"%s\"", (AAPath)));
+  UnicodeString Path = LocalCanonify(AAPath);
   bool TryParent = false;
   try
   {
@@ -3472,7 +3474,7 @@ void __fastcall TSFTPFileSystem::ReadDirectory(TRemoteFileList * FileList)
               IsRealFile(File->FileName))
           {
             UnicodeString FullFileName = UnixExcludeTrailingBackslash(File->FullFileName);
-            UnicodeString FileName = UnixExtractFileName(FTerminal->DecryptFileName(FullFileName));
+            UnicodeString FileName = UnixExtractFileName(FTerminal->DecryptFileName(FullFileName, false, false));
             if (File->FileName != FileName)
             {
               File->SetEncrypted();
@@ -3641,7 +3643,9 @@ void __fastcall TSFTPFileSystem::ReadSymlink(TRemoteFile * SymlinkFile,
   {
     FTerminal->FatalError(NULL, LoadStr(SFTP_NON_ONE_FXP_NAME_PACKET));
   }
-  SymlinkFile->LinkTo = FTerminal->DecryptFileName(ReadLinkPacket.GetPathString(FUtfStrings));
+  // Not sure about the DontCache parameter here. Actually we should not get here for encrypted sessions.
+  DebugAssert(!FTerminal->IsEncryptingFiles());
+  SymlinkFile->LinkTo = FTerminal->DecryptFileName(ReadLinkPacket.GetPathString(FUtfStrings), true, true);
   FTerminal->LogEvent(FORMAT(L"Link resolved to \"%s\".", (SymlinkFile->LinkTo)));
 
   ReceiveResponse(&AttrsPacket, &AttrsPacket, SSH_FXP_ATTRS);
@@ -3707,14 +3711,15 @@ void __fastcall TSFTPFileSystem::CustomReadFile(const UnicodeString FileName,
     SSH_FILEXFER_ATTR_ACCESSTIME | SSH_FILEXFER_ATTR_MODIFYTIME |
     SSH_FILEXFER_ATTR_OWNERGROUP;
   TSFTPPacket Packet(Type);
-  AddPathString(Packet, LocalCanonify(FileName));
+  UnicodeString FullName = LocalCanonify(FileName);
+  AddPathString(Packet, FullName);
   SendCustomReadFile(&Packet, &Packet, Flags);
   ReceiveResponse(&Packet, &Packet, SSH_FXP_ATTRS, AllowStatus);
 
   if (Packet.Type == SSH_FXP_ATTRS)
   {
     File = LoadFile(&Packet, ALinkedByFile, UnixExtractFileName(FileName));
-    if (FTerminal->IsFileEncrypted(FileName))
+    if (FTerminal->IsFileEncrypted(FullName))
     {
       File->SetEncrypted();
     }

+ 3 - 3
source/core/SftpFileSystem.h

@@ -142,9 +142,9 @@ protected:
   void __fastcall LoadFile(TRemoteFile * File, TSFTPPacket * Packet,
     bool Complete = true);
   UnicodeString __fastcall LocalCanonify(const UnicodeString & Path);
-  UnicodeString __fastcall Canonify(UnicodeString Path);
-  UnicodeString __fastcall RealPath(const UnicodeString Path);
-  UnicodeString __fastcall RealPath(const UnicodeString Path, const UnicodeString BaseDir);
+  UnicodeString __fastcall Canonify(const UnicodeString & Path);
+  UnicodeString __fastcall RealPath(const UnicodeString & Path);
+  UnicodeString __fastcall RealPath(const UnicodeString & Path, const UnicodeString & BaseDir);
   void __fastcall ReserveResponse(const TSFTPPacket * Packet,
     TSFTPPacket * Response);
   int __fastcall ReceivePacket(TSFTPPacket * Packet, int ExpectedType = -1,

+ 6 - 3
source/core/Terminal.cpp

@@ -8170,7 +8170,7 @@ UnicodeString __fastcall TTerminal::EncryptFileName(const UnicodeString & Path,
   return Result;
 }
 //---------------------------------------------------------------------------
-UnicodeString __fastcall TTerminal::DecryptFileName(const UnicodeString & Path)
+UnicodeString __fastcall TTerminal::DecryptFileName(const UnicodeString & Path, bool DecryptFullPath, bool DontCache)
 {
   UnicodeString Result = Path;
   if (IsEncryptingFiles() && !IsUnixRootPath(Path))
@@ -8183,15 +8183,18 @@ UnicodeString __fastcall TTerminal::DecryptFileName(const UnicodeString & Path)
     {
       TEncryption Encryption(FEncryptKey);
       FileName = Encryption.DecryptFileName(FileName);
+    }
 
+    if (Encrypted || DecryptFullPath) // DecryptFullPath is just an optimization
+    {
       UnicodeString FileDir = UnixExtractFileDir(Path);
-      FileDir = DecryptFileName(FileDir);
+      FileDir = DecryptFileName(FileDir, DecryptFullPath, DontCache);
       Result = UnixCombinePaths(FileDir, FileName);
     }
 
     TEncryptedFileNames::iterator Iter = FEncryptedFileNames.find(Result);
     bool NotCached = (Iter == FEncryptedFileNames.end());
-    if (Encrypted || NotCached)
+    if (!DontCache && (Encrypted || NotCached))
     {
       if (Encrypted && (NotCached || (Iter->second != FileNameEncrypted)))
       {

+ 1 - 1
source/core/Terminal.h

@@ -489,7 +489,7 @@ protected:
   void __fastcall UpdateTargetTime(HANDLE Handle, TDateTime Modification, TDSTMode DSTMode);
 
   UnicodeString __fastcall EncryptFileName(const UnicodeString & Path, bool EncryptNewFiles);
-  UnicodeString __fastcall DecryptFileName(const UnicodeString & Path);
+  UnicodeString __fastcall DecryptFileName(const UnicodeString & Path, bool DecryptFullPath, bool DontCache);
   TEncryptedFileNames::const_iterator __fastcall GetEncryptedFileName(const UnicodeString & Path);
   bool __fastcall IsFileEncrypted(const UnicodeString & Path, bool EncryptNewFiles = false);