Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

transp: deref qent only if qentp is not set #1061

Merged
merged 1 commit into from
Jan 31, 2024

Conversation

maximilianfridrich
Copy link
Contributor

If qentp is set, the caller of sip_transp_send is responsible for derefing qent.

This caused undesirable behavior in the following scenario: A message is sent using sip_transp_send and the transport is TLS 1.3. The peer (i.e. server) requests a client certificate from us and then the server terminates the TLS and TCP connection (e.g. due to an invalid ceritificate). In this case, the caller of sip_transp_send never gets alerted that there was a transport error and some other timeout mechanism kicks in (e.g. in SIP 64 * T1). In BareSIP, this means e.g. that we start an outgoing call and the call stays in this outgoing call state for 32 seconds while the underlying TCP/TLS connection has long be terminated. Ideally, this transport error would immediately be propagated upwards.

This happens due to the abbreviated TLS 1.3 handshake (see RFC 8446): The server sends a Finished message in the ServerHello and the client responds with a Finished message and a Certificate if requested. After this message, the handshake is considered completed (but the server has not verified our certificate yet, if requested).

So in re in tcp_estab_handler, tcp_send is called and it succeeds because SSL_write correctly succeeds in tls_tcp.c:305. Then, in tcp_estab_handler the qent element is derefed and removed from conn->ql. This qent element contains the callback to the transport_handler in case there are any transport errors and after we have removed qent, there is no reference to the transport handler anymore. Finally, we receive a TLS Alert and the TCP connection is closed. The conn->ql is now empty and so in conn_close there is no transport handler to call and the transport error can no longer be propagated upwards.

This can be fixed by not derefing qent in transp.c if qent->qentp is set. Because if qent->qentp is set, the caller of sip_transp_send will have a pointer to qent and dereference it in its destructor (e.g. the ctrans destructor).

I have tested this extensively manually in many different scenarios with valgrind and running BareSIP selftest.

src/sip/transp.c Outdated Show resolved Hide resolved
If qentp is set, the caller of sip_transp_send is responsible for
derefing qent.
@alfredh alfredh merged commit e4d2ab7 into baresip:main Jan 31, 2024
36 checks passed
@maximilianfridrich maximilianfridrich deleted the transp_qent_deref branch February 12, 2024 13:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants