Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions plugins/in_forward/fw.c
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,16 @@ static int in_fw_init(struct flb_input_instance *ins,
return -1;
}

/* Users-only configuration must be rejected unless a (possibly empty) shared key is enabled. */
if (mk_list_size(&ctx->users) > 0 &&
ctx->shared_key == NULL &&
ctx->empty_shared_key == FLB_FALSE) {
flb_plg_error(ctx->ins, "security.users is set but no shared_key or empty_shared_key");
delete_users(ctx);
fw_config_destroy(ctx);
return -1;
}

flb_input_downstream_set(ctx->downstream, ctx->ins);

flb_net_socket_nonblocking(ctx->downstream->server_fd);
Expand Down
3 changes: 2 additions & 1 deletion plugins/in_forward/fw.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,8 @@ struct flb_in_fw_config {
flb_sds_t unix_perm_str; /* Permission (config map) */

/* secure forward */
flb_sds_t shared_key; /* shared key */
flb_sds_t shared_key; /* shared key */
int owns_shared_key; /* own flag of shared key */
flb_sds_t self_hostname; /* hostname used in certificate */
struct mk_list users; /* username and password pairs */
int empty_shared_key; /* use an empty string as shared key */
Expand Down
36 changes: 32 additions & 4 deletions plugins/in_forward/fw_config.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,35 @@
#include "fw_conn.h"
#include "fw_config.h"

static void fw_destory_shared_key(struct flb_in_fw_config *config)
Comment thread
cosmo0920 marked this conversation as resolved.
Outdated
{
if (config->owns_shared_key && config->shared_key) {
flb_sds_destroy(config->shared_key);
}

config->shared_key = NULL;
config->owns_shared_key = FLB_FALSE;
}

static int fw_create_empty_shared_key(struct flb_in_fw_config *config,
struct flb_input_instance *i_ins)
{
flb_sds_t empty_key = flb_sds_create("");
if (!empty_key) {
flb_plg_error(i_ins, "empty shared_key alloc failed");
return -1;
}
else {
if (config->owns_shared_key && config->shared_key) {
flb_sds_destroy(config->shared_key);
}
config->shared_key = empty_key;
config->owns_shared_key = FLB_TRUE;
}

return 0;
}

struct flb_in_fw_config *fw_config_init(struct flb_input_instance *i_ins)
{
char tmp[16];
Expand Down Expand Up @@ -87,10 +116,9 @@ struct flb_in_fw_config *fw_config_init(struct flb_input_instance *i_ins)

/* Shared Key */
if (config->empty_shared_key) {
if (config->shared_key) {
flb_sds_destroy(config->shared_key);
if (fw_create_empty_shared_key(config, i_ins) == -1) {
return NULL;
}
config->shared_key = flb_sds_create("");
}
Comment thread
cosmo0920 marked this conversation as resolved.

/* Self Hostname */
Expand Down Expand Up @@ -131,7 +159,7 @@ int fw_config_destroy(struct flb_in_fw_config *config)
flb_free(config->tcp_port);
}

flb_sds_destroy(config->shared_key);
fw_destory_shared_key(config);
flb_sds_destroy(config->self_hostname);

flb_free(config);
Expand Down
13 changes: 12 additions & 1 deletion plugins/in_forward/fw_conn.c
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,18 @@ struct fw_conn *fw_conn_add(struct flb_connection *connection, struct flb_in_fw_
}

conn->handshake_status = FW_HANDSHAKE_ESTABLISHED;
if (ctx->shared_key != NULL) {
/*
* Always force the secure-forward handshake when:
* - a shared key is configured, or
* - empty_shared_key is enabled (empty string shared key), or
* - user authentication is configured (users > 0).
*
* This closes the gap where "users-only" previously skipped authentication entirely.
*/
conn->handshake_status = FW_HANDSHAKE_ESTABLISHED; /* default */
if (ctx->shared_key != NULL ||
ctx->empty_shared_key == FLB_TRUE ||
mk_list_size(&ctx->users) > 0) {
conn->handshake_status = FW_HANDSHAKE_HELO;
helo = flb_calloc(1, sizeof(struct flb_in_fw_helo));
if (!helo) {
Expand Down
146 changes: 146 additions & 0 deletions tests/runtime/in_forward.c
Original file line number Diff line number Diff line change
Expand Up @@ -903,6 +903,148 @@ void flb_test_threaded_forward_issue_10946()
flb_destroy(ctx);
}

static flb_ctx_t *fw_make_ctx_with_forward(int *in_ffd_out, int *out_ffd_out)
{
struct flb_lib_out_cb cb = {0};
flb_ctx_t *ctx;
int in_ffd, out_ffd, ret;

ctx = flb_create();
TEST_CHECK(ctx != NULL);
if (!ctx) { return NULL; }

flb_service_set(ctx,
"Flush", "0.200000000",
"Grace", "1",
"Log_Level", "error",
NULL);

/* forward input */
in_ffd = flb_input(ctx, (char *) "forward", NULL);
TEST_CHECK(in_ffd >= 0);
if (in_ffd < 0) { flb_destroy(ctx); return NULL; }

/* lib output: count only (no payload check) */
cb.cb = cb_count_only;
cb.data = NULL;
out_ffd = flb_output(ctx, (char *) "lib", (void *) &cb);
TEST_CHECK(out_ffd >= 0);
if (out_ffd < 0) {
flb_destroy(ctx);
return NULL;
}
ret = flb_output_set(ctx, out_ffd,
"match", "*",
"format", "json",
NULL);
TEST_CHECK(ret == 0);

if (in_ffd_out) *in_ffd_out = in_ffd;
if (out_ffd_out) *out_ffd_out = out_ffd;
return ctx;
}

/* 1) users-only => must fail to start (fail-close) */
void flb_test_fw_auth_users_only_fail_start()
{
flb_ctx_t *ctx;
int in_ffd, out_ffd, ret;

ctx = fw_make_ctx_with_forward(&in_ffd, &out_ffd);
TEST_CHECK(ctx != NULL);
if (!ctx) {
return;
}

ret = flb_input_set(ctx, in_ffd,
"tag", "test",
"security.users", "alice s3cr3t",
NULL);
TEST_CHECK(ret == 0);

ret = flb_start(ctx);
TEST_CHECK(ret != 0);
if (ret == 0) {
TEST_MSG("users-only config unexpectedly started; fail-close not enforced");
flb_stop(ctx);
}
flb_destroy(ctx);
}

/* 2) empty_shared_key + users => start OK */
void flb_test_fw_auth_empty_shared_key_plus_users_start_ok()
{
flb_ctx_t *ctx;
int in_ffd, out_ffd, ret;

ctx = fw_make_ctx_with_forward(&in_ffd, &out_ffd);
TEST_CHECK(ctx != NULL);
if (!ctx) { return; }

ret = flb_input_set(ctx, in_ffd,
"tag", "test",
"empty_shared_key", "true",
"security.users", "alice s3cr3t",
NULL);
TEST_CHECK(ret == 0);

ret = flb_start(ctx);
TEST_CHECK(ret == 0);
if (ret == 0) {
flb_stop(ctx);
}
flb_destroy(ctx);
}

/* 3) shared_key only => start OK (backward compatible) */
void flb_test_fw_auth_shared_key_only_start_ok()
{
flb_ctx_t *ctx;
int in_ffd, out_ffd, ret;

ctx = fw_make_ctx_with_forward(&in_ffd, &out_ffd);
TEST_CHECK(ctx != NULL);
if (!ctx) { return; }

ret = flb_input_set(ctx, in_ffd,
"tag", "test",
"shared_key", "k",
NULL);
TEST_CHECK(ret == 0);

ret = flb_start(ctx);
TEST_CHECK(ret == 0);
if (ret == 0) {
flb_stop(ctx);
}
flb_destroy(ctx);
}

/* 4) shared_key + users => start OK (both checks) */
void flb_test_fw_auth_shared_key_plus_users_start_ok()
{
flb_ctx_t *ctx;
int in_ffd, out_ffd, ret;

ctx = fw_make_ctx_with_forward(&in_ffd, &out_ffd);
TEST_CHECK(ctx != NULL);
if (!ctx) { return; }

ret = flb_input_set(ctx, in_ffd,
"tag", "test",
"shared_key", "k",
"security.users", "alice s3cr3t",
NULL);
TEST_CHECK(ret == 0);

ret = flb_start(ctx);
TEST_CHECK(ret == 0);
if (ret == 0) {
flb_stop(ctx);
}
flb_destroy(ctx);
}

TEST_LIST = {
{"forward", flb_test_forward},
{"forward_port", flb_test_forward_port},
Expand All @@ -914,5 +1056,9 @@ TEST_LIST = {
{"forward_gzip", flb_test_forward_gzip},
{"forward_zstd", flb_test_forward_zstd},
{"issue_10946", flb_test_threaded_forward_issue_10946},
{"fw_auth_users_only_fail_start", flb_test_fw_auth_users_only_fail_start},
{"fw_auth_empty_shared_key_plus_users_start_ok", flb_test_fw_auth_empty_shared_key_plus_users_start_ok},
{"fw_auth_shared_key_only_start_ok", flb_test_fw_auth_shared_key_only_start_ok},
{"fw_auth_shared_key_plus_users_start_ok", flb_test_fw_auth_shared_key_plus_users_start_ok},
{NULL, NULL}
};
Loading