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

Add tls and http apis for post handshake #713

Merged

Conversation

fAuernigg
Copy link
Contributor

No description provided.

@fAuernigg
Copy link
Contributor Author

fAuernigg commented Feb 27, 2023

PR #712 is required to fix the tls statemachine issue during tls v1.2 renegotiation.

Without PR #712 the test added for tls renegotiation fails under TLS v1.2

PR #711 is required to fix reading of certificate files on Win32 during renegotiation in the test added in this PR.

@cspiel1
Copy link
Collaborator

cspiel1 commented Feb 28, 2023

I think we should preserve the standard naming scheme for call back function of re/baresip:

struct tls_conn_d {
	int (*verifyh) (int ok, void *arg);
	void *arg;
int tls_set_verify_client_handler(struct tls_conn *tc, int depth,
	int (*verifyh) (int ok, void *arg), void *arg);

int tls_set_verify_client_handler(struct tls_conn *tc, int depth,
int (*cb) (int ok, void *d), void *d)
{
#if !defined(LIBRESSL_VERSION_NUMBER)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just upgraded LibreSSL for CI tests, can you try to enable these parts. At first quick look all required APIs are available now.

@sreimers
Copy link
Member

Is TLS 1.2 renegotiation support needed? Maybe better only support secure TLS 1.3 handling for this use case?

@cspiel1
Copy link
Collaborator

cspiel1 commented Mar 1, 2023

Is TLS 1.2 renegotiation support needed? Maybe better only support secure TLS 1.3 handling for this use case?

Indeed, we need it for HTTPS clients against MS Azure. And they are very lazy with security updates.

@fAuernigg
Copy link
Contributor Author

Is TLS 1.2 renegotiation support needed? Maybe better only support secure TLS 1.3 handling for this use case?

As far as I known renegotiation in TLSv1.2 has only security flaws, if it is initiated by the client. In the test added in this PR the server initiates renegotiation.

@sreimers
Copy link
Member

sreimers commented Mar 1, 2023

curl/curl#3258 (comment)

Note renegotiation is an extremely dangerous protocol feature. It is disabled by default in BoringSSL for security reasons and was removed in TLS 1.3.

Yeah, I wrote that text in BoringSSL. :-P Those limitations do not avoid renegotiation's problems. They are merely the bare minimum of simplifications we've been able to manage. Mid-renegotiation a lot of state is still pretty fuzzy, and renegotiation still exposes a lot of I/O patterns applications don't expect. I've rarely seen OpenSSL-consuming code that actually gets it right. And one still must be concerned with the renegotiation attacks from way back (lack of binding between the two handshakes without RI extension), as well as 3-SHAKE.

I wonder if this opens client side attacks:

https://github.com/baresip/re/pull/712/files#diff-2907ed5afee94d2389faf81e1d83c4110381960c319b5fb5d0a009cf2b170dc8R233

Since OpenSSL does not prevent this.

@fAuernigg
Copy link
Contributor Author

I assume our only chance to get #712 to main branch is by making it configurable like in boring ssl?
Would this be acceptable?

A http client could then enable it only for certain http connections.

@fAuernigg fAuernigg force-pushed the add_tls_and_http_apis_for_renegotiation branch from 5db194e to 1b8f3ee Compare March 1, 2023 09:07
@fAuernigg fAuernigg marked this pull request as ready for review March 1, 2023 10:43
@fAuernigg fAuernigg force-pushed the add_tls_and_http_apis_for_renegotiation branch 2 times, most recently from deb2220 to f63c397 Compare March 1, 2023 15:12
@fAuernigg fAuernigg marked this pull request as draft March 2, 2023 09:58
@fAuernigg fAuernigg force-pushed the add_tls_and_http_apis_for_renegotiation branch 2 times, most recently from 4a81e04 to 2dbcfbf Compare March 2, 2023 10:01
@fAuernigg
Copy link
Contributor Author

I assume our only chance to get #712 to main branch is by making it configurable like in boring ssl? Would this be acceptable?

A http client could then enable it only for certain http connections.

TLS v1.2 renegotiation was removed from this PR. (Preparing another PR with TLSv1.2 enable api per connection)

@fAuernigg fAuernigg marked this pull request as ready for review March 2, 2023 10:09
Copy link
Collaborator

@cspiel1 cspiel1 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Took the naming scheme from src/dns/client.c.

}
else {
tc->cd.verifyh = cb;
tc->cd.verify_d = arg;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rename please!

tc->cd.arg = arg;

include/re_tls.h Outdated
@@ -46,6 +50,10 @@ int tls_set_certificate_der(struct tls *tls, enum tls_keytype keytype,
const uint8_t *key, size_t len_key);
int tls_set_certificate(struct tls *tls, const char *cert, size_t len);
void tls_set_verify_client(struct tls *tls);
void tls_set_verify_client_trust_all(struct tls *tls);
int tls_set_verify_client_handler(struct tls_conn *tc, int depth,
int (*cb) (int ok, void *arg), void *arg);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rename
cb --> verifyh

include/re_tls.h Outdated
@@ -28,6 +28,10 @@ enum tls_keytype {
TLS_KEYTYPE_EC,
};

struct tls_conn_d {
int (*verifyh) (int ok, void *arg);
void *verify_d;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rename:
verify_d --> arg

@@ -29,6 +30,7 @@ struct http_sock {
struct tcp_sock *ts;
struct tls *tls;
http_req_h *reqh;
https_verify_msg_h *verify_msg_h;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rename to:
verify_msg_h --> verifyh

* @return 0 if success, otherwise errorcode
*/
int https_set_verify_msgh(struct http_sock *sock,
https_verify_msg_h *verify_msg_h)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rename
verify_msg_h --> verifyh

if (!sock || !verify_msg_h)
return EINVAL;

sock->verify_msg_h = verify_msg_h;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rename to
sock->verifyh = verifyh;


int http_listen_fd(struct http_sock **sockp, re_sock_t fd, http_req_h *reqh,
void *arg);
int http_listen(struct http_sock **sockp, const struct sa *laddr,
http_req_h *reqh, void *arg);
int https_listen(struct http_sock **sockp, const struct sa *laddr,
const char *cert, http_req_h *reqh, void *arg);
int https_set_verify_msgh(struct http_sock *sock,
https_verify_msg_h *verify_msg_h);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rename to

int  https_set_verify_msgh(struct http_sock *sock,
			   https_verify_msg_h *verifyh);

@alfredh
Copy link
Contributor

alfredh commented Mar 3, 2023

I have some more comments, please take them with a grain of salt :)

There are changes to HTTP and TLS modules, and the re-negotiation feature belongs to TLS.
There are probably other protocols sitting on top of TLS which may need the same feature,
for example SIP.

Is it possible to add the feature to TLS module so that all users of TLS gets
the feature transparently ?

For example in retest this means changes to tls.c only, not http.c

If this is possible, we could split this patch in two parts, where the first part
is for TLS and the second part is for HTTP.

*
* @return TLS struct
*/
struct tls *http_sock_tls(struct http_sock *sock)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can the input param be const ?

@@ -205,6 +207,19 @@ int tls_verify_handler(int ok, X509_STORE_CTX *ctx)
#endif


static int tls_verify_idx = -1;
static once_flag oflag = ONCE_FLAG_INIT;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is it possible to avoid this global data and use the TLS context instead ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was trying to do that but it is not possible. It is not nice but openssl requires global indices initialized once. in tls_alloc call_once(&oflag, tls_init_verify_idx) is called.

Code examples are taken from openssl and apache2/httpd implementation to get application inside the openssl verify handlers, which are not supporting application data (so no tls context is present). So the only way to get application data is to use global openssl indices initialized once. (SSL_set_ex_data, SSL_get_ex_data(..., tls_verify_idx))

*
* @return 0 if success, otherwise errorcode
*/
int tls_set_posthandshake_auth(struct tls *tls, int value)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can this return void ?

err = EIO;
DEBUG_WARNING("%s: error: %m, ssl_err=%d\n", __func__, err,
SSL_get_error(tc->ssl, ret));
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

global openssl error queue must be cleared in both error cases


if (!(ret=SSL_verify_client_post_handshake(tc->ssl))) {
err = EFAULT;
DEBUG_WARNING("%s: error: %m, ssl_err=%d\n", __func__, err,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please avoid func as it makes it harder to grep the code

@fAuernigg
Copy link
Contributor Author

I have some more comments, please take them with a grain of salt :)

There are changes to HTTP and TLS modules, and the re-negotiation feature belongs to TLS. There are probably other protocols sitting on top of TLS which may need the same feature, for example SIP.

Is it possible to add the feature to TLS module so that all users of TLS gets the feature transparently ?

For example in retest this means changes to tls.c only, not http.c

If this is possible, we could split this patch in two parts, where the first part is for TLS and the second part is for HTTP.

I'm afraid but there is no transparent tls post handshake on server side.

For example a http server requests a post handshake (using SSL_verify_client_post_handshake) after it received http data. (Typically a specific http path, which requires more authentication data from the client).

Clients can support tls posthandshake transparently by setting for example a client certificate before a https request and enabling post handshake support using SSL_CTX_set_post_handshake_auth.

Anyhow of course I can split up the tls and http commit to make it easier to implement posthandshake in for example sip:

A sip server side implementation would need to support what "https_set_verify_msgh" of this PR does:

  • Allow to set a callback receiving OSI level 7 data (e.g. comparable to http data and http path) upon which it can decide, if a post handshake should be done.

@fAuernigg fAuernigg force-pushed the add_tls_and_http_apis_for_renegotiation branch 2 times, most recently from 4ea5112 to 0f5e885 Compare March 8, 2023 14:01
@fAuernigg fAuernigg requested review from cspiel1 and removed request for cspiel1 March 8, 2023 14:53
@fAuernigg fAuernigg requested review from sreimers, alfredh and cspiel1 and removed request for sreimers, alfredh and cspiel1 March 8, 2023 14:53
@sreimers sreimers added this to the v2.14.0 milestone Mar 9, 2023
@fAuernigg fAuernigg changed the title Add tls and http apis for renegotiation Add tls and http apis for post handshake Mar 11, 2023
@fAuernigg fAuernigg requested review from cspiel1 and removed request for alfredh March 13, 2023 08:09
src/tls/openssl/tls.c Outdated Show resolved Hide resolved
src/tls/openssl/tls.c Outdated Show resolved Hide resolved
@fAuernigg fAuernigg force-pushed the add_tls_and_http_apis_for_renegotiation branch from 0f5e885 to 5ecf983 Compare March 20, 2023 08:59
@fAuernigg fAuernigg requested a review from cspiel1 March 20, 2023 08:59
@fAuernigg fAuernigg force-pushed the add_tls_and_http_apis_for_renegotiation branch from 5ecf983 to 54ff0e1 Compare March 20, 2023 09:10
Add tls_set_conn_verify_client_handler,
tls_set_posthandshake_auth, tls_conn_verify_client_post_handshake
available in tls >= v1.3
Support post handshake using https_set_verify_msgh and http_sock_tls.
Allow decide to request certificate authorisation from client based on
content of first http msg.
@fAuernigg fAuernigg force-pushed the add_tls_and_http_apis_for_renegotiation branch from 54ff0e1 to 51013cb Compare March 20, 2023 09:13
@sreimers sreimers merged commit bac6984 into baresip:main Mar 20, 2023
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.

4 participants