#1 2019-02-04 17:42:16

damiand
Member
From: Greece
Registered: 2018-09-21
Posts: 94

OpenHttp raises ECrtSocket exception

Trying to execute the following line

Http := OpenHttp('https://test3.diavgeia.gov.gr/luminapi/opendata/decisions', nil);

raises the following exception:

Project test1.exe raised exception class ECrtSocket with message 'OpenBind(test3.diavgeia.gov.gr:443,open): aTLS failed [ESChannel System Error 87 [The parameter is incorrect]] [87  "The parameter is incorrect"]'. Process stopped. Use Step or Run to continue.

at line 4765 of SynCrtSock.pas:

fSecure.AfterConnection(fSock,pointer(aServer));

which belongs to the procedure OpenBind:

procedure TCrtSocket.OpenBind(const aServer, aPort: SockString;
  doBind: boolean; aSock: integer; aLayer: TCrtSocketLayer; aTLS: boolean);
const BINDTXT: array[boolean] of string[4] = ('open','bind');
      BINDMSG: array[boolean] of string = ('Is a server running on this address:port?',
        'Another process may be currently listening to this port!');
begin
  fSocketLayer := aLayer;
  if aSock<0 then begin
    if (aPort='') and (aLayer<>cslUNIX) then
      fPort := DEFAULT_PORT[aTLS] else // default port is 80/443 (HTTP/S)
      fPort := aPort;
    fServer := aServer;
    fSock := CallServer(aServer,Port,doBind,aLayer,Timeout); // OPEN or BIND
    if fSock<0 then
      raise ECrtSocket.CreateFmt('OpenBind(%s:%s,%s) failed: %s',
        [aServer,fPort,BINDTXT[doBind],BINDMSG[doBind]],-1);
  end else
    fSock := aSock; // ACCEPT mode -> socket is already created by caller
  if TimeOut>0 then begin // set timout values for both directions
    ReceiveTimeout := TimeOut;
    SendTimeout := TimeOut;
  end;
  if aLayer = cslTCP then begin
    TCPNoDelay := 1; // disable Nagle algorithm since we use our own buffers
    KeepAlive := 1; // enable TCP keepalive (even if we rely on transport layer)
    if aTLS and (aSock<0) and not doBind then
    try
      {$ifdef MSWINDOWS}
      fSecure.AfterConnection(fSock,pointer(aServer));
      {$else}
      raise ECrtSocket.Create('Unsupported');
      {$endif MSWINDOWS}
      fTLS := true;
    except
      on E: Exception do
        raise ECrtSocket.CreateFmt('OpenBind(%s:%s,%s): aTLS failed [%s %s]',
          [aServer,Port,BINDTXT[doBind],E.ClassName,E.Message],-1);
    end;
  end;
end;

Do you have any idea why it is happening? System is Windows 7 64-bit professional, compilers are either Delphi 6 or Lazarus 2.1.0/FPC 3.3.1. Thanks.

Offline

#2 2019-02-04 22:06:35

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,182
Website

Re: OpenHttp raises ECrtSocket exception

Offline

#3 2019-02-05 04:03:14

Chaa
Member
Registered: 2011-03-26
Posts: 244

Re: OpenHttp raises ECrtSocket exception

In my Windows 10, the real error message is SEC_E_INVALID_TOKEN: The token supplied to the function is invalid, when function InitializeSecurityContext called second time in TSChannelClient.HandshakeLoop.

Commit [4dd8e7cce5] not important here, as TSChannelClient.Send is not called at all.

Offline

#4 2019-02-05 05:00:54

Chaa
Member
Registered: 2011-03-26
Posts: 244

Re: OpenHttp raises ECrtSocket exception

damiand, I see two problems with your server:

1. Your server has requested a client certificate, but do not require it.
You can avoid problem with it by adding ISC_REQ_USE_SUPPLIED_CREDS to ISC_REQ_FLAGS const.

2. First call to Recv returns only 4096 bytes and InitializeSecurityContext fails with SEC_E_INVALID_TOKEN (but should be SEC_E_INCOMPLETE_MESSAGE, I guess).
If I insert some delay before first call to Recv, then I recieve 4995 bytes and handshake succeeded.

Last edited by Chaa (2019-02-05 08:58:07)

Offline

#5 2019-02-05 09:44:53

damiand
Member
From: Greece
Registered: 2018-09-21
Posts: 94

Re: OpenHttp raises ECrtSocket exception

Chaa wrote:

If I insert some delay before first call to Recv, then I recieve 4995 bytes and handshake succeeded.

Thank you both ab and Chaa for your help and the latter's in depth analysis. Following Chaa's recommendation, I added the following in SynWinStock.pas:

  ISC_REQ_FLAGS =
    ISC_REQ_SEQUENCE_DETECT or ISC_REQ_REPLAY_DETECT or
    ISC_REQ_CONFIDENTIALITY or ISC_REQ_EXTENDED_ERROR or
    ISC_REQ_ALLOCATE_MEMORY or ISC_REQ_STREAM
// added by damian for https://synopse.info/forum/viewtopic.php?pid=28971#p28971
    or ISC_REQ_USE_SUPPLIED_CREDS;

and after trial and error, the following sleep call before calling HandshakeLoop in TSChannelClient.AfterConnection procedure:

  
  sleep(40);
  HandshakeLoop(aSocket);

In my hardware and internet connection, sleep parameters till 30 were inadequate, but sleep(40) prevents the exception. However, this does not seem to be safe enough and infrastructure independent. If the above can lead you to any conclusion about this, you are most welcomed. smile

Last edited by damiand (2019-02-11 09:05:18)

Offline

#6 2019-02-05 10:30:26

damiand
Member
From: Greece
Registered: 2018-09-21
Posts: 94

Re: OpenHttp raises ECrtSocket exception

Chaa wrote:

Commit [4dd8e7cce5] not important here, as TSChannelClient.Send is not called at all.

Indeed. I applied the patch (removed len assignment after trailer and added the new len assignment before sent := 0) but the code doesn't seem to be called in this case.

By the way, the build I'm using is mORMot_and_Open_Source_friends_2019-01-23_234301_06b24ae728

Last edited by damiand (2019-02-05 10:36:21)

Offline

#7 2019-02-05 11:18:57

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,182
Website

Re: OpenHttp raises ECrtSocket exception

Did you try with the latest trunk?

Offline

#8 2019-02-05 11:30:42

damiand
Member
From: Greece
Registered: 2018-09-21
Posts: 94

Re: OpenHttp raises ECrtSocket exception

I've just cloned the github repository, side by side with my original installation, and the problem persists.

Offline

#9 2019-02-11 09:16:16

damiand
Member
From: Greece
Registered: 2018-09-21
Posts: 94

Re: OpenHttp raises ECrtSocket exception

Just for information, I overcame the problem by calling directly TWinHTTP.Post, as follows:

procedure TForm1.Button2Click(Sender: TObject);
var
  sResponse, sData, sOutHeaders: SockString;
begin
     SetPostHeaders;
     sData := ConstructDataString;
     sResponse := TWinHTTP.Post(sURL + '/decisions', sData, sHeaders, true, @sOutHeaders);
    ...
end;

Offline

Board footer

Powered by FluxBB