89a126810703c666309310d0f3189e9834d70b5bTimo Sirainen/* Copyright (c) 2002-2018 Dovecot authors, see the included COPYING file */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "login-common.h"
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen#include "str.h"
16f816d3f3c32ae3351834253f52ddd0212bcbf3Timo Sirainen#include "imap-parser.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "imap-quote.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "imap-login-settings.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "imap-login-client.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
463e82bdf0e990f4f2252d2b53ea23a5abe5883cTimo Sirainenstruct imap_id_param_handler {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const char *key;
d41573018e85896ec836d897fd554e87126147f5Timo Sirainen bool key_is_prefix;
d41573018e85896ec836d897fd554e87126147f5Timo Sirainen
d41573018e85896ec836d897fd554e87126147f5Timo Sirainen void (*callback)(struct imap_client *client,
d41573018e85896ec836d897fd554e87126147f5Timo Sirainen const char *key, const char *value);
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainen};
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainen
2c677e9d339bc91d5b54376ba2986f71476c06abTimo Sirainenstatic void
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainencmd_id_x_originating_ip(struct imap_client *client,
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainen const char *key ATTR_UNUSED, const char *value)
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainen{
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainen (void)net_addr2ip(value, &client->common.ip);
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainen}
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainen
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainenstatic void
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainencmd_id_x_originating_port(struct imap_client *client,
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen const char *key ATTR_UNUSED, const char *value)
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen{
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen (void)net_str2port(value, &client->common.remote_port);
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen}
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainenstatic void
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainencmd_id_x_connected_ip(struct imap_client *client,
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen const char *key ATTR_UNUSED, const char *value)
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen{
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen (void)net_addr2ip(value, &client->common.local_ip);
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen}
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainenstatic void
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainencmd_id_x_connected_port(struct imap_client *client,
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen const char *key ATTR_UNUSED, const char *value)
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen{
2c677e9d339bc91d5b54376ba2986f71476c06abTimo Sirainen (void)net_str2port(value, &client->common.local_port);
51795bfe9d05d92fe942cb451aec2b9d16d32a11Timo Sirainen}
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainen
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainenstatic void
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainencmd_id_x_proxy_ttl(struct imap_client *client,
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen const char *key ATTR_UNUSED, const char *value)
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen{
e6d7d19c328e7043ad35d5a52c1617bde915a16fTimo Sirainen if (str_to_uint(value, &client->common.proxy_ttl) < 0) {
d7095f3a4466fbb78b2d5eb3d322bc15a5b0ab1fTimo Sirainen /* nothing */
153de7823e64c67678b3fc95719c41a8ec5b864dTimo Sirainen }
153de7823e64c67678b3fc95719c41a8ec5b864dTimo Sirainen}
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen
b0be0bead3d6963149f7f2a9504b8ab5aced9af5Timo Sirainenstatic void
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainencmd_id_x_session_id(struct imap_client *client,
e6d7d19c328e7043ad35d5a52c1617bde915a16fTimo Sirainen const char *key ATTR_UNUSED, const char *value)
8d131435ba4648c8821160ec38d508c97177c715Timo Sirainen{
9315dd69233d554452df0c12bc57002d2042a8f4Timo Sirainen if (strlen(value) <= LOGIN_MAX_SESSION_ID_LEN) {
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen client->common.session_id =
538c58fc95200fcc5e91abdda8b912b574a2f968Timo Sirainen p_strdup(client->common.pool, value);
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen }
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen}
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainenstatic void
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainencmd_id_x_forward_(struct imap_client *client,
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen const char *key, const char *value)
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen{
bf91bed88d4e294b4577ba2a3b14d87cf35ae135Timo Sirainen i_assert(strncasecmp(key, "x-forward-", 10) == 0);
bf91bed88d4e294b4577ba2a3b14d87cf35ae135Timo Sirainen client_add_forward_field(&client->common, key+10, value);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen}
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainenstatic const struct imap_id_param_handler imap_login_id_params[] = {
bf91bed88d4e294b4577ba2a3b14d87cf35ae135Timo Sirainen { "x-originating-ip", FALSE, cmd_id_x_originating_ip },
bf91bed88d4e294b4577ba2a3b14d87cf35ae135Timo Sirainen { "x-originating-port", FALSE, cmd_id_x_originating_port },
bf91bed88d4e294b4577ba2a3b14d87cf35ae135Timo Sirainen { "x-connected-ip", FALSE, cmd_id_x_connected_ip },
bf91bed88d4e294b4577ba2a3b14d87cf35ae135Timo Sirainen { "x-connected-port", FALSE, cmd_id_x_connected_port },
bf91bed88d4e294b4577ba2a3b14d87cf35ae135Timo Sirainen { "x-proxy-ttl", FALSE, cmd_id_x_proxy_ttl },
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen { "x-session-id", FALSE, cmd_id_x_session_id },
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen { "x-session-ext-id", FALSE, cmd_id_x_session_id },
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen { "x-forward-", TRUE, cmd_id_x_forward_ },
bf91bed88d4e294b4577ba2a3b14d87cf35ae135Timo Sirainen
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen { NULL, FALSE, NULL }
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen};
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainenstatic const struct imap_id_param_handler *
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainenimap_id_param_handler_find(const char *key)
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen{
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen for (unsigned int i = 0; imap_login_id_params[i].key != NULL; i++) {
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen unsigned int prefix_len = strlen(imap_login_id_params[i].key);
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (strncasecmp(imap_login_id_params[i].key, key, prefix_len) == 0 &&
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen (key[prefix_len] == '\0' ||
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen imap_login_id_params[i].key_is_prefix))
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen return &imap_login_id_params[i];
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen }
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen return NULL;
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen}
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic bool
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainenclient_try_update_info(struct imap_client *client,
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen const char *key, const char *value)
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen{
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen const struct imap_id_param_handler *handler;
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen handler = imap_id_param_handler_find(key);
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen if (handler == NULL)
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen return FALSE;
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* do not try to process NIL values as client-info,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen but store them for non-reserved keys */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (client->common.trusted && !client->id_logged && value != NULL)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen handler->callback(client, key, value);
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen return TRUE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainenstatic void cmd_id_handle_keyvalue(struct imap_client *client,
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen const char *key, const char *value)
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen{
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen bool client_id_str;
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen /* length of key + length of value (NIL for NULL) and two set of
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen quotes and space */
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen size_t kvlen = strlen(key) + 2 + 1 +
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen (value == NULL ? 3 : strlen(value)) + 2;
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen client_id_str = !client_try_update_info(client, key, value);
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen if (client->set->imap_id_retain && client_id_str &&
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen (client->common.client_id == NULL ||
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen str_len(client->common.client_id) + kvlen < LOGIN_MAX_CLIENT_ID_LEN)) {
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen if (client->common.client_id == NULL) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen client->common.client_id = str_new(client->common.preproxy_pool, 64);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen } else {
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen str_append_c(client->common.client_id, ' ');
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen }
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen imap_append_quoted(client->common.client_id, key);
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen str_append_c(client->common.client_id, ' ');
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen if (value == NULL)
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen str_append(client->common.client_id, "NIL");
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen else
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen imap_append_quoted(client->common.client_id, value);
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen }
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen if (client->cmd_id->log_reply != NULL &&
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen (client->cmd_id->log_keys == NULL ||
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen str_array_icase_find((void *)client->cmd_id->log_keys, key)))
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen imap_id_log_reply_append(client->cmd_id->log_reply, key, value);
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen}
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainenstatic int cmd_id_handle_args(struct imap_client *client,
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen const struct imap_arg *arg)
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen{
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen struct imap_client_cmd_id *id = client->cmd_id;
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen const char *key, *value;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen switch (id->state) {
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen case IMAP_CLIENT_ID_STATE_LIST:
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen if (arg->type == IMAP_ARG_NIL)
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen return 1;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen if (arg->type != IMAP_ARG_LIST)
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen return -1;
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen if (client->set->imap_id_log[0] == '\0') {
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen /* no ID logging */
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen } else if (client->id_logged) {
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen /* already logged the ID reply */
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen } else {
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen id->log_reply = str_new(default_pool, 64);
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen if (strcmp(client->set->imap_id_log, "*") == 0) {
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen /* log all keys */
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen } else {
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen /* log only specified keys */
fa5957ffc9b676bfd649fa9953e63e72ee4ebeb4Timo Sirainen id->log_keys = p_strsplit_spaces(default_pool,
fa5957ffc9b676bfd649fa9953e63e72ee4ebeb4Timo Sirainen client->set->imap_id_log, " ");
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen }
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen }
3342badd8c69adff34db589fb0a221ace5996212Timo Sirainen id->state = IMAP_CLIENT_ID_STATE_KEY;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen break;
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen case IMAP_CLIENT_ID_STATE_KEY:
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen if (!imap_arg_get_string(arg, &key))
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen return -1;
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen if (i_strocpy(id->key, key, sizeof(id->key)) < 0)
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen return -1;
3342badd8c69adff34db589fb0a221ace5996212Timo Sirainen id->state = IMAP_CLIENT_ID_STATE_VALUE;
3342badd8c69adff34db589fb0a221ace5996212Timo Sirainen break;
3342badd8c69adff34db589fb0a221ace5996212Timo Sirainen case IMAP_CLIENT_ID_STATE_VALUE:
3342badd8c69adff34db589fb0a221ace5996212Timo Sirainen if (!imap_arg_get_nstring(arg, &value))
3342badd8c69adff34db589fb0a221ace5996212Timo Sirainen return -1;
3342badd8c69adff34db589fb0a221ace5996212Timo Sirainen cmd_id_handle_keyvalue(client, id->key, value);
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen id->state = IMAP_CLIENT_ID_STATE_KEY;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen break;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen return 0;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen}
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic void cmd_id_finish(struct imap_client *client)
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* finished handling the parameters */
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen if (!client->id_logged) {
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen client->id_logged = TRUE;
9315dd69233d554452df0c12bc57002d2042a8f4Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen if (client->cmd_id->log_reply != NULL) {
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen client_log(&client->common, t_strdup_printf(
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen "ID sent: %s", str_c(client->cmd_id->log_reply)));
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen }
7889c9f65e23c83fc31cecf304cab4ab070d6aa1Timo Sirainen }
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen client_send_raw(&client->common,
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen t_strdup_printf("* ID %s\r\n",
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen imap_id_reply_generate(client->set->imap_id_send)));
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen client_send_reply(&client->common, IMAP_CMD_REPLY_OK, "ID completed.");
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen}
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainenstatic void cmd_id_free(struct imap_client *client)
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen{
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen struct imap_client_cmd_id *id = client->cmd_id;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen str_free(&id->log_reply);
fa5957ffc9b676bfd649fa9953e63e72ee4ebeb4Timo Sirainen if (id->log_keys != NULL)
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen p_strsplit_free(default_pool, id->log_keys);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen imap_parser_unref(&id->parser);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen i_free_and_null(client->cmd_id);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen client->skip_line = TRUE;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen}
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainenint cmd_id(struct imap_client *client)
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen{
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen struct imap_client_cmd_id *id;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen enum imap_parser_flags parser_flags;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen const struct imap_arg *args;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen int ret;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
3da614c39dd29f536c485089e67839b4cf89fed3Timo Sirainen if (client->common.client_id != NULL)
3da614c39dd29f536c485089e67839b4cf89fed3Timo Sirainen str_truncate(client->common.client_id, 0);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen if (client->cmd_id == NULL) {
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen client->cmd_id = id = i_new(struct imap_client_cmd_id, 1);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen id->parser = imap_parser_create(client->common.input,
075f90abe6b6b12dc72bca21bfce8086b4b190ecTimo Sirainen client->common.output,
9bc6e10d9c6d6ffb4a2ed49a3b3d2a180f2a87a3Timo Sirainen IMAP_LOGIN_MAX_LINE_LENGTH);
9bc6e10d9c6d6ffb4a2ed49a3b3d2a180f2a87a3Timo Sirainen if (client->set->imap_literal_minus)
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen imap_parser_enable_literal_minus(id->parser);
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen parser_flags = IMAP_PARSE_FLAG_STOP_AT_LIST;
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen } else {
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen id = client->cmd_id;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen parser_flags = IMAP_PARSE_FLAG_INSIDE_LIST;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen }
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen while ((ret = imap_parser_read_args(id->parser, 1, parser_flags, &args)) > 0) {
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen i_assert(ret == 1);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen if ((ret = cmd_id_handle_args(client, args)) < 0) {
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen client_send_reply(&client->common,
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen IMAP_CMD_REPLY_BAD,
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen "Invalid ID parameters");
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen cmd_id_free(client);
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen return -1;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen }
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen if (ret > 0) {
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen /* NIL parameter */
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen ret = 0;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen break;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen }
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen imap_parser_reset(id->parser);
abfcd9f73b9ad1eeef4fe6e9940383defabf68c3Timo Sirainen parser_flags = IMAP_PARSE_FLAG_INSIDE_LIST;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen }
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen if (ret == 0) {
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen /* finished the line */
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen cmd_id_finish(client);
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen cmd_id_free(client);
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen return 1;
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen } else if (ret == -1) {
abfcd9f73b9ad1eeef4fe6e9940383defabf68c3Timo Sirainen if (!client_handle_parser_error(client, id->parser))
abfcd9f73b9ad1eeef4fe6e9940383defabf68c3Timo Sirainen return 0;
cd5ee8630497fdbd853ef588a858b4ef619a5e03Timo Sirainen cmd_id_free(client);
cd5ee8630497fdbd853ef588a858b4ef619a5e03Timo Sirainen return -1;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen } else {
7394389230750c45b105cdefb5850c81cae8cdc0Timo Sirainen i_assert(ret == -2);
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen return 0;
3342badd8c69adff34db589fb0a221ace5996212Timo Sirainen }
7e94cf9d70ce9fdeccb7a85ff400b899e6386f36Timo Sirainen}
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen