changeset 20842:8c389aa81c15

doveadm proxy kick: Added -f <passdb field> parameter. This works for all the user_* passdb fields.
author Timo Sirainen <timo.sirainen@dovecot.fi>
date Thu, 06 Oct 2016 14:53:11 +0300
parents c3cc30b7eda6
children 99c3726c1551
files src/doveadm/doveadm-proxy.c src/login-common/login-proxy.c
diffstat 2 files changed, 81 insertions(+), 7 deletions(-) [+]
line wrap: on
line diff
--- a/src/doveadm/doveadm-proxy.c	Thu Oct 06 14:38:04 2016 +0300
+++ b/src/doveadm/doveadm-proxy.c	Thu Oct 06 14:53:11 2016 +0300
@@ -2,6 +2,8 @@
 
 #include "lib.h"
 #include "ioloop.h"
+#include "str.h"
+#include "strescape.h"
 #include "ipc-client.h"
 #include "doveadm.h"
 #include "doveadm-print.h"
@@ -11,6 +13,7 @@
 
 struct proxy_context {
 	struct ipc_client *ipc;
+	const char *username_field;
 };
 
 extern struct doveadm_cmd_ver2 doveadm_cmd_proxy[];
@@ -33,6 +36,9 @@
 		case 'a':
 			socket_path = optarg;
 			break;
+		case 'f':
+			ctx->username_field = optarg;
+			break;
 		default:
 			proxy_cmd_help(cmd);
 		}
@@ -138,8 +144,9 @@
 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);
@@ -149,8 +156,18 @@
 	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);
 }
@@ -166,10 +183,11 @@
 },
 {
 	.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
 }
--- a/src/login-common/login-proxy.c	Thu Oct 06 14:38:04 2016 +0300
+++ b/src/login-common/login-proxy.c	Thu Oct 06 14:53:11 2016 +0300
@@ -839,8 +839,32 @@
 	}
 }
 
+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;
@@ -853,7 +877,7 @@
 	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++;
 		}
@@ -861,7 +885,7 @@
 	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++;
 		}
@@ -869,6 +893,36 @@
 	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,
@@ -973,6 +1027,8 @@
 	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)