You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by as...@apache.org on 2017/06/02 22:51:34 UTC
[20/20] qpid-proton git commit: WIP: allow sasl implementation to be
selected per connection
WIP: allow sasl implementation to be selected per connection
Project: http://git-wip-us.apache.org/repos/asf/qpid-proton/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-proton/commit/53b90544
Tree: http://git-wip-us.apache.org/repos/asf/qpid-proton/tree/53b90544
Diff: http://git-wip-us.apache.org/repos/asf/qpid-proton/diff/53b90544
Branch: refs/heads/PROTON-1488
Commit: 53b905449d9b042e96ce7aaa824f1ef414c57601
Parents: 54645b7
Author: Gordon Sim <gs...@redhat.com>
Authored: Wed May 17 16:19:47 2017 +0100
Committer: Andrew Stitcher <as...@apache.org>
Committed: Fri Jun 2 18:50:55 2017 -0400
----------------------------------------------------------------------
proton-c/src/sasl/cyrus_sasl.c | 9 +++-
proton-c/src/sasl/none_sasl.c | 5 ++
proton-c/src/sasl/sasl-internal.h | 37 ++++++++++---
proton-c/src/sasl/sasl.c | 99 +++++++++++++++++++++++++++-------
4 files changed, 123 insertions(+), 27 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/53b90544/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/53b90544/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/53b90544/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..9d91311 100644
--- a/proton-c/src/sasl/sasl-internal.h
+++ b/proton-c/src/sasl/sasl-internal.h
@@ -35,8 +35,15 @@ void pni_sasl_set_user_password(pn_transport_t *transport, const char *user, con
void pni_sasl_set_remote_hostname(pn_transport_t *transport, const char* fqdn);
void pni_sasl_set_external_security(pn_transport_t *transport, int ssf, const char *authid);
+// Internal SASL security layer interface
+bool pni_sasl_impl_can_encrypt(pn_transport_t *transport);
+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);
+
// Internal SASL authenticator interface
void pni_sasl_impl_free(pn_transport_t *transport);
+void pni_sasl_prepare(pn_transport_t *transport);
int pni_sasl_impl_list_mechs(pn_transport_t *transport, char **mechlist);
bool pni_init_server(pn_transport_t *transport);
void pni_process_init(pn_transport_t *transport, const char *mechanism, const pn_bytes_t *recv);
@@ -45,13 +52,28 @@ void pni_process_response(pn_transport_t *transport, const pn_bytes_t *recv);
bool pni_init_client(pn_transport_t *transport);
bool pni_process_mechanisms(pn_transport_t *transport, const char *mechs);
void pni_process_challenge(pn_transport_t *transport, const pn_bytes_t *recv);
+void pni_process_outcome(pn_transport_t *transport);
-// Internal SASL security layer interface
-bool pni_sasl_impl_can_encrypt(pn_transport_t *transport);
-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 void (*pni_sasl_free_function)(pn_transport_t *transport);
+typedef struct pn_sasl_implementation
+{
+ pni_sasl_function prepare;
+ pni_sasl_free_function impl_free;
+ pni_sasl_get_mechanisms list_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;
+} pn_sasl_implementation;
// Shared SASL API used by the actual SASL authenticators
enum pni_sasl_state {
@@ -68,6 +90,7 @@ enum pni_sasl_state {
struct pni_sasl_t {
void *impl_context;
+ pn_sasl_implementation* impl;
char *selected_mechanism;
char *included_mechanisms;
const char *username;
@@ -91,6 +114,8 @@ 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);
+PN_EXTERN void pni_sasl_set_implementation(pn_transport_t *transport, pn_sasl_implementation impl, void* context);
+
#endif /* sasl-internal.h */
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/53b90544/proton-c/src/sasl/sasl.c
----------------------------------------------------------------------
diff --git a/proton-c/src/sasl/sasl.c b/proton-c/src/sasl/sasl.c
index 55c489d..4729574 100644
--- a/proton-c/src/sasl/sasl.c
+++ b/proton-c/src/sasl/sasl.c
@@ -136,6 +136,61 @@ static void pni_emit(pn_transport_t *transport)
}
}
+void pni_sasl_set_implementation(pn_transport_t *transport, pn_sasl_implementation i, void* context)
+{
+ *(transport->sasl->impl) = i;
+ transport->sasl->impl_context = context;
+}
+
+void pni_sasl_impl_free_(pn_transport_t *transport)
+{
+ transport->sasl->impl->impl_free(transport);
+}
+
+int pni_sasl_impl_list_mechs_(pn_transport_t *transport, char **mechlist)
+{
+ return transport->sasl->impl->list_mechs(transport, mechlist);
+}
+
+bool pni_init_server_(pn_transport_t *transport)
+{
+ return transport->sasl->impl->init_server(transport);
+}
+
+void pni_sasl_prepare_(pn_transport_t *transport)
+{
+ transport->sasl->impl->prepare(transport);
+}
+
+void pni_process_init_(pn_transport_t *transport, const char *mechanism, const pn_bytes_t *recv)
+{
+ transport->sasl->impl->process_init(transport, mechanism, recv);
+}
+
+void pni_process_response_(pn_transport_t *transport, const pn_bytes_t *recv)
+{
+ transport->sasl->impl->process_response(transport, recv);
+}
+
+bool pni_init_client_(pn_transport_t *transport)
+{
+ return transport->sasl->impl->init_client(transport);
+}
+bool pni_process_mechanisms_(pn_transport_t *transport, const char *mechs)
+{
+ return transport->sasl->impl->process_mechanisms(transport, mechs);
+}
+
+void pni_process_challenge_(pn_transport_t *transport, const pn_bytes_t *recv)
+{
+ transport->sasl->impl->process_challenge(transport, recv);
+}
+
+void pni_process_outcome_(pn_transport_t *transport)
+{
+ transport->sasl->impl->process_outcome(transport);
+}
+
void pni_sasl_set_desired_state(pn_transport_t *transport, enum pni_sasl_state desired_state)
{
pni_sasl_t *sasl = transport->sasl;
@@ -157,9 +212,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 +238,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 +248,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 +336,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 +422,9 @@ static ssize_t pn_output_write_sasl(pn_transport_t* transport, unsigned int laye
pni_sasl_start_server_if_needed(transport);
+ // XXX: this needs a better name - I don#'t really understand its purpose
+ pni_sasl_prepare_(transport);
+
pni_post_sasl_frame(transport);
if (transport->available != 0 || !pni_sasl_is_final_output_state(sasl)) {
@@ -479,6 +538,7 @@ pn_sasl_t *pn_sasl(pn_transport_t *transport)
const char *sasl_config_path = getenv("PN_SASL_CONFIG_PATH");
sasl->impl_context = NULL;
+ sasl->impl = NULL; // XXX: This will make us crash!
sasl->client = !transport->server;
sasl->selected_mechanism = NULL;
sasl->included_mechanisms = NULL;
@@ -490,7 +550,6 @@ pn_sasl_t *pn_sasl(pn_transport_t *transport)
sasl->external_auth = NULL;
sasl->external_ssf = 0;
sasl->outcome = PN_SASL_NONE;
- sasl->impl_context = NULL;
sasl->decoded_buffer = pn_buffer(0);
sasl->encoded_buffer = pn_buffer(0);
sasl->bytes_out.size = 0;
@@ -520,8 +579,9 @@ void pn_sasl_free(pn_transport_t *transport)
// CYRUS_SASL
if (sasl->impl_context) {
- pni_sasl_impl_free(transport);
+ pni_sasl_impl_free_(transport);
}
+ free(sasl->impl);
pn_buffer_free(sasl->decoded_buffer);
pn_buffer_free(sasl->encoded_buffer);
free(sasl);
@@ -620,7 +680,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 +721,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 +739,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 +751,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 +769,8 @@ 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);
+ pni_process_outcome_(transport);
+
return 0;
}
-
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org