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/07/01 21:42:27 UTC
qpid-proton git commit: PROTON-911: Implemented encryption/decryption
functionality for Cyrus SASL
Repository: qpid-proton
Updated Branches:
refs/heads/master c78392f19 -> 395b23f5f
PROTON-911: Implemented encryption/decryption functionality for Cyrus SASL
Project: http://git-wip-us.apache.org/repos/asf/qpid-proton/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-proton/commit/395b23f5
Tree: http://git-wip-us.apache.org/repos/asf/qpid-proton/tree/395b23f5
Diff: http://git-wip-us.apache.org/repos/asf/qpid-proton/diff/395b23f5
Branch: refs/heads/master
Commit: 395b23f5fee57d55ed7395723f560eefe3747c07
Parents: c78392f
Author: Andrew Stitcher <as...@apache.org>
Authored: Tue Jun 30 13:09:51 2015 -0400
Committer: Andrew Stitcher <as...@apache.org>
Committed: Wed Jul 1 14:29:46 2015 -0400
----------------------------------------------------------------------
proton-c/src/config.h | 8 ++-
proton-c/src/sasl/cyrus_sasl.c | 91 +++++++++++++++++++++++++++------
proton-c/src/sasl/none_sasl.c | 11 ++--
proton-c/src/sasl/sasl-internal.h | 6 ++-
proton-c/src/sasl/sasl.c | 57 +++++++++++++++++----
proton-c/src/transport/transport.c | 2 +-
6 files changed, 141 insertions(+), 34 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/395b23f5/proton-c/src/config.h
----------------------------------------------------------------------
diff --git a/proton-c/src/config.h b/proton-c/src/config.h
index 9bc5b27..5a2e7bc 100644
--- a/proton-c/src/config.h
+++ b/proton-c/src/config.h
@@ -21,6 +21,12 @@
#ifndef _PROTON_SRC_CONFIG_H
#define _PROTON_SRC_CONFIG_H
-#define TRANSPORT_INITIAL_FRAME_SIZE (512) /* bytes */
+#ifndef PN_TRANSPORT_INITIAL_FRAME_SIZE
+# define PN_TRANSPORT_INITIAL_FRAME_SIZE (512) /* bytes */
+#endif
+
+#ifndef PN_SASL_MAX_BUFFSIZE
+# define PN_SASL_MAX_BUFFSIZE (32768) /* bytes */
+#endif
#endif /* _PROTON_SRC_CONFIG_H */
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/395b23f5/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 cdcd0bf..b71a435 100644
--- a/proton-c/src/sasl/cyrus_sasl.c
+++ b/proton-c/src/sasl/cyrus_sasl.c
@@ -19,6 +19,7 @@
*
*/
+#include "config.h"
#include "sasl-internal.h"
#include "engine/engine-internal.h"
@@ -125,7 +126,10 @@ bool pni_init_client(pn_transport_t* transport) {
sasl_security_properties_t secprops = {0};
secprops.security_flags =
SASL_SEC_NOPLAINTEXT |
- ( transport->auth_required ? SASL_SEC_NOANONYMOUS : 0 ) ;
+ ( transport->auth_required ? SASL_SEC_NOANONYMOUS : 0 ) ;
+ secprops.min_ssf = 0;
+ secprops.max_ssf = 2048;
+ secprops.maxbufsize = PN_SASL_MAX_BUFFSIZE;
result = sasl_setprop(cyrus_conn, SASL_SEC_PROPS, &secprops);
if (result!=SASL_OK) break;
@@ -256,6 +260,9 @@ bool pni_init_server(pn_transport_t* transport)
secprops.security_flags =
SASL_SEC_NOPLAINTEXT |
( transport->auth_required ? SASL_SEC_NOANONYMOUS : 0 ) ;
+ secprops.min_ssf = 0;
+ secprops.max_ssf = 2048;
+ secprops.maxbufsize = PN_SASL_MAX_BUFFSIZE;
result = sasl_setprop(cyrus_conn, SASL_SEC_PROPS, &secprops);
if (result!=SASL_OK) break;
@@ -369,31 +376,83 @@ void pni_process_response(pn_transport_t *transport, const pn_bytes_t *recv)
pni_process_server_result(transport, result);
}
-void pni_sasl_impl_free(pn_transport_t *transport)
+bool pni_sasl_impl_can_encrypt(pn_transport_t *transport)
{
- sasl_conn_t *cyrus_conn = (sasl_conn_t*)transport->sasl->impl_context;
- sasl_dispose(&cyrus_conn);
- transport->sasl->impl_context = cyrus_conn;
- if (transport->sasl->client) {
- sasl_client_done();
- } else {
- sasl_server_done();
- }
+ if (!transport->sasl->impl_context) return false;
+
+ sasl_conn_t *cyrus_conn = (sasl_conn_t*)transport->sasl->impl_context;
+ // Get SSF to find out if we need to encrypt or not
+ const void* value;
+ int r = sasl_getprop(cyrus_conn, SASL_SSF, &value);
+ if (r != SASL_OK) {
+ // TODO: Should log an error here too, maybe assert here
+ return false;
+ }
+ int ssf = *(int *) value;
+ if (ssf > 0) {
+ pn_transport_logf(transport, "SASL Encryption enabled: ssf=%d", ssf);
+ return true;
+ }
+ return false;
}
-bool pni_sasl_impl_can_encrypt(pn_transport_t *transport)
+ssize_t pni_sasl_impl_max_encrypt_size(pn_transport_t *transport)
{
- return false;
+ if (!transport->sasl->impl_context) return PN_ERR;
+
+ sasl_conn_t *cyrus_conn = (sasl_conn_t*)transport->sasl->impl_context;
+ const void* value;
+ int r = sasl_getprop(cyrus_conn, SASL_MAXOUTBUF, &value);
+ if (r != SASL_OK) {
+ // TODO: Should log an error here too, maybe assert here
+ return PN_ERR;
+ }
+ int outbuf_size = *(int *) value;
+ return outbuf_size;
+}
+
+ssize_t pni_sasl_impl_encode(pn_transport_t *transport, pn_bytes_t in, pn_bytes_t *out)
+{
+ if ( in.size==0 ) return 0;
+ sasl_conn_t *cyrus_conn = (sasl_conn_t*)transport->sasl->impl_context;
+ const char *output;
+ unsigned int outlen;
+ int r = sasl_encode(cyrus_conn, in.start, in.size, &output, &outlen);
+ if (outlen==0) return 0;
+ if ( r==SASL_OK ) {
+ *out = pn_bytes(outlen, output);
+ return outlen;
+ }
+ pn_transport_logf(transport, "SASL encode error: %s", sasl_errdetail(cyrus_conn));
+ return PN_ERR;
}
-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_bytes_t *out)
{
- return 0;
+ if ( in.size==0 ) return 0;
+ sasl_conn_t *cyrus_conn = (sasl_conn_t*)transport->sasl->impl_context;
+ const char *output;
+ unsigned int outlen;
+ int r = sasl_decode(cyrus_conn, in.start, in.size, &output, &outlen);
+ if (outlen==0) return 0;
+ if ( r==SASL_OK ) {
+ *out = pn_bytes(outlen, output);
+ return outlen;
+ }
+ pn_transport_logf(transport, "SASL decode error: %s", sasl_errdetail(cyrus_conn));
+ return PN_ERR;
}
-ssize_t pni_sasl_impl_decode(pn_transport_t *transport, pn_bytes_t in, pn_buffer_t *out)
+void pni_sasl_impl_free(pn_transport_t *transport)
{
- return 0;
+ sasl_conn_t *cyrus_conn = (sasl_conn_t*)transport->sasl->impl_context;
+ sasl_dispose(&cyrus_conn);
+ transport->sasl->impl_context = cyrus_conn;
+ if (transport->sasl->client) {
+ sasl_client_done();
+ } else {
+ sasl_server_done();
+ }
}
bool pn_sasl_extended(void)
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/395b23f5/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 ccb4818..7cbf8d4 100644
--- a/proton-c/src/sasl/none_sasl.c
+++ b/proton-c/src/sasl/none_sasl.c
@@ -174,15 +174,20 @@ 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;
+ return false;
+}
+
+ssize_t pni_sasl_impl_max_encrypt_size(pn_transport_t *transport)
+{
+ return 0;
}
-ssize_t pni_sasl_impl_encode(pn_transport_t *transport, pn_bytes_t in, pn_buffer_t *out)
+ssize_t pni_sasl_impl_encode(pn_transport_t *transport, pn_bytes_t in, pn_bytes_t *out)
{
return 0;
}
-ssize_t pni_sasl_impl_decode(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_bytes_t *out)
{
return 0;
}
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/395b23f5/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 fb40b9c..b81cf03 100644
--- a/proton-c/src/sasl/sasl-internal.h
+++ b/proton-c/src/sasl/sasl-internal.h
@@ -47,8 +47,9 @@ 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);
+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);
// Shared SASL API used by the actual SASL authenticators
@@ -74,6 +75,7 @@ struct pni_sasl_t {
const char *remote_fqdn;
char *external_auth;
int external_ssf;
+ size_t max_encrypt_size;
pn_sasl_outcome_t outcome;
pn_buffer_t* decoded_buffer;
pn_buffer_t* encoded_buffer;
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/395b23f5/proton-c/src/sasl/sasl.c
----------------------------------------------------------------------
diff --git a/proton-c/src/sasl/sasl.c b/proton-c/src/sasl/sasl.c
index ac177c7..a7e02e8 100644
--- a/proton-c/src/sasl/sasl.c
+++ b/proton-c/src/sasl/sasl.c
@@ -281,10 +281,13 @@ static ssize_t pn_input_read_sasl(pn_transport_t* transport, unsigned int layer,
return n;
}
+ pni_sasl_t *sasl = transport->sasl;
if (pni_sasl_impl_can_encrypt(transport)) {
transport->io_layers[layer] = &sasl_encrypt_layer;
+ sasl->max_encrypt_size = pni_sasl_impl_max_encrypt_size(transport);
+ pn_transport_logf(transport, "SASL max buffer: %d", sasl->max_encrypt_size);
return transport->io_layers[layer]->process_input(transport, layer, bytes, available);
- } else if (transport->sasl->client) {
+ } else if (sasl->client) {
transport->io_layers[layer] = &pni_passthru_layer;
}
return pni_passthru_layer.process_input(transport, layer, bytes, available );
@@ -293,11 +296,28 @@ static ssize_t pn_input_read_sasl(pn_transport_t* transport, unsigned int layer,
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);
+ const size_t max_buffer = transport->sasl->max_encrypt_size;
+ for (size_t processed = 0; processed<available;) {
+ pn_bytes_t decoded = pn_bytes(0, NULL);
+ size_t decode_size = (available-processed)<=max_buffer?(available-processed):max_buffer;
+ ssize_t size = pni_sasl_impl_decode(transport, pn_bytes(decode_size, bytes+processed), &decoded);
+ if (size<0) return size;
+ if (size>0) {
+ size = pn_buffer_append(in, decoded.start, decoded.size);
+ if (size) return size;
+ }
+ processed += decode_size;
+ }
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;
+ size_t processed_size = 0;
+ while (processed_size < decoded.size) {
+ ssize_t size = pni_passthru_layer.process_input(transport, layer, decoded.start+processed_size, decoded.size-processed_size);
+ if (size==0) break;
+ if (size<0) return size;
+ pn_buffer_trim(in, size, 0);
+ processed_size += size;
+ }
+ return available;
}
static ssize_t pn_output_write_sasl_header(pn_transport_t *transport, unsigned int layer, char *bytes, size_t size)
@@ -316,26 +336,30 @@ 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)
{
+ pni_sasl_t *sasl = transport->sasl;
+
// 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_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);
+ return PN_EOS;
}
}
}
if (pni_sasl_impl_can_encrypt(transport)) {
transport->io_layers[layer] = &sasl_encrypt_layer;
+ sasl->max_encrypt_size = pni_sasl_impl_max_encrypt_size(transport);
+ pn_transport_logf(transport, "SASL max buffer: %d", sasl->max_encrypt_size);
return transport->io_layers[layer]->process_output(transport, layer, bytes, available);
- } else if (!transport->sasl->client) {
+ } else if (!sasl->client) {
transport->io_layers[layer] = &pni_passthru_layer;
}
return pni_passthru_layer.process_output(transport, layer, bytes, available );
@@ -343,12 +367,23 @@ static ssize_t pn_output_write_sasl(pn_transport_t* transport, unsigned int laye
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;
+ ssize_t clear_size = pni_passthru_layer.process_output(transport, layer, bytes, available );
+ if (clear_size<0) return clear_size;
+ const ssize_t max_buffer = transport->sasl->max_encrypt_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);
+ for (ssize_t processed = 0; processed<clear_size;) {
+ pn_bytes_t encoded = pn_bytes(0, NULL);
+ ssize_t encode_size = (clear_size-processed)<=max_buffer?(clear_size-processed):max_buffer;
+ size_t size = pni_sasl_impl_encode(transport, pn_bytes(encode_size, bytes+processed), &encoded);
+ if (size<0) return size;
+ if (size>0) {
+ size = pn_buffer_append(out, encoded.start, encoded.size);
+ if (size) return size;
+ }
+ processed += encode_size;
+ }
+ ssize_t size = pn_buffer_get(out, 0, available, bytes);
pn_buffer_trim(out, size, 0);
return size;
}
http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/395b23f5/proton-c/src/transport/transport.c
----------------------------------------------------------------------
diff --git a/proton-c/src/transport/transport.c b/proton-c/src/transport/transport.c
index 2271f27..a4b07c3 100644
--- a/proton-c/src/transport/transport.c
+++ b/proton-c/src/transport/transport.c
@@ -373,7 +373,7 @@ static void pn_transport_initialize(void *object)
transport->scratch = pn_string(NULL);
transport->args = pn_data(16);
transport->output_args = pn_data(16);
- transport->frame = pn_buffer(TRANSPORT_INITIAL_FRAME_SIZE);
+ transport->frame = pn_buffer(PN_TRANSPORT_INITIAL_FRAME_SIZE);
transport->input_frames_ct = 0;
transport->output_frames_ct = 0;
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org
Re: qpid-proton git commit: PROTON-911: Implemented encryption/decryption
functionality for Cyrus SASL
Posted by Gordon Sim <gs...@redhat.com>.
On 07/01/2015 08:42 PM, astitcher@apache.org wrote:
> Repository: qpid-proton
> Updated Branches:
> refs/heads/master c78392f19 -> 395b23f5f
>
>
> PROTON-911: Implemented encryption/decryption functionality for Cyrus SASL
[...]
> Committer: Andrew Stitcher <as...@apache.org>
> Committed: Wed Jul 1 14:29:46 2015 -0400
[...]
> @@ -343,12 +367,23 @@ static ssize_t pn_output_write_sasl(pn_transport_t* transport, unsigned int laye
>
> 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;
> + ssize_t clear_size = pni_passthru_layer.process_output(transport, layer, bytes, available );
> + if (clear_size<0) return clear_size;
>
> + const ssize_t max_buffer = transport->sasl->max_encrypt_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);
> + for (ssize_t processed = 0; processed<clear_size;) {
> + pn_bytes_t encoded = pn_bytes(0, NULL);
> + ssize_t encode_size = (clear_size-processed)<=max_buffer?(clear_size-processed):max_buffer;
> + size_t size = pni_sasl_impl_encode(transport, pn_bytes(encode_size, bytes+processed), &encoded);
> + if (size<0) return size;
This test makes no sense as size_t is unsigned so the value can never be
negative. Clang complains.
> + if (size>0) {
> + size = pn_buffer_append(out, encoded.start, encoded.size);
> + if (size) return size;
> + }
> + processed += encode_size;
> + }
> + ssize_t size = pn_buffer_get(out, 0, available, bytes);
> pn_buffer_trim(out, size, 0);
> return size;
> }
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@qpid.apache.org
For additional commands, e-mail: dev-help@qpid.apache.org