Archived Forum Post

Index of archived forum posts

Question:

TlsRenegotiate gives error

May 17 '16 at 06:28

When I try no perform a TlsRenegotiate, it always fails with this error:

ChilkatLog:
  TlsRenegotiate:
    ChilkatVersion: 9.5.0.56
    socket2_tlsRenegotiate:
      clientRenegotiate:
        clientHandshake:
          clientHandshake2:
            readHandshakeMessages:
              processAlert:
                TlsAlert:
                  level: fatal
                  descrip: internal error
                --TlsAlert
                Closing connection in response to fatal SSL/TLS alert.
              --processAlert
              Aborting handshake because of fatal alert.
            --readHandshakeMessages
          --clientHandshake2
        --clientHandshake
      --clientRenegotiate
    --socket2_tlsRenegotiate
    Failed.
  --TlsRenegotiate
--ChilkatLog
Any idea why this is happening?


Accepted Answer

The problem is fixed: It should now be possible to initiate the TlsRenegotiate from both sides: client or server.

Here's the new build:
32-bit Download: http://www.chilkatsoft.com/download/preRelease/ChilkatDotNet4-9.5.0-win32.zip
64-bit Download: http://www.chilkatsoft.com/download/preRelease/ChilkatDotNet4-9.5.0-x64.zip


Answer

Thanks. I don't know why it's happening, but I can describe in a little more detail. The "internal error" is a message sent from the server to Chilkat. You called TlsRenegotiate, and Chilkat sends the TLS protocol message to begin renegotiation. The server then responded with a TLS alert with the message "internal error". My guess is that the server implementation had just that -- an internal implementation error. In other words, it's likely some sort of internal assertion failed and the "internal error" was the action taken. (By the way.. TLS servers can, and should, sometimes send error messages that cloud the real reason for failure, and this is for security purposes. But I don't recall anything from the TLS protocol specs about sending an "internal error" in lieu of something else..)

When I have a chance, I'll give the TlsRenegotiate a test. It should already be in the QA test suite, so a new release can't go out without passing it..


Answer

Thanks! I tested by initiating the renegotiate from the client side. As far as I know, the renegotiate can be initiated by either side at any time. I'll test by initiating from the server-side.

Here's a snippet of my C++ code I used for testing:

Client Side

    success = sock.Connect("localhost",QA_ACCEPT_PORT,true,1000);
    if (!success) QA_FAILED_LASTERR(sock);
    printf("Client connected.n");

// Send something..
success = sock.SendString("Hello 1");
if (!success) QA_FAILED_LASTERR(sock);

// Now renegotiate.
success = sock.TlsRenegotiate();
if (!success) QA_FAILED_LASTERR(sock);

// Now send something else.
success = sock.SendString("Hello 2");
if (!success) QA_FAILED_LASTERR(sock);

// Read the final response.
CkString s;
success = sock.ReceiveUntilMatch("1",s);
if (!success) QA_FAILED_LASTERR(sock);

printf("Received %s\n",s.getString());

Server Side

    //  Accept a single client connection and establish the secure SSL/TLS channel:
    CkSocket *clientSock = 0;
    int maxWaitMillisec = 5000;
    clientSock = listenSslSocket.AcceptNextConnection(maxWaitMillisec);
    if (clientSock == 0 ) {
    printf("AcceptFailReason: %dn",listenSslSocket.get_AcceptFailReason());
        std::cout << listenSslSocket.lastErrorText() << "rn";
        return;
    }
        //std::cout << listenSslSocket.lastErrorText() << "rn";

printf("accepted client sock TLS version: %s\n",clientSock->tlsVersion());
printf("accepted client sock TLS cipherSuite: %s\n",clientSock->tlsCipherSuite());

printf("listen sock TLS version: %s\n",listenSslSocket.tlsVersion());
printf("listen sock TLS cipherSuite: %s\n",listenSslSocket.tlsCipherSuite());

printf("Client connection accepted.\n");

if (testNum == TLS_TEST_RENEGOTIATE)
{
CkString s;
success = clientSock->ReceiveUntilMatch("1",s);
if (!success) 
    {
    std::cout << clientSock->lastErrorText() << "\r\n";
    delete clientSock;
    return;
    }
    //std::cout << clientSock->lastErrorText() << "\r\n";
printf("Server received %s\n",s.getString());

s.clear();
success = clientSock->ReceiveUntilMatch("2",s);
if (!success) 
    {
    std::cout << clientSock->lastErrorText() << "\r\n";
    delete clientSock;
    return;
    }
   // std::cout << clientSock->lastErrorText() << "\r\n";
printf("Server received %s\n",s.getString());

success = clientSock->SendString("Hello my client 1");
if (!success) 
    {
    std::cout << clientSock->lastErrorText() << "\r\n";
    delete clientSock;
    return;
    }
printf("Server sent msg\n");
}

delete clientSock;

Answer

To clarify: To renegotiate the TLS connection, one side calls TlsRenegotiate. The other side automatically handles it within the communications. In the example above, the client calls TlsRenegotiate after sending "Hello 1". On the server side, the 2nd call to ReceiveUntilMatch will (internally) receive the renegotiate and automatically handle it. Your application code never has to worry about explicitly handling an incoming renegotiate -- it's just part of the TLS protocol..


Answer

After some investigation, it seemed renegotiation was only working from the client side to the server side, but not the other way around. Thanks to a quick fix, I now have a version which works both sides.