Skip to content

Commit

Permalink
Issue #921: add SSH tunnel support for SQL Server in TCP/IP mode. "SS…
Browse files Browse the repository at this point in the history
…H tunnel" tab is not hidden any longer for unsupported network types, only the checkbox is disabled then.
  • Loading branch information
ansgarbecker committed Jan 10, 2023
1 parent 4a591df commit 9c5da0f
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 32 deletions.
2 changes: 1 addition & 1 deletion source/connections.pas
Original file line number Diff line number Diff line change
Expand Up @@ -1470,7 +1470,7 @@ procedure Tconnform.ValidateControls;
lblDatabase.Enabled := Params.NetTypeGroup in [ngMySQL, ngMSSQL, ngPgSQL, ngInterbase];
editDatabases.Enabled := lblDatabase.Enabled;
// SSH tunnel tab:
tabSSHtunnel.TabVisible := Params.SshSupport;
chkSSHActive.Enabled := Params.SshSupport;
lblSSHExe.Enabled := Params.SSHActive;
comboSSHExe.Enabled := Params.SSHActive;
lblSSHhost.Enabled := Params.SSHActive;
Expand Down
71 changes: 40 additions & 31 deletions source/dbconnection.pas
Original file line number Diff line number Diff line change
Expand Up @@ -485,6 +485,8 @@ TDBConnection = class(TComponent)
FSQLFunctions: TSQLFunctionList;
procedure SetActive(Value: Boolean); virtual; abstract;
procedure DoBeforeConnect; virtual;
procedure StartSSHTunnel(var FinalHost: String; var FinalPort: Integer);
procedure EndSSHTunnel;
procedure DoAfterConnect; virtual;
procedure DetectUSEQuery(SQL: String); virtual;
procedure SetDatabase(Value: String);
Expand Down Expand Up @@ -1667,7 +1669,7 @@ function TConnectionParameters.GetNetTypeGroup: TNetTypeGroup;

function TConnectionParameters.SshSupport: Boolean;
begin
Result := FNetType in [ntMySQL_SSHtunnel, ntMySQL_RDS, ntPgSQL_SSHtunnel];
Result := FNetType in [ntMySQL_SSHtunnel, ntMySQL_RDS, ntPgSQL_SSHtunnel, ntMSSQL_TCPIP];
end;


Expand Down Expand Up @@ -2358,13 +2360,7 @@ procedure TMySQLConnection.SetActive( Value: Boolean );
end;

ntMySQL_SSHtunnel, ntMySQL_RDS: begin
// Create SSH process
if Parameters.SSHActive then begin
FSecureShellCmd := TSecureShellCmd.Create(Self);
FSecureShellCmd.Connect;
FinalHost := '127.0.0.1';
FinalPort := FParameters.SSHLocalPort;
end;
StartSSHTunnel(FinalHost, FinalPort);
end;
end;

