]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
anvil, doveadm: Add alt usernames to CONNECT-DUMP output
authorTimo Sirainen <timo.sirainen@open-xchange.com>
Thu, 16 Dec 2021 02:50:09 +0000 (04:50 +0200)
committerTimo Sirainen <timo.sirainen@open-xchange.com>
Tue, 8 Feb 2022 09:48:24 +0000 (10:48 +0100)
src/anvil/connect-limit.c
src/anvil/test-connect-limit.c
src/doveadm/doveadm-who.c
src/doveadm/doveadm-who.h

index dbbaed794aaf335e5f7919209fb64fbeeb80e472..012dfbd17747e3094b7f38503cd0c00cad05eb29 100644 (file)
@@ -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;
index 10fe244c6b51524526809efe22cd4be33176ccd9..90a3f4468f538767d21f9727b7ef63edd4a30ef6 100644 (file)
@@ -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);
index 609ac9222e7c86c65f61aefefdb05f1e5a802877..d478bcdb3c2ed83dc22c29d5c389a0f1b6107a9e 100644 (file)
@@ -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);
 
-       /* <pid> <username> <service> <ip> <conn-guid> <dest-ip> */
+       /* <pid> <username> <service> <ip> <conn-guid> <dest-ip>
+          [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;
index 9018fa5d1f79e79a0db0caf606d23c4227653a9e..7466222511b68ff46b31dc1b44be3e2815c5af94 100644 (file)
@@ -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;