Sfoglia il codice sorgente

Trusted host certification authorities can be loaded from PuTTY (Bug 2145)

Source commit: 89ce74adb56ae374f5e0e3930f107dd2b5d2b67e
Martin Prikryl 2 anni fa
parent
commit
fa89d3764e

+ 45 - 11
source/core/Configuration.cpp

@@ -58,13 +58,14 @@ TSshHostCA::TSshHostCA()
   PermitRsaSha512 = true;
 }
 //---------------------------------------------------------------------------
-void TSshHostCA::Load(THierarchicalStorage * Storage)
+bool TSshHostCA::Load(THierarchicalStorage * Storage)
 {
   PublicKey = DecodeBase64ToStr(Storage->ReadString(L"PublicKey", PublicKey));
   ValidityExpression = Storage->ReadString(L"Validity", ValidityExpression);
   PermitRsaSha1 = Storage->ReadBool(L"PermitRSASHA1", PermitRsaSha1);
   PermitRsaSha256 = Storage->ReadBool(L"PermitRSASHA256", PermitRsaSha256);
   PermitRsaSha512 = Storage->ReadBool(L"PermitRSASHA512", PermitRsaSha512);
+  return !PublicKey.IsEmpty() && !ValidityExpression.IsEmpty();
 }
 //---------------------------------------------------------------------------
 void TSshHostCA::Save(THierarchicalStorage * Storage) const
@@ -119,10 +120,12 @@ void TSshHostCAList::Load(THierarchicalStorage * Storage)
     SshHostCA.Name = SubKeys->Strings[Index];
     if (Storage->OpenSubKey(SshHostCA.Name, false))
     {
-      SshHostCA.Load(Storage);
-      Storage->CloseSubKey();
+      if (SshHostCA.Load(Storage))
+      {
+        FList.push_back(SshHostCA);
+      }
 
-      FList.push_back(SshHostCA);
+      Storage->CloseSubKey();
     }
   }
 }
@@ -152,7 +155,7 @@ const TSshHostCA * TSshHostCAList::Find(const UnicodeString & Name) const
   return NULL;
 }
 //---------------------------------------------------------------------------
-TSshHostCA::TList TSshHostCAList::GetList() const
+const TSshHostCA::TList & TSshHostCAList::GetList() const
 {
   return FList;
 }
@@ -245,6 +248,8 @@ void __fastcall TConfiguration::Default()
   FParallelTransferThreshold = -1; // default (currently off), 0 = explicitly off
   FKeyVersion = 0;
   FSshHostCAList->Default();
+  RefreshPuttySshHostCAList();
+  FSshHostCAsFromPuTTY = false;
   CollectUsage = FDefaultCollectUsage;
 
   FLogging = false;
@@ -383,6 +388,7 @@ UnicodeString __fastcall TConfiguration::PropertyToKey(const UnicodeString & Pro
     KEY(Integer,  QueueTransfersLimit); \
     KEY(Integer,  ParallelTransferThreshold); \
     KEY(Integer,  KeyVersion); \
+    KEY(Bool,     SshHostCAsFromPuTTY); \
     KEY(Bool,     CollectUsage); \
     KEY(String,   CertificateStorage); \
     KEY(String,   AWSMetadataService); \
@@ -594,18 +600,23 @@ void __fastcall TConfiguration::LoadAdmin(THierarchicalStorage * Storage)
   FDefaultCollectUsage = Storage->ReadBool(L"DefaultCollectUsage", FDefaultCollectUsage);
 }
 //---------------------------------------------------------------------------
-void __fastcall TConfiguration::LoadFrom(THierarchicalStorage * Storage)
+void TConfiguration::LoadSshHostCAList(TSshHostCAList * SshHostCAList, THierarchicalStorage * Storage)
 {
-  if (Storage->OpenSubKey(ConfigurationSubKey, false))
+  if (Storage->OpenSubKey(SshHostCAsKey, false))
   {
-    LoadData(Storage);
+    SshHostCAList->Load(Storage);
     Storage->CloseSubKey();
   }
-  if (Storage->OpenSubKey(SshHostCAsKey, false))
+}
+//---------------------------------------------------------------------------
+void __fastcall TConfiguration::LoadFrom(THierarchicalStorage * Storage)
+{
+  if (Storage->OpenSubKey(ConfigurationSubKey, false))
   {
-    FSshHostCAList->Load(Storage);
+    LoadData(Storage);
     Storage->CloseSubKey();
   }
+  LoadSshHostCAList(FSshHostCAList.get(), Storage);
 }
 //---------------------------------------------------------------------------
 UnicodeString __fastcall TConfiguration::GetRegistryStorageOverrideKey()
