WIP: a sasl implementation that delegates to a remote authentication service, using AMQP SASL frame relaying
Project: http://git-wip-us.apache.org/repos/asf/qpid-proton/repo Commit: http://git-wip-us.apache.org/repos/asf/qpid-proton/commit/4894265b Tree: http://git-wip-us.apache.org/repos/asf/qpid-proton/tree/4894265b Diff: http://git-wip-us.apache.org/repos/asf/qpid-proton/diff/4894265b Branch: refs/heads/PROTON-1488 Commit: 4894265b3d1517f62265907000dfc948cbb1c75d Parents: d652405 Author: Gordon Sim <g...@redhat.com> Authored: Wed May 17 16:19:47 2017 +0100 Committer: Gordon Sim <g...@redhat.com> Committed: Thu May 25 14:44:45 2017 +0100 ---------------------------------------------------------------------- proton-c/CMakeLists.txt | 4 +- proton-c/include/proton/proactor.h | 2 + proton-c/src/core/util.h | 2 +- proton-c/src/sasl/cyrus_sasl.c | 9 +- proton-c/src/sasl/none_sasl.c | 5 + proton-c/src/sasl/remote_sasl.c | 271 ++++++++++++++++++++++++++++++++ proton-c/src/sasl/sasl-internal.h | 23 ++- proton-c/src/sasl/sasl.c | 122 +++++++++++--- 8 files changed, 414 insertions(+), 24 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/4894265b/proton-c/CMakeLists.txt ---------------------------------------------------------------------- diff --git a/proton-c/CMakeLists.txt b/proton-c/CMakeLists.txt index 33933b8..094fba4 100644 --- a/proton-c/CMakeLists.txt +++ b/proton-c/CMakeLists.txt @@ -486,7 +486,7 @@ if (PROACTOR STREQUAL "epoll" OR (NOT PROACTOR AND NOT BUILD_PROACTOR)) check_symbol_exists(epoll_wait "sys/epoll.h" HAVE_EPOLL) if (HAVE_EPOLL) set (PROACTOR_OK epoll) - set (qpid-proton-proactor src/proactor/epoll.c src/proactor/proactor-internal.c) + set (qpid-proton-proactor src/proactor/epoll.c src/proactor/proactor-internal.c src/sasl/remote_sasl.c) set (PROACTOR_LIBS -lpthread) set_source_files_properties (${qpid-proton-proactor} PROPERTIES COMPILE_FLAGS "${COMPILE_WARNING_FLAGS} ${COMPILE_LANGUAGE_FLAGS} ${LTO}" @@ -498,7 +498,7 @@ if (PROACTOR STREQUAL "libuv" OR (NOT PROACTOR AND NOT PROACTOR_OK)) find_package(Libuv) if (LIBUV_FOUND) set (PROACTOR_OK libuv) - set (qpid-proton-proactor src/proactor/libuv.c src/proactor/proactor-internal.c) + set (qpid-proton-proactor src/proactor/libuv.c src/proactor/proactor-internal.c src/sasl/remote_sasl.c) set (PROACTOR_LIBS ${Libuv_LIBRARIES}) set_source_files_properties (${qpid-proton-proactor} PROPERTIES COMPILE_FLAGS "${COMPILE_WARNING_FLAGS} ${COMPILE_LANGUAGE_FLAGS} ${LTO}" http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/4894265b/proton-c/include/proton/proactor.h ---------------------------------------------------------------------- diff --git a/proton-c/include/proton/proactor.h b/proton-c/include/proton/proactor.h index 861afbe..5dd16f9 100644 --- a/proton-c/include/proton/proactor.h +++ b/proton-c/include/proton/proactor.h @@ -285,6 +285,8 @@ PNP_EXTERN pn_proactor_t *pn_event_proactor(pn_event_t *event); */ PNP_EXTERN pn_millis_t pn_proactor_now(void); +PNP_EXTERN void pn_use_remote_authentication_service(const char* address); + /** * @defgroup proactor_events Events * http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/4894265b/proton-c/src/core/util.h ---------------------------------------------------------------------- diff --git a/proton-c/src/core/util.h b/proton-c/src/core/util.h index 4d3ba3b..ee83f90 100644 --- a/proton-c/src/core/util.h +++ b/proton-c/src/core/util.h @@ -39,7 +39,7 @@ void pn_print_data(const char *bytes, size_t size); bool pn_env_bool(const char *name); pn_timestamp_t pn_timestamp_min(pn_timestamp_t a, pn_timestamp_t b); -char *pn_strdup(const char *src); +PN_EXTERN char *pn_strdup(const char *src); char *pn_strndup(const char *src, size_t n); int pn_strcasecmp(const char* a, const char* b); int pn_strncasecmp(const char* a, const char* b, size_t len); http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/4894265b/proton-c/src/sasl/cyrus_sasl.c ---------------------------------------------------------------------- diff --git a/proton-c/src/sasl/cyrus_sasl.c b/proton-c/src/sasl/cyrus_sasl.c index ef1db9d..74e124f 100644 --- a/proton-c/src/sasl/cyrus_sasl.c +++ b/proton-c/src/sasl/cyrus_sasl.c @@ -247,6 +247,7 @@ bool pni_process_mechanisms(pn_transport_t *transport, const char *mechs) case SASL_OK: case SASL_CONTINUE: sasl->selected_mechanism = pn_strdup(mech_selected); + pni_sasl_set_desired_state(transport, SASL_POSTED_INIT); return true; case SASL_NOMECH: default: @@ -350,7 +351,13 @@ bool pni_init_server(pn_transport_t* transport) } } while (false); cyrus_conn = (sasl_conn_t*) sasl->impl_context; - return pni_check_sasl_result(cyrus_conn, result, transport); + if (pni_check_sasl_result(cyrus_conn, result, transport)) { + // Setup to send SASL mechanisms frame + pni_sasl_set_desired_state(transport, SASL_POSTED_MECHANISMS); + return true; + } else { + return false; + } } static int pni_wrap_server_start(pni_sasl_t *sasl, const char *mech_selected, const pn_bytes_t *in) http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/4894265b/proton-c/src/sasl/none_sasl.c ---------------------------------------------------------------------- diff --git a/proton-c/src/sasl/none_sasl.c b/proton-c/src/sasl/none_sasl.c index 0408a8f..84a6640 100644 --- a/proton-c/src/sasl/none_sasl.c +++ b/proton-c/src/sasl/none_sasl.c @@ -29,6 +29,8 @@ static const char PLAIN[] = "PLAIN"; bool pni_init_server(pn_transport_t* transport) { + // Setup to send SASL mechanisms frame + pni_sasl_set_desired_state(transport, SASL_POSTED_MECHANISMS); return true; } @@ -67,6 +69,7 @@ bool pni_process_mechanisms(pn_transport_t *transport, const char *mechs) transport->sasl->bytes_out.start = empty; transport->sasl->bytes_out.size = 0; } + pni_sasl_set_desired_state(transport, SASL_POSTED_INIT); return true; } @@ -98,6 +101,7 @@ bool pni_process_mechanisms(pn_transport_t *transport, const char *mechs) free(memset(transport->sasl->password, 0, psize)); transport->sasl->password = NULL; + pni_sasl_set_desired_state(transport, SASL_POSTED_INIT); return true; } @@ -122,6 +126,7 @@ bool pni_process_mechanisms(pn_transport_t *transport, const char *mechs) transport->sasl->bytes_out.start = anon; transport->sasl->bytes_out.size = sizeof anon-1; } + pni_sasl_set_desired_state(transport, SASL_POSTED_INIT); return true; } return false; http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/4894265b/proton-c/src/sasl/remote_sasl.c ---------------------------------------------------------------------- diff --git a/proton-c/src/sasl/remote_sasl.c b/proton-c/src/sasl/remote_sasl.c new file mode 100644 index 0000000..9ef3484 --- /dev/null +++ b/proton-c/src/sasl/remote_sasl.c @@ -0,0 +1,271 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +#include "sasl-internal.h" + +#include "core/engine-internal.h" +#include "core/util.h" +#include "proton/proactor.h" + +typedef struct +{ + size_t size; + char *start; +} pni_owned_bytes_t; + +const int8_t UPSTREAM_INIT_RECEIVED = 1; +const int8_t UPSTREAM_RESPONSE_RECEIVED = 2; +const int8_t DOWNSTREAM_MECHANISMS_RECEIVED = 3; +const int8_t DOWNSTREAM_CHALLENGE_RECEIVED = 4; +const int8_t DOWNSTREAM_OUTCOME_RECEIVED = 5; + +const char* authentication_service_address = NULL; + +typedef struct +{ + pn_connection_t* downstream; + char* selected_mechanism; + pni_owned_bytes_t response; + int8_t downstream_state; + + pn_connection_t* upstream; + char* mechlist; + pni_owned_bytes_t challenge; + int8_t upstream_state; + + pn_sasl_outcome_t outcome; + int refcount; +} pni_sasl_relay_t; + +void pni_copy_bytes(const pn_bytes_t* from, pni_owned_bytes_t* to) +{ + if (to->start) { + free(to->start); + } + to->start = (char*) malloc(from->size); + to->size = from->size; + memcpy(to->start, from->start, from->size); +} + +pni_sasl_relay_t* new_pni_sasl_relay_t(void) +{ + pni_sasl_relay_t* instance = (pni_sasl_relay_t*) malloc(sizeof(pni_sasl_relay_t)); + instance->selected_mechanism = 0; + instance->response.start = 0; + instance->response.size = 0; + instance->mechlist = 0; + instance->challenge.start = 0; + instance->challenge.size = 0; + instance->refcount = 1; + instance->upstream_state = 0; + instance->downstream_state = 0; + return instance; +} + +void delete_pni_sasl_relay_t(pni_sasl_relay_t* instance) +{ + if (instance->mechlist) free(instance->mechlist); + if (instance->selected_mechanism) free(instance->selected_mechanism); + if (instance->response.start) free(instance->response.start); + if (instance->challenge.start) free(instance->challenge.start); + free(instance); +} + +void release_pni_sasl_relay_t(pni_sasl_relay_t* instance) +{ + if (instance && --(instance->refcount) == 0) { + delete_pni_sasl_relay_t(instance); + } +} + +bool remote_init_server(pn_transport_t* transport) +{ + pn_connection_t* upstream = pn_transport_connection(transport); + if (upstream) { + if (transport->sasl->impl_context) { + return true; + } + pni_sasl_relay_t* impl = new_pni_sasl_relay_t(); + transport->sasl->impl_context = impl; + impl->upstream = upstream; + pn_proactor_t* proactor = pn_connection_proactor(upstream); + if (!proactor) return false; + impl->downstream = pn_connection(); + pn_connection_set_hostname(impl->downstream, pn_connection_get_hostname(upstream)); + //do I need to explicitly set up sasl? if so how? need to handle connection_bound? + //for now just fake it with dummy user + pn_connection_set_user(impl->downstream, "dummy"); + pn_connection_set_context(impl->downstream, transport->sasl->impl_context);//TODO: use record? + + pn_proactor_connect(proactor, impl->downstream, authentication_service_address); + return true; + } else { + return false; + } +} + +bool remote_init_client(pn_transport_t* transport) +{ + //for the client side of the connection to the authentication + //service, need to use the same context as the server side of the + //connection it is authenticating on behalf of + pn_connection_t* conn = pn_transport_connection(transport); + transport->sasl->impl_context = pn_connection_get_context(conn); + ((pni_sasl_relay_t*) transport->sasl->impl_context)->refcount++; + return true; +} + +bool remote_free(pn_transport_t *transport) +{ + if (transport->sasl->impl_context) { + release_pni_sasl_relay_t((pni_sasl_relay_t*) transport->sasl->impl_context); + return true; + } else { + return false; + } +} + +bool remote_prepare(pn_transport_t *transport) +{ + pni_sasl_relay_t* impl = (pni_sasl_relay_t*) transport->sasl->impl_context; + if (!impl) return false; + if (transport->sasl->client) { + if (impl->downstream_state == UPSTREAM_INIT_RECEIVED) { + transport->sasl->selected_mechanism = impl->selected_mechanism; + transport->sasl->bytes_out.start = impl->response.start; + transport->sasl->bytes_out.size = impl->response.size; + pni_sasl_set_desired_state(transport, SASL_POSTED_INIT); + } else if (impl->downstream_state == UPSTREAM_RESPONSE_RECEIVED) { + transport->sasl->bytes_out.start = impl->response.start; + transport->sasl->bytes_out.size = impl->response.size; + pni_sasl_set_desired_state(transport, SASL_POSTED_RESPONSE); + } + impl->downstream_state = 0; + } else { + if (impl->upstream_state == DOWNSTREAM_MECHANISMS_RECEIVED) { + pni_sasl_set_desired_state(transport, SASL_POSTED_MECHANISMS); + } else if (impl->upstream_state == DOWNSTREAM_CHALLENGE_RECEIVED) { + transport->sasl->bytes_out.start = impl->challenge.start; + transport->sasl->bytes_out.size = impl->challenge.size; + pni_sasl_set_desired_state(transport, SASL_POSTED_CHALLENGE); + } else if (impl->upstream_state == DOWNSTREAM_OUTCOME_RECEIVED) { + transport->sasl->outcome = impl->outcome; + pni_sasl_set_desired_state(transport, SASL_POSTED_OUTCOME); + } + impl->upstream_state = 0; + } + return true; +} + +// Client / Downstream +bool remote_process_mechanisms(pn_transport_t *transport, const char *mechs) +{ + pni_sasl_relay_t* impl = (pni_sasl_relay_t*) transport->sasl->impl_context; + if (impl) { + if (impl->upstream_state != DOWNSTREAM_MECHANISMS_RECEIVED) { + impl->mechlist = pn_strdup(mechs); + impl->upstream_state = DOWNSTREAM_MECHANISMS_RECEIVED; + pn_connection_wake(impl->upstream); + } + return true; + } else { + return false; + } +} + +// Client / Downstream +void remote_process_challenge(pn_transport_t *transport, const pn_bytes_t *recv) +{ + pni_sasl_relay_t* impl = (pni_sasl_relay_t*) transport->sasl->impl_context; + if (impl && impl->upstream_state != DOWNSTREAM_CHALLENGE_RECEIVED) { + pni_copy_bytes(recv, &(impl->challenge)); + impl->upstream_state = DOWNSTREAM_CHALLENGE_RECEIVED; + pn_connection_wake(impl->upstream); + } +} + +// Client / Downstream +bool remote_process_outcome(pn_transport_t *transport) +{ + pni_sasl_relay_t* impl = (pni_sasl_relay_t*) transport->sasl->impl_context; + if (impl) { + if (impl->upstream_state != DOWNSTREAM_OUTCOME_RECEIVED) { + impl->outcome = transport->sasl->outcome; + impl->upstream_state = DOWNSTREAM_OUTCOME_RECEIVED; + pn_connection_wake(impl->upstream); + } + return true; + } else { + return false; + } +} + +// Server / Upstream +int remote_get_mechs(pn_transport_t *transport, char **mechlist) +{ + pni_sasl_relay_t* impl = (pni_sasl_relay_t*) transport->sasl->impl_context; + if (impl && impl->mechlist) { + *mechlist = pn_strdup(impl->mechlist); + return 1; + } else { + return 0; + } +} + +// Server / Upstream +void remote_process_init(pn_transport_t *transport, const char *mechanism, const pn_bytes_t *recv) +{ + pni_sasl_relay_t* impl = (pni_sasl_relay_t*) transport->sasl->impl_context; + if (impl) { + impl->selected_mechanism = pn_strdup(mechanism); + pni_copy_bytes(recv, &(impl->response)); + impl->downstream_state = UPSTREAM_INIT_RECEIVED; + pn_connection_wake(impl->downstream); + } +} + +// Server / Upstream +void remote_process_response(pn_transport_t *transport, const pn_bytes_t *recv) +{ + pni_sasl_relay_t* impl = (pni_sasl_relay_t*) transport->sasl->impl_context; + if (impl) { + pni_copy_bytes(recv, &(impl->response)); + impl->downstream_state = UPSTREAM_RESPONSE_RECEIVED; + pn_connection_wake(impl->downstream); + } +} + +void pn_use_remote_authentication_service(const char* address) +{ + authentication_service_address = address; + pni_sasl_implementation remote_impl; + remote_impl.free = &remote_free; + remote_impl.get_mechs = &remote_get_mechs; + remote_impl.init_server = &remote_init_server; + remote_impl.process_init = &remote_process_init; + remote_impl.process_response = &remote_process_response; + remote_impl.init_client = &remote_init_client; + remote_impl.process_mechanisms = &remote_process_mechanisms; + remote_impl.process_challenge = &remote_process_challenge; + remote_impl.process_outcome = &remote_process_outcome; + remote_impl.prepare = &remote_prepare; + pni_sasl_set_implementation(remote_impl); +} http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/4894265b/proton-c/src/sasl/sasl-internal.h ---------------------------------------------------------------------- diff --git a/proton-c/src/sasl/sasl-internal.h b/proton-c/src/sasl/sasl-internal.h index 2873777..8fef243 100644 --- a/proton-c/src/sasl/sasl-internal.h +++ b/proton-c/src/sasl/sasl-internal.h @@ -52,6 +52,27 @@ ssize_t pni_sasl_impl_max_encrypt_size(pn_transport_t *transport); ssize_t pni_sasl_impl_encode(pn_transport_t *transport, pn_bytes_t in, pn_bytes_t *out); ssize_t pni_sasl_impl_decode(pn_transport_t *transport, pn_bytes_t in, pn_bytes_t *out); +typedef bool (*pni_sasl_function)(pn_transport_t *transport); +typedef void (*pni_sasl_challenge_response)(pn_transport_t *transport, const pn_bytes_t *recv); +typedef void (*pni_sasl_init)(pn_transport_t *transport, const char *mechanism, const pn_bytes_t *recv); +typedef bool (*pni_sasl_set_mechanisms)(pn_transport_t *transport, const char *mechanism); +typedef int (*pni_sasl_get_mechanisms)(pn_transport_t *transport, char **mechlist); + +typedef struct +{ + pni_sasl_function free; + pni_sasl_get_mechanisms get_mechs; + pni_sasl_function init_server; + pni_sasl_init process_init; + pni_sasl_challenge_response process_response; + pni_sasl_function init_client; + pni_sasl_set_mechanisms process_mechanisms; + pni_sasl_challenge_response process_challenge; + pni_sasl_function process_outcome; + pni_sasl_function prepare; +} pni_sasl_implementation; + +PN_EXTERN void pni_sasl_set_implementation(pni_sasl_implementation); // Shared SASL API used by the actual SASL authenticators enum pni_sasl_state { @@ -91,6 +112,6 @@ struct pni_sasl_t { // Shared Utility used by sasl implementations void pni_split_mechs(char *mechlist, const char* included_mechs, char *mechs[], int *count); bool pni_included_mech(const char *included_mech_list, pn_bytes_t s); -void pni_sasl_set_desired_state(pn_transport_t *transport, enum pni_sasl_state desired_state); +PN_EXTERN void pni_sasl_set_desired_state(pn_transport_t *transport, enum pni_sasl_state desired_state); #endif /* sasl-internal.h */ http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/4894265b/proton-c/src/sasl/sasl.c ---------------------------------------------------------------------- diff --git a/proton-c/src/sasl/sasl.c b/proton-c/src/sasl/sasl.c index 55c489d..dcdcd17 100644 --- a/proton-c/src/sasl/sasl.c +++ b/proton-c/src/sasl/sasl.c @@ -136,6 +136,85 @@ static void pni_emit(pn_transport_t *transport) } } +static pni_sasl_implementation* implementation = 0; + +void pni_sasl_set_implementation(pni_sasl_implementation i) +{ + implementation = (pni_sasl_implementation*) malloc(sizeof(pni_sasl_implementation)); + *implementation = i; +} + +void pni_sasl_impl_free_(pn_transport_t *transport) +{ + if (implementation) { + implementation->free(transport); + } else { + pni_sasl_impl_free(transport); + } +} + +int pni_sasl_impl_list_mechs_(pn_transport_t *transport, char **mechlist) +{ + if (implementation) { + return implementation->get_mechs(transport, mechlist); + } else { + return pni_sasl_impl_list_mechs(transport, mechlist); + } +} + +bool pni_init_server_(pn_transport_t *transport) +{ + if (implementation) { + return implementation->init_server(transport); + } else { + return pni_init_server(transport); + } +} + +void pni_process_init_(pn_transport_t *transport, const char *mechanism, const pn_bytes_t *recv) +{ + if (implementation) { + implementation->process_init(transport, mechanism, recv); + } else { + pni_process_init(transport, mechanism, recv); + } +} + +void pni_process_response_(pn_transport_t *transport, const pn_bytes_t *recv) +{ + if (implementation) { + implementation->process_response(transport, recv); + } else { + pni_process_response(transport, recv); + } +} + +bool pni_init_client_(pn_transport_t *transport) +{ + if (implementation) { + return implementation->init_client(transport); + } else { + return pni_init_client(transport); + } +} +bool pni_process_mechanisms_(pn_transport_t *transport, const char *mechs) +{ + if (implementation) { + return implementation->process_mechanisms(transport, mechs); + } else { + return pni_process_mechanisms(transport, mechs); + } +} + +void pni_process_challenge_(pn_transport_t *transport, const pn_bytes_t *recv) +{ + if (implementation) { + implementation->process_challenge(transport, recv); + } else { + pni_process_challenge(transport, recv); + } +} + void pni_sasl_set_desired_state(pn_transport_t *transport, enum pni_sasl_state desired_state) { pni_sasl_t *sasl = transport->sasl; @@ -157,9 +236,10 @@ void pni_sasl_set_desired_state(pn_transport_t *transport, enum pni_sasl_state d if (sasl->last_state==desired_state && desired_state==SASL_POSTED_CHALLENGE) { sasl->last_state = SASL_POSTED_MECHANISMS; } + bool changed = sasl->desired_state != desired_state; sasl->desired_state = desired_state; // Don't emit transport event on error as there will be a TRANSPORT_ERROR event - if (desired_state != SASL_ERROR) pni_emit(transport); + if (desired_state != SASL_ERROR && changed) pni_emit(transport); } } @@ -182,7 +262,7 @@ static void pni_post_sasl_frame(pn_transport_t *transport) char *mechlist = NULL; int count = 0; - if (pni_sasl_impl_list_mechs(transport, &mechlist) > 0) { + if (pni_sasl_impl_list_mechs_(transport, &mechlist) > 0) { pni_split_mechs(mechlist, sasl->included_mechanisms, mechs, &count); } @@ -192,16 +272,19 @@ static void pni_post_sasl_frame(pn_transport_t *transport) break; } case SASL_POSTED_RESPONSE: - pn_post_frame(transport, SASL_FRAME_TYPE, 0, "DL[z]", SASL_RESPONSE, out.size, out.start); - pni_emit(transport); + if (sasl->last_state != SASL_POSTED_RESPONSE) { + pn_post_frame(transport, SASL_FRAME_TYPE, 0, "DL[z]", SASL_RESPONSE, out.size, out.start); + 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) { + pn_post_frame(transport, SASL_FRAME_TYPE, 0, "DL[z]", SASL_CHALLENGE, out.size, out.start); + pni_emit(transport); } - pn_post_frame(transport, SASL_FRAME_TYPE, 0, "DL[z]", SASL_CHALLENGE, out.size, out.start); - pni_emit(transport); break; case SASL_POSTED_OUTCOME: if (sasl->last_state < SASL_POSTED_MECHANISMS) { @@ -277,10 +360,7 @@ 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); + if (!pni_init_server_(transport)) return; } } @@ -366,6 +446,9 @@ static ssize_t pn_output_write_sasl(pn_transport_t* transport, unsigned int laye pni_sasl_start_server_if_needed(transport); + if (implementation) { + implementation->prepare(transport);//allow impl to adjust sasl object on the right thread if needed + } pni_post_sasl_frame(transport); if (transport->available != 0 || !pni_sasl_is_final_output_state(sasl)) { @@ -520,7 +603,7 @@ void pn_sasl_free(pn_transport_t *transport) // CYRUS_SASL if (sasl->impl_context) { - pni_sasl_impl_free(transport); + pni_sasl_impl_free_(transport); } pn_buffer_free(sasl->decoded_buffer); pn_buffer_free(sasl->encoded_buffer); @@ -620,7 +703,7 @@ int pn_do_init(pn_transport_t *transport, uint8_t frame_type, uint16_t channel, if (err) return err; sasl->selected_mechanism = pn_strndup(mech.start, mech.size); - pni_process_init(transport, sasl->selected_mechanism, &recv); + pni_process_init_(transport, sasl->selected_mechanism, &recv); return 0; } @@ -661,11 +744,9 @@ int pn_do_mechanisms(pn_transport_t *transport, uint8_t frame_type, uint16_t cha pn_string_setn(mechs, symbol.start, symbol.size); } - if (pni_init_client(transport) && + if (!(pni_init_client_(transport) && pn_string_size(mechs) && - pni_process_mechanisms(transport, pn_string_get(mechs))) { - pni_sasl_set_desired_state(transport, SASL_POSTED_INIT); - } else { + pni_process_mechanisms_(transport, pn_string_get(mechs)))) { sasl->outcome = PN_SASL_PERM; pni_sasl_set_desired_state(transport, SASL_RECVED_OUTCOME_FAIL); } @@ -681,7 +762,7 @@ int pn_do_challenge(pn_transport_t *transport, uint8_t frame_type, uint16_t chan int err = pn_data_scan(args, "D.[z]", &recv); if (err) return err; - pni_process_challenge(transport, &recv); + pni_process_challenge_(transport, &recv); return 0; } @@ -693,7 +774,7 @@ int pn_do_response(pn_transport_t *transport, uint8_t frame_type, uint16_t chann int err = pn_data_scan(args, "D.[z]", &recv); if (err) return err; - pni_process_response(transport, &recv); + pni_process_response_(transport, &recv); return 0; } @@ -711,7 +792,10 @@ int pn_do_outcome(pn_transport_t *transport, uint8_t frame_type, uint16_t channe transport->authenticated = authenticated; pni_sasl_set_desired_state(transport, authenticated ? SASL_RECVED_OUTCOME_SUCCEED : SASL_RECVED_OUTCOME_FAIL); + if (implementation) { + implementation->process_outcome(transport); + } + return 0; } - --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@qpid.apache.org For additional commands, e-mail: commits-h...@qpid.apache.org