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 2016/07/14 19:42:20 UTC
[2/3] qpid-proton git commit: PROTON-1256: Track and check
auto-detected protocol layers
PROTON-1256: Track and check auto-detected protocol layers
Project: http://git-wip-us.apache.org/repos/asf/qpid-proton/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-proton/commit/391685a9
Tree: http://git-wip-us.apache.org/repos/asf/qpid-proton/tree/391685a9
Diff: http://git-wip-us.apache.org/repos/asf/qpid-proton/diff/391685a9
Branch: refs/heads/master
Commit: 391685a9e922eb56ee2fd220ee3e904b2e28f5f6
Parents: f137151
Author: Andrew Stitcher <as...@apache.org>
Authored: Thu Jul 14 10:57:30 2016 -0400
Committer: Andrew Stitcher <as...@apache.org>
Committed: Thu Jul 14 15:17:43 2016 -0400
----------------------------------------------------------------------
proton-c/src/engine/engine-internal.h | 11 +++++++++
proton-c/src/transport/transport.c | 27 +++++++++++++++++++++
tests/python/proton_tests/sasl.py | 38 +++++++++++++++++++++++++++++-
3 files changed, 75 insertions(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/391685a9/proton-c/src/engine/engine-internal.h
----------------------------------------------------------------------
diff --git a/proton-c/src/engine/engine-internal.h b/proton-c/src/engine/engine-internal.h
index 0b052a7..761a840 100644
--- a/proton-c/src/engine/engine-internal.h
+++ b/proton-c/src/engine/engine-internal.h
@@ -110,6 +110,14 @@ extern const pn_io_layer_t ssl_layer;
extern const pn_io_layer_t sasl_header_layer;
extern const pn_io_layer_t sasl_write_header_layer;
+// Bit flag defines for the protocol layers
+typedef uint8_t pn_io_layer_flags_t;
+#define LAYER_NONE 0
+#define LAYER_AMQP1 1
+#define LAYER_AMQPSASL 2
+#define LAYER_AMQPSSL 4
+#define LAYER_SSL 8
+
typedef struct pni_sasl_t pni_sasl_t;
typedef struct pni_ssl_t pni_ssl_t;
@@ -193,6 +201,9 @@ struct pn_transport_t {
uint16_t remote_channel_max;
uint16_t channel_max;
+ pn_io_layer_flags_t allowed_layers;
+ pn_io_layer_flags_t present_layers;
+
bool freed;
bool open_sent;
bool open_rcvd;
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/391685a9/proton-c/src/transport/transport.c
----------------------------------------------------------------------
diff --git a/proton-c/src/transport/transport.c b/proton-c/src/transport/transport.c
index cc0bc2f..0d77977 100644
--- a/proton-c/src/transport/transport.c
+++ b/proton-c/src/transport/transport.c
@@ -273,6 +273,12 @@ ssize_t pn_io_layer_input_autodetect(pn_transport_t *transport, unsigned int lay
pn_transport_logf(transport, "%s detected", pni_protocol_name(protocol));
switch (protocol) {
case PNI_PROTOCOL_SSL:
+ if (!(transport->allowed_layers & LAYER_SSL)) {
+ error = "SSL protocol header not allowed (maybe detected twice)";
+ break;
+ }
+ transport->present_layers |= LAYER_SSL;
+ transport->allowed_layers &= LAYER_AMQP1 | LAYER_AMQPSASL;
if (!transport->ssl) {
pn_ssl(transport);
}
@@ -280,6 +286,12 @@ ssize_t pn_io_layer_input_autodetect(pn_transport_t *transport, unsigned int lay
transport->io_layers[layer+1] = &pni_autodetect_layer;
return ssl_layer.process_input(transport, layer, bytes, available);
case PNI_PROTOCOL_AMQP_SSL:
+ if (!(transport->allowed_layers & LAYER_AMQPSSL)) {
+ error = "AMQP SSL protocol header not allowed (maybe detected twice)";
+ break;
+ }
+ transport->present_layers |= LAYER_AMQPSSL;
+ transport->allowed_layers &= LAYER_AMQP1 | LAYER_AMQPSASL;
if (!transport->ssl) {
pn_ssl(transport);
}
@@ -287,6 +299,12 @@ ssize_t pn_io_layer_input_autodetect(pn_transport_t *transport, unsigned int lay
transport->io_layers[layer+1] = &pni_autodetect_layer;
return 8;
case PNI_PROTOCOL_AMQP_SASL:
+ if (!(transport->allowed_layers & LAYER_AMQPSASL)) {
+ error = "AMQP SASL protocol header not allowed (maybe detected twice)";
+ break;
+ }
+ transport->present_layers |= LAYER_AMQPSASL;
+ transport->allowed_layers &= LAYER_AMQP1 | LAYER_AMQPSSL;
if (!transport->sasl) {
pn_sasl(transport);
}
@@ -297,6 +315,12 @@ ssize_t pn_io_layer_input_autodetect(pn_transport_t *transport, unsigned int lay
pni_sasl_set_external_security(transport, pn_ssl_get_ssf((pn_ssl_t*)transport), pn_ssl_get_remote_subject((pn_ssl_t*)transport));
return 8;
case PNI_PROTOCOL_AMQP1:
+ if (!(transport->allowed_layers & LAYER_AMQP1)) {
+ error = "AMQP1.0 protocol header not allowed (maybe detected twice)";
+ break;
+ }
+ transport->present_layers |= LAYER_AMQP1;
+ transport->allowed_layers = LAYER_NONE;
if (transport->auth_required && !pn_transport_is_authenticated(transport)) {
pn_do_error(transport, "amqp:connection:policy-error",
"Client skipped authentication - forbidden");
@@ -394,6 +418,9 @@ static void pn_transport_initialize(void *object)
transport->io_layers[layer] = NULL;
}
+ transport->allowed_layers = LAYER_AMQP1 | LAYER_AMQPSASL | LAYER_AMQPSSL | LAYER_SSL;
+ transport->present_layers = LAYER_NONE;
+
// Defer setting up the layers until the first data arrives or is sent
transport->io_layers[0] = &pni_setup_layer;
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/391685a9/tests/python/proton_tests/sasl.py
----------------------------------------------------------------------
diff --git a/tests/python/proton_tests/sasl.py b/tests/python/proton_tests/sasl.py
index 29b578d..0f5f525 100644
--- a/tests/python/proton_tests/sasl.py
+++ b/tests/python/proton_tests/sasl.py
@@ -84,7 +84,7 @@ def consumeAllOuput(t):
stops = 0
while stops<1:
out = t.peek(1024)
- l = len(out)
+ l = len(out) if out else 0
t.pop(l)
if l <= 0:
stops += 1
@@ -103,6 +103,41 @@ class SaslTest(Test):
# We have to generate the client frames manually because proton does not
# generate pipelined SASL and AMQP frames together
+ def testIllegalProtocolLayering(self):
+ # TODO: Skip Proton-J for now
+ if "java" in sys.platform:
+ raise Skipped("Proton-J does not set error condition on protocol layering violation")
+
+ # Server
+ self.s2.allowed_mechs('ANONYMOUS')
+
+ c2 = Connection()
+ self.t2.bind(c2)
+
+ assert self.s2.outcome is None
+
+ # Push client bytes into server
+ self.t2.push(str2bin(
+ # SASL
+ 'AMQP\x03\x01\x00\x00'
+ # @sasl-init(65) [mechanism=:ANONYMOUS, initial-response=b"anonymous@fuschia"]
+ '\x00\x00\x002\x02\x01\x00\x00\x00SA\xd0\x00\x00\x00"\x00\x00\x00\x02\xa3\x09ANONYMOUS\xa0\x11anonymous@fuschia'
+ # SASL (again illegally)
+ 'AMQP\x03\x01\x00\x00'
+ # @sasl-init(65) [mechanism=:ANONYMOUS, initial-response=b"anonymous@fuschia"]
+ '\x00\x00\x002\x02\x01\x00\x00\x00SA\xd0\x00\x00\x00"\x00\x00\x00\x02\xa3\x09ANONYMOUS\xa0\x11anonymous@fuschia'
+ # AMQP
+ 'AMQP\x00\x01\x00\x00'
+ # @open(16) [container-id="", channel-max=1234]
+ '\x00\x00\x00!\x02\x00\x00\x00\x00S\x10\xd0\x00\x00\x00\x11\x00\x00\x00\x0a\xa1\x00@@`\x04\xd2@@@@@@'
+ ))
+
+ consumeAllOuput(self.t2)
+
+ assert self.t2.condition
+ assert self.t2.closed
+ assert not c2.state & Endpoint.REMOTE_ACTIVE
+
def testPipelinedClient(self):
# TODO: When PROTON-1136 is fixed then remove this test
if "java" in sys.platform:
@@ -130,6 +165,7 @@ class SaslTest(Test):
consumeAllOuput(self.t2)
+ assert not self.t2.condition
assert self.s2.outcome == SASL.OK
assert c2.state & Endpoint.REMOTE_ACTIVE
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org