Expand Down Expand Up @@ -2438,8 +2434,7 @@ procedure TMySQLConnection.SetActive( Value: Boolean );
Log(lcError, Error);
FConnectionStarted := 0;
FHandle := nil;
if FSecureShellCmd <> nil then
FSecureShellCmd.Free;
EndSSHTunnel;
if (FParameters.DefaultLibrary <> '') and (FParameters.LibraryOrProvider <> FParameters.DefaultLibrary) then begin
ErrorHint := f_('You could try the default library %s in your session settings. (Current: %s)',
[FParameters.DefaultLibrary, FParameters.LibraryOrProvider]
Expand Down Expand Up @@ -2547,8 +2542,7 @@ procedure TMySQLConnection.SetActive( Value: Boolean );
ClearCache(False);
FConnectionStarted := 0;
FHandle := nil;
if FSecureShellCmd <> nil then
FSecureShellCmd.Free;
EndSSHTunnel;
Log(lcInfo, f_(MsgDisconnect, [FParameters.Hostname, DateTimeToStr(Now)]));
end;

Expand All @@ -2558,12 +2552,17 @@ procedure TMySQLConnection.SetActive( Value: Boolean );
procedure TAdoDBConnection.SetActive(Value: Boolean);
var
Error, NetLib, DataSource, QuotedPassword, ServerVersion, ErrorHint: String;
FinalHost: String;
rx: TRegExpr;
i: Integer;
FinalPort, i: Integer;
IsOldProvider: Boolean;
begin
if Value then begin
DoBeforeConnect;
FinalHost := Parameters.Hostname;
FinalPort := Parameters.Port;
StartSSHTunnel(FinalHost, FinalPort);

try
// Creating the ADO object throws exceptions if MDAC is missing, especially on Wine
FAdoHandle := TAdoConnection.Create(Owner);
Expand Down Expand Up @@ -2596,9 +2595,9 @@ procedure TAdoDBConnection.SetActive(Value: Boolean);
ntMSSQL_RPC: NetLib := 'DBMSRPCN';
end;

DataSource := Parameters.Hostname;
if (Parameters.NetType = ntMSSQL_TCPIP) and (Parameters.Port <> 0) then
DataSource := DataSource + ','+IntToStr(Parameters.Port);
DataSource := FinalHost;
if (Parameters.NetType = ntMSSQL_TCPIP) and (FinalPort <> 0) then
DataSource := DataSource + ','+IntToStr(FinalPort);

// Quote password, just in case there is a semicolon or a double quote in it.
// See http://forums.asp.net/t/1957484.aspx?Passwords+ending+with+semi+colon+as+the+terminal+element+in+connection+strings+
Expand Down Expand Up @@ -2713,6 +2712,7 @@ procedure TAdoDBConnection.SetActive(Value: Boolean);
FActive := False;
ClearCache(False);
FConnectionStarted := 0;
EndSSHTunnel;
Log(lcInfo, f_(MsgDisconnect, [FParameters.Hostname, DateTimeToStr(Now)]));
end;
end;
Expand Down Expand Up @@ -2743,17 +2743,7 @@ procedure TPgConnection.SetActive(Value: Boolean);
FinalHost := FParameters.Hostname;
FinalPort := FParameters.Port;

case FParameters.NetType of
ntPgSQL_SSHtunnel: begin
// Create SSH process
if Parameters.SSHActive then begin
FSecureShellCmd := TSecureShellCmd.Create(Self);
FSecureShellCmd.Connect;
FinalHost := '127.0.0.1';
FinalPort := FParameters.SSHLocalPort;
end;
end;
end;
StartSSHTunnel(FinalHost, FinalPort);

ConnInfo := 'host='''+EscapeConnectOption(FinalHost)+''' '+
'port='''+IntToStr(FinalPort)+''' '+
Expand Down Expand Up @@ -2784,8 +2774,7 @@ procedure TPgConnection.SetActive(Value: Boolean);
on E:EAccessViolation do;
end;
FHandle := nil;
if FSecureShellCmd <> nil then
FSecureShellCmd.Free;
EndSSHTunnel;
if (FParameters.DefaultLibrary <> '') and (FParameters.LibraryOrProvider <> FParameters.DefaultLibrary) then begin
ErrorHint := f_('You could try the default library %s in your session settings. (Current: %s)',
[FParameters.DefaultLibrary, FParameters.LibraryOrProvider]
Expand Down Expand Up @@ -2823,8 +2812,7 @@ procedure TPgConnection.SetActive(Value: Boolean);
FActive := False;
ClearCache(False);
FConnectionStarted := 0;
if FSecureShellCmd <> nil then
FSecureShellCmd.Free;
EndSSHTunnel;
Log(lcInfo, f_(MsgDisconnect, [FParameters.Hostname, DateTimeToStr(Now)]));
end;
end;
Expand Down Expand Up @@ -3240,6 +3228,27 @@ procedure TInterbaseConnection.DoBeforeConnect;
end;


procedure TDBConnection.StartSSHTunnel(var FinalHost: String; var FinalPort: Integer);
begin
// Create SSH process
if Parameters.SSHActive and (FSecureShellCmd = nil) then begin
FSecureShellCmd := TSecureShellCmd.Create(Self);
FSecureShellCmd.Connect;
FinalHost := '127.0.0.1';
FinalPort := FParameters.SSHLocalPort;
end;
end;


procedure TDBConnection.EndSSHTunnel;
begin
if FSecureShellCmd <> nil then begin
FSecureShellCmd.Free;
FSecureShellCmd := nil;
end;
end;


procedure TDBConnection.DoAfterConnect;
var
SQLFunctionsFileOrder: String;
Expand Down

0 comments on commit 9c5da0f

Please sign in to comment.