1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-22 13:34:15 +03:00

s4:lib/tls: add tstream_tls_channel_bindings()

This is based on GNUTLS_CB_TLS_SERVER_END_POINT
and is the value that is required for channel bindings
in LDAP of active directory domain controllers.

For gnutls versions before 3.7.2 we basically
copied the code from the GNUTLS_CB_TLS_SERVER_END_POINT
implementation as it only uses public gnutls functions
and it was easy to re-implement.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=15621

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
(cherry picked from commit cbd7ce4412)
This commit is contained in:
Stefan Metzmacher 2023-09-28 12:34:35 +02:00 committed by Jule Anger
parent 6fec41bdb3
commit 20d5335dc1
2 changed files with 68 additions and 0 deletions

View File

@ -81,6 +81,8 @@ NTSTATUS tstream_tls_params_server(TALLOC_CTX *mem_ctx,
bool tstream_tls_params_enabled(struct tstream_tls_params *params);
const DATA_BLOB *tstream_tls_channel_bindings(struct tstream_context *tls_tstream);
struct tevent_req *_tstream_tls_connect_send(TALLOC_CTX *mem_ctx,
struct tevent_context *ev,
struct tstream_context *plain_stream,

View File

@ -69,6 +69,8 @@ struct tstream_tls {
enum tls_verify_peer_state verify_peer;
const char *peer_name;
DATA_BLOB channel_bindings;
struct tevent_context *current_ev;
struct tevent_immediate *retry_im;
@ -889,6 +891,63 @@ bool tstream_tls_params_enabled(struct tstream_tls_params *tls_params)
return tlsp->tls_enabled;
}
static NTSTATUS tstream_tls_setup_channel_bindings(struct tstream_tls *tlss)
{
gnutls_datum_t cb = { .size = 0 };
int ret;
#ifdef HAVE_GNUTLS_CB_TLS_SERVER_END_POINT
ret = gnutls_session_channel_binding(tlss->tls_session,
GNUTLS_CB_TLS_SERVER_END_POINT,
&cb);
#else /* not HAVE_GNUTLS_CB_TLS_SERVER_END_POINT */
ret = legacy_gnutls_server_end_point_cb(tlss->tls_session,
tlss->is_server,
&cb);
#endif /* not HAVE_GNUTLS_CB_TLS_SERVER_END_POINT */
if (ret != GNUTLS_E_SUCCESS) {
return gnutls_error_to_ntstatus(ret,
NT_STATUS_CRYPTO_SYSTEM_INVALID);
}
if (cb.size != 0) {
/*
* Looking at the OpenLDAP implementation
* for LDAP_OPT_X_SASL_CBINDING_TLS_ENDPOINT
* revealed that we need to prefix it with
* 'tls-server-end-point:'
*/
const char endpoint_prefix[] = "tls-server-end-point:";
size_t prefix_size = strlen(endpoint_prefix);
size_t size = prefix_size + cb.size;
tlss->channel_bindings = data_blob_talloc_named(tlss, NULL, size,
"tls_channel_bindings");
if (tlss->channel_bindings.data == NULL) {
gnutls_free(cb.data);
return NT_STATUS_NO_MEMORY;
}
memcpy(tlss->channel_bindings.data, endpoint_prefix, prefix_size);
memcpy(tlss->channel_bindings.data + prefix_size, cb.data, cb.size);
gnutls_free(cb.data);
}
return NT_STATUS_OK;
}
const DATA_BLOB *tstream_tls_channel_bindings(struct tstream_context *tls_tstream)
{
struct tstream_tls *tlss =
talloc_get_type(_tstream_context_data(tls_tstream),
struct tstream_tls);
if (tlss == NULL) {
return NULL;
}
return &tlss->channel_bindings;
}
NTSTATUS tstream_tls_params_client(TALLOC_CTX *mem_ctx,
const char *ca_file,
const char *crl_file,
@ -1573,6 +1632,13 @@ static void tstream_tls_retry_handshake(struct tstream_context *stream)
return;
}
status = tstream_tls_setup_channel_bindings(tlss);
if (!NT_STATUS_IS_OK(status)) {
tlss->error = EIO;
tevent_req_error(req, tlss->error);
return;
}
if (tlss->push.subreq != NULL || tlss->pull.subreq != NULL) {
tlss->waiting_flush.mgmt_req = req;
return;