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 2015/06/30 19:40:54 UTC

[2/2] qpid-proton git commit: PROTON-911: Create SASL encryption layer, and logic which switches it on - Currently no encryption is implemented - Simplify SASL state a little too

PROTON-911: Create SASL encryption layer, and logic which switches it on
- Currently no encryption is implemented
- Simplify SASL state a little too


Project: http://git-wip-us.apache.org/repos/asf/qpid-proton/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-proton/commit/2c383aaa
Tree: http://git-wip-us.apache.org/repos/asf/qpid-proton/tree/2c383aaa
Diff: http://git-wip-us.apache.org/repos/asf/qpid-proton/diff/2c383aaa

Branch: refs/heads/master
Commit: 2c383aaa83dc1b0dff7c473762cd49d7ce207c74
Parents: 37730cc
Author: Andrew Stitcher <as...@apache.org>
Authored: Fri Jun 19 17:39:02 2015 -0400
Committer: Andrew Stitcher <as...@apache.org>
Committed: Tue Jun 30 13:33:08 2015 -0400

----------------------------------------------------------------------
 proton-c/src/sasl/cyrus_sasl.c    | 15 ++++++
 proton-c/src/sasl/none_sasl.c     | 15 ++++++
 proton-c/src/sasl/sasl-internal.h | 21 +++++---
 proton-c/src/sasl/sasl.c          | 91 +++++++++++++++++++++++-----------
 4 files changed, 108 insertions(+), 34 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/2c383aaa/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 c84d0af..cdcd0bf 100644
--- a/proton-c/src/sasl/cyrus_sasl.c
+++ b/proton-c/src/sasl/cyrus_sasl.c
@@ -381,6 +381,21 @@ void pni_sasl_impl_free(pn_transport_t *transport)
     }
 }
 
+bool pni_sasl_impl_can_encrypt(pn_transport_t *transport)
+{
+  return false;
+}
+
+ssize_t pni_sasl_impl_encode(pn_transport_t *transport, pn_bytes_t in, pn_buffer_t *out)
+{
+  return 0;
+}
+
+ssize_t pni_sasl_impl_decode(pn_transport_t *transport, pn_bytes_t in, pn_buffer_t *out)
+{
+  return 0;
+}
+
 bool pn_sasl_extended(void)
 {
   return true;

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/2c383aaa/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 be27871..ccb4818 100644
--- a/proton-c/src/sasl/none_sasl.c
+++ b/proton-c/src/sasl/none_sasl.c
@@ -172,6 +172,21 @@ void pni_process_response(pn_transport_t *transport, const pn_bytes_t *recv)
 {
 }
 
+bool pni_sasl_impl_can_encrypt(pn_transport_t *transport)
+{
+    return false;
+}
+
+ssize_t pni_sasl_impl_encode(pn_transport_t *transport, pn_bytes_t in, pn_buffer_t *out)
+{
+  return 0;
+}
+
+ssize_t pni_sasl_impl_decode(pn_transport_t *transport, pn_bytes_t in, pn_buffer_t *out)
+{
+  return 0;
+}
+
 bool pn_sasl_extended(void)
 {
   return false;

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/2c383aaa/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 71205f5..fb40b9c 100644
--- a/proton-c/src/sasl/sasl-internal.h
+++ b/proton-c/src/sasl/sasl-internal.h
@@ -22,9 +22,12 @@
 #ifndef PROTON_SASL_INTERNAL_H
 #define PROTON_SASL_INTERNAL_H 1
 
+#include "buffer.h"
 #include "proton/types.h"
 #include "proton/sasl.h"
 
+#include "engine/engine-internal.h"
+
 // SASL APIs used by transport code
 void pn_sasl_free(pn_transport_t *transport);
 void pni_sasl_set_user_password(pn_transport_t *transport, const char *user, const char *password);
@@ -33,15 +36,21 @@ void pni_sasl_set_external_security(pn_transport_t *transport, int ssf, const ch
 
 // Internal SASL authenticator interface
 void pni_sasl_impl_free(pn_transport_t *transport);
-int pni_sasl_impl_list_mechs(pn_transport_t* transport, char** mechlist);
-bool pni_init_server(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);
 void pni_process_response(pn_transport_t *transport, const pn_bytes_t *recv);
 
-bool pni_init_client(pn_transport_t* transport);
+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);
 
+// Internal SASL security layer interface
+bool pni_sasl_impl_can_encrypt(pn_transport_t *transport);
+ssize_t pni_sasl_impl_encode(pn_transport_t *transport, pn_bytes_t in, pn_buffer_t *out);
+ssize_t pni_sasl_impl_decode(pn_transport_t *transport, pn_bytes_t in, pn_buffer_t *out);
+
+
 // Shared SASL API used by the actual SASL authenticators
 enum pni_sasl_state {
   SASL_NONE,
@@ -56,7 +65,6 @@ enum pni_sasl_state {
 
 struct pni_sasl_t {
   void *impl_context;
-  // Client selected mechanism
   char *selected_mechanism;
   char *included_mechanisms;
   const char *username;
@@ -67,14 +75,15 @@ struct pni_sasl_t {
   char *external_auth;
   int external_ssf;
   pn_sasl_outcome_t outcome;
+  pn_buffer_t* decoded_buffer;
+  pn_buffer_t* encoded_buffer;
   pn_bytes_t bytes_out;
   enum pni_sasl_state desired_state;
   enum pni_sasl_state last_state;
   bool client;
-  bool input_bypass;
-  bool output_bypass;
 };
 
+// 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);

http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/2c383aaa/proton-c/src/sasl/sasl.c
----------------------------------------------------------------------
diff --git a/proton-c/src/sasl/sasl.c b/proton-c/src/sasl/sasl.c
index 4ef9e99..ac177c7 100644
--- a/proton-c/src/sasl/sasl.c
+++ b/proton-c/src/sasl/sasl.c
@@ -25,6 +25,7 @@
 #include "engine/engine-internal.h"
 #include "protocol.h"
 #include "proton/ssl.h"
+#include "proton/types.h"
 #include "util.h"
 #include "transport/autodetect.h"
 
@@ -44,8 +45,10 @@ static inline pni_sasl_t *get_sasl_internal(pn_sasl_t *sasl)
 
 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);
+static ssize_t pn_input_read_sasl_encrypt(pn_transport_t *transport, unsigned int layer, const char *bytes, size_t available);
 static ssize_t pn_output_write_sasl_header(pn_transport_t* transport, unsigned int layer, char* bytes, size_t size);
 static ssize_t pn_output_write_sasl(pn_transport_t *transport, unsigned int layer, char *bytes, size_t available);
+static ssize_t pn_output_write_sasl_encrypt(pn_transport_t *transport, unsigned int layer, char *bytes, size_t available);
 
 const pn_io_layer_t sasl_header_layer = {
     pn_input_read_sasl_header,
@@ -75,6 +78,13 @@ const pn_io_layer_t sasl_layer = {
     NULL
 };
 
+const pn_io_layer_t sasl_encrypt_layer = {
+    pn_input_read_sasl_encrypt,
+    pn_output_write_sasl_encrypt,
+    NULL,
+    NULL
+};
+
 #define SASL_HEADER ("AMQP\x03\x01\x00\x00")
 #define SASL_HEADER_LEN 8
 
@@ -262,23 +272,34 @@ static ssize_t pn_input_read_sasl(pn_transport_t* transport, unsigned int layer,
     return PN_EOS;
   }
 
-  if (!transport->sasl->input_bypass) {
-    pni_sasl_start_server_if_needed(transport);
+  pni_sasl_start_server_if_needed(transport);
 
-    bool dummy = false;
-    ssize_t n = pn_dispatcher_input(transport, bytes, available, false, &dummy);
+  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;
-    }
+  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;
+  if (pni_sasl_impl_can_encrypt(transport)) {
+    transport->io_layers[layer] = &sasl_encrypt_layer;
+    return transport->io_layers[layer]->process_input(transport, layer, bytes, available);
+  } else if (transport->sasl->client) {
+    transport->io_layers[layer] = &pni_passthru_layer;
   }
   return pni_passthru_layer.process_input(transport, layer, bytes, available );
 }
 
+static ssize_t pn_input_read_sasl_encrypt(pn_transport_t* transport, unsigned int layer, const char* bytes, size_t available)
+{
+  pn_buffer_t *in = transport->sasl->decoded_buffer;
+  pni_sasl_impl_decode(transport, pn_bytes(available, bytes), in);
+  pn_bytes_t decoded = pn_buffer_bytes(in);
+  ssize_t size = pni_passthru_layer.process_input(transport, layer, decoded.start, decoded.size );
+  pn_buffer_trim(in, size, 0);
+  return size;
+}
+
 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)
@@ -295,30 +316,43 @@ static ssize_t pn_output_write_sasl_header(pn_transport_t *transport, unsigned i
 
 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);
+  // 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_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);
-        }
+    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;
+  if (pni_sasl_impl_can_encrypt(transport)) {
+    transport->io_layers[layer] = &sasl_encrypt_layer;
+    return transport->io_layers[layer]->process_output(transport, layer, bytes, available);
+  } else if (!transport->sasl->client) {
+    transport->io_layers[layer] = &pni_passthru_layer;
   }
   return pni_passthru_layer.process_output(transport, layer, bytes, available );
 }
 
+static ssize_t pn_output_write_sasl_encrypt(pn_transport_t* transport, unsigned int layer, char* bytes, size_t available)
+{
+  ssize_t size = pni_passthru_layer.process_output(transport, layer, bytes, available );
+  if (size<=0) return size;
+
+  pn_buffer_t *out = transport->sasl->encoded_buffer;
+  pni_sasl_impl_encode(transport, pn_bytes(size, bytes), out);
+  size = pn_buffer_get(out, 0, available, bytes);
+  pn_buffer_trim(out, size, 0);
+  return size;
+}
+
 // Look for symbol in the mech include list - not particlarly efficient,
 // but probably not used enough to matter.
 //
@@ -394,12 +428,12 @@ pn_sasl_t *pn_sasl(pn_transport_t *transport)
     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;
     sasl->bytes_out.start = NULL;
     sasl->desired_state = SASL_NONE;
     sasl->last_state = SASL_NONE;
-    sasl->input_bypass = false;
-    sasl->output_bypass = false;
 
     transport->sasl = sasl;
   }
@@ -424,7 +458,8 @@ void pn_sasl_free(pn_transport_t *transport)
       if (sasl->impl_context) {
           pni_sasl_impl_free(transport);
       }
-
+      pn_buffer_free(sasl->decoded_buffer);
+      pn_buffer_free(sasl->encoded_buffer);
       free(sasl);
     }
   }


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org