@@ -1906,7 +1917,8 @@ void __fastcall TConfiguration::SetParallelDurationThreshold(int value)
 //---------------------------------------------------------------------
 void __fastcall TConfiguration::SetPuttyRegistryStorageKey(UnicodeString value)
 {
-  SET_CONFIG_PROPERTY(PuttyRegistryStorageKey);
+  SET_CONFIG_PROPERTY_EX(PuttyRegistryStorageKey,
+    RefreshPuttySshHostCAList());
 }
 //---------------------------------------------------------------------------
 TEOLType __fastcall TConfiguration::GetLocalEOLType()
@@ -2222,6 +2234,28 @@ void TConfiguration::SetSshHostCAList(const TSshHostCAList * value)
   *FSshHostCAList = *value;
 }
 //---------------------------------------------------------------------------
+const TSshHostCAList * TConfiguration::GetPuttySshHostCAList()
+{
+  if (FPuttySshHostCAList.get() == NULL)
+  {
+    std::unique_ptr<TRegistryStorage> Storage(new TRegistryStorage(PuttyRegistryStorageKey));
+    Storage->ConfigureForPutty();
+    FPuttySshHostCAList.reset(new TSshHostCAList());
+    LoadSshHostCAList(FPuttySshHostCAList.get(), Storage.get());
+  }
+  return FPuttySshHostCAList.get();
+}
+//---------------------------------------------------------------------------
+void TConfiguration::RefreshPuttySshHostCAList()
+{
+  FPuttySshHostCAList.reset(NULL);
+}
+//---------------------------------------------------------------------------
+const TSshHostCAList * TConfiguration::GetActiveSshHostCAList()
+{
+  return FSshHostCAsFromPuTTY ? PuttySshHostCAList : SshHostCAList;
+}
+//---------------------------------------------------------------------------
 bool __fastcall TConfiguration::GetPersistent()
 {
   return (Storage != stNul) && !FDontSave;

+ 11 - 2
source/core/Configuration.h

@@ -26,7 +26,7 @@ class TSshHostCA
 public:
   TSshHostCA();
   void Save(THierarchicalStorage * Storage) const;
-  void Load(THierarchicalStorage * Storage);
+  bool Load(THierarchicalStorage * Storage);
 
   UnicodeString Name;
   RawByteString PublicKey;
@@ -45,7 +45,7 @@ public:
   TSshHostCAList(const TSshHostCA::TList & List);
   TSshHostCAList & operator =(const TSshHostCAList & other);
   void Default();
-  TSshHostCA::TList GetList() const;
+  const TSshHostCA::TList & GetList() const;
   int GetCount() const;
   const TSshHostCA * Get(int Index) const;
   const TSshHostCA * Find(const UnicodeString & Name) const;
@@ -123,6 +123,8 @@ private:
   UnicodeString FAWSMetadataService;
   UnicodeString FChecksumCommands;
   std::unique_ptr<TSshHostCAList> FSshHostCAList;
+  std::unique_ptr<TSshHostCAList> FPuttySshHostCAList;
+  bool FSshHostCAsFromPuTTY;
 
   bool FDisablePasswordStoring;
   bool FForceBanners;
@@ -199,6 +201,8 @@ private:
   void SetQueueTransfersLimit(int value);
   const TSshHostCAList * GetSshHostCAList();
   void SetSshHostCAList(const TSshHostCAList * value);
+  const TSshHostCAList * GetPuttySshHostCAList();
+  const TSshHostCAList * GetActiveSshHostCAList();
 
 protected:
   TStorage FStorage;
@@ -211,6 +215,7 @@ protected:
   virtual void __fastcall LoadFrom(THierarchicalStorage * Storage);
   virtual void __fastcall CopyData(THierarchicalStorage * Source, THierarchicalStorage * Target);
   virtual void __fastcall LoadAdmin(THierarchicalStorage * Storage);
+  void LoadSshHostCAList(TSshHostCAList * SshHostCAList, THierarchicalStorage * Storage);
   virtual UnicodeString __fastcall GetDefaultKeyFile();
   virtual void __fastcall Saved();
   void __fastcall CleanupRegistry(const UnicodeString & RegistryPath);
@@ -327,6 +332,7 @@ public:
     TStrings * Lines, TStoredSessionList * Sessions, UnicodeString & Error);
   TStoredSessionList * SelectOpensshSessionsForImport(TStoredSessionList * Sessions, UnicodeString & Error);
   UnicodeString GetPuttySessionsKey(const UnicodeString & RootKey);
