Watch, Follow, &
Connect with Us

For forums, blogs and more please visit our
Developer Tools Community.


Welcome, Guest
Guest Settings
Help

Thread: SSL Socket Error #10060 when IdTCPClient Connects to IdTCPServer with SSL


This question is answered. Helpful answers available: 2. Correct answers available: 1.


Permlink Replies: 4 - Last Post: Jan 9, 2017 1:46 PM Last Post By: Bob Rasmusens
Bob Rasmusens

Posts: 10
Registered: 5/18/00
SSL Socket Error #10060 when IdTCPClient Connects to IdTCPServer with SSL  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Jan 6, 2017 2:51 PM
My Environment is Windows 10, Indy 10.6.2.5341, Delphi 10.1 Berlin Version 24.0.25048.9432.
I am new to SSL so please bear with me.

I have downloaded and built the pasEchoDemo project for SSL with Indy. I have generated SSL certificates using openssl.
The issue is that after starting the server and trying to connect the client I get a Socket Error #10060 Connection timed out.

I know the server is valid because if i run the following openssl command
openssl s_client -connect 127.0.0.1:6050 -showcerts
I get the response Welcome to the Echo Server which is what I expect

I have played with readtimeout values and SSLOptions methods and mode but no difference.

I have also added in output on the on status callbacks for Client and Server as well as a Try Except around the Client.Connect and received the following in my Delphi program.
Using openssl command above
SSL Server StatusInfo: SSL status: "before/accept initialization"
SSL Server StatusInfo: SSL status: "before/accept initialization"
SSL Server StatusInfo: SSL status: "SSLv3 read client hello A"
SSL Server StatusInfo: SSL status: "SSLv3 write server hello A"
SSL Server StatusInfo: SSL status: "SSLv3 write certificate A"
SSL Server StatusInfo: SSL status: "SSLv3 write server done A"
SSL Server StatusInfo: SSL status: "SSLv3 flush data"
SSL Server StatusInfo: SSL status: "SSLv3 read client key exchange A"
SSL Server StatusInfo: SSL status: "SSLv3 read finished A"
SSL Server StatusInfo: SSL status: "SSLv3 write session ticket A"
SSL Server StatusInfo: SSL status: "SSLv3 write change cipher spec A"
SSL Server StatusInfo: SSL status: "SSLv3 write finished A"
SSL Server StatusInfo: SSL status: "SSLv3 flush data"
SSL Server StatusInfo: SSL status: "SSL negotiation finished successfully"
SSL Server StatusInfo: SSL status: "SSL negotiation finished successfully"

Using TIdTCPClient
SSL Client StatusInfo: SSL status: "before/connect initialization"
SSL Client StatusInfo: SSL status: "SSLv3 write client hello A"
SSL Client StatusInfo: SSL status: "SSLv3 read server hello A"
Client Exception: Socket Error # 10060
Connection timed out.
Server Connect Begin
SSL Server StatusInfo: SSL status: "before/accept initialization"
SSL Server StatusInfo: SSL status: "before/accept initialization"
SSL Server StatusInfo: SSL status: "SSLv3 read client hello A"
SSL Server StatusInfo: SSL status: "SSLv3 write server hello A"
SSL Server StatusInfo: SSL status: "SSLv3 write certificate A"
SSL Server StatusInfo: SSL status: "SSLv3 write server done A"
SSL Server StatusInfo: SSL status: "SSLv3 flush data"
SSL Server StatusInfo: SSL status: "SSLv3 read client certificate A"
Server Exception: Socket Error # 10053 - This error is due to the 10060 error I believe.

The odd part in the above, for me, is that Timeout Error 10060 seems to occurs before any server status messages.

I would appreciate any thoughts suggestions on the above.
Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: SSL Socket Error #10060 when IdTCPClient Connects to IdTCPServer withSSL  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Jan 6, 2017 6:11 PM   in response to: Bob Rasmusens in response to: Bob Rasmusens
Bob wrote:

Using TIdTCPClient
SSL Client StatusInfo: SSL status: "before/connect initialization"
SSL Client StatusInfo: SSL status: "SSLv3 write client hello A"
SSL Client StatusInfo: SSL status: "SSLv3 read server hello A"
Client Exception: Socket Error # 10060
Connection timed out.

