From: Timo Sirainen Date: Thu, 16 Dec 2021 02:50:09 +0000 (+0200) Subject: anvil, doveadm: Add alt usernames to CONNECT-DUMP output X-Git-Tag: 2.4.0~4510 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=82b47d94bae013d6f31789da9d4d6bc4afbc2c7f;p=thirdparty%2Fdovecot%2Fcore.git anvil, doveadm: Add alt usernames to CONNECT-DUMP output --- diff --git a/src/anvil/connect-limit.c b/src/anvil/connect-limit.c index dbbaed794a..012dfbd177 100644 --- a/src/anvil/connect-limit.c +++ b/src/anvil/connect-limit.c @@ -539,9 +539,21 @@ void connect_limit_dump(struct connect_limit *limit, struct ostream *output) struct hash_iterate_context *iter; struct session *session; const uint8_t *conn_guid; + const struct alt_username_field *alt_field; + unsigned int alt_idx; string_t *str = str_new(default_pool, 256); ssize_t ret = 0; + /* Send list of alt usernames in the header */ + array_foreach(&limit->alt_username_fields, alt_field) { + if (str_len(str) > 0) + str_append_c(str, '\t'); + str_append_tabescaped(str, alt_field->name); + } + str_append_c(str, '\n'); + o_stream_nsend(output, str_data(str), str_len(str)); + + /* Send all sessions */ iter = hash_table_iterate_init(limit->session_hash); while (ret >= 0 && hash_table_iterate(iter, limit->session_hash, @@ -559,6 +571,13 @@ void connect_limit_dump(struct connect_limit *limit, struct ostream *output) str_append_c(str, '\t'); if (session->dest_ip.family != 0) str_append(str, net_ip2addr(&session->dest_ip)); + for (alt_idx = 0; alt_idx < session->alt_usernames_count; alt_idx++) { + str_append_c(str, '\t'); + if (session->alt_usernames[alt_idx].alt_username != NULL) { + str_append_tabescaped(str, + session->alt_usernames[alt_idx].alt_username); + } + } str_append_c(str, '\n'); ret = o_stream_send(output, str_data(str), str_len(str)); } T_END; diff --git a/src/anvil/test-connect-limit.c b/src/anvil/test-connect-limit.c index 10fe244c6b..90a3f4468f 100644 --- a/src/anvil/test-connect-limit.c +++ b/src/anvil/test-connect-limit.c @@ -21,7 +21,8 @@ static guid_128_t session3_guid = { #define SESSION3_HEX "300000000000000000000000000000f3" static void -test_session_dump(struct connect_limit *limit, const char *expected_dump) +test_session_dump(struct connect_limit *limit, const char *expected_altnames, + const char *expected_dump) { string_t *str = str_new(default_pool, 128); struct ostream *output = o_stream_create_buffer(str); @@ -33,13 +34,25 @@ test_session_dump(struct connect_limit *limit, const char *expected_dump) str_free(&str); return; } + + /* check the alt usernames header */ + const char *p = strchr(str_c(str), '\n'); + if (p == NULL) { + test_assert(str_len(str) == 0); + test_assert_strcmp(expected_altnames, ""); + } else { + test_assert_strcmp(expected_altnames, + t_strndup(str_c(str), p - str_c(str))); + str_delete(str, 0, p - str_c(str) + 1); + } + /* The output comes from hash table, so the order isn't stable. Sort the lines so we can test it. */ const char **lines = t_strsplit(str_c(str), "\n"); unsigned int lines_count = str_array_length(lines); i_qsort(lines, lines_count, sizeof(const char *), i_strcmp_p); - string_t *new_str = t_str_new(str_len(str)); + string_t *new_str = str_new(default_pool, str_len(str)); /* the output ends with \n\n and they're sorted first */ i_assert(lines_count >= 2); i_assert(lines[0][0] == '\0'); @@ -49,6 +62,7 @@ test_session_dump(struct connect_limit *limit, const char *expected_dump) str_append_c(new_str, '\n'); } test_assert_strcmp(str_c(new_str), expected_dump); + str_free(&new_str); o_stream_destroy(&output); str_free(&str); @@ -76,8 +90,8 @@ static void test_connect_limit(void) test_assert(net_addr2ip("1.2.3.4", &key.ip) == 0); connect_limit_connect(limit, 501, &key, session1_guid, KICK_TYPE_NONE, &dest_ip, alt_usernames1); -#define TEST_SESSION1_STR "501\tuser1\tservice1\t1.2.3.4\t"SESSION1_HEX"\t\n" - test_session_dump(limit, TEST_SESSION1_STR); +#define TEST_SESSION1_STR "501\tuser1\tservice1\t1.2.3.4\t"SESSION1_HEX"\t\taltvalueA\taltvalueB\n" + test_session_dump(limit, "altkey1\taltkey2", TEST_SESSION1_STR); test_assert(connect_limit_lookup(limit, &key) == 1); /* same userip and pid */ @@ -95,8 +109,9 @@ static void test_connect_limit(void) i_zero(&dest_ip); connect_limit_connect(limit, 501, &key2, session2_guid, KICK_TYPE_NONE, &dest_ip, alt_usernames2); -#define TEST_SESSION2_STR "501\tuser1\tservice1\t1.2.3.4\t"SESSION2_HEX"\t\n" - test_session_dump(limit, TEST_SESSION1_STR TEST_SESSION2_STR); +#define TEST_SESSION2_STR "501\tuser1\tservice1\t1.2.3.4\t"SESSION2_HEX"\t\taltvalueA\taltvalueC\taltvalueA\n" + test_session_dump(limit, "altkey1\taltkey2\taltkey3", + TEST_SESSION1_STR TEST_SESSION2_STR); test_assert(connect_limit_lookup(limit, &key) == 2); /* different user */ @@ -114,8 +129,9 @@ static void test_connect_limit(void) test_assert(net_addr2ip("1.0.0.2", &dest_ip) == 0); connect_limit_connect(limit, 600, &key3, session3_guid, KICK_TYPE_SIGNAL, &dest_ip, alt_usernames3); -#define TEST_SESSION3_STR "600\tuser2\tservice2\t4.3.2.1\t"SESSION3_HEX"\t1.0.0.2\n" - test_session_dump(limit, TEST_SESSION1_STR TEST_SESSION2_STR TEST_SESSION3_STR); +#define TEST_SESSION3_STR "600\tuser2\tservice2\t4.3.2.1\t"SESSION3_HEX"\t1.0.0.2\taltvalueA\taltvalueC\t\taltvalueD\n" + test_session_dump(limit, "altkey1\taltkey2\taltkey3\taltkey4", + TEST_SESSION1_STR TEST_SESSION2_STR TEST_SESSION3_STR); test_assert(connect_limit_lookup(limit, &key) == 2); test_assert(connect_limit_lookup(limit, &key3) == 0); @@ -130,7 +146,8 @@ static void test_connect_limit(void) connect_limit_connect(limit, 600, &key4, session2_guid, KICK_TYPE_SIGNAL, &dest_ip, alt_usernames3); test_expect_no_more_errors(); - test_session_dump(limit, TEST_SESSION1_STR TEST_SESSION2_STR TEST_SESSION3_STR); + test_session_dump(limit, "altkey1\taltkey2\taltkey3\taltkey4", + TEST_SESSION1_STR TEST_SESSION2_STR TEST_SESSION3_STR); /* test user iteration for user1 */ struct connect_limit_iter *iter = @@ -187,13 +204,14 @@ static void test_connect_limit(void) /* disconnect a single session */ connect_limit_disconnect(limit, 600, &key3, session3_guid); - test_session_dump(limit, TEST_SESSION1_STR TEST_SESSION2_STR); + test_session_dump(limit, "altkey1\taltkey2\taltkey3\taltkey4", + TEST_SESSION1_STR TEST_SESSION2_STR); test_assert(connect_limit_lookup(limit, &key) == 2); test_assert(connect_limit_lookup(limit, &key3) == 0); /* disconnect all sessions from a process */ connect_limit_disconnect_pid(limit, 501); - test_session_dump(limit, ""); + test_session_dump(limit, "altkey1\taltkey2\taltkey3\taltkey4", ""); test_assert(connect_limit_lookup(limit, &key3) == 0); connect_limit_deinit(&limit); diff --git a/src/doveadm/doveadm-who.c b/src/doveadm/doveadm-who.c index 609ac9222e..d478bcdb3c 100644 --- a/src/doveadm/doveadm-who.c +++ b/src/doveadm/doveadm-who.c @@ -26,6 +26,10 @@ struct who_user { struct doveadm_who_iter { struct istream *input; pool_t pool, line_pool; + + unsigned int alt_username_fields_count; + const char **alt_username_fields; + bool failed; }; @@ -90,7 +94,8 @@ static int who_parse_line(struct doveadm_who_iter *iter, const char *const *args = t_strsplit_tabescaped(line); i_zero(line_r); - /* */ + /* + [alt usernames] */ if (str_array_length(args) < 6) return -1; @@ -109,6 +114,7 @@ static int who_parse_line(struct doveadm_who_iter *iter, if (net_addr2ip(args[5], &line_r->dest_ip) < 0) return -1; } + line_r->alt_usernames = p_strarray_dup(iter->line_pool, args + 6); return 0; } @@ -202,6 +208,11 @@ struct doveadm_who_iter *doveadm_who_iter_init(const char *anvil_path) if ((line = i_stream_read_next_line(iter->input)) == NULL) { i_error("anvil didn't send header line"); iter->failed = TRUE; + } else { + iter->alt_username_fields = + (const char **)p_strsplit_tabescaped(iter->pool, line); + iter->alt_username_fields_count = + str_array_length(iter->alt_username_fields); } return iter; } @@ -341,9 +352,12 @@ bool who_line_filter_match(const struct who_line *line, return TRUE; } -static void who_print_line(struct who_context *ctx, - const struct who_line *line) +static void +who_print_line(struct who_context *ctx, struct doveadm_who_iter *iter, + const struct who_line *line) { + unsigned int alt_idx; + if (!who_line_filter_match(line, &ctx->filter)) return; @@ -352,6 +366,11 @@ static void who_print_line(struct who_context *ctx, doveadm_print(dec2str(line->pid)); doveadm_print(net_ip2addr(&line->ip)); doveadm_print(net_ip2addr(&line->dest_ip)); + + for (alt_idx = 0; line->alt_usernames[alt_idx] != NULL; alt_idx++) + doveadm_print(line->alt_usernames[alt_idx]); + for (; alt_idx < iter->alt_username_fields_count; alt_idx++) + doveadm_print(""); } static void cmd_who(struct doveadm_cmd_context *cctx) @@ -390,8 +409,10 @@ static void cmd_who(struct doveadm_cmd_context *cctx) doveadm_print_header_simple("pid"); doveadm_print_header_simple("ip"); doveadm_print_header_simple("dest_ip"); + for (unsigned int i = 0; i < iter->alt_username_fields_count; i++) + doveadm_print_header_simple(iter->alt_username_fields[i]); while (doveadm_who_iter_next(iter, &who_line)) - who_print_line(&ctx, &who_line); + who_print_line(&ctx, iter, &who_line); } if (doveadm_who_iter_deinit(&iter) < 0) doveadm_exit_code = EX_TEMPFAIL; diff --git a/src/doveadm/doveadm-who.h b/src/doveadm/doveadm-who.h index 9018fa5d1f..7466222511 100644 --- a/src/doveadm/doveadm-who.h +++ b/src/doveadm/doveadm-who.h @@ -7,6 +7,7 @@ struct who_line { const char *username; const char *service; guid_128_t conn_guid; + const char *const *alt_usernames; struct ip_addr ip; struct ip_addr dest_ip; pid_t pid;