tech-pkg archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: wip.pkgsrc.org broken TLS? (GnuTLS Fatal error: The TLS connection was non-properly terminated.)



Am Sun, 16 Aug 2020 13:13:10 +0000
schrieb S.P.Zeidler <spz%NetBSD.org@localhost>: 

> Thus wrote Dr. Thomas Orgis (thomas.orgis%uni-hamburg.de@localhost):
> 
> > Connecting to wip.pkgsrc.org (wip.pkgsrc.org)|2a00:19e0:3004:219:2a92:4aff:fe33:3b71|:443... failed: Connection refused.  
> 
> that should be fixed.

Seems to be right now, got IPv6 response now … maybe that's an artifact
of the server being down for a time? It didn't respond in between
testing on Saturday.

> wip.pkgsrc.org's httpd now supposedly sends a TLS shutdown notification
> (someone have a decent analyzer?) but doesn't wait around for an ack,
> but just exits. gnutls-cli still thinks it stinks.

It's supposed to send close_notify, but closes the connection, also the
read side, before receiving the same? This would mean GnuTLS errors on
writing it's close_notify  …  or is GnuTLS closing its end and
expecting an orderly close of the server side and doesn't get that?

Possibly in preparation for bug report for either participant … this
should be the relevant sections.

	https://tools.ietf.org/html/rfc5246#section-7.2.1
(TLS 1.2)

7.2.1.  Closure Alerts

   The client and the server must share knowledge that the connection is
   ending in order to avoid a truncation attack.  Either party may
   initiate the exchange of closing messages.

   close_notify
      This message notifies the recipient that the sender will not send
      any more messages on this connection.  Note that as of TLS 1.1,
      failure to properly close a connection no longer requires that a
      session not be resumed.  This is a change from TLS 1.0 to conform
      with widespread implementation practice.

   Either party may initiate a close by sending a close_notify alert.
   Any data received after a closure alert is ignored.

   Unless some other fatal alert has been transmitted, each party is
   required to send a close_notify alert before closing the write side
   of the connection.  The other party MUST respond with a close_notify
   alert of its own and close down the connection immediately,
   discarding any pending writes.  It is not required for the initiator
   of the close to wait for the responding close_notify alert before
   closing the read side of the connection.

   If the application protocol using TLS provides that any data may be
   carried over the underlying transport after the TLS connection is
   closed, the TLS implementation must receive the responding
   close_notify alert before indicating to the application layer that
   the TLS connection has ended.  If the application protocol will not
   transfer any additional data, but will only close the underlying
   transport connection, then the implementation MAY choose to close the
   transport without waiting for the responding close_notify.  No part
    of this standard should be taken to dictate the manner in which a
   usage profile for TLS manages its data transport, including when
   connections are opened or closed.

   Note: It is assumed that closing a connection reliably delivers
   pending data before destroying the transport.


TLS 1.3 is a bit different:

	https://tools.ietf.org/html/rfc8446#section-6.1

6.1.  Closure Alerts

   The client and the server must share knowledge that the connection is
   ending in order to avoid a truncation attack.

   close_notify:  This alert notifies the recipient that the sender will
      not send any more messages on this connection.  Any data received
      after a closure alert has been received MUST be ignored.

   user_canceled:  This alert notifies the recipient that the sender is
      canceling the handshake for some reason unrelated to a protocol
      failure.  If a user cancels an operation after the handshake is
      complete, just closing the connection by sending a "close_notify"
      is more appropriate.  This alert SHOULD be followed by a
      "close_notify".  This alert generally has AlertLevel=warning.

   Either party MAY initiate a close of its write side of the connection
   by sending a "close_notify" alert.  Any data received after a closure
   alert has been received MUST be ignored.  If a transport-level close
   is received prior to a "close_notify", the receiver cannot know that
   all the data that was sent has been received.

   Each party MUST send a "close_notify" alert before closing its write
   side of the connection, unless it has already sent some error alert.
   This does not have any effect on its read side of the connection.
   Note that this is a change from versions of TLS prior to TLS 1.3 in
   which implementations were required to react to a "close_notify" by
   discarding pending writes and sending an immediate "close_notify"
   alert of their own.  That previous requirement could cause truncation
   in the read side.  Both parties need not wait to receive a
   "close_notify" alert before closing their read side of the
   connection, though doing so would introduce the possibility of
   truncation.

   If the application protocol using TLS provides that any data may be
   carried over the underlying transport after the TLS connection is
   closed, the TLS implementation MUST receive a "close_notify" alert
   before indicating end-of-data to the application layer.  No part of
   this standard should be taken to dictate the manner in which a usage
   profile for TLS manages its data transport, including when
   connections are opened or closed.

   Note: It is assumed that closing the write side of a connection
   reliably delivers pending data before destroying the transport.

Now, dialing up the detail on gnutls-cli:

