فهرست منبع

List of supported ciphers and algorithms can be printed using /info command-line switch

Source commit: 66090389e3bdb71e4ca50d70bb022352e7f53dd3
Martin Prikryl 7 سال پیش
والد
کامیت
60875e3fe2

+ 25 - 0
source/core/Common.cpp

@@ -17,6 +17,7 @@
 #include <openssl/pkcs12.h>
 #include <openssl/pem.h>
 #include <openssl/err.h>
+#include <openssl/ssl.h>
 //---------------------------------------------------------------------------
 #pragma package(smart_init)
 //---------------------------------------------------------------------------
@@ -3867,3 +3868,27 @@ UnicodeString NormalizeString(const UnicodeString & S)
   }
   return Result;
 }
+//---------------------------------------------------------------------------
+TStrings * TlsCipherList()
+{
+  // OpenSSL initialization happens in NeonInitialize
+  std::unique_ptr<TStrings> Result(new TStringList());
+  const SSL_METHOD * Method = TLSv1_client_method();
+  SSL_CTX * Ctx = SSL_CTX_new(Method);
+  SSL * Ssl = SSL_new(Ctx);
+
+  int Index = 0;
+  const char * CipherName;
+  do
+  {
+    CipherName = SSL_get_cipher_list(Ssl, Index);
+    Index++;
+    if (CipherName != NULL)
+    {
+      Result->Add(UnicodeString(CipherName));
+    }
+  }
+  while (CipherName != NULL);
+
+  return Result.release();
+}

+ 1 - 0
source/core/Common.h

@@ -245,6 +245,7 @@ int __fastcall TimeToMSec(TDateTime T);
 int __fastcall TimeToSeconds(TDateTime T);
 int __fastcall TimeToMinutes(TDateTime T);
 UnicodeString __fastcall FormatDateTimeSpan(const UnicodeString TimeFormat, TDateTime DateTime);
+TStrings * TlsCipherList();
 //---------------------------------------------------------------------------
 template<class MethodT>
 MethodT __fastcall MakeMethod(void * Data, void * Code)

+ 1 - 0
source/core/CoreMain.cpp

@@ -171,6 +171,7 @@ void CoreInitialize()
 
   PuttyInitialize();
   TFileZillaIntf::Initialize();
+  // TlsCipherList() also relies on this to be called
   NeonInitialize();
 
   CoreLoad();

+ 64 - 0
source/core/PuttyIntf.cpp

@@ -932,4 +932,68 @@ bool IsOpenSSH(const UnicodeString & SshImplementation)
     (SshImplementation.Pos(L"Sun_SSH") == 1);
 }
 //---------------------------------------------------------------------------
+TStrings * SshCipherList()
+{
+  std::unique_ptr<TStrings> Result(new TStringList());
+  // Same order as DefaultCipherList
+  const ssh2_ciphers * Ciphers[] = { &ssh2_aes, &ssh2_ccp, &ssh2_blowfish, &ssh2_3des, &ssh2_arcfour, &ssh2_des };
+  for (unsigned int Index = 0; Index < LENOF(Ciphers); Index++)
+  {
+    for (int Index2 = 0; Index2 < Ciphers[Index]->nciphers; Index2++)
+    {
+      UnicodeString Name = UnicodeString(Ciphers[Index]->list[Index2]->name);
+      Result->Add(Name);
+    }
+  }
+  return Result.release();
+}
+//---------------------------------------------------------------------------
+TStrings * SshKexList()
+{
+  std::unique_ptr<TStrings> Result(new TStringList());
+  // Same order as DefaultKexList
+  const ssh_kexes * Kexes[] = { &ssh_ecdh_kex, &ssh_diffiehellman_gex, &ssh_diffiehellman_group14, &ssh_rsa_kex, &ssh_diffiehellman_group1 };
+  for (unsigned int Index = 0; Index < LENOF(Kexes); Index++)
+  {
+    for (int Index2 = 0; Index2 < Kexes[Index]->nkexes; Index2++)
+    {
+      UnicodeString Name = UnicodeString(Kexes[Index]->list[Index2]->name);
+      Result->Add(Name);
+    }
+  }
+  return Result.release();
+}
+//---------------------------------------------------------------------------
+TStrings * SshHostKeyList()
+{
+  std::unique_ptr<TStrings> Result(new TStringList());
+  const int MaxCount = 10;
+  const ssh_signkey * SignKeys[MaxCount];
+  int Count = LENOF(SignKeys);
+  get_hostkey_algs(&Count, SignKeys);
+
+  for (int Index = 0; Index < Count; Index++)
+  {
+    const ssh_signkey * SignKey = SignKeys[Index];
+    UnicodeString Name = UnicodeString(SignKey->name);
+    Result->Add(Name);
+  }
+  return Result.release();
+}
+//---------------------------------------------------------------------------
+TStrings * SshMacList()
+{
+  std::unique_ptr<TStrings> Result(new TStringList());
+  const struct ssh_mac ** Macs = NULL;
+  int Count = 0;
+  get_macs(&Count, &Macs);
+
+  for (int Index = 0; Index < Count; Index++)
+  {
+    UnicodeString Name = UnicodeString(Macs[Index]->name);
+    Result->Add(Name);
+  }
+  return Result.release();
+}
+//---------------------------------------------------------------------------
 //---------------------------------------------------------------------------

