diff options
author | Alan Antonuk <alan.antonuk@gmail.com> | 2014-03-30 22:28:06 -0700 |
---|---|---|
committer | Alan Antonuk <alan.antonuk@gmail.com> | 2015-03-18 21:19:14 -0700 |
commit | 58045d4d09b98d2f3b003c9bea5472f7a3904674 (patch) | |
tree | f38506244c402d3564cb0d28ddcf0b0e5b4218ef | |
parent | d7029dbc2c3088cf5bf3c5044ef2fee7a1b12dcc (diff) | |
download | rabbitmq-c-external_sasl.tar.gz |
Add EXTERNAL SASL mechanism.external_sasl
-rw-r--r-- | librabbitmq/amqp.h | 8 | ||||
-rw-r--r-- | librabbitmq/amqp_socket.c | 67 |
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; + } } { |