That usually suggests that you are not connected to an SSL port. However...

Server Connect Begin
SSL Server StatusInfo: SSL status: "before/accept initialization"
SSL Server StatusInfo: SSL status: "before/accept initialization"
SSL Server StatusInfo: SSL status: "SSLv3 read client hello A"
SSL Server StatusInfo: SSL status: "SSLv3 write server hello A"
SSL Server StatusInfo: SSL status: "SSLv3 write certificate A"
SSL Server StatusInfo: SSL status: "SSLv3 write server done A"
SSL Server StatusInfo: SSL status: "SSLv3 flush data"
SSL Server StatusInfo: SSL status: "SSLv3 read client certificate A"
Server Exception: Socket Error # 10053 - This error is due to the
10060 error I believe.

Since you are getting SSL status messages on the server side, then clearly
the client is connected to an SSL port.

The odd part in the above, for me, is that Timeout Error 10060
seems to occurs before any server status messages.

Then the server is not processing and replying to the client's SSL handshake
in a timely manner before the client times out. On Vista and later, Indy's
TIdSSLIOHandlerSocketOpenSSL component sets a default 30 second timeout directly
on the underlying socket for blocking read/write operations, unless you specify
a non-infinite ReadTimeout value, in which case the component sets the socket's
timeout to that value instead. By default, Indy uses infinite timeouts.

Can you show your actual code on both ends?

--
Remy Lebeau (TeamB)
Bob Rasmusens

Posts: 10
Registered: 5/18/00
Re: SSL Socket Error #10060 when IdTCPClient Connects to IdTCPServer withSSL  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Jan 9, 2017 11:43 AM   in response to: Remy Lebeau (Te... in response to: Remy Lebeau (Te...
I found an error in my code but it does not change the question it just for me makes it more odd.
I had added in a try/except around the client.connect but left the readln outside the block.
The following is what the output looks like with this corrected.
To me it shows that even though there is a connection timeout error the SSL handshake still completes but there is no connection?

Server Setup
Client Connecting
Client Socket Connected
SSL Client Status: Connecting to 127.0.0.1.
Server Connect Begin
SSL Client StatusInfo: SSL status: "before/connect initialization"
SSL Client StatusInfo: SSL status: "before/connect initialization"
SSL Client StatusInfo: SSL status: "SSLv3 write client hello A"
SSL Client StatusInfo: SSL status: "SSLv3 read server hello A"
Client Exception: Socket Error # 10060
Connection timed out.
SSL Server StatusInfo: SSL status: "before/accept initialization"
SSL Server StatusInfo: SSL status: "before/accept initialization"
SSL Server StatusInfo: SSL status: "SSLv3 read client hello A"
SSL Server StatusInfo: SSL status: "SSLv3 write server hello A"
SSL Server StatusInfo: SSL status: "SSLv3 write certificate A"
SSL Server StatusInfo: SSL status: "SSLv3 write server done A"
SSL Server StatusInfo: SSL status: "SSLv3 flush data"
SSL Server StatusInfo: SSL status: "SSLv3 read client certificate A"
Server Exception: Socket Error # 10053
Software caused connection abort.

Below is the source code from the pasechodemo with my modifications for outputing status messages.
unit TestForm;
 
 
interface
 
uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
  System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, IdServerIOHandler, IdSSL, IdSSLOpenSSL,
  IdBaseComponent, IdComponent, IdCustomTCPServer, IdTCPServer, IdContext,
  Vcl.StdCtrls,
  IdIOHandler, IdIOHandlerSocket, IdIOHandlerStack, IdTCPConnection,
  IdTCPClient,
  IdAntiFreezeBase, Vcl.IdAntiFreeze;
 
