From: Timo Sirainen Date: Wed, 14 Jun 2017 07:46:53 +0000 (+0300) Subject: imap-login: Rewrite ID parameter handling to be less fragile X-Git-Tag: 2.3.2.rc1~72 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=82875d3a0c373638b35bbfa93799d84b62a3dc85;p=thirdparty%2Fdovecot%2Fcore.git imap-login: Rewrite ID parameter handling to be less fragile There's no longer two places that need to be kept in sync. --- diff --git a/src/imap-login/imap-login-cmd-id.c b/src/imap-login/imap-login-cmd-id.c index 7bc994751d..ba848ecc17 100644 --- a/src/imap-login/imap-login-cmd-id.c +++ b/src/imap-login/imap-login-cmd-id.c @@ -7,57 +7,112 @@ #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,