Skip to content

Commit

Permalink
Add callback SASL_CB_SERVER_CHANNEL_BINDING
Browse files Browse the repository at this point in the history
Provide a callback function to change the channel binding type
of servers (e.g. "tls-server-end-point" instead of "tls-unique")
during authentication of secure mechanisms like GS2-KRB5-PLUS or
SCRAM-SHA-256-PLUS.

The callback is used by the plugins SCRAM and GS2 when the desired
binding type of the client does not match the binding type set with
property SASL_CHANNEL_BINDING.
A server can check the requested type of channel binding and
overwrite the current channel binding data with the property
SASL_CHANNEL_BINDING before the authentication proceeds.

Issue cyrusimap#823

Signed-off-by: Guido Kiener <guido.kiener@rohde-schwarz.com>
  • Loading branch information
GuidoKiener committed Feb 16, 2024
1 parent 7e2feae commit 32b3072
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 1 deletion.
21 changes: 21 additions & 0 deletions include/sasl.h
Original file line number Diff line number Diff line change
Expand Up @@ -671,6 +671,27 @@ typedef int sasl_canon_user_t(sasl_conn_t *conn,

#define SASL_CB_CANON_USER (0x8007)

/* Callback for servers to change channel binding type
* (e.g. "tls-server-end-point" instead of "tls-unique" or "tls-exporter").
* The callback is used by plugins like SCRAM-SHA-*-PLUS or GS2-KRB5-PLUS
* when the desired binding type of the client does not match the binding
* type set with property SASL_CHANNEL_BINDING.
* A server should check the requested 'cbindingname' of the 'plugin' and
* overwrite the channel binding data with the property SASL_CHANNEL_BINDING
* within the callback function.
* Note that plugins only store a pointer of your channel binding data and
* the memory of your struct sasl_channel_binding_t must be valid during
* the complete authentication process.
*
* plugin -- name of plugin
* cbindingname -- name of desired channel binding type
*/
typedef int sasl_server_channel_binding_t(sasl_conn_t* conn,
void* context,
const char* plugin,
const char* cbindingname);
#define SASL_CB_SERVER_CHANNEL_BINDING (0x8008)

/**********************************
* Common Client/server functions *
**********************************/
Expand Down
30 changes: 30 additions & 0 deletions plugins/gs2.c
Original file line number Diff line number Diff line change
Expand Up @@ -1025,6 +1025,29 @@ gs2_save_cbindings(context_t *text,
return SASL_OK;
}

/*
* Request for (alternate) channel binding data
*/
static int
gs2_server_get_channel_binding(sasl_server_params_t* sparams,
const char *mech,
const char *cbindingname)
{
sasl_server_channel_binding_t* binding = NULL;
void* context = NULL;
/* try to get alternate channel binding data */
if (sparams->utils->callback(sparams->utils->conn,
SASL_CB_SERVER_CHANNEL_BINDING,
(sasl_callback_ft*)&binding,
&context) == SASL_OK) {
int ret = binding(sparams->utils->conn,
context,
mech, cbindingname);
return ret;
}
return SASL_BADPROT;
}

#define CHECK_REMAIN(n) do { if (remain < (n)) return SASL_BADPROT; } while (0)

/*
Expand Down Expand Up @@ -1073,6 +1096,13 @@ gs2_verify_initial_message(context_t *text,
if (ret != SASL_OK)
return ret;

if (sparams->cbinding == NULL ||
strcmp(sparams->cbinding->name, text->cbindingname) != 0) {
/* Try to get desired channel binding data */
gs2_server_get_channel_binding(sparams,
text->plug.server->mech_name,
text->cbindingname);
}
text->gs2_flags |= GS2_CB_FLAG_P;
break;
case 'n':
Expand Down
30 changes: 29 additions & 1 deletion plugins/scram.c
Original file line number Diff line number Diff line change
Expand Up @@ -1155,7 +1155,27 @@ scram_server_mech_step1(server_context_t *text,
}
return result;
}


static int
scram_server_get_channel_binding(sasl_server_params_t* sparams,
const char *mech,
const char *cbindingname)
{
sasl_server_channel_binding_t* binding = NULL;
void* context = NULL;
/* try to get alternate channel binding data */
if (sparams->utils->callback(sparams->utils->conn,
SASL_CB_SERVER_CHANNEL_BINDING,
(sasl_callback_ft*)&binding,
&context) == SASL_OK) {
int ret = binding(sparams->utils->conn,
context,
mech, cbindingname);
return ret;
}
return SASL_BADPROT;
}

static int
scram_server_mech_step2(server_context_t *text,
sasl_server_params_t *sparams,
Expand Down Expand Up @@ -1281,6 +1301,14 @@ scram_server_mech_step2(server_context_t *text,
goto cleanup;
}

if (sparams->cbinding == NULL ||
strcmp(sparams->cbinding->name, text->cbindingname) != 0) {
/* Try to get desired channel binding data */
scram_server_get_channel_binding(sparams,
scram_sasl_mech,
text->cbindingname);
}

if (sparams->cbinding == NULL) {
sparams->utils->seterror (sparams->utils->conn,
0,
Expand Down

0 comments on commit 32b3072

Please sign in to comment.