in c/src/sasl/default_sasl.c [97:179]
bool default_sasl_process_mechanisms(pn_transport_t *transport, const char *mechs)
{
const char *username = pnx_sasl_get_username(transport);
const char *password = pnx_sasl_get_password(transport);
const char *authzid = pnx_sasl_get_authorization(transport);
// Check whether offered EXTERNAL, PLAIN or ANONYMOUS
// Look for "EXTERNAL" in mechs
const char *found = strstr(mechs, EXTERNAL);
// Make sure that string is separated and terminated
if (found && (found==mechs || found[-1]==' ') && (found[8]==0 || found[8]==' ')) {
pnx_sasl_set_selected_mechanism(transport, EXTERNAL);
if (authzid) {
size_t size = strlen(authzid);
char *iresp = (char *) malloc(size);
if (!iresp) return false;
pnx_sasl_set_context(transport, iresp);
memmove(iresp, authzid, size);
pnx_sasl_set_bytes_out(transport, pn_bytes(size, iresp));
} else {
static const char empty[] = "";
pnx_sasl_set_bytes_out(transport, pn_bytes(0, empty));
}
pnx_sasl_set_desired_state(transport, SASL_POSTED_INIT);
return true;
}
// Look for "PLAIN" in mechs
found = strstr(mechs, PLAIN);
// Make sure that string is separated and terminated, allowed
// and we have a username and password and connection is encrypted or we allow insecure
if (found && (found==mechs || found[-1]==' ') && (found[5]==0 || found[5]==' ') &&
(pnx_sasl_is_transport_encrypted(transport) || pnx_sasl_get_allow_insecure_mechanisms(transport)) &&
username && password) {
pnx_sasl_set_selected_mechanism(transport, PLAIN);
size_t zsize = authzid ? strlen(authzid) : 0;
size_t usize = strlen(username);
size_t psize = strlen(password);
size_t size = zsize + usize + psize + 2;
char *iresp = (char *) malloc(size);
if (!iresp) return false;
pnx_sasl_set_context(transport, iresp);
if (authzid) memmove(&iresp[0], authzid, zsize);
iresp[zsize] = 0;
memmove(&iresp[zsize + 1], username, usize);
iresp[zsize + usize + 1] = 0;
memmove(&iresp[zsize + usize + 2], password, psize);
pnx_sasl_set_bytes_out(transport, pn_bytes(size, iresp));
// Zero out password and dealloc
pnx_sasl_clear_password(transport);
pnx_sasl_set_desired_state(transport, SASL_POSTED_INIT);
return true;
}
// Look for "ANONYMOUS" in mechs
found = strstr(mechs, ANONYMOUS);
// Make sure that string is separated and terminated and allowed
if (found && (found==mechs || found[-1]==' ') && (found[9]==0 || found[9]==' ')) {
pnx_sasl_set_selected_mechanism(transport, ANONYMOUS);
if (username) {
size_t size = strlen(username);
char *iresp = (char *) malloc(size);
if (!iresp) return false;
pnx_sasl_set_context(transport, iresp);
memmove(iresp, username, size);
pnx_sasl_set_bytes_out(transport, pn_bytes(size, iresp));
} else {
static const char anon[] = "anonymous";
pnx_sasl_set_bytes_out(transport, pn_bytes(sizeof anon-1, anon));
}
pnx_sasl_set_desired_state(transport, SASL_POSTED_INIT);
return true;
}
return false;
}