]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
anvil: Add kick-type parameter for CONNECT
authorTimo Sirainen <timo.sirainen@open-xchange.com>
Mon, 17 Jan 2022 22:25:09 +0000 (23:25 +0100)
committerTimo Sirainen <timo.sirainen@open-xchange.com>
Tue, 8 Feb 2022 09:48:24 +0000 (10:48 +0100)
This indicates how the process supports kicking users.

src/anvil/anvil-connection.c
src/anvil/connect-limit.c
src/anvil/connect-limit.h

index 0ad686f96680bf23869380abd3f80b190ac60689..ae01034f819bf0ad5c8fb9827976f1a7e12446b5 100644 (file)
@@ -63,6 +63,24 @@ connect_limit_key_parse(const char *const **_args,
        return TRUE;
 }
 
+static int str_to_kick_type(const char *str, enum kick_type *kick_type_r)
+{
+       switch (str[0]) {
+       case 'N':
+               *kick_type_r = KICK_TYPE_NONE;
+               break;
+       case 'S':
+               *kick_type_r = KICK_TYPE_SIGNAL;
+               break;
+       case 'A':
+               *kick_type_r = KICK_TYPE_ADMIN_SOCKET;
+               break;
+       default:
+               return -1;
+       }
+       return str[1] == '\0' ? 0 : -1;
+}
+
 static int
 anvil_connection_request(struct anvil_connection *conn,
                         const char *const *args, const char **error_r)
@@ -94,7 +112,17 @@ anvil_connection_request(struct anvil_connection *conn,
                        *error_r = "CONNECT: Invalid ident string";
                        return -1;
                }
-               connect_limit_connect(connect_limit, pid, &key, conn_guid);
+               /* extra parameters: */
+               enum kick_type kick_type = KICK_TYPE_NONE;
+               if (args[0] != NULL) {
+                       if (str_to_kick_type(args[0], &kick_type) < 0) {
+                               *error_r = "CONNECT: Invalid kick_type";
+                               return -1;
+                       }
+                       args++;
+               }
+               connect_limit_connect(connect_limit, pid, &key,
+                                     conn_guid, kick_type);
        } else if (strcmp(cmd, "DISCONNECT") == 0) {
                if (args[0] == NULL || args[1] == NULL) {
                        *error_r = "DISCONNECT: Not enough parameters";
index c15ab3244fcb1403d5ded49300cfa31124e18dc5..8464782f337a0822ac3ff2a27bd9ea613e8fcb28 100644 (file)
@@ -12,6 +12,7 @@
 
 struct process {
        pid_t pid;
+       enum kick_type kick_type;
        struct session *sessions;
 };
 
@@ -123,7 +124,7 @@ static struct process *process_lookup(struct connect_limit *limit, pid_t pid)
 
 static void
 session_link_process(struct connect_limit *limit, struct session *session,
-                    pid_t pid)
+                    pid_t pid, enum kick_type kick_type)
 {
        struct process *process;
 
@@ -138,6 +139,9 @@ session_link_process(struct connect_limit *limit, struct session *session,
        session->process = process;
        DLLIST_PREPEND_FULL(&process->sessions, session,
                            process_prev, process_next);
+       /* The kick_type shouldn't change for the process, but keep updating
+          it anyway. */
+       process->kick_type = kick_type;
 }
 
 static void
@@ -157,7 +161,8 @@ session_unlink_process(struct connect_limit *limit, struct session *session)
 
 void connect_limit_connect(struct connect_limit *limit, pid_t pid,
                           const struct connect_limit_key *key,
-                          const guid_128_t conn_guid)
+                          const guid_128_t conn_guid,
+                          enum kick_type kick_type)
 {
        struct session *session, *first_user_session;
        struct userip *userip;
@@ -206,7 +211,7 @@ void connect_limit_connect(struct connect_limit *limit, pid_t pid,
        session->userip = userip;
        guid_128_copy(session->conn_guid, conn_guid);
 
-       session_link_process(limit, session, pid);
+       session_link_process(limit, session, pid, kick_type);
        const uint8_t *conn_guid_p = session->conn_guid;
        hash_table_insert(limit->session_hash, conn_guid_p, session);
        DLLIST_PREPEND_FULL(&first_user_session, session,
@@ -362,6 +367,7 @@ connect_limit_iter_begin(struct connect_limit *limit, const char *username)
        while (session != NULL) {
                struct connect_limit_iter_result *result =
                        array_append_space(&iter->results);
+               result->kick_type = session->process->kick_type;
                result->pid = session->process->pid;
                result->service = session->userip->service;
                guid_128_copy(result->conn_guid, session->conn_guid);
index 4552e3f8e80f0553c83d72b20eeaa127db483d28..30b5971a38f7d9c77368671909f4d8565a20d53e 100644 (file)
@@ -4,6 +4,16 @@
 #include "net.h"
 #include "guid.h"
 
+enum kick_type {
+       /* This process doesn't support kicking users */
+       KICK_TYPE_NONE,
+       /* User kicking should be done by sending TERM signal */
+       KICK_TYPE_SIGNAL,
+       /* User kicking should be done by sending KICK-USER command to the
+          process's admin socket or the existing anvil connection. */
+       KICK_TYPE_ADMIN_SOCKET,
+};
+
 struct connect_limit_key {
        /* User's primary username */
        const char *username;
@@ -14,6 +24,7 @@ struct connect_limit_key {
 };
 
 struct connect_limit_iter_result {
+       enum kick_type kick_type;
        pid_t pid;
        const char *service;
        guid_128_t conn_guid;
@@ -27,7 +38,8 @@ connect_limit_lookup(struct connect_limit *limit,
                     const struct connect_limit_key *key);
 void connect_limit_connect(struct connect_limit *limit, pid_t pid,
                           const struct connect_limit_key *key,
-                          const guid_128_t conn_guid);
+                          const guid_128_t conn_guid,
+                          enum kick_type kick_type);
 void connect_limit_disconnect(struct connect_limit *limit, pid_t pid,
                              const struct connect_limit_key *key,
                              const guid_128_t conn_guid);