blob: 57650eef5045a723cbae18e68aae6ee6502e5a8c [file] [log] [blame]
/*
* librdkafka - The Apache Kafka C/C++ library
*
* Copyright (c) 2017 Magnus Edenhill
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/**
* Builtin SASL PLAIN support when Cyrus SASL is not available
*/
#include "rdkafka_int.h"
#include "rdkafka_transport.h"
#include "rdkafka_transport_int.h"
#include "rdkafka_sasl.h"
#include "rdkafka_sasl_int.h"
/**
* @brief Handle received frame from broker.
*/
static int rd_kafka_sasl_plain_recv (struct rd_kafka_transport_s *rktrans,
const void *buf, size_t size,
char *errstr, size_t errstr_size) {
if (size)
rd_rkb_dbg(rktrans->rktrans_rkb, SECURITY, "SASLPLAIN",
"Received non-empty SASL PLAIN (builtin) "
"response from broker (%"PRIusz" bytes)", size);
rd_kafka_sasl_auth_done(rktrans);
return 0;
}
/**
* @brief Initialize and start SASL PLAIN (builtin) authentication.
*
* Returns 0 on successful init and -1 on error.
*
* @locality broker thread
*/
int rd_kafka_sasl_plain_client_new (rd_kafka_transport_t *rktrans,
const char *hostname,
char *errstr, size_t errstr_size) {
rd_kafka_broker_t *rkb = rktrans->rktrans_rkb;
rd_kafka_t *rk = rkb->rkb_rk;
/* [authzid] UTF8NUL authcid UTF8NUL passwd */
char buf[255+1+255+1+255+1];
int of = 0;
/* authzid: none (empty) */
/* UTF8NUL */
buf[of++] = 0;
/* authcid */
if (rk->rk_conf.sasl.username) {
int r = (int)strlen(rk->rk_conf.sasl.username);
r = RD_MIN(255, r);
memcpy(&buf[of], rk->rk_conf.sasl.username, r);
of += r;
}
/* UTF8NUL */
buf[of++] = 0;
/* passwd */
if (rk->rk_conf.sasl.password) {
int r = (int)strlen(rk->rk_conf.sasl.password);
r = RD_MIN(255, r);
memcpy(&buf[of], rk->rk_conf.sasl.password, r);
of += r;
}
rd_rkb_dbg(rkb, SECURITY, "SASLPLAIN",
"Sending SASL PLAIN (builtin) authentication token");
if (rd_kafka_sasl_send(rktrans, buf, of,
errstr, errstr_size))
return -1;
/* PLAIN is appearantly done here, but we still need to make sure
* the PLAIN frame is sent and we get a response back (empty) */
rktrans->rktrans_sasl.complete = 1;
return 0;
}
/**
* @brief Validate PLAIN config
*/
static int rd_kafka_sasl_plain_conf_validate (rd_kafka_t *rk,
char *errstr,
size_t errstr_size) {
if (!rk->rk_conf.sasl.username || !rk->rk_conf.sasl.password) {
rd_snprintf(errstr, errstr_size,
"sasl.username and sasl.password must be set");
return -1;
}
return 0;
}
const struct rd_kafka_sasl_provider rd_kafka_sasl_plain_provider = {
.name = "PLAIN (builtin)",
.client_new = rd_kafka_sasl_plain_client_new,
.recv = rd_kafka_sasl_plain_recv,
.conf_validate = rd_kafka_sasl_plain_conf_validate
};