+ 5 - 0
source/core/PuttyTools.h

@@ -40,4 +40,9 @@ UnicodeString __fastcall GetKeyTypeHuman(const UnicodeString & KeyType);
 //---------------------------------------------------------------------------
 bool IsOpenSSH(const UnicodeString & SshImplementation);
 //---------------------------------------------------------------------------
+TStrings * SshCipherList();
+TStrings * SshKexList();
+TStrings * SshHostKeyList();
+TStrings * SshMacList();
+//---------------------------------------------------------------------------
 #endif

+ 2 - 0
source/core/SessionData.cpp

@@ -29,8 +29,10 @@ const UnicodeString KexNames[KEX_COUNT] = {L"WARN", L"dh-group1-sha1", L"dh-grou
 const UnicodeString HostKeyNames[HOSTKEY_COUNT] = {L"WARN", L"rsa", L"dsa", L"ecdsa", L"ed25519"};
 const UnicodeString GssLibNames[GSSLIB_COUNT] = {L"gssapi32", L"sspi", L"custom"};
 const wchar_t SshProtList[][10] = {L"1", L"1>2", L"2>1", L"2"};
+// Update also order in Ssh2CipherList()
 const TCipher DefaultCipherList[CIPHER_COUNT] =
   { cipAES, cipChaCha20, cipBlowfish, cip3DES, cipWarn, cipArcfour, cipDES };
+// Update also order in SshKexList()
 const TKex DefaultKexList[KEX_COUNT] =
   { kexECDH, kexDHGEx, kexDHGroup14, kexRSA, kexWarn, kexDHGroup1 };
 const THostKey DefaultHostKeyList[HOSTKEY_COUNT] =

+ 1 - 0
source/putty/puttyexp.h

@@ -23,6 +23,7 @@ const unsigned int * ssh2_remwindow(void * handle);
 void md5checksum(const char * buffer, int len, unsigned char output[16]);
 typedef const struct ssh_signkey * cp_ssh_signkey;
 void get_hostkey_algs(int * count, cp_ssh_signkey * SignKeys);
+void get_macs(int * count, const struct ssh_mac *** amacs);
 
 // from wingss.c
 

+ 7 - 1
source/putty/ssh.c

@@ -424,8 +424,9 @@ const static struct ssh_signkey_with_user_pref_id hostkey_algs[] = {
     { &ssh_ecdsa_nistp256, HK_ECDSA },
     { &ssh_ecdsa_nistp384, HK_ECDSA },
     { &ssh_ecdsa_nistp521, HK_ECDSA },
-    { &ssh_dss, HK_DSA },
+    /* Changed order to match WinSCP default preference list for SshHostKeyList() */
     { &ssh_rsa, HK_RSA },
+    { &ssh_dss, HK_DSA },
 };
 
 const static struct ssh_mac *const macs[] = {
@@ -12214,4 +12215,9 @@ void get_hostkey_algs(int * count, cp_ssh_signkey * SignKeys)
   }
 }
 
+void get_macs(int * count, const struct ssh_mac *** amacs)
+{
+  *amacs = macs;
+  *count = lenof(macs);
+}
 #endif

+ 1 - 0
source/resource/TextsWin.h

@@ -289,6 +289,7 @@
 #define OPEN_DOWNLOADED_FILE    1578
 #define ENCRYPT_KEY_GENERATED   1579
 #define LOCATION_PROFILE_HINT   1580
+#define USAGE_INFO              1581
 
 #define WIN_FORMS_STRINGS       1600
 #define COPY_FILE               1605

+ 1 - 0
source/resource/TextsWin1.rc

@@ -292,6 +292,7 @@ BEGIN
         OPEN_DOWNLOADED_FILE, "Open &Downloaded File"
         ENCRYPT_KEY_GENERATED, "**Encryption key was generated.**\n\nYou should safely backup the generated encryption key. If you lose it, you won't be able to read your files."
         LOCATION_PROFILE_HINT, "Open location profile \"%s\".|Local directory:\n  %s|Remote directory:\n  %s"
