浏览代码

Bug 1971: Prevent another application (or WinSCP instance) stealing the selected tunnel port

https://winscp.net/tracker/1971

Source commit: c78487fcb22dc8e04c32a90272a2a3d0caf37a79
Martin Prikryl 4 年之前
父节点
当前提交
804abe4890
共有 1 个文件被更改,包括 18 次插入6 次删除
  1. 18 6
      source/core/Terminal.cpp

+ 18 - 6
source/core/Terminal.cpp

@@ -1475,18 +1475,30 @@ void __fastcall TTerminal::OpenTunnel()
   FTunnelLocalPortNumber = FSessionData->TunnelLocalPortNumber;
   if (FTunnelLocalPortNumber == 0)
   {
-    FTunnelLocalPortNumber = Configuration->TunnelLocalPortNumberLow;
-    while (!IsListenerFree(FTunnelLocalPortNumber))
+    // Randomizing the port selection to reduce a chance of conflicts.
+    std::vector<int> Ports;
+    for (int Port = Configuration->TunnelLocalPortNumberLow; Port <= Configuration->TunnelLocalPortNumberHigh; Port++)
     {
-      FTunnelLocalPortNumber++;
-      if (FTunnelLocalPortNumber > Configuration->TunnelLocalPortNumberHigh)
+      Ports.push_back(Port);
+    }
+
+    do
+    {
+      if (Ports.empty())
       {
-        FTunnelLocalPortNumber = 0;
         FatalError(NULL, FMTLOAD(TUNNEL_NO_FREE_PORT,
           (Configuration->TunnelLocalPortNumberLow, Configuration->TunnelLocalPortNumberHigh)));
       }
+      int Index = Random(Ports.size());
+      int Port = Ports[Index];
+      Ports.erase(&Ports.at(Index));
+      if (IsListenerFree(Port))
+      {
+        FTunnelLocalPortNumber = Port;
+        LogEvent(FORMAT(L"Autoselected tunnel local port number %d", (FTunnelLocalPortNumber)));
+      }
     }
-    LogEvent(FORMAT(L"Autoselected tunnel local port number %d", (FTunnelLocalPortNumber)));
+    while (FTunnelLocalPortNumber == 0);
   }
 
   try