#include "lib.h"
#include "ioloop.h"
+#include "str.h"
+#include "strescape.h"
#include "ipc-client.h"
#include "doveadm.h"
#include "doveadm-print.h"
struct proxy_context {
struct ipc_client *ipc;
+ const char *username_field;
};
extern struct doveadm_cmd_ver2 doveadm_cmd_proxy[];
case 'a':
socket_path = optarg;
break;
+ case 'f':
+ ctx->username_field = optarg;
+ break;
default:
proxy_cmd_help(cmd);
}
static void cmd_proxy_kick(int argc, char *argv[])
{
struct proxy_context *ctx;
+ string_t *cmd;
- ctx = cmd_proxy_init(argc, argv, "a:", cmd_proxy_kick);
+ ctx = cmd_proxy_init(argc, argv, "a:f:", cmd_proxy_kick);
if (argv[optind] == NULL) {
proxy_cmd_help(cmd_proxy_kick);
doveadm_print_init(DOVEADM_PRINT_TYPE_FORMATTED);
doveadm_print_formatted_set_format("%{count} connections kicked");
doveadm_print_header_simple("count");
- ipc_client_cmd(ctx->ipc, t_strdup_printf("proxy\t*\tKICK\t%s", argv[optind]),
- cmd_proxy_kick_callback, NULL);
+
+ cmd = t_str_new(128);
+ str_append(cmd, "proxy\t*\t");
+ if (ctx->username_field == NULL)
+ str_append(cmd, "KICK");
+ else {
+ str_append(cmd, "KICK-ALT\t");
+ str_append_tabescaped(cmd, ctx->username_field);
+ }
+ str_append_c(cmd, '\t');
+ str_append_tabescaped(cmd, argv[optind]);
+ ipc_client_cmd(ctx->ipc, str_c(cmd), cmd_proxy_kick_callback, NULL);
io_loop_run(current_ioloop);
ipc_client_deinit(&ctx->ipc);
}
},
{
.name = "proxy kick",
- .usage = "[-a <ipc socket path>] <user>",
+ .usage = "[-a <ipc socket path>] [-f <passdb field>] <user>",
.old_cmd = cmd_proxy_kick,
DOVEADM_CMD_PARAMS_START
DOVEADM_CMD_PARAM('a', "socket-path", CMD_PARAM_STR, 0)
+DOVEADM_CMD_PARAM('f', "passdb-field", CMD_PARAM_STR, 0)
DOVEADM_CMD_PARAM('\0', "user", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL)
DOVEADM_CMD_PARAMS_END
}
}
}
+static bool
+want_kick_virtual_user(struct client *client, const char *const *args,
+ unsigned int key_idx ATTR_UNUSED)
+{
+ return str_array_find(args, client->virtual_user);
+}
+
+static bool
+want_kick_alt_username(struct client *client, const char *const *args,
+ unsigned int key_idx)
+{
+ unsigned int i;
+
+ if (client->alt_usernames == NULL)
+ return FALSE;
+ for (i = 0; i < key_idx; i++) {
+ if (client->alt_usernames[i] == NULL)
+ return FALSE;
+ }
+ return str_array_find(args, client->alt_usernames[i]);
+}
+
static void
-login_proxy_cmd_kick(struct ipc_cmd *cmd, const char *const *args)
+login_proxy_cmd_kick_full(struct ipc_cmd *cmd, const char *const *args,
+ bool (*want_kick)(struct client *, const char *const *,
+ unsigned int), unsigned int key_idx)
{
struct login_proxy *proxy, *next;
unsigned int count = 0;
for (proxy = login_proxies; proxy != NULL; proxy = next) {
next = proxy->next;
- if (strcmp(proxy->client->virtual_user, args[0]) == 0) {
+ if (want_kick(proxy->client, args, key_idx)) {
login_proxy_free_delayed(&proxy, KILLED_BY_ADMIN_REASON);
count++;
}
for (proxy = login_proxies_pending; proxy != NULL; proxy = next) {
next = proxy->next;
- if (strcmp(proxy->client->virtual_user, args[0]) == 0) {
+ if (want_kick(proxy->client, args, key_idx)) {
client_destroy(proxy->client, "Connection kicked");
count++;
}
ipc_cmd_success_reply(&cmd, t_strdup_printf("%u", count));
}
+static void
+login_proxy_cmd_kick(struct ipc_cmd *cmd, const char *const *args)
+{
+ login_proxy_cmd_kick_full(cmd, args, want_kick_virtual_user, 0);
+}
+
+static void
+login_proxy_cmd_kick_alt(struct ipc_cmd *cmd, const char *const *args)
+{
+ char *const *fields;
+ unsigned int i, count;
+
+ if (args[0] == NULL) {
+ ipc_cmd_fail(&cmd, "Missing parameter");
+ return;
+ }
+ fields = array_get(&global_alt_usernames, &count);
+ for (i = 0; i < count; i++) {
+ if (strcmp(fields[i], args[0]) == 0)
+ break;
+ }
+ if (i == count) {
+ /* field doesn't exist, but it's not an error necessarily */
+ ipc_cmd_success_reply(&cmd, "0");
+ return;
+ }
+
+ login_proxy_cmd_kick_full(cmd, args+1, want_kick_alt_username, i);
+}
+
static unsigned int director_username_hash(struct client *client)
{
return mail_user_hash(client->virtual_user,
args++;
if (strcmp(name, "KICK") == 0)
login_proxy_cmd_kick(cmd, args);
+ else if (strcmp(name, "KICK-ALT") == 0)
+ login_proxy_cmd_kick_alt(cmd, args);
else if (strcmp(name, "KICK-DIRECTOR-HASH") == 0)
login_proxy_cmd_kick_director_hash(cmd, args);
else if (strcmp(name, "LIST-FULL") == 0)