type
  TfrmSSLIndyTest = class(TForm)
    btnSetupServer: TButton;
    IdTCPServer1: TIdTCPServer;
    IdServerIOHandlerSSLOpenSSL1: TIdServerIOHandlerSSLOpenSSL;
    memResults: TMemo;
    btnSend: TButton;
    IdTCPClient1: TIdTCPClient;
    IdSSLIOHandlerSocketOpenSSL1: TIdSSLIOHandlerSocketOpenSSL;
    btnSetupClient: TButton;
    edtEcho: TEdit;
    btnCloseServer: TButton;
    btnCloseClient: TButton;
    Label1: TLabel;
    IdAntiFreeze1: TIdAntiFreeze;
    procedure btnSetupServerClick(Sender: TObject);
    procedure btnSendClick(Sender: TObject);
    procedure btnCloseClientClick(Sender: TObject);
    procedure btnCloseServerClick(Sender: TObject);
    procedure btnSetupClientClick(Sender: TObject);
    procedure IdSSLIOHandlerSocketOpenSSL1Status(ASender: TObject;
      const AStatus: TIdStatus; const AStatusText: string);
    procedure IdServerIOHandlerSSLOpenSSL1Status(ASender: TObject;
      const AStatus: TIdStatus; const AStatusText: string);
    procedure IdServerIOHandlerSSLOpenSSL1StatusInfo(const AMsg: string);
    procedure IdSSLIOHandlerSocketOpenSSL1StatusInfo(const AMsg: string);
    procedure IdTCPServer1Status(ASender: TObject; const AStatus: TIdStatus;
      const AStatusText: string);
    procedure IdTCPClient1Status(ASender: TObject; const AStatus: TIdStatus;
      const AStatusText: string);
    procedure IdTCPServer1Connect(AContext: TIdContext);
    procedure IdTCPServer1Exception(AContext: TIdContext;
      AException: Exception);
    procedure IdTCPServer1ListenException(AThread: TIdListenerThread;
      AException: Exception);
    function IdSSLIOHandlerSocketOpenSSL1VerifyPeer(Certificate: TIdX509;
      AOk: Boolean; ADepth, AError: Integer): Boolean;
    function IdServerIOHandlerSSLOpenSSL1VerifyPeer(Certificate: TIdX509;
      AOk: Boolean; ADepth, AError: Integer): Boolean;
    procedure IdTCPClient1Connected(Sender: TObject);
    procedure IdTCPClient1SocketAllocated(Sender: TObject);
 
  private
    { Private declarations }
    procedure ServerExecute(AContext: TIdContext);
    procedure GetPassword(var Password: string);
    procedure ServerConnect(AContext: TIdContext);
  public
    { Public declarations }
  end;
 
var
  frmSSLIndyTest: TfrmSSLIndyTest;
 
implementation
 
const
  SERVER_PORT = 6050;
 
{$R *.dfm}
 
procedure TfrmSSLIndyTest.btnSetupServerClick(Sender: TObject);
begin
  // In the real world:
  // FileNames should not be hardcoded, let the be configured external.
  // Certs expire and change be prepared to handle it.
  IdServerIOHandlerSSLOpenSSL1.SSLOptions.CertFile :=
    'D:\DevelAll\Test Code\SSL\keys\self-signed\localhost.cert.pem';
  IdServerIOHandlerSSLOpenSSL1.SSLOptions.KeyFile :=
    'D:\DevelAll\Test Code\SSL\keys\self-signed\localhost.key.pem';
  IdServerIOHandlerSSLOpenSSL1.SSLOptions.RootCertFile :=
    'D:\DevelAll\Test Code\SSL\keys\self-signed\ca.cert.pem';
  IdServerIOHandlerSSLOpenSSL1.SSLOptions.Mode := sslmServer;
  IdServerIOHandlerSSLOpenSSL1.SSLOptions.VerifyMode := [];
  IdServerIOHandlerSSLOpenSSL1.SSLOptions.VerifyDepth := 0;
  IdServerIOHandlerSSLOpenSSL1.SSLOptions.SSLVersions := [sslvTLSv1_2];
  // Avoid using SSL
  IdServerIOHandlerSSLOpenSSL1.OnGetPassword := GetPassword;
 
  IdTCPServer1.DefaultPort := SERVER_PORT;
  IdTCPServer1.IOHandler := IdServerIOHandlerSSLOpenSSL1;
  IdTCPServer1.OnConnect := ServerConnect;
 
  IdTCPServer1.OnExecute := ServerExecute;
  IdTCPServer1.Active := True;
  memResults.Lines.add('Server Setup');
 
end;
 
