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. */
#define DOVEADM_CMD_KICK_FIELDS \
.cmd = cmd_kick, \
- .usage = "[-a <anvil socket path>] [-f <passdb field>] [-h <dest host>] <user mask>[|]<ip/bits>", \
+ .usage = "[-a <anvil socket path>] [-f <passdb field>] [-h <dest host>] <user mask>[|]<ip/bits> [<user mask> [...]]", \
DOVEADM_CMD_PARAMS_START \
DOVEADM_CMD_PARAM('a',"socket-path",CMD_PARAM_STR,0) \
DOVEADM_CMD_PARAM('f',"passdb-field",CMD_PARAM_STR,0) \
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;
}
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;
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;
{
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);
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) {