Browse Source

Bug 1988: Cannot use passwords and passphrases longer than 255 characters in automation and various other purposes

https://winscp.net/tracker/1988

Source commit: 110dfdfe3834b90ad412786b075d6052b517d653
Martin Prikryl 4 years ago
parent
commit
d2ffb0b01f
1 changed files with 53 additions and 17 deletions
  1. 53 17
      source/core/Security.cpp

+ 53 - 17
source/core/Security.cpp

@@ -2,6 +2,7 @@
 #include <vcl.h>
 #pragma hdrstop
 
+#include <limits>
 #include "Common.h"
 #include "Security.h"
 //---------------------------------------------------------------------------
@@ -9,6 +10,7 @@
 //---------------------------------------------------------------------------
 #define PWALG_SIMPLE_INTERNAL 0x00
 #define PWALG_SIMPLE_EXTERNAL 0x01
+#define PWALG_SIMPLE_INTERNAL2 0x02
 //---------------------------------------------------------------------------
 RawByteString SimpleEncryptChar(unsigned char Ch)
 {
@@ -44,8 +46,18 @@ RawByteString EncryptPassword(UnicodeString UnicodePassword, UnicodeString Unico
   Shift = (Password.Length() < PWALG_SIMPLE_MAXLEN) ?
     (unsigned char)random(PWALG_SIMPLE_MAXLEN - Password.Length()) : 0;
   Result += SimpleEncryptChar((unsigned char)PWALG_SIMPLE_FLAG); // Flag
-  Result += SimpleEncryptChar((unsigned char)PWALG_SIMPLE_INTERNAL); // Dummy
-  Result += SimpleEncryptChar((unsigned char)Password.Length());
+  int Len = Password.Length();
+  if (Len > std::numeric_limits<unsigned char>::max())
+  {
+    Result += SimpleEncryptChar((unsigned char)PWALG_SIMPLE_INTERNAL2);
+    Result += SimpleEncryptChar((unsigned char)(Len >> 8));
+    Result += SimpleEncryptChar((unsigned char)(Len & 0xFF));
+  }
+  else
+  {
+    Result += SimpleEncryptChar((unsigned char)PWALG_SIMPLE_INTERNAL);
+    Result += SimpleEncryptChar((unsigned char)Len);
+  }
   Result += SimpleEncryptChar((unsigned char)Shift);
   for (Index = 0; Index < Shift; Index++)
     Result += SimpleEncryptChar((unsigned char)random(256));
@@ -58,25 +70,49 @@ RawByteString EncryptPassword(UnicodeString UnicodePassword, UnicodeString Unico
 //---------------------------------------------------------------------------
 UnicodeString DecryptPassword(RawByteString Password, UnicodeString UnicodeKey, Integer /* Algorithm */)
 {
-  UTF8String Key = UnicodeKey;
-  UTF8String Result("");
-  Integer Index;
-  unsigned char Length, Flag;
-
-  Flag = SimpleDecryptNextChar(Password);
+  int Length;
+  unsigned char Flag = SimpleDecryptNextChar(Password);
   if (Flag == PWALG_SIMPLE_FLAG)
   {
-    /* Dummy = */ SimpleDecryptNextChar(Password);
-    Length = SimpleDecryptNextChar(Password);
+    unsigned char Version = SimpleDecryptNextChar(Password);
+    if (Version == PWALG_SIMPLE_INTERNAL)
+    {
+      Length = SimpleDecryptNextChar(Password);
+    }
+    else if (Version == PWALG_SIMPLE_INTERNAL2)
+    {
+      Length = (int(SimpleDecryptNextChar(Password)) << 8) + SimpleDecryptNextChar(Password);
+    }
+    else
+    {
+      Length = -1;
+    }
+  }
+  else
+  {
+    Length = Flag;
   }
-    else Length = Flag;
-  Password.Delete(1, ((Integer)SimpleDecryptNextChar(Password))*2);
-  for (Index = 0; Index < Length; Index++)
-    Result += (char)SimpleDecryptNextChar(Password);
-  if (Flag == PWALG_SIMPLE_FLAG)
+
+  UTF8String Result;
+  if (Length >= 0)
   {
-    if (Result.SubString(1, Key.Length()) != Key) Result = "";
-      else Result.Delete(1, Key.Length());
+    Password.Delete(1, ((Integer)SimpleDecryptNextChar(Password))*2);
+    for (int Index = 0; Index < Length; Index++)
+    {
+      Result += (char)SimpleDecryptNextChar(Password);
+    }
+    if (Flag == PWALG_SIMPLE_FLAG)
+    {
+      UTF8String Key = UnicodeKey;
+      if (Result.SubString(1, Key.Length()) != Key)
+      {
+        Result = UTF8String();
+      }
+      else
+      {
+        Result.Delete(1, Key.Length());
+      }
+    }
   }
   return UnicodeString(Result);
 }