procedure TfrmSSLIndyTest.btnSendClick(Sender: TObject);
begin
  IdTCPClient1.IOHandler.WriteLn(edtEcho.text);
  memResults.Lines.add(IdTCPClient1.IOHandler.Readln());
end;
 
procedure TfrmSSLIndyTest.btnSetupClientClick(Sender: TObject);
begin
  // Ok for self singned but you will want to verify if you are using signed certs
  IdSSLIOHandlerSocketOpenSSL1.SSLOptions.VerifyMode := [];
  IdSSLIOHandlerSocketOpenSSL1.SSLOptions.VerifyDepth := 0;
 
  IdSSLIOHandlerSocketOpenSSL1.SSLOptions.SSLVersions := [sslvTLSv1_2];
  IdSSLIOHandlerSocketOpenSSL1.SSLOptions.Mode := sslmUnassigned;
 
  IdTCPClient1.Host := '127.0.0.1';
  IdTCPClient1.Port := SERVER_PORT;
  IdTCPClient1.ReadTimeout := 50;
  IdTCPClient1.IOHandler := IdSSLIOHandlerSocketOpenSSL1;
 
  memResults.Lines.add('Client Connecting');
  Application.ProcessMessages;
  try
    IdTCPClient1.Connect;
    memResults.Lines.add('Client Connected');
    memResults.Lines.add(IdTCPClient1.IOHandler.Readln);
  except
    on E: Exception do
    begin
      memResults.Lines.add('Client Exception: ' + E.Message);
    end;
  end;
 
end;
 
procedure TfrmSSLIndyTest.btnCloseServerClick(Sender: TObject);
begin
  IdTCPServer1.Active := false;
end;
 
procedure TfrmSSLIndyTest.btnCloseClientClick(Sender: TObject);
begin
  IdTCPClient1.SendCmd('QUIT');
  IdTCPClient1.Disconnect;
end;
 
procedure TfrmSSLIndyTest.GetPassword(var Password: string);
begin
  // In the real world:
  // This should never be hardcoded as it could change when the cert changes.
  // Don't use Dictonary Words or your key can be brute force attacked.
 Password := 'test';
end;
 
procedure TfrmSSLIndyTest.IdServerIOHandlerSSLOpenSSL1Status(ASender: TObject;
  const AStatus: TIdStatus; const AStatusText: string);
begin
  memResults.Lines.add('SSL Server Status: ' + AStatusText);
end;
 
procedure TfrmSSLIndyTest.IdServerIOHandlerSSLOpenSSL1StatusInfo
  (const AMsg: string);
begin
  memResults.Lines.add('SSL Server StatusInfo: ' + AMsg);
end;
 
function TfrmSSLIndyTest.IdServerIOHandlerSSLOpenSSL1VerifyPeer
  (Certificate: TIdX509; AOk: Boolean; ADepth, AError: Integer): Boolean;
begin
  Result := True;
end;
 
procedure TfrmSSLIndyTest.IdSSLIOHandlerSocketOpenSSL1Status(ASender: TObject;
  const AStatus: TIdStatus; const AStatusText: string);
begin
  memResults.Lines.add('SSL Client Status: ' + AStatusText);
end;
 
procedure TfrmSSLIndyTest.IdSSLIOHandlerSocketOpenSSL1StatusInfo
  (const AMsg: string);
begin
  memResults.Lines.add('SSL Client StatusInfo: ' + AMsg);
end;
 
function TfrmSSLIndyTest.IdSSLIOHandlerSocketOpenSSL1VerifyPeer
  (Certificate: TIdX509; AOk: Boolean; ADepth, AError: Integer): Boolean;
begin
  Result := True;
end;
 
procedure TfrmSSLIndyTest.IdTCPClient1Connected(Sender: TObject);
begin
  memResults.Lines.add('Client Connected');
end;
 
procedure TfrmSSLIndyTest.IdTCPClient1SocketAllocated(Sender: TObject);
begin
  memResults.Lines.add('Client Socket Connected');
end;
 
procedure TfrmSSLIndyTest.IdTCPClient1Status(ASender: TObject;
  const AStatus: TIdStatus; const AStatusText: string);
begin
  memResults.Lines.add('Client Status: ' + AStatusText);
end;
 
