]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
imap-login: Rewrite ID parameter handling to be less fragile
authorTimo Sirainen <timo.sirainen@dovecot.fi>
Wed, 14 Jun 2017 07:46:53 +0000 (10:46 +0300)
committerVille Savolainen <ville.savolainen@dovecot.fi>
Mon, 28 May 2018 07:33:23 +0000 (10:33 +0300)
There's no longer two places that need to be kept in sync.

src/imap-login/imap-login-cmd-id.c

index 7bc994751da9fbbd66b854d8539f48b29c0fbba7..ba848ecc1721d8381c74299bb8145d3338ae32b7 100644 (file)
 #include "imap-login-settings.h"
 #include "imap-login-client.h"
 
-static const char *const imap_login_reserved_id_keys[] = {
-       "x-originating-ip",
-       "x-originating-port",
-       "x-connected-ip",
-       "x-connected-port",
-       "x-proxy-ttl",
-       "x-session-id",
-       "x-session-ext-id",
-       NULL
+struct imap_id_param_handler {
+       const char *key;
+       bool key_is_prefix;
+
+       void (*callback)(struct imap_client *client,
+                        const char *key, const char *value);
 };
 
+static void
+cmd_id_x_originating_ip(struct imap_client *client,
+                       const char *key ATTR_UNUSED, const char *value)
+{
+       (void)net_addr2ip(value, &client->common.ip);
+}
+
+static void
+cmd_id_x_originating_port(struct imap_client *client,
+                         const char *key ATTR_UNUSED, const char *value)
+{
+       (void)net_str2port(value, &client->common.remote_port);
+}
+
+static void
+cmd_id_x_connected_ip(struct imap_client *client,
+                     const char *key ATTR_UNUSED, const char *value)
+{
+       (void)net_addr2ip(value, &client->common.local_ip);
+}
+
+static void
+cmd_id_x_connected_port(struct imap_client *client,
+                       const char *key ATTR_UNUSED, const char *value)
+{
+       (void)net_str2port(value, &client->common.local_port);
+}
+
+static void
+cmd_id_x_proxy_ttl(struct imap_client *client,
+                  const char *key ATTR_UNUSED, const char *value)
+{
+       if (str_to_uint(value, &client->common.proxy_ttl) < 0) {
+               /* nothing */
+       }
+}
+
+static void
+cmd_id_x_session_id(struct imap_client *client,
+                   const char *key ATTR_UNUSED, const char *value)
+{
+       if (strlen(value) <= LOGIN_MAX_SESSION_ID_LEN) {
+               client->common.session_id =
+                       p_strdup(client->common.pool, value);
+       }
+}
+
+static void
+cmd_id_x_forward_(struct imap_client *client,
+                 const char *key, const char *value)
+{
+       i_assert(strncasecmp(key, "x-forward-", 10) == 0);
+       client_add_forward_field(&client->common, key+10, value);
+}
+
+static const struct imap_id_param_handler imap_login_id_params[] = {
+       { "x-originating-ip", FALSE, cmd_id_x_originating_ip },
+       { "x-originating-port", FALSE, cmd_id_x_originating_port },
+       { "x-connected-ip", FALSE, cmd_id_x_connected_ip },
+       { "x-connected-port", FALSE, cmd_id_x_connected_port },
+       { "x-proxy-ttl", FALSE, cmd_id_x_proxy_ttl },
+       { "x-session-id", FALSE, cmd_id_x_session_id },
+       { "x-session-ext-id", FALSE, cmd_id_x_session_id },
+       { "x-forward-", TRUE, cmd_id_x_forward_ },
+
+       { NULL, FALSE, NULL }
+};
+
+static const struct imap_id_param_handler *
+imap_id_param_handler_find(const char *key)
+{
+       for (unsigned int i = 0; imap_login_id_params[i].key != NULL; i++) {
+               unsigned int prefix_len = strlen(imap_login_id_params[i].key);
+
+               if (strncasecmp(imap_login_id_params[i].key, key, prefix_len) == 0 &&
+                   (key[prefix_len] == '\0' ||
+                    imap_login_id_params[i].key_is_prefix))
+                       return &imap_login_id_params[i];
+       }
+       return NULL;
+}
+
 static bool
 client_update_info(struct imap_client *client,
                   const char *key, const char *value)
 {
-       i_assert(value != NULL);
-
-       /* SYNC WITH imap_login_reserved_id_keys */
-
-       if (strcasecmp(key, "x-originating-ip") == 0) {
-               (void)net_addr2ip(value, &client->common.ip);
-       } else if (strcasecmp(key, "x-originating-port") == 0) {
-               (void)net_str2port(value, &client->common.remote_port);
-       } else if (strcasecmp(key, "x-connected-ip") == 0) {
-               (void)net_addr2ip(value, &client->common.local_ip);
-       } else if (strcasecmp(key, "x-connected-port") == 0) {
-               (void)net_str2port(value, &client->common.local_port);
-       }       else if (strcasecmp(key, "x-proxy-ttl") == 0) {
-               if (str_to_uint(value, &client->common.proxy_ttl) < 0) {
-                       /* nothing */
-               }
-       } else if (strcasecmp(key, "x-session-id") == 0 ||
-                strcasecmp(key, "x-session-ext-id") == 0) {
-               if (strlen(value) <= LOGIN_MAX_SESSION_ID_LEN) {
-                       client->common.session_id =
-                               p_strdup(client->common.pool, value);
-               }
-       } else if (strncasecmp(key, "x-forward-", 10) == 0) {
-               /* handle extra field */
-               client_add_forward_field(&client->common, key+10, value);
-       } else {
+       const struct imap_id_param_handler *handler;
+
+       handler = imap_id_param_handler_find(key);
+       if (handler == NULL)
                return FALSE;
-       }
+       handler->callback(client, key, value);
        return TRUE;
 }
 
 static bool client_id_reserved_word(const char *key)
 {
-       i_assert(key != NULL);
-       return (strncasecmp(key, "x-forward-", 10) == 0 ||
-               str_array_icase_find(imap_login_reserved_id_keys, key));
+       return imap_id_param_handler_find(key) != NULL;
 }
 
 static void cmd_id_handle_keyvalue(struct imap_client *client,