summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlan Antonuk <alan.antonuk@gmail.com>2014-03-30 22:28:06 -0700
committerAlan Antonuk <alan.antonuk@gmail.com>2015-03-18 21:19:14 -0700
commit58045d4d09b98d2f3b003c9bea5472f7a3904674 (patch)
treef38506244c402d3564cb0d28ddcf0b0e5b4218ef
parentd7029dbc2c3088cf5bf3c5044ef2fee7a1b12dcc (diff)
downloadrabbitmq-c-external_sasl.tar.gz
Add EXTERNAL SASL mechanism.external_sasl
-rw-r--r--librabbitmq/amqp.h8
-rw-r--r--librabbitmq/amqp_socket.c67
2 files changed, 73 insertions, 2 deletions
diff --git a/librabbitmq/amqp.h b/librabbitmq/amqp.h
index 7f6f47d..1473ccd 100644
--- a/librabbitmq/amqp.h
+++ b/librabbitmq/amqp.h
@@ -634,7 +634,8 @@ typedef struct amqp_rpc_reply_t_ {
* \since v0.1
*/
typedef enum amqp_sasl_method_enum_ {
- AMQP_SASL_METHOD_PLAIN = 0 /**< the PLAIN SASL method for authentication to the broker */
+ AMQP_SASL_METHOD_PLAIN = 0, /**< the PLAIN SASL method for authentication to the broker */
+ AMQP_SASL_METHOD_EXTERNAL = 1 /**< the EXTERNAL SASL method for authentication to the broker */
} amqp_sasl_method_enum;
/**
@@ -703,7 +704,10 @@ typedef enum amqp_status_enum_
closed */
AMQP_STATUS_SOCKET_INUSE = -0x0012, /**< Underlying socket is
already open */
- _AMQP_STATUS_NEXT_VALUE = -0x0013, /**< Internal value */
+ AMQP_STATUS_BROKER_UNSUPPORTED_SASL_METHOD = -0x0013, /**< Broker does not
+ support the requested
+ SASL mechanism */
+ _AMQP_STATUS_NEXT_VALUE = -0x0014, /**< Internal value */
AMQP_STATUS_TCP_ERROR = -0x0100, /**< A generic TCP error
occurred */
diff --git a/librabbitmq/amqp_socket.c b/librabbitmq/amqp_socket.c
index 29a7389..b789784 100644
--- a/librabbitmq/amqp_socket.c
+++ b/librabbitmq/amqp_socket.c
@@ -471,6 +471,10 @@ static amqp_bytes_t sasl_method_name(amqp_sasl_method_enum method)
res.bytes = "PLAIN";
res.len = 5;
break;
+ case AMQP_SASL_METHOD_EXTERNAL:
+ res.bytes = "EXTERNAL";
+ res.len = 8;
+ break;
default:
amqp_abort("Invalid SASL method: %d", (int) method);
@@ -479,6 +483,53 @@ static amqp_bytes_t sasl_method_name(amqp_sasl_method_enum method)
return res;
}
+static int bytes_equal(amqp_bytes_t l, amqp_bytes_t r)
+{
+ if (l.len == r.len) {
+ if (l.bytes && r.bytes) {
+ if (0 == memcmp(l.bytes, r.bytes, l.len)) {
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+static int sasl_mechanism_in_list(amqp_bytes_t mechanisms,
+ amqp_sasl_method_enum method)
+{
+ amqp_bytes_t mechanism;
+ amqp_bytes_t supported_mechanism;
+ uint8_t* start;
+ uint8_t* end;
+ uint8_t* current;
+
+ assert(NULL != mechanisms.bytes);
+
+ mechanism = sasl_method_name(method);
+
+ start = (uint8_t*)mechanisms.bytes;
+ current = start;
+ end = start + mechanisms.len;
+
+ for ( ; current != end; start = current + 1) {
+ /* HACK: SASL states that we should be parsing this string as a UTF-8
+ * string, which we're plainly not doing here. At this point its not worth
+ * dragging an entire UTF-8 parser for this one case, and this should work
+ * most of the time */
+ current = memchr(start, ' ', end - start);
+ if (NULL == current) {
+ current = end;
+ }
+ supported_mechanism.bytes = start;
+ supported_mechanism.len = current - start;
+ if (bytes_equal(mechanism, supported_mechanism)) {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
static amqp_bytes_t sasl_response(amqp_pool_t *pool,
amqp_sasl_method_enum method,
va_list args)
@@ -508,6 +559,18 @@ static amqp_bytes_t sasl_response(amqp_pool_t *pool,
memcpy(response_buf + username_len + 2, password, password_len);
break;
}
+ case AMQP_SASL_METHOD_EXTERNAL: {
+ char *identity = va_arg(args, char *);
+ size_t identity_len = strlen(identity);
+
+ amqp_pool_alloc_bytes(pool, identity_len, &response);
+ if (response.bytes == NULL) {
+ return response;
+ }
+
+ memcpy(response.bytes, identity, identity_len);
+ break;
+ }
default:
amqp_abort("Invalid SASL method: %d", (int) method);
}
@@ -1155,6 +1218,10 @@ static amqp_rpc_reply_t amqp_login_inner(amqp_connection_state_t state,
/* TODO: check that our chosen SASL mechanism is in the list of
acceptable mechanisms. Or even let the application choose from
the list! */
+ if (!sasl_mechanism_in_list(s->mechanisms, sasl_method)) {
+ res = AMQP_STATUS_BROKER_UNSUPPORTED_SASL_METHOD;
+ goto error_res;
+ }
}
{