+  void RefreshPuttySshHostCAList();
 
   __property TVSFixedFileInfo *FixedApplicationInfo  = { read=GetFixedApplicationInfo };
   __property void * ApplicationInfo  = { read=GetApplicationInfo };
@@ -391,6 +397,9 @@ public:
   __property int ParallelTransferThreshold = { read = FParallelTransferThreshold, write = FParallelTransferThreshold };
   __property int KeyVersion = { read = FKeyVersion, write = FKeyVersion };
   __property TSshHostCAList * SshHostCAList = { read = GetSshHostCAList, write = SetSshHostCAList };
+  __property TSshHostCAList * PuttySshHostCAList = { read = GetPuttySshHostCAList };
+  __property TSshHostCAList * ActiveSshHostCAList = { read = GetActiveSshHostCAList };
+  __property bool SshHostCAsFromPuTTY = { read = FSshHostCAsFromPuTTY, write = FSshHostCAsFromPuTTY };
 
   __property UnicodeString TimeFormat = { read = GetTimeFormat };
   __property TStorage Storage  = { read=GetStorage };

+ 3 - 2
source/core/PuttyIntf.cpp

@@ -1518,6 +1518,7 @@ struct host_ca_enum
 //---------------------------------------------------------------------------
 host_ca_enum * enum_host_ca_start()
 {
+  Configuration->RefreshPuttySshHostCAList();
   host_ca_enum * Result = new host_ca_enum();
   Result->Index = 0;
   return Result;
@@ -1525,7 +1526,7 @@ host_ca_enum * enum_host_ca_start()
 //---------------------------------------------------------------------------
 bool enum_host_ca_next(host_ca_enum * Enum, strbuf * StrBuf)
 {
-  const TSshHostCAList * SshHostCAList = Configuration->SshHostCAList;
+  const TSshHostCAList * SshHostCAList = Configuration->ActiveSshHostCAList;
   bool Result = (Enum->Index < SshHostCAList->GetCount());
   if (Result)
   {
@@ -1544,7 +1545,7 @@ host_ca * host_ca_load(const char * NameStr)
 {
   host_ca * Result = NULL;
   UnicodeString Name = UTF8String(NameStr);
-  const TSshHostCA * SshHostCA = Configuration->SshHostCAList->Find(Name);
+  const TSshHostCA * SshHostCA = Configuration->ActiveSshHostCAList->Find(Name);
   if (DebugAlwaysTrue(SshHostCA != NULL))
   {
     Result = host_ca_new();

+ 56 - 2
source/forms/Preferences.cpp

@@ -640,7 +640,9 @@ void __fastcall TPreferencesDialog::LoadConfiguration()
     // security
     UseMasterPasswordCheck->Checked = WinConfiguration->UseMasterPassword;
     SessionRememberPasswordCheck->Checked = GUIConfiguration->SessionRememberPassword;
+    SshHostCAsFromPuTTYCheck->Checked = Configuration->SshHostCAsFromPuTTY;
     FSshHostCAPlainList = Configuration->SshHostCAList->GetList();
+    Configuration->RefreshPuttySshHostCAList();
 
     // network
     RetrieveExternalIpAddressButton->Checked = Configuration->ExternalIpAddress.IsEmpty();
@@ -1001,6 +1003,7 @@ void __fastcall TPreferencesDialog::SaveConfiguration()
 
     // security
     GUIConfiguration->SessionRememberPassword = SessionRememberPasswordCheck->Checked;
+    Configuration->SshHostCAsFromPuTTY = SshHostCAsFromPuTTYCheck->Checked;
     std::unique_ptr<TSshHostCAList> SshHostCAList(new TSshHostCAList(FSshHostCAPlainList));
     Configuration->SshHostCAList = SshHostCAList.get();
 
@@ -1432,9 +1435,14 @@ void __fastcall TPreferencesDialog::UpdateControls()
     // security
     EnableControl(SetMasterPasswordButton, WinConfiguration->UseMasterPassword);
     UpdateSshHostCAsViewView();
+    EnableControl(SshHostCAsView, !SshHostCAsFromPuTTYCheck->Checked);
+    AddSshHostCAButton->Visible = SshHostCAsView->Enabled;
     bool SshHostCASelected = (SshHostCAsView->Selected != NULL);
+    EditSshHostCAButton->Visible = AddSshHostCAButton->Visible;
     EnableControl(EditSshHostCAButton, SshHostCASelected);
+    RemoveSshHostCAButton->Visible = AddSshHostCAButton->Visible;
     EnableControl(RemoveSshHostCAButton, SshHostCASelected);
+    ConfigureSshHostCAsButton->Visible = !AddSshHostCAButton->Visible;
 
     // network
     EnableControl(CustomExternalIpAddressEdit, CustomExternalIpAddressButton->Checked);
@@ -2218,6 +2226,15 @@ void __fastcall TPreferencesDialog::CMDpiChanged(TMessage & Message)
   TForm::Dispatch(&Message);
 }
 //---------------------------------------------------------------------------
+void TPreferencesDialog::WMActivate(TWMActivate & Message)
+{
+  if ((Message.Active != WA_INACTIVE) && (PageControl->ActivePage == SecuritySheet))
+  {
+    SshHostCAsRefresh();
+  }
+  TForm::Dispatch(&Message);
+}
+//---------------------------------------------------------------------------
 void __fastcall TPreferencesDialog::Dispatch(void *Message)
 {
   TMessage * M = reinterpret_cast<TMessage*>(Message);
@@ -2234,6 +2251,10 @@ void __fastcall TPreferencesDialog::Dispatch(void *Message)
   {
     WMHelp(*((TWMHelp *)Message));
   }
+  else if (M->Msg == WM_ACTIVATE)
+  {
+    WMActivate(*((TWMActivate *)Message));
+  }
   else
   {
     TForm::Dispatch(Message);
@@ -2558,6 +2579,10 @@ void __fastcall TPreferencesDialog::NavigationTreeChanging(TObject * /*Sender*/,
   {
     LoadLanguages();
   }
+  else if (Sheet == SecuritySheet)
+  {
+    SshHostCAsRefresh();
+  }
 }
 //---------------------------------------------------------------------------
 void __fastcall TPreferencesDialog::LanguagesGetMoreButtonClick(TObject * /*Sender*/)
@@ -3312,8 +3337,12 @@ void __fastcall TPreferencesDialog::SshHostCAsViewKeyDown(TObject *, WORD & Key,
 //---------------------------------------------------------------------------
 void TPreferencesDialog::UpdateSshHostCAsViewView()
 {
-  SshHostCAsView->Items->Count = FSshHostCAPlainList.size();
+  SshHostCAsView->Items->Count = GetSshHostCAPlainList().size();
   AutoSizeListColumnsWidth(SshHostCAsView, 1);
+  if (SshHostCAsFromPuTTYCheck->Checked)
+  {
+    SshHostCAsView->Items->Item[0]->MakeVisible(false);
+  }
   SshHostCAsView->Invalidate();
 }
 //---------------------------------------------------------------------------
@@ -3332,7 +3361,7 @@ void __fastcall TPreferencesDialog::AddSshHostCAButtonClick(TObject *)
 //---------------------------------------------------------------------------
 void __fastcall TPreferencesDialog::SshHostCAsViewData(TObject *, TListItem * Item)
 {
-  TSshHostCA & SshHostCA = FSshHostCAPlainList[Item->Index];
+  const TSshHostCA & SshHostCA = GetSshHostCAPlainList()[Item->Index];
   Item->Caption = SshHostCA.Name;
   Item->SubItems->Add(SshHostCA.ValidityExpression);
 }
@@ -3353,3 +3382,28 @@ void __fastcall TPreferencesDialog::RemoveSshHostCAButtonClick(TObject *)
   UpdateControls();
 }
 //---------------------------------------------------------------------------
+const TSshHostCA::TList & TPreferencesDialog::GetSshHostCAPlainList()
+{
+  return SshHostCAsFromPuTTYCheck->Checked ? Configuration->PuttySshHostCAList->GetList() : FSshHostCAPlainList;
+}
+//---------------------------------------------------------------------------
+void TPreferencesDialog::SshHostCAsRefresh()
+{
+  if (SshHostCAsFromPuTTYCheck->Checked)
+  {
+    Configuration->RefreshPuttySshHostCAList();
+  }
+  UpdateControls();
+}
+//---------------------------------------------------------------------------
+void __fastcall TPreferencesDialog::SshHostCAsFromPuTTYCheckClick(TObject *)
+{
+  SshHostCAsRefresh();
+}
+//---------------------------------------------------------------------------
+void __fastcall TPreferencesDialog::ConfigureSshHostCAsButtonClick(TObject *)
+{
+  UnicodeString Program = FindPuttyPath();
+  ExecuteShellChecked(Program, L"-host-ca");
+}
+//---------------------------------------------------------------------------

+ 29 - 10
source/forms/Preferences.dfm

@@ -2741,16 +2741,16 @@ object PreferencesDialog: TPreferencesDialog
           Left = 8
           Top = 164
           Width = 389
-          Height = 205
+          Height = 228
           Anchors = [akLeft, akTop, akRight, akBottom]
           Caption = 'Trusted host certification authorities'
           TabOrder = 2
           DesignSize = (
             389
-            205)
+            228)
           object SshHostCAsView: TListView
             Left = 16
-            Top = 24
+            Top = 47
             Width = 356
             Height = 139
             Anchors = [akLeft, akTop, akRight, akBottom]
@@ -2770,7 +2770,7 @@ object PreferencesDialog: TPreferencesDialog
             ReadOnly = True
             RowSelect = True
             ParentDoubleBuffered = False
-            TabOrder = 0
+            TabOrder = 1
             ViewStyle = vsReport
             OnData = SshHostCAsViewData
             OnDblClick = SshHostCAsViewDblClick
@@ -2779,34 +2779,53 @@ object PreferencesDialog: TPreferencesDialog
           end
           object AddSshHostCAButton: TButton
             Left = 16
-            Top = 169
+            Top = 192
             Width = 83
             Height = 25
             Anchors = [akLeft, akBottom]
             Caption = '&Add...'
-            TabOrder = 1
+            TabOrder = 2
             OnClick = AddSshHostCAButtonClick
           end
           object RemoveSshHostCAButton: TButton
             Left = 208
-            Top = 169
+            Top = 192
             Width = 83
             Height = 25
             Anchors = [akLeft, akBottom]
             Caption = '&Remove'
-            TabOrder = 3
+            TabOrder = 4
             OnClick = RemoveSshHostCAButtonClick
           end
           object EditSshHostCAButton: TButton
             Left = 112
-            Top = 169
+            Top = 192
             Width = 83
             Height = 25
             Anchors = [akLeft, akBottom]
             Caption = '&Edit...'
-            TabOrder = 2
+            TabOrder = 3
             OnClick = EditSshHostCAButtonClick
           end
+          object SshHostCAsFromPuTTYCheck: TCheckBox
+            Left = 16
+            Top = 24
+            Width = 356
+            Height = 17
+            Caption = '&Load authorities from PuTTY'
+            TabOrder = 0
+            OnClick = SshHostCAsFromPuTTYCheckClick
+          end
+          object ConfigureSshHostCAsButton: TButton
+            Left = 16
+            Top = 192
+            Width = 125
+            Height = 25
+            Anchors = [akLeft, akBottom]
+            Caption = '&Edit in PuTTY...'
+            TabOrder = 5
+            OnClick = ConfigureSshHostCAsButtonClick
+          end
         end
       end
       object IntegrationAppSheet: TTabSheet

+ 7 - 0
source/forms/Preferences.h

@@ -352,6 +352,8 @@ __published:
   TButton *AddSshHostCAButton;
   TButton *RemoveSshHostCAButton;
   TButton *EditSshHostCAButton;
+  TCheckBox *SshHostCAsFromPuTTYCheck;
+  TButton *ConfigureSshHostCAsButton;
   void __fastcall FormShow(TObject *Sender);
   void __fastcall ControlChange(TObject *Sender);
   void __fastcall EditorFontButtonClick(TObject *Sender);
@@ -464,6 +466,8 @@ __published:
   void __fastcall SshHostCAsViewData(TObject *Sender, TListItem *Item);
   void __fastcall EditSshHostCAButtonClick(TObject *Sender);
   void __fastcall RemoveSshHostCAButtonClick(TObject *Sender);
+  void __fastcall SshHostCAsFromPuTTYCheckClick(TObject *Sender);
+  void __fastcall ConfigureSshHostCAsButtonClick(TObject *Sender);
 
 private:
   TPreferencesMode FPreferencesMode;
@@ -500,6 +504,7 @@ private:
   void __fastcall CMDialogKey(TWMKeyDown & Message);
   void __fastcall WMHelp(TWMHelp & Message);
   void __fastcall CMDpiChanged(TMessage & Message);
+  void WMActivate(TWMActivate & Message);
   UnicodeString __fastcall TabSample(UnicodeString Values);
   void __fastcall AddEditCopyParam(TCopyParamPresetMode Mode);
   const TCopyParamType * GetCopyParam(int Index);
@@ -513,6 +518,7 @@ private:
   int __fastcall GetListCommandIndex(TCustomCommandList * List);
   UnicodeString __fastcall GetSessionKey();
   void __fastcall ExtensionHttpError(THttp * Sender, int Status, const UnicodeString & Message);
+  const TSshHostCA::TList & GetSshHostCAPlainList();
 public:
   virtual __fastcall ~TPreferencesDialog();
   bool __fastcall Execute(TPreferencesDialogData * DialogData);
@@ -550,6 +556,7 @@ protected:
   void __fastcall AddEditFileColor(bool Edit);
   UnicodeString Bullet(const UnicodeString & S);
   void UpdateSshHostCAsViewView();
+  void SshHostCAsRefresh();
 
   INTERFACE_HOOK;
 };

+ 3 - 7
source/forms/SiteAdvanced.cpp

@@ -1844,16 +1844,12 @@ void __fastcall TSiteAdvancedDialog::PuttySettingsButtonClick(TObject *)
   SessionData->PuttySettings = PuttySettings;
   ExportSessionToPutty(SessionData.get(), false, SiteName);
 
-  UnicodeString Program, Params, Dir;
-  SplitCommand(GUIConfiguration->PuttyPath, Program, Params, Dir);
-  Program = ExpandEnvironmentVariables(Program);
-  if (!FindFile(Program))
-  {
-    throw Exception(FMTLOAD(EXECUTE_APP_ERROR, (Program)));
-  }
+  UnicodeString Program = FindPuttyPath();
 
   ExecuteShellChecked(Program, L"");
 
+  // Maybe replace this with update on WM_ACTIVATE,
+  // the way it works with certificate authorities on Preferences dialog
   FPuttySettingsTimer.reset(new TTimer(this));
   FPuttySettingsTimer->OnTimer = PuttySettingsTimer;
   FPuttySettingsTimer->Interval = MSecsPerSec;

+ 22 - 5
source/windows/GUITools.cpp

@@ -402,22 +402,39 @@ void __fastcall TPuttyPasswordThread::Execute()
   }
 }
 //---------------------------------------------------------------------------
+void SplitPuttyCommand(UnicodeString & Program, UnicodeString & Params)
+{
+  // See also TSiteAdvancedDialog::PuttySettingsButtonClick
+  UnicodeString Dir;
+  SplitCommand(GUIConfiguration->PuttyPath, Program, Params, Dir);
+  Program = ExpandEnvironmentVariables(Program);
+  Params = ExpandEnvironmentVariables(Params);
+}
+//---------------------------------------------------------------------------
+UnicodeString FindPuttyPath()
+{
+  UnicodeString Program, Params;
+  SplitPuttyCommand(Program, Params);
+  if (!FindFile(Program))
+  {
+    throw Exception(FMTLOAD(EXECUTE_APP_ERROR, (Program)));
+  }
+  return Program;
+}
+//---------------------------------------------------------------------------
 unsigned int PipeCounter = 0;
 //---------------------------------------------------------------------------
 void OpenSessionInPutty(TSessionData * SessionData)
 {
   // putty does not support resolving environment variables in session settings
   SessionData->ExpandEnvironmentVariables();
-  // See also TSiteAdvancedDialog::PuttySettingsButtonClick
-  UnicodeString Program, AParams, Dir;
-  SplitCommand(GUIConfiguration->PuttyPath, Program, AParams, Dir);
-  Program = ExpandEnvironmentVariables(Program);
+  UnicodeString Program, AParams;
+  SplitPuttyCommand(Program, AParams);
   AppLogFmt(L"PuTTY program: %s", (Program));
   AppLogFmt(L"Params: %s", (AParams));
   if (FindFile(Program))
   {
 
-    AParams = ExpandEnvironmentVariables(AParams);
     UnicodeString Password;
     if (GUIConfiguration->PuttyPassword)
     {

+ 1 - 0
source/windows/GUITools.h

@@ -12,6 +12,7 @@ typedef void __fastcall (__closure* TProcessMessagesEvent)();
 //---------------------------------------------------------------------------
 void GUIFinalize();
 bool __fastcall FindFile(UnicodeString & Path);
+UnicodeString FindPuttyPath();
 bool __fastcall FindTool(const UnicodeString & Name, UnicodeString & Path);
 void __fastcall ExecuteTool(const UnicodeString & Name);
 void __fastcall ExecuteShellChecked(const UnicodeString Path, const UnicodeString Params,