procedure TfrmSSLIndyTest.IdTCPServer1Connect(AContext: TIdContext);
begin
  memResults.Lines.add('Server Connect');
end;
 
procedure TfrmSSLIndyTest.IdTCPServer1Exception(AContext: TIdContext;
  AException: Exception);
begin
  memResults.Lines.add('Server Exception: ' + AException.Message);
end;
 
procedure TfrmSSLIndyTest.IdTCPServer1ListenException
  (AThread: TIdListenerThread; AException: Exception);
begin
  memResults.Lines.add('Server Listen Exception: ' + AException.Message);
end;
 
procedure TfrmSSLIndyTest.IdTCPServer1Status(ASender: TObject;
  const AStatus: TIdStatus; const AStatusText: string);
begin
  memResults.Lines.add('Server Status: ' + AStatusText);
end;
 
procedure TfrmSSLIndyTest.ServerConnect(AContext: TIdContext);
begin
  memResults.Lines.add('Server Connect Begin');
 
  // These two lines are required to get SSL to work.
  if (AContext.Connection.IOHandler is TIdSSLIOHandlerSocketBase) then
  begin
    TIdSSLIOHandlerSocketBase(AContext.Connection.IOHandler)
      .PassThrough := false;
  end;
 
  memResults.Lines.add('Server Connect End');
 
end;
 
procedure TfrmSSLIndyTest.ServerExecute(AContext: TIdContext);
var
  lCmdLine: string;
  connected: Boolean;
begin
  AContext.Connection.IOHandler.WriteLn('Welcome to the Echo Server');
  connected := True;
  while connected do
  begin
    lCmdLine := AContext.Connection.IOHandler.Readln;
    AContext.Connection.IOHandler.WriteLn('>' + lCmdLine);
 
    if SameText(lCmdLine, 'QUIT') then
    begin
      AContext.Connection.IOHandler.WriteLn('Disconnecting');
      AContext.Connection.Disconnect;
      connected := false;
    end;
  end;
end;
 
end.
Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: SSL Socket Error #10060 when IdTCPClient Connects to IdTCPServerwithSSL  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Jan 9, 2017 12:57 PM   in response to: Bob Rasmusens in response to: Bob Rasmusens
Bob wrote:

The following is what the output looks like with this corrected.

To me it shows that even though there is a connection timeout error
the SSL handshake still completes but there is no connection?

No, it does not complete, and that is not what the log is indicating. It
is indicating that the server does not start processing the client's handshake
until after the client has already timed out. The client sends its SSL hello
and then times out waiting for a reply. The hello is in the socket's inbound
buffer on the server side, so the server can still receive it, but the server
then times out waiting for the client's SSL certificate after sending the
server's SSL hello. The client does not send its certificate since the client
had timed out waiting for the server's hello.

Below is the source code from the pasechodemo with my modifications
for outputing status messages.

I see problems with your code. In particular, your server's event handlers
are not thread-safe. TIdTCPServer is a multi-threaded component, its events
are triggered in the context of worker threads. You MUST synchronize with
the main thread when accessing the UI, bu you are not doing that. That can
easily cause delays/deadlocks, and a whole lot of other problems.

On a side note, if you run the client and server in the same process, any
sync you perform will normally be blocked while the client is busy doing
something (connecting to the server, writing/reading data, etc). The client
is running in the main UI thread, and will block the main message loop.
To avoid that, you do have a TIdAntiFreeze component on your MainForm, which
allows Indy to call Application.ProcessMessages() periodically, but that
is not without its share of problems, too. If the client and server are
in the same process, it would be better to move the client to a worker thread
so the main thread is not blocked at all. Otherwise, run the client and
server in separate processes.