$ gnutls-cli -p 443 -V -d 999 -- wip.pkgsrc.org

GET /
|<5>| REC[0x5568d933c690]: Preparing Packet Application Data(23) with length: 6 and min pad: 0
|<9>| ENC[0x5568d933c690]: cipher: AES-256-GCM, MAC: AEAD, Epoch: 1
|<11>| WRITE: enqueued 35 bytes for 0x3. Total 35 bytes.
|<11>| WRITE FLUSH: 35 bytes in buffer.
|<11>| WRITE: wrote 35 bytes, 0 bytes left.
|<5>| REC[0x5568d933c690]: Sent Packet[2] Application Data(23) in epoch 1 and length: 35
- Sent: 6 bytes
|<10>| READ: Got 5 bytes from 0x3
|<10>| READ: read 5 bytes from 0x3
|<10>| RB: Have 0 bytes into buffer. Adding 5 bytes.
|<10>| RB: Requested 5 bytes
|<5>| REC[0x5568d933c690]: SSL 3.3 Application Data packet received. Epoch 0, length: 41
|<5>| REC[0x5568d933c690]: Expected Packet Application Data(23)
|<5>| REC[0x5568d933c690]: Received Packet Application Data(23) with length: 41
|<10>| READ: Got 41 bytes from 0x3
|<10>| READ: read 41 bytes from 0x3
|<10>| RB: Have 5 bytes into buffer. Adding 41 bytes.
|<10>| RB: Requested 46 bytes
|<5>| REC[0x5568d933c690]: Decrypted Packet[1] Application Data(23) with length: 17
|<13>| BUF[REC]: Inserted 17 bytes of Data(23)
- Received[17]: HTTP/0.9 200 OK
|<10>| READ: Got 5 bytes from 0x3
|<10>| READ: read 5 bytes from 0x3
|<10>| RB: Have 0 bytes into buffer. Adding 5 bytes.
|<10>| RB: Requested 5 bytes
|<5>| REC[0x5568d933c690]: SSL 3.3 Application Data packet received. Epoch 0, length: 292
|<5>| REC[0x5568d933c690]: Expected Packet Application Data(23)
|<5>| REC[0x5568d933c690]: Received Packet Application Data(23) with length: 292
|<10>| READ: Got 292 bytes from 0x3
|<10>| READ: read 292 bytes from 0x3
|<10>| RB: Have 5 bytes into buffer. Adding 292 bytes.
|<10>| RB: Requested 297 bytes
|<5>| REC[0x5568d933c690]: Decrypted Packet[2] Application Data(23) with length: 268
|<13>| BUF[REC]: Inserted 268 bytes of Data(23)
- Received[268]: <html>
<head>
<title>pkgsrc-wip git repository</title>
<meta http-equiv="refresh" content="0; URL=https://wip.pkgsrc.org/cgi-bin/gitweb.cgi";>
</head>
<body>
The pkgsrc-wip git repository is <a href="https://wip.pkgsrc.org/cgi-bin/gitweb.cgi";>here</a>.
</body>
</html>
|<10>| READ: Got 0 bytes from 0x3
|<10>| READ: read 0 bytes from 0x3
|<3>| ASSERT: buffers.c[_gnutls_io_read_buffered]:591
|<3>| ASSERT: record.c[recv_headers]:1055
|<3>| ASSERT: record.c[_gnutls_recv_in_buffers]:1175
|<3>| ASSERT: record.c[_gnutls_recv_int]:1473
*** Fatal error: The TLS connection was non-properly terminated.
*** Server has terminated the connection abnormally.
|<5>| REC[0x5568d933c690]: Start of epoch cleanup
|<5>| REC[0x5568d933c690]: End of epoch cleanup
|<5>| REC[0x5568d933c690]: Epoch #1 freed

Looks like just a short read. Compare that to my university site (I'm
not the admin of that):

$ gnutls-cli -p 443 -V -d 999 -- uni-hamburg.de
GET /
|<5>| REC[0x561dd30f2070]: Preparing Packet Application Data(23) with length: 6 and min pad: 0
|<9>| ENC[0x561dd30f2070]: cipher: AES-256-GCM, MAC: AEAD, Epoch: 1
|<11>| WRITE: enqueued 35 bytes for 0x3. Total 35 bytes.
|<11>| WRITE FLUSH: 35 bytes in buffer.
|<11>| WRITE: wrote 35 bytes, 0 bytes left.
|<5>| REC[0x561dd30f2070]: Sent Packet[2] Application Data(23) in epoch 1 and length: 35
- Sent: 6 bytes
|<10>| READ: Got 5 bytes from 0x3
|<10>| READ: read 5 bytes from 0x3
|<10>| RB: Have 0 bytes into buffer. Adding 5 bytes.
|<10>| RB: Requested 5 bytes
|<5>| REC[0x561dd30f2070]: SSL 3.3 Application Data packet received. Epoch 0, length: 416
|<5>| REC[0x561dd30f2070]: Expected Packet Application Data(23)
|<5>| REC[0x561dd30f2070]: Received Packet Application Data(23) with length: 416
|<10>| READ: Got 416 bytes from 0x3
|<10>| READ: read 416 bytes from 0x3
|<10>| RB: Have 5 bytes into buffer. Adding 416 bytes.
|<10>| RB: Requested 421 bytes
|<5>| REC[0x561dd30f2070]: Decrypted Packet[1] Application Data(23) with length: 392
|<13>| BUF[REC]: Inserted 392 bytes of Data(23)
- Received[392]: HTTP/1.1 400 Bad Request
Date: Mon, 17 Aug 2020 05:12:26 GMT
Server: Apache
Content-Length: 226
Connection: close
Content-Type: text/html; charset=iso-8859-1

