// This takes a space separated list and zero terminates it in place // whilst adding pointers to the existing strings in a string array. // This means that you can't free the original storage until you have // finished with the resulting list. void pni_split_mechs(char *mechlist, const char* included_mechs, char *mechs[], int *count) { char *start = mechlist; char *end = start; while (*end) { if (*end == ' ') { if (start != end) { *end = '\0'; if (pni_included_mech(included_mechs, pn_bytes(end-start, start))) { mechs[(*count)++] = start; } } end++; start = end; } else { end++; } } if (start != end) { if (pni_included_mech(included_mechs, pn_bytes(end-start, start))) { mechs[(*count)++] = start; } } }
void pni_process_init(pn_transport_t *transport, const char *mechanism, const pn_bytes_t *recv) { pni_sasl_t *sasl = transport->sasl; int result = pni_wrap_server_start(sasl, mechanism, recv); if (result==SASL_OK) { // We need to filter out a supplied mech in in the inclusion list // as the client could have used a mech that we support, but that // wasn't on the list we sent. if (!pni_included_mech(sasl->included_mechanisms, pn_bytes(strlen(mechanism), mechanism))) { sasl_conn_t *cyrus_conn = (sasl_conn_t*)sasl->impl_context; sasl_seterror(cyrus_conn, 0, "Client mechanism not in mechanism inclusion list."); result = SASL_FAIL; } } pni_process_server_result(transport, result); }
// Received client side int pn_do_mechanisms(pn_transport_t *transport, uint8_t frame_type, uint16_t channel, pn_data_t *args, const pn_bytes_t *payload) { pni_sasl_t *sasl = transport->sasl; // If we already pretended we got the ANONYMOUS mech then ignore if (sasl->last_state==SASL_PRETEND_OUTCOME) return 0; // This scanning relies on pn_data_scan leaving the pn_data_t cursors // where they are after finishing the scan int err = pn_data_scan(args, "D.[@["); if (err) return err; pn_string_t *mechs = pn_string(""); // Now keep checking for end of array and pull a symbol while(pn_data_next(args)) { pn_bytes_t s = pn_data_get_symbol(args); if (pni_included_mech(transport->sasl->included_mechanisms, s)) { pn_string_addf(mechs, "%*s ", (int)s.size, s.start); } } if (pn_string_size(mechs)) { pn_string_buffer(mechs)[pn_string_size(mechs)-1] = 0; } if (pni_init_client(transport) && pni_process_mechanisms(transport, pn_string_get(mechs))) { pni_sasl_set_desired_state(transport, SASL_POSTED_INIT); } else { sasl->outcome = PN_SASL_PERM; pni_sasl_set_desired_state(transport, SASL_RECVED_OUTCOME_FAIL); } pn_free(mechs); return 0; }