Also, your server's OnExecute code is not technically wrong, but it is not
ideal, either. You should send the greeting in the OnConnect event instead
(or even just use the server's Greeting property), and the manual loop should
be removed from the OnExecute event as it is a looped event to begin with.
TIdTCPServer calls OnExecute in a continuous loop for the life of the connection,
so just read one client message, reply to it, and then exit, letting the
server call the event again for the next message.

Try something more like this:

unit TestForm;
 
interface
 
uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes,
  Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, IdServerIOHandler, 
IdSSL, IdSSLOpenSSL,
  IdBaseComponent, IdComponent, IdCustomTCPServer, IdTCPServer, IdContext,
  Vcl.StdCtrls, IdIOHandler, IdIOHandlerSocket, IdIOHandlerStack, IdTCPConnection, 
IdTCPClient,
  IdAntiFreezeBase, Vcl.IdAntiFreeze;
 
type
  TfrmSSLIndyTest = class(TForm)
    btnSetupServer: TButton;
    IdTCPServer1: TIdTCPServer;
    IdServerIOHandlerSSLOpenSSL1: TIdServerIOHandlerSSLOpenSSL;
    memResults: TMemo;
    btnSend: TButton;
    IdTCPClient1: TIdTCPClient;
    IdSSLIOHandlerSocketOpenSSL1: TIdSSLIOHandlerSocketOpenSSL;
    btnSetupClient: TButton;
    edtEcho: TEdit;
    btnCloseServer: TButton;
    btnCloseClient: TButton;
    Label1: TLabel;
    IdAntiFreeze1: TIdAntiFreeze;
    procedure btnSetupServerClick(Sender: TObject);
    procedure btnSendClick(Sender: TObject);
    procedure btnCloseClientClick(Sender: TObject);
    procedure btnCloseServerClick(Sender: TObject);
    procedure btnSetupClientClick(Sender: TObject);
    procedure IdSSLIOHandlerSocketOpenSSL1Status(ASender: TObject; const 
AStatus: TIdStatus; const AStatusText: string);
    procedure IdSSLIOHandlerSocketOpenSSL1StatusInfo(const AMsg: string);
    function IdSSLIOHandlerSocketOpenSSL1VerifyPeer(Certificate: TIdX509; 
AOk: Boolean; ADepth, AError: Integer): Boolean;
    procedure IdServerIOHandlerSSLOpenSSL1GetPassword(var Password: string);
    procedure IdServerIOHandlerSSLOpenSSL1Status(ASender: TObject; const 
AStatus: TIdStatus; const AStatusText: string);
    procedure IdServerIOHandlerSSLOpenSSL1StatusInfo(const AMsg: string);
    function IdServerIOHandlerSSLOpenSSL1VerifyPeer(Certificate: TIdX509; 
AOk: Boolean; ADepth, AError: Integer): Boolean;
    procedure IdTCPClient1Connected(Sender: TObject);
    procedure IdTCPClient1Disconnected(Sender: TObject);
    procedure IdTCPClient1Status(ASender: TObject; const AStatus: TIdStatus; 
const AStatusText: string);
    procedure IdTCPServer1Connect(AContext: TIdContext);
    procedure IdTCPServer1Disconnect(AContext: TIdContext);
    procedure IdTCPServer1Execute(AContext: TIdContext);
    procedure IdTCPServer1Exception(AContext: TIdContext; AException: Exception);
    procedure IdTCPServer1ListenException(AThread: TIdListenerThread; AException: 
Exception);
    procedure IdTCPServer1Status(ASender: TObject; const AStatus: TIdStatus; 
const AStatusText: string);
  private
    { Private declarations }
    procedure Log(const Msg: String);
  public
    { Public declarations }
end;
 
var
  frmSSLIndyTest: TfrmSSLIndyTest;
 
implementation
 
const
  SERVER_PORT = 6050;
 
{$R *.dfm}
 
procedure TfrmSSLIndyTest.Log(const Msg: String);
begin
  TThread.Queue(nil,
    procedure
    begin
      memResults.Lines.Add(Msg);
    end
  );
end;
 
procedure TfrmSSLIndyTest.btnSetupServerClick(Sender: TObject);
begin
  Log('Server Setup Begin');
 
  // In the real world:
  // FileNames should not be hardcoded, let them be configured external.
  // Certs expire and change be prepared to handle it.
  IdServerIOHandlerSSLOpenSSL1.SSLOptions.CertFile := 'D:\DevelAll\Test Code\SSL\keys\self-signed\localhost.cert.pem';
  IdServerIOHandlerSSLOpenSSL1.SSLOptions.KeyFile := 'D:\DevelAll\Test Code\SSL\keys\self-signed\localhost.key.pem';
  IdServerIOHandlerSSLOpenSSL1.SSLOptions.RootCertFile := 'D:\DevelAll\Test 
Code\SSL\keys\self-signed\ca.cert.pem';
  IdServerIOHandlerSSLOpenSSL1.SSLOptions.VerifyMode := [];
  IdServerIOHandlerSSLOpenSSL1.SSLOptions.VerifyDepth := 0;
  IdServerIOHandlerSSLOpenSSL1.SSLOptions.SSLVersions := [sslvTLSv1_2];
 
  // these can all be assigned at design-time, and should be in this example...
  //IdServerIOHandlerSSLOpenSSL1.SSLOptions.Mode := sslmServer;
  //IdServerIOHandlerSSLOpenSSL1.OnGetPassword := IdServerIOHandlerSSLOpenSSL1GetPassword;
  //IdTCPServer1.DefaultPort := SERVER_PORT;
  //IdTCPServer1.IOHandler := IdServerIOHandlerSSLOpenSSL1;
  //IdTCPServer1.OnConnect := IdTCPServer1Connect;
  //IdTCPServer1.OnDisconnect := IdTCPServer1Disconnect;
  //IdTCPServer1.OnExecute := IdTCPServer1Execute;
  //IdTCPServer1.OnException := IdTCPServer1Exception;
  //IdTCPServer1.OnListenException := IdTCPServer1ListenException;
  //IdTCPServer1.OnStatus := IdTCPServer1Status;
 
  IdTCPServer1.Active := True;
  Log('Server Setup End');
end;
 
procedure TfrmSSLIndyTest.btnSendClick(Sender: TObject);
begin
  IdTCPClient1.IOHandler.WriteLn(edtEcho.text);
  Log(IdTCPClient1.IOHandler.ReadLn);
end;
 
procedure TfrmSSLIndyTest.btnSetupClientClick(Sender: TObject);
begin
  // Ok for self signed but you will want to verify if you are using signed 
certs
  IdSSLIOHandlerSocketOpenSSL1.SSLOptions.VerifyMode := [];
  IdSSLIOHandlerSocketOpenSSL1.SSLOptions.VerifyDepth := 0;
  IdSSLIOHandlerSocketOpenSSL1.SSLOptions.SSLVersions := [sslvTLSv1_2];
 
  // these can all be assigned at design-time, and should be in this example...
  //IdSSLIOHandlerSocketOpenSSL1.SSLOptions.Mode := sslmClient;
  //IdTCPClient1.Host := '127.0.0.1';
  //IdTCPClient1.Port := SERVER_PORT;
  //IdTCPClient1.ConnectTimeout := 5000;
  //IdTCPClient1.ReadTimeout := 50;
  //IdTCPClient1.IOHandler := IdSSLIOHandlerSocketOpenSSL1;
  //IdTCPClient1.OnConnect := IdTCPClient1Connected;
  //IdTCPClient1.OnDisconnect := IdTCPClient1Disconnected;
  //IdTCPClient1.OnStatus := IdTCPClient1Status;
 
  Log('Client Connecting');
  Update;
  try
    IdTCPClient1.Connect;
    try
      Log(IdTCPClient1.IOHandler.ReadLn);
    except
      IdTCPClient1.Disconnect;
      raise;
    end;
  except
    on E: Exception do
    begin
      Log('Client Exception: ' + E.Message);
    end;
  end;
end;
 
procedure TfrmSSLIndyTest.btnCloseServerClick(Sender: TObject);
begin
  IdTCPServer1.Active := false;
end;
 
procedure TfrmSSLIndyTest.btnCloseClientClick(Sender: TObject);
begin
  try
    IdTCPClient1.IOHandler.WriteLn('QUIT');
    Log(IdTCPClient1.IOHandler.ReadLn);
  finally
    IdTCPClient1.Disconnect;
  end;
end;
 
procedure TfrmSSLIndyTest.IdServerIOHandlerSSLOpenSSL1GetPassword(var Password: 
string);
begin
  // In the real world:
  // This should never be hardcoded as it could change when the cert changes.
  // Don't use Dictonary Words or your key can be brute force attacked.
  Password := 'test';
end;
 
procedure TfrmSSLIndyTest.IdServerIOHandlerSSLOpenSSL1Status(ASender: TObject; 
const AStatus: TIdStatus; const AStatusText: string);
begin
  Log('Server SSL Status: ' + AStatusText);
end;
 
procedure TfrmSSLIndyTest.IdServerIOHandlerSSLOpenSSL1StatusInfo(const AMsg: 
string);
begin
  Log('Server SSL StatusInfo: ' + AMsg);
end;
 
function TfrmSSLIndyTest.IdServerIOHandlerSSLOpenSSL1VerifyPeer(Certificate: 
TIdX509; AOk: Boolean; ADepth, AError: Integer): Boolean;
begin
  Result := True;
end;
 
procedure TfrmSSLIndyTest.IdSSLIOHandlerSocketOpenSSL1Status(ASender: TObject; 
const AStatus: TIdStatus; const AStatusText: string);
begin
  Log('Client SSL Status: ' + AStatusText);
end;
 
procedure TfrmSSLIndyTest.IdSSLIOHandlerSocketOpenSSL1StatusInfo(const AMsg: 
string);
begin
  Log('Client SSL StatusInfo: ' + AMsg);
end;
 
function TfrmSSLIndyTest.IdSSLIOHandlerSocketOpenSSL1VerifyPeer(Certificate: 
TIdX509; AOk: Boolean; ADepth, AError: Integer): Boolean;
begin
  Result := True;
end;
 
procedure TfrmSSLIndyTest.IdTCPClient1Connected(Sender: TObject);
begin
  Log('Client Connected');
end;
 
procedure TfrmSSLIndyTest.IdTCPClient1Disconnected(Sender: TObject);
begin
  Log('Client Disconnected');
end;
 
procedure TfrmSSLIndyTest.IdTCPClient1Status(ASender: TObject; const AStatus: 
TIdStatus; const AStatusText: string);
begin
  Log('Client Status: ' + AStatusText);
end;
 
procedure TfrmSSLIndyTest.IdTCPServer1Connect(AContext: TIdContext);
begin
  Log('Client Connected to Server');
  // These two lines are required to get SSL to work.
  if (AContext.Connection.IOHandler is TIdSSLIOHandlerSocketBase) then
  begin
    TIdSSLIOHandlerSocketBase(AContext.Connection.IOHandler).PassThrough 
:= False;
  end;
  AContext.Connection.IOHandler.WriteLn('Welcome to the Echo Server');
end;
 
procedure TfrmSSLIndyTest.IdTCPServer1Disconnect(AContext: TIdContext);
begin
  Log('Client Disconnected from Server');
end;
 
procedure TfrmSSLIndyTest.IdTCPServer1Execute(AContext: TIdContext);
var
  lCmdLine: string;
begin
  lCmdLine := AContext.Connection.IOHandler.ReadLn;
  AContext.Connection.IOHandler.WriteLn('>' + lCmdLine);
  if TextIsSame(lCmdLine, 'QUIT') then
  begin
    Log('Client Disconnecting from Server');
    AContext.Connection.Disconnect;
  end;
end;
 
procedure TfrmSSLIndyTest.IdTCPServer1Exception(AContext: TIdContext; AException: 
Exception);
begin
  Log('Server Exception: ' + AException.Message);
end;
 
procedure TfrmSSLIndyTest.IdTCPServer1ListenException(AThread: TIdListenerThread; 
AException: Exception);
begin
  Log('Server Listen Exception: ' + AException.Message);
end;
 
procedure TfrmSSLIndyTest.IdTCPServer1Status(ASender: TObject; const AStatus: 
TIdStatus; const AStatusText: string);
begin
  Log('Server Status: ' + AStatusText);
end;
 
end.


--
Remy Lebeau (TeamB)
Bob Rasmusens

Posts: 10
Registered: 5/18/00
Re: SSL Socket Error #10060 when IdTCPClient Connects to IdTCPServer with SSL  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Jan 9, 2017 1:46 PM   in response to: Bob Rasmusens in response to: Bob Rasmusens
Noted the comments and suggestions you made most of which I was aware but obviously not paying attention.
With your changes everything worked correctly.

Thank-you very much.
Legend
Helpful Answer (5 pts)
Correct Answer (10 pts)

Server Response from: ETNAJIVE02