<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>400 Bad Request</title>
</head><body>
<h1>Bad Request</h1>
<p>Your browser sent a request that this server could not understand.<br />
</p>
</body></html>
|<10>| READ: Got 5 bytes from 0x3
|<10>| READ: read 5 bytes from 0x3
|<10>| RB: Have 0 bytes into buffer. Adding 5 bytes.
|<10>| RB: Requested 5 bytes
|<5>| REC[0x561dd30f2070]: SSL 3.3 Alert packet received. Epoch 0, length: 26
|<5>| REC[0x561dd30f2070]: Expected Packet Application Data(23)
|<5>| REC[0x561dd30f2070]: Received Packet Alert(21) with length: 26
|<10>| READ: Got 26 bytes from 0x3
|<10>| READ: read 26 bytes from 0x3
|<10>| RB: Have 5 bytes into buffer. Adding 26 bytes.
|<10>| RB: Requested 31 bytes
|<5>| REC[0x561dd30f2070]: Decrypted Packet[2] Alert(21) with length: 2
|<5>| REC[0x561dd30f2070]: Alert[1|0] - Close notify - was received
|<3>| ASSERT: record.c[_gnutls_recv_in_buffers]:1328
- Peer has closed the GnuTLS connection
|<5>| REC[0x561dd30f2070]: Start of epoch cleanup
|<5>| REC[0x561dd30f2070]: End of epoch cleanup
|<5>| REC[0x561dd30f2070]: Epoch #1 freed

There's the close_notify. If wip.pkgsrc.org sent its notification and
then immediately closes the socket (r/w), shouldn't it still reach the
client? Is there some TCP-level failure? I can understand that the
server doesn't wait around for clients confirming closing of
connections. Maybe gnutls tries to answer immediately and is upset that the
connection is already closed?

$ openssl s_client -connect  wip.pkgsrc.org:443 -debug
[…]
</body>
</html>
read from 0x556d61c616d0 [0x556d61c694b3] (5 bytes => 0 (0x0))
read:errno=0
write to 0x556d61c616d0 [0x556d61c6d603] (24 bytes => 24 (0x18))
0000 - 17 03 03 00 13 27 93 df-dd da 99 20 b7 38 f3 9a   .....'..... .8..
0010 - 3d 59 ef 98 3b 14 b4 69-                          =Y..;..i
read from 0x556d61c616d0 [0x556d61c56d80] (8192 bytes => 0 (0x0))

$ openssl s_client -connect uni-hamburg.de:443 -debug
[…]
<p>Your browser sent a request that this server could not understand.<br />
</p>
</body></html>
read from 0x56047240f6d0 [0x560472416e93] (5 bytes => 5 (0x5))
0000 - 15 03 03 00 1a                                    .....
read from 0x56047240f6d0 [0x560472416e98] (26 bytes => 26 (0x1A))
0000 - a2 79 61 8e 83 7b d1 8b-3c b9 39 32 6c 87 46 32   .ya..{..<.92l.F2
0010 - a1 e3 a2 31 9f 1d 33 3b-96 48                     ...1..3;.H
closed
write to 0x56047240f6d0 [0x56047241afe3] (31 bytes => 31 (0x1F))
0000 - 15 03 03 00 1a 86 2a 80-73 4c 3e 0d 49 70 67 ba   ......*.sL>.Ipg.
0010 - d2 dc 1e 27 f7 c9 a2 f9-50 c7 9b 7d ec 38 bd      ...'....P..}.8.
read from 0x56047240f6d0 [0x560472404d80] (8192 bytes => 0 (0x0))

This also very much looks like the close alert/notification from
wip.pkgsrc.org just doesn't arrive. I wonder if it is rather a bug in
openssl that it does not warn about the apparently truncated
communication. Isn't GnuTLS right in complaining in that case?


Alrighty then,

Thomas

-- 
Dr. Thomas Orgis
HPC @ Universität Hamburg


Home | Main Index | Thread Index | Old Index