in c/src/sasl/sasl.c [485:572]
static void pni_post_sasl_frame(pn_transport_t *transport)
{
pni_sasl_t *sasl = transport->sasl;
pn_bytes_t out = sasl->bytes_out;
enum pnx_sasl_state desired_state = sasl->desired_state;
while (sasl->desired_state > sasl->last_state) {
switch (desired_state) {
case SASL_POSTED_INIT: {
/* GENERATE_CODEC_CODE: "DL[szS]" */
pn_bytes_t buf = pn_amqp_encode_DLEszSe(&transport->scratch_space, SASL_INIT, pn_string_bytes(sasl->selected_mechanism), out.size, out.start, pn_string_bytes(sasl->local_fqdn));
pn_framing_send_sasl(transport, buf);
pni_emit(transport);
break;
}
case SASL_POSTED_MECHANISMS: {
// TODO(PROTON-2122) Replace magic number 32 with dynamically sized memory
char *mechs[32];
char *mechlist = pn_strdup(pni_sasl_impl_list_mechs(transport));
int count = 0;
if (mechlist) {
pni_split_mechs(mechlist, sasl->included_mechanisms, mechs, &count);
}
/* GENERATE_CODEC_CODE: "DL[@T[*s]]" */
pn_bytes_t buf = pn_amqp_encode_DLEATEjsee(&transport->scratch_space, SASL_MECHANISMS, PN_SYMBOL, count, mechs);
free(mechlist);
pn_framing_send_sasl(transport, buf);
pni_emit(transport);
break;
}
case SASL_POSTED_RESPONSE:
if (sasl->last_state != SASL_POSTED_RESPONSE) {
/* "DL[Z]" */
pn_bytes_t buf = pn_amqp_encode_DLEZe(&transport->scratch_space, SASL_RESPONSE, out.size, out.start);
pn_framing_send_sasl(transport, buf);
pni_emit(transport);
}
break;
case SASL_POSTED_CHALLENGE:
if (sasl->last_state < SASL_POSTED_MECHANISMS) {
desired_state = SASL_POSTED_MECHANISMS;
continue;
} else if (sasl->last_state != SASL_POSTED_CHALLENGE) {
/* "DL[Z]" */
pn_bytes_t buf = pn_amqp_encode_DLEZe(&transport->scratch_space, SASL_CHALLENGE, out.size, out.start);
pn_framing_send_sasl(transport, buf);
pni_emit(transport);
}
break;
case SASL_POSTED_OUTCOME: {
if (sasl->last_state < SASL_POSTED_MECHANISMS) {
desired_state = SASL_POSTED_MECHANISMS;
continue;
}
/* "DL[Bz]" */
pn_bytes_t buf = pn_amqp_encode_DLEBze(&transport->scratch_space, SASL_OUTCOME, sasl->outcome, out.size, out.start);
pn_framing_send_sasl(transport, buf);
pni_emit(transport);
if (sasl->outcome!=PN_SASL_OK) {
const char *selected_mechanism = transport->sasl->selected_mechanism ? pn_string_get(transport->sasl->selected_mechanism) : NULL;
pn_do_error(transport, "amqp:unauthorized-access", "Failed to authenticate client [mech=%s]",
selected_mechanism ? selected_mechanism : "none");
desired_state = SASL_ERROR;
}
break;
}
case SASL_RECVED_SUCCESS:
if (sasl->last_state < SASL_POSTED_INIT) {
desired_state = SASL_POSTED_INIT;
continue;
}
break;
case SASL_RECVED_FAILURE: {
const char *selected_mechanism = transport->sasl->selected_mechanism ? pn_string_get(transport->sasl->selected_mechanism) : NULL;
pn_do_error(transport, "amqp:unauthorized-access", "Authentication failed [mech=%s]",
selected_mechanism ? selected_mechanism : "none");
desired_state = SASL_ERROR;
break;
}
case SASL_ERROR:
break;
case SASL_NONE:
return;
}
sasl->last_state = desired_state;
desired_state = sasl->desired_state;
}
}