GNOME Bugzilla – Bug 581890
gtls doesn't handle GNUTLS_E_REHANDSHAKE
Last modified: 2012-01-22 05:34:10 UTC
Either end of a TLS connection is allowed to demand a rehandshake at any time. In particular, some servers do this after you authenticate via a certificate, to negotiate a different encryption mode or something. When this happens, gnutls_record_send/recv return GNUTLS_E_REHANDSHAKE, and then you have to go back and handshake again before you can continue what you were doing. I'm attaching a port of libsoup/tests/ssl-test.c. I don't know if it's actually completely correct or not, because it doesn't get very far. (In particular, it doesn't get to the async test at all...)
Created attachment 134264 [details] [review] quick port of libsoup/tests/ssl-test. Doesn't currently work
This is sort of tricky because we have to be able to do this async. As I understand it, the rehandshake process would be synchronous. When implementing GTlsConnection I read the following in the GNUTLS docs: http://www.gnu.org/software/gnutls/manual/gnutls.html#Error-handling This is the case with the error code GNUTLS_E_REHANDSHAKE returned by gnutls_record_recv. This error code indicates that the server requests a re-handshake. The client may ignore this request, or may reply with an alert. and so I ignored it.
(In reply to comment #2) > This is sort of tricky because we have to be able to do this async. As I > understand it, the rehandshake process would be synchronous. No, you can handshake asynchronously just like reading/writing. If your push or pull funcs return -1 with errno set to EAGAIN, then gnutls_handshake() will return GNUTLS_E_AGAIN and you can call it again to resume the handshake when the data is ready. > When implementing GTlsConnection I read the following in the GNUTLS docs: > > http://www.gnu.org/software/gnutls/manual/gnutls.html#Error-handling > > This is the case with the error code GNUTLS_E_REHANDSHAKE returned by > gnutls_record_recv. This error code indicates that the server requests a > re-handshake. The client may ignore this request, or may reply with an alert. > > and so I ignored it. Mmmm... I suspect that should be read as "the protocol allows a client to ignore the request", and not as, "the server won't mind if you ignore this request"; if the server was satisfied with the existing parameters, it would have no reason to have requested a rehandshake, so there's a strong possibility that if you fail to rehandshake, it will close the connection. (The particular case that I know of that resulted in this being fixed in libsoup is that Exchange requests a rehandshake after you authenticate using a client certificate, presumably because it wants to do encryption based on the key in the cert. But I don't know what it does if you ignore the rehandshake request.) Also: A server may also receive GNUTLS_E_REHANDSHAKE when a client has initiated a handshake. In that case the server can only initiate a handshake or terminate the connection. (from the gnutls_record_recv() docs). So on the server side, you can't just ignore it. Although gtls doesn't support server-side TLS does it... Also also, Alex and I were discussing the possibility of putting TLS at the GSocket layer rather than the GIOStream layer (on the grounds that all of the use cases that apply for wanting to use g_socket_send/g_socket_receive directly in the non-TLS case apply in the TLS case too). See gtk-devel-list. That would make the implementation of all of this vastly simpler, since you wouldn't need to translate between EAGAIN-style and callback style.
duping to the current gsocket tls bug (which does handle rehandshaking) *** This bug has been marked as a duplicate of bug 588189 ***