+        USAGE_INFO, "Prints list of supported ciphers and algorithms."
 
         WIN_FORMS_STRINGS, "WIN_FORMS_STRINGS"
         COPY_FILE, "%s file '%s' to %s:"

+ 37 - 0
source/windows/ConsoleRunner.cpp

@@ -2215,6 +2215,7 @@ void __fastcall Usage(TConsole * Console)
   {
     PrintUsageSyntax(Console, L"/update");
   }
+  PrintUsageSyntax(Console, TProgramParams::FormatSwitch(LowerCase(INFO_SWITCH)));
   PrintUsageSyntax(Console, L"/help");
 
   ConsolePrintLine(Console, L"");
@@ -2262,6 +2263,7 @@ void __fastcall Usage(TConsole * Console)
   {
     RegisterSwitch(SwitchesUsage, L"/update", USAGE_UPDATE);
   }
+  RegisterSwitch(SwitchesUsage, TProgramParams::FormatSwitch(INFO_SWITCH), USAGE_INFO);
   RegisterSwitch(SwitchesUsage, L"/help", USAGE_HELP);
 
   int MaxSwitchLen = 0;
@@ -2628,6 +2630,37 @@ int __fastcall DumpCallstack(TConsole * Console, TProgramParams * Params)
   return Result;
 }
 //---------------------------------------------------------------------------
+void static PrintList(TConsole * Console, const UnicodeString & Caption, TStrings * List)
+{
+  std::unique_ptr<TStrings> Owner(List);
+  ConsolePrintLine(Console, Caption);
+  for (int Index = 0; Index < List->Count; Index++)
+  {
+    ConsolePrintLine(Console, List->Strings[Index]);
+  }
+  ConsolePrintLine(Console, UnicodeString());
+}
+//---------------------------------------------------------------------------
+int Info(TConsole * Console)
+{
+  int Result = RESULT_SUCCESS;
+  try
+  {
+    PrintList(Console, L"SSH encryption ciphers:", SshCipherList());
+    PrintList(Console, L"SSH key exchange algoritms:", SshKexList());
+    PrintList(Console, L"SSH host key algoritms:", SshHostKeyList());
+    PrintList(Console, L"SSH MAC algoritms:", SshMacList());
+    PrintList(Console, L"TLS/SSL cipher suites:", TlsCipherList());
+  }
+  catch (Exception & E)
+  {
+    Result = HandleException(Console, E);
+  }
+
+  Console->WaitBeforeExit();
+  return Result;
+}
+//---------------------------------------------------------------------------
 int __fastcall Console(TConsoleMode Mode)
 {
   DebugAssert(Mode != cmNone);
@@ -2692,6 +2725,10 @@ int __fastcall Console(TConsoleMode Mode)
     {
       Result = DumpCallstack(Console, Params);
     }
+    else if (Mode == cmInfo)
+    {
+      Result = Info(Console);
+    }
     else
     {
       Runner = new TConsoleRunner(Console);

+ 2 - 1
source/windows/WinInterface.h

@@ -44,6 +44,7 @@ const int mpAllowContinueOnError = 0x02;
 #define RAW_CONFIG_SWITCH L"RawConfig"
 #define FINGERPRINTSCAN_SWITCH L"FingerprintScan"
 #define DUMPCALLSTACK_SWITCH L"DumpCallstack"
+#define INFO_SWITCH L"Info"
 
 #define DUMPCALLSTACK_EVENT L"WinSCPCallstack%d"
 
@@ -411,7 +412,7 @@ extern const UnicodeString YesButtonName;
 extern const UnicodeString OKButtonName;
 
 // windows\Console.cpp
-enum TConsoleMode { cmNone, cmScripting, cmHelp, cmBatchSettings, cmKeyGen, cmFingerprintScan, cmDumpCallstack };
+enum TConsoleMode { cmNone, cmScripting, cmHelp, cmBatchSettings, cmKeyGen, cmFingerprintScan, cmDumpCallstack, cmInfo };
 int __fastcall Console(TConsoleMode Mode);
 
 // forms\EditorPreferences.cpp

+ 4 - 0
source/windows/WinMain.cpp

@@ -787,6 +787,10 @@ int __fastcall Execute()
   {
     Mode = cmDumpCallstack;
   }
+  else if (Params->FindSwitch(INFO_SWITCH))
+  {
+    Mode = cmInfo;
+  }
   // We have to check for /console only after the other options,
   // as the /console is always used when we are run by winscp.com
   // (ambiguous use to pass console version)