Repository: qpid-proton Updated Branches: refs/heads/master 70a463f00 -> 2c383aaa8
NO-JIRA: Rearrange file order and small tidying changes Project: http://git-wip-us.apache.org/repos/asf/qpid-proton/repo Commit: http://git-wip-us.apache.org/repos/asf/qpid-proton/commit/37730cc8 Tree: http://git-wip-us.apache.org/repos/asf/qpid-proton/tree/37730cc8 Diff: http://git-wip-us.apache.org/repos/asf/qpid-proton/diff/37730cc8 Branch: refs/heads/master Commit: 37730cc83133b9424e8be261c98abf868638046e Parents: 70a463f Author: Andrew Stitcher <astitc...@apache.org> Authored: Fri Jun 19 16:53:41 2015 -0400 Committer: Andrew Stitcher <astitc...@apache.org> Committed: Tue Jun 30 13:23:22 2015 -0400 ---------------------------------------------------------------------- proton-c/src/sasl/sasl.c | 414 ++++++++++++++++++++---------------------- 1 file changed, 193 insertions(+), 221 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/37730cc8/proton-c/src/sasl/sasl.c ---------------------------------------------------------------------- diff --git a/proton-c/src/sasl/sasl.c b/proton-c/src/sasl/sasl.c index 2e6be06..4ef9e99 100644 --- a/proton-c/src/sasl/sasl.c +++ b/proton-c/src/sasl/sasl.c @@ -32,12 +32,15 @@ static inline pn_transport_t *get_transport_internal(pn_sasl_t *sasl) { - // The external pn_sasl_t is really a pointer to the internal pni_transport_t - return ((pn_transport_t *)sasl); + // The external pn_sasl_t is really a pointer to the internal pni_transport_t + return ((pn_transport_t *)sasl); } -static ssize_t pn_sasl_input(pn_transport_t *transport, const char *bytes, size_t available); -static ssize_t pn_sasl_output(pn_transport_t *transport, char *bytes, size_t size); +static inline pni_sasl_t *get_sasl_internal(pn_sasl_t *sasl) +{ + // The external pn_sasl_t is really a pointer to the internal pni_transport_t + return sasl ? ((pn_transport_t *)sasl)->sasl : NULL; +} static ssize_t pn_input_read_sasl_header(pn_transport_t* transport, unsigned int layer, const char* bytes, size_t available); static ssize_t pn_input_read_sasl(pn_transport_t *transport, unsigned int layer, const char *bytes, size_t available); @@ -75,91 +78,6 @@ const pn_io_layer_t sasl_layer = { #define SASL_HEADER ("AMQP\x03\x01\x00\x00") #define SASL_HEADER_LEN 8 -static ssize_t pn_input_read_sasl_header(pn_transport_t* transport, unsigned int layer, const char* bytes, size_t available) -{ - bool eos = pn_transport_capacity(transport)==PN_EOS; - pni_protocol_type_t protocol = pni_sniff_header(bytes, available); - switch (protocol) { - case PNI_PROTOCOL_AMQP_SASL: - if (transport->io_layers[layer] == &sasl_read_header_layer) { - transport->io_layers[layer] = &sasl_layer; - } else { - transport->io_layers[layer] = &sasl_write_header_layer; - } - if (transport->trace & PN_TRACE_FRM) - pn_transport_logf(transport, " <- %s", "SASL"); - pni_sasl_set_external_security(transport, pn_ssl_get_ssf((pn_ssl_t*)transport), pn_ssl_get_remote_subject((pn_ssl_t*)transport)); - return SASL_HEADER_LEN; - case PNI_PROTOCOL_INSUFFICIENT: - if (!eos) return 0; - /* Fallthru */ - default: - break; - } - transport->close_sent = true; - char quoted[1024]; - pn_quote_data(quoted, 1024, bytes, available); - pn_do_error(transport, "amqp:connection:framing-error", - "%s header mismatch: %s ['%s']%s", "SASL", pni_protocol_name(protocol), quoted, - !eos ? "" : " (connection aborted)"); - pn_set_error_layer(transport); - return PN_EOS; -} - -static ssize_t pn_input_read_sasl(pn_transport_t* transport, unsigned int layer, const char* bytes, size_t available) -{ - bool eos = pn_transport_capacity(transport)==PN_EOS; - if (eos) { - transport->close_sent = true; - pn_do_error(transport, "amqp:connection:framing-error", "connection aborted"); - pn_set_error_layer(transport); - return PN_EOS; - } - - if (!transport->sasl->input_bypass) { - ssize_t n = pn_sasl_input(transport, bytes, available); - if (n != PN_EOS) return n; - - transport->sasl->input_bypass = true; - if (transport->sasl->output_bypass) - transport->io_layers[layer] = &pni_passthru_layer; - } - return pni_passthru_layer.process_input(transport, layer, bytes, available ); -} - -static ssize_t pn_output_write_sasl_header(pn_transport_t *transport, unsigned int layer, char *bytes, size_t size) -{ - if (transport->trace & PN_TRACE_FRM) - pn_transport_logf(transport, " -> %s", "SASL"); - assert(size >= SASL_HEADER_LEN); - memmove(bytes, SASL_HEADER, SASL_HEADER_LEN); - if (transport->io_layers[layer]==&sasl_write_header_layer) { - transport->io_layers[layer] = &sasl_layer; - } else { - transport->io_layers[layer] = &sasl_read_header_layer; - } - return SASL_HEADER_LEN; -} - -static ssize_t pn_output_write_sasl(pn_transport_t* transport, unsigned int layer, char* bytes, size_t available) -{ - if (!transport->sasl->output_bypass) { - // this accounts for when pn_do_error is invoked, e.g. by idle timeout - ssize_t n; - if (transport->close_sent) { - n = PN_EOS; - } else { - n = pn_sasl_output(transport, bytes, available); - } - if (n != PN_EOS) return n; - - transport->sasl->output_bypass = true; - if (transport->sasl->input_bypass) - transport->io_layers[layer] = &pni_passthru_layer; - } - return pni_passthru_layer.process_output(transport, layer, bytes, available ); -} - static bool pni_sasl_is_server_state(enum pni_sasl_state state) { return state==SASL_NONE @@ -193,12 +111,6 @@ static bool pni_sasl_is_final_output_state(pni_sasl_t *sasl) || last_state==SASL_POSTED_OUTCOME; } -static inline pni_sasl_t *get_sasl_internal(pn_sasl_t *sasl) -{ - // The external pn_sasl_t is really a pointer to the internal pni_transport_t - return sasl ? ((pn_transport_t *)sasl)->sasl : NULL; -} - static void pni_emit(pn_transport_t *transport) { if (transport->connection && transport->connection->collector) { @@ -207,61 +119,6 @@ static void pni_emit(pn_transport_t *transport) } } -// Look for symbol in the mech include list - not particlarly efficient, -// but probably not used enough to matter. -// -// Note that if there is no inclusion list then every mech is implicitly included. -bool pni_included_mech(const char *included_mech_list, pn_bytes_t s) -{ - if (!included_mech_list) return true; - - const char * end_list = included_mech_list+strlen(included_mech_list); - size_t len = s.size; - const char *c = included_mech_list; - while (c!=NULL) { - // If there are not enough chars left in the list no matches - if ((ptrdiff_t)len > end_list-c) return false; - - // Is word equal with a space or end of string afterwards? - if (pn_strncasecmp(c, s.start, len)==0 && (c[len]==' ' || c[len]==0) ) return true; - - c = strchr(c, ' '); - c = c ? c+1 : NULL; - } - return false; -} - -// 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_sasl_set_desired_state(pn_transport_t *transport, enum pni_sasl_state desired_state) { pni_sasl_t *sasl = transport->sasl; @@ -353,6 +210,170 @@ static void pni_post_sasl_frame(pn_transport_t *transport) } } +static ssize_t pn_input_read_sasl_header(pn_transport_t* transport, unsigned int layer, const char* bytes, size_t available) +{ + bool eos = pn_transport_capacity(transport)==PN_EOS; + pni_protocol_type_t protocol = pni_sniff_header(bytes, available); + switch (protocol) { + case PNI_PROTOCOL_AMQP_SASL: + if (transport->io_layers[layer] == &sasl_read_header_layer) { + transport->io_layers[layer] = &sasl_layer; + } else { + transport->io_layers[layer] = &sasl_write_header_layer; + } + if (transport->trace & PN_TRACE_FRM) + pn_transport_logf(transport, " <- %s", "SASL"); + pni_sasl_set_external_security(transport, pn_ssl_get_ssf((pn_ssl_t*)transport), pn_ssl_get_remote_subject((pn_ssl_t*)transport)); + return SASL_HEADER_LEN; + case PNI_PROTOCOL_INSUFFICIENT: + if (!eos) return 0; + /* Fallthru */ + default: + break; + } + transport->close_sent = true; + char quoted[1024]; + pn_quote_data(quoted, 1024, bytes, available); + pn_do_error(transport, "amqp:connection:framing-error", + "%s header mismatch: %s ['%s']%s", "SASL", pni_protocol_name(protocol), quoted, + !eos ? "" : " (connection aborted)"); + pn_set_error_layer(transport); + return PN_EOS; +} + +static void pni_sasl_start_server_if_needed(pn_transport_t *transport) +{ + pni_sasl_t *sasl = transport->sasl; + if (!sasl->client && sasl->desired_state<SASL_POSTED_MECHANISMS) { + if (!pni_init_server(transport)) return; + + // Setup to send SASL mechanisms frame + pni_sasl_set_desired_state(transport, SASL_POSTED_MECHANISMS); + } +} + +static ssize_t pn_input_read_sasl(pn_transport_t* transport, unsigned int layer, const char* bytes, size_t available) +{ + bool eos = pn_transport_capacity(transport)==PN_EOS; + if (eos) { + transport->close_sent = true; + pn_do_error(transport, "amqp:connection:framing-error", "connection aborted"); + pn_set_error_layer(transport); + return PN_EOS; + } + + if (!transport->sasl->input_bypass) { + pni_sasl_start_server_if_needed(transport); + + bool dummy = false; + ssize_t n = pn_dispatcher_input(transport, bytes, available, false, &dummy); + + if (n!=0 || !pni_sasl_is_final_input_state(transport->sasl)) { + return n; + } + + transport->sasl->input_bypass = true; + if (transport->sasl->output_bypass) + transport->io_layers[layer] = &pni_passthru_layer; + } + return pni_passthru_layer.process_input(transport, layer, bytes, available ); +} + +static ssize_t pn_output_write_sasl_header(pn_transport_t *transport, unsigned int layer, char *bytes, size_t size) +{ + if (transport->trace & PN_TRACE_FRM) + pn_transport_logf(transport, " -> %s", "SASL"); + assert(size >= SASL_HEADER_LEN); + memmove(bytes, SASL_HEADER, SASL_HEADER_LEN); + if (transport->io_layers[layer]==&sasl_write_header_layer) { + transport->io_layers[layer] = &sasl_layer; + } else { + transport->io_layers[layer] = &sasl_read_header_layer; + } + return SASL_HEADER_LEN; +} + +static ssize_t pn_output_write_sasl(pn_transport_t* transport, unsigned int layer, char* bytes, size_t available) +{ + if (!transport->sasl->output_bypass) { + // this accounts for when pn_do_error is invoked, e.g. by idle timeout + if (!transport->close_sent) { + pni_sasl_start_server_if_needed(transport); + + pni_post_sasl_frame(transport); + + pni_sasl_t *sasl = transport->sasl; + if (transport->available != 0 || !pni_sasl_is_final_output_state(sasl)) { + return pn_dispatcher_output(transport, bytes, available); + } else { + if (sasl->outcome != PN_SASL_OK && pni_sasl_is_final_input_state(sasl)) { + pn_transport_close_tail(transport); + } + } + } + + transport->sasl->output_bypass = true; + if (transport->sasl->input_bypass) + transport->io_layers[layer] = &pni_passthru_layer; + } + return pni_passthru_layer.process_output(transport, layer, bytes, available ); +} + +// Look for symbol in the mech include list - not particlarly efficient, +// but probably not used enough to matter. +// +// Note that if there is no inclusion list then every mech is implicitly included. +bool pni_included_mech(const char *included_mech_list, pn_bytes_t s) +{ + if (!included_mech_list) return true; + + const char * end_list = included_mech_list+strlen(included_mech_list); + size_t len = s.size; + const char *c = included_mech_list; + while (c!=NULL) { + // If there are not enough chars left in the list no matches + if ((ptrdiff_t)len > end_list-c) return false; + + // Is word equal with a space or end of string afterwards? + if (pn_strncasecmp(c, s.start, len)==0 && (c[len]==' ' || c[len]==0) ) return true; + + c = strchr(c, ' '); + c = c ? c+1 : NULL; + } + return false; +} + +// 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; + } + } +} + pn_sasl_t *pn_sasl(pn_transport_t *transport) { if (!transport->sasl) { @@ -387,6 +408,28 @@ pn_sasl_t *pn_sasl(pn_transport_t *transport) return (pn_sasl_t *)transport; } +void pn_sasl_free(pn_transport_t *transport) +{ + if (transport) { + pni_sasl_t *sasl = transport->sasl; + if (sasl) { + free(sasl->selected_mechanism); + free(sasl->included_mechanisms); + free(sasl->password); + free(sasl->config_name); + free(sasl->config_dir); + free(sasl->external_auth); + + // CYRUS_SASL + if (sasl->impl_context) { + pni_sasl_impl_free(transport); + } + + free(sasl); + } + } +} + // This is a hack to tell us that // no actual negotiation is going to happen and we can go // straight to the AMQP layer; it can only work on the client side @@ -480,77 +523,6 @@ pn_sasl_outcome_t pn_sasl_outcome(pn_sasl_t *sasl0) return sasl ? sasl->outcome : PN_SASL_NONE; } -void pn_sasl_free(pn_transport_t *transport) -{ - if (transport) { - pni_sasl_t *sasl = transport->sasl; - if (sasl) { - free(sasl->selected_mechanism); - free(sasl->included_mechanisms); - free(sasl->password); - free(sasl->config_name); - free(sasl->config_dir); - free(sasl->external_auth); - - // CYRUS_SASL - if (sasl->impl_context) { - pni_sasl_impl_free(transport); - } - - free(sasl); - } - } -} - -static void pni_sasl_server_init(pn_transport_t *transport) -{ - if (!pni_init_server(transport)) return; - - // Setup to send SASL mechanisms frame - pni_sasl_set_desired_state(transport, SASL_POSTED_MECHANISMS); -} - -static void pn_sasl_process(pn_transport_t *transport) -{ - pni_sasl_t *sasl = transport->sasl; - if (!sasl->client) { - if (sasl->desired_state<SASL_POSTED_MECHANISMS) { - pni_sasl_server_init(transport); - } - } -} - -ssize_t pn_sasl_input(pn_transport_t *transport, const char *bytes, size_t available) -{ - pn_sasl_process(transport); - - pni_sasl_t *sasl = transport->sasl; - bool dummy = false; - ssize_t n = pn_dispatcher_input(transport, bytes, available, false, &dummy); - - if (n==0 && pni_sasl_is_final_input_state(sasl)) { - return PN_EOS; - } - return n; -} - -ssize_t pn_sasl_output(pn_transport_t *transport, char *bytes, size_t size) -{ - pn_sasl_process(transport); - - pni_post_sasl_frame(transport); - - pni_sasl_t *sasl = transport->sasl; - if (transport->available == 0 && pni_sasl_is_final_output_state(sasl)) { - if (sasl->outcome != PN_SASL_OK && pni_sasl_is_final_input_state(sasl)) { - pn_transport_close_tail(transport); - } - return PN_EOS; - } else { - return pn_dispatcher_output(transport, bytes, size); - } -} - // Received Server side int pn_do_init(pn_transport_t *transport, uint8_t frame_type, uint16_t channel, pn_data_t *args, const pn_bytes_t *payload) { --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@qpid.apache.org For additional commands, e-mail: commits-h...@qpid.apache.org