From: Timo Sirainen Date: Tue, 25 Mar 2025 10:11:26 +0000 (+0200) Subject: doveadm kick: Add support for kicking multiple usernames X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=37160e9ae12d0e8897c0baae2bdfa872e4101316;p=thirdparty%2Fdovecot%2Fcore.git doveadm kick: Add support for kicking multiple usernames --- diff --git a/src/doveadm/doveadm-kick.c b/src/doveadm/doveadm-kick.c index 380467a013..204e6c0615 100644 --- a/src/doveadm/doveadm-kick.c +++ b/src/doveadm/doveadm-kick.c @@ -154,10 +154,14 @@ static void cmd_kick(struct doveadm_cmd_context *cctx) if (ctx.who.filter.net_bits == 0 && ctx.who.filter.dest_ip.family == 0 && !ctx.who.filter.username_wildcards) { - /* kick a single [alternative] user's all connections */ + /* kick explicit [alternative] usernames' all connections */ + const char *username; p_array_init(&ctx.kicks, ctx.who.pool, 1); - struct kick_session *session = array_append_space(&ctx.kicks); - session->username = ctx.who.filter.username; + array_foreach_elem(&ctx.who.filter.usernames, username) { + struct kick_session *session = + array_append_space(&ctx.kicks); + session->username = username; + } } else { /* Complex kick filter. Iterate all connections and figure out locally which ones to kick. */ @@ -170,7 +174,7 @@ static void cmd_kick(struct doveadm_cmd_context *cctx) #define DOVEADM_CMD_KICK_FIELDS \ .cmd = cmd_kick, \ - .usage = "[-a ] [-f ] [-h ] [|]", \ + .usage = "[-a ] [-f ] [-h ] [|] [ [...]]", \ DOVEADM_CMD_PARAMS_START \ DOVEADM_CMD_PARAM('a',"socket-path",CMD_PARAM_STR,0) \ DOVEADM_CMD_PARAM('f',"passdb-field",CMD_PARAM_STR,0) \ diff --git a/src/doveadm/doveadm-who.c b/src/doveadm/doveadm-who.c index 336112028c..2aae5ed684 100644 --- a/src/doveadm/doveadm-who.c +++ b/src/doveadm/doveadm-who.c @@ -173,13 +173,7 @@ who_parse_masks(struct who_context *ctx, const char *const *masks) ctx->filter.net_ip = net_ip; ctx->filter.net_bits = net_bits; } else { - if (ctx->filter.username != NULL) { - e_error(ctx->event, - "Multiple username masks not supported"); - doveadm_exit_code = EX_USAGE; - return -1; - } - ctx->filter.username = masks[i]; + array_push_back(&ctx->filter.usernames, &masks[i]); if (strpbrk(masks[i], "*?") != NULL) ctx->filter.username_wildcards = TRUE; } @@ -195,11 +189,12 @@ int who_parse_args(struct who_context *ctx, const char *alt_username_field, if (dest_ip != NULL) ctx->filter.dest_ip = *dest_ip; + t_array_init(&ctx->filter.usernames, 4); if (masks != NULL) { if (who_parse_masks(ctx, masks) < 0) return -1; } - if (alt_username_field != NULL && ctx->filter.username == NULL) { + if (alt_username_field != NULL && array_is_empty(&ctx->filter.usernames)) { e_error(ctx->event, "Username must be given with passdb-field parameter"); doveadm_exit_code = EX_USAGE; @@ -318,13 +313,26 @@ int doveadm_who_iter_deinit(struct doveadm_who_iter **_iter, return failed ? -1 : 0; } +static bool who_filter_match_username(const struct who_filter *filter, + const char *username) +{ + if (array_is_empty(&filter->usernames)) + return TRUE; + + const char *filter_username; + array_foreach_elem(&filter->usernames, filter_username) { + if (wildcard_match_icase(username, filter_username)) + return TRUE; + } + return FALSE; +} + static bool who_user_filter_match(const struct who_user *user, const struct who_filter *filter) { - if (filter->username != NULL) { - if (!wildcard_match_icase(user->username, filter->username)) - return FALSE; - } + if (!who_filter_match_username(filter, user->username)) + return FALSE; + if (filter->net_bits > 0) { const struct ip_addr *ip; bool ret = FALSE; @@ -398,10 +406,10 @@ bool who_line_filter_match(const struct who_line *line, { unsigned int i; - if (filter->username == NULL) + if (array_is_empty(&filter->usernames)) ; else if (filter->alt_username_field == NULL) { - if (!wildcard_match_icase(line->username, filter->username)) + if (!who_filter_match_username(filter, line->username)) return FALSE; } else { i_assert(filter->alt_username_idx != UINT_MAX); @@ -412,8 +420,7 @@ bool who_line_filter_match(const struct who_line *line, break; } if (i != filter->alt_username_idx || - !wildcard_match_icase(line->alt_usernames[i], - filter->username)) + !who_filter_match_username(filter, line->alt_usernames[i])) return FALSE; } if (filter->net_bits > 0) { diff --git a/src/doveadm/doveadm-who.h b/src/doveadm/doveadm-who.h index f068b1c14f..16d821d859 100644 --- a/src/doveadm/doveadm-who.h +++ b/src/doveadm/doveadm-who.h @@ -15,7 +15,7 @@ struct who_line { struct who_filter { - const char *username; + ARRAY_TYPE(const_string) usernames; bool username_wildcards; const char *alt_username_field;