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