client.c revision 7cb128dc4cae2a03a742f63ba7afee23c78e3af0
c25356d5978632df6203437e1953bcb29e0c736fTimo Sirainen/* Copyright (c) 2002-2015 Dovecot authors, see the included COPYING file */
c25356d5978632df6203437e1953bcb29e0c736fTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "login-common.h"
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen#include "buffer.h"
d9076f5939edf5d20a261494b1a861dcbb0d32e2Timo Sirainen#include "ioloop.h"
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen#include "istream.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "ostream.h"
5666a3d6a7ea89362b8d9e8b39b15424cd9d6388Timo Sirainen#include "safe-memset.h"
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen#include "str.h"
146f9076cd456ea1e9b3f8536456d9d3c962fadbStephan Bosch#include "strescape.h"
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen#include "imap-parser.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "imap-id.h"
8c909e451d14075c05d90382cf8eebc4e354f569Timo Sirainen#include "imap-resp-code.h"
8c909e451d14075c05d90382cf8eebc4e354f569Timo Sirainen#include "master-service.h"
8c909e451d14075c05d90382cf8eebc4e354f569Timo Sirainen#include "master-service-ssl-settings.h"
573f0491a5733fe21fa062a455acb4790b4e0499Timo Sirainen#include "master-auth.h"
573f0491a5733fe21fa062a455acb4790b4e0499Timo Sirainen#include "client.h"
573f0491a5733fe21fa062a455acb4790b4e0499Timo Sirainen#include "client-authenticate.h"
3ed2d0f6b5e67e2663d44489d9da3176823789a8Timo Sirainen#include "auth-client.h"
65f8fb656051f1059f7b5a2da9c5555adcc30439Timo Sirainen#include "ssl-proxy.h"
1a5573ebc32fae2fe576ec544e1781323c1db609Timo Sirainen#include "imap-proxy.h"
1a5573ebc32fae2fe576ec544e1781323c1db609Timo Sirainen#include "imap-login-settings.h"
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen#include <stdlib.h>
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen#if LOGIN_MAX_INBUF_SIZE < 1024+2
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen# error LOGIN_MAX_INBUF_SIZE too short to fit all ID command parameters
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen#endif
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen/* maximum length for IMAP command line. */
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen#define MAX_IMAP_LINE 8192
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen/* Disconnect client when it sends too many bad commands */
f7539a17ea306191b53b8f5e752e228937df9ec3Timo Sirainen#define CLIENT_MAX_BAD_COMMANDS 3
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
2dd39e478269d6fb0bb26d12b394aa30ee965e38Timo Sirainen/* Skip incoming data until newline is found,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen returns TRUE if newline was found. */
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainenbool client_skip_line(struct imap_client *client)
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const unsigned char *data;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen size_t i, data_size;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen data = i_stream_get_data(client->common.input, &data_size);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen for (i = 0; i < data_size; i++) {
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen if (data[i] == '\n') {
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen i_stream_skip(client->common.input, i+1);
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen return TRUE;
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen }
3e564425db51f3921ce4de11859777135fdedd15Timo Sirainen }
857c471c13ca215f4be9dd4b336b742b8d434e31Timo Sirainen
857c471c13ca215f4be9dd4b336b742b8d434e31Timo Sirainen return FALSE;
857c471c13ca215f4be9dd4b336b742b8d434e31Timo Sirainen}
857c471c13ca215f4be9dd4b336b742b8d434e31Timo Sirainen
857c471c13ca215f4be9dd4b336b742b8d434e31Timo Sirainenstatic bool client_handle_parser_error(struct imap_client *client,
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen struct imap_parser *parser)
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen{
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen const char *msg;
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen bool fatal;
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen msg = imap_parser_get_error(parser, &fatal);
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen if (fatal) {
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainen client_send_reply(&client->common,
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainen IMAP_CMD_REPLY_BYE, msg);
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainen client_destroy(&client->common,
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainen t_strconcat("Disconnected: ", msg, NULL));
e5fd6dfd0a492e4708d4dbb7971d7fc5d7b8fd85Timo Sirainen return FALSE;
e5fd6dfd0a492e4708d4dbb7971d7fc5d7b8fd85Timo Sirainen }
4ba9a1d3facc515b3feb5238a16bcf91f76fac61Timo Sirainen
4ba9a1d3facc515b3feb5238a16bcf91f76fac61Timo Sirainen client_send_reply(&client->common, IMAP_CMD_REPLY_BAD, msg);
dfaefeabae939803ceb8c503101e86b5496541d1Timo Sirainen client->cmd_finished = TRUE;
dfaefeabae939803ceb8c503101e86b5496541d1Timo Sirainen client->skip_line = TRUE;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen return TRUE;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen}
8b31f966d9688e07672ef1958dcbdb7686523c04Timo Sirainen
8b31f966d9688e07672ef1958dcbdb7686523c04Timo Sirainenstatic bool is_login_cmd_disabled(struct client *client)
9847ec56efa15fa063eea9988eee2d4ed9ec7d58Timo Sirainen{
9847ec56efa15fa063eea9988eee2d4ed9ec7d58Timo Sirainen if (client->secured) {
9847ec56efa15fa063eea9988eee2d4ed9ec7d58Timo Sirainen if (auth_client_find_mech(auth_client, "PLAIN") == NULL) {
d46a1e3f999dda802dc5137e883adcd7a6629cd3Timo Sirainen /* no PLAIN authentication, can't use LOGIN command */
d46a1e3f999dda802dc5137e883adcd7a6629cd3Timo Sirainen return TRUE;
d46a1e3f999dda802dc5137e883adcd7a6629cd3Timo Sirainen }
d1e843e77f4760e303c53d9fce10123fc8d230a1Timo Sirainen return FALSE;
d1e843e77f4760e303c53d9fce10123fc8d230a1Timo Sirainen }
d1e843e77f4760e303c53d9fce10123fc8d230a1Timo Sirainen if (client->set->disable_plaintext_auth)
291ce16fffca75e8598a8c9dceb08613413dcb07Timo Sirainen return TRUE;
291ce16fffca75e8598a8c9dceb08613413dcb07Timo Sirainen if (strcmp(client->ssl_set->ssl, "required") == 0)
291ce16fffca75e8598a8c9dceb08613413dcb07Timo Sirainen return TRUE;
08e9fd42eb8007e1f9db62c088eef74f906114a5Josef 'Jeff' Sipek return FALSE;
08e9fd42eb8007e1f9db62c088eef74f906114a5Josef 'Jeff' Sipek}
08e9fd42eb8007e1f9db62c088eef74f906114a5Josef 'Jeff' Sipek
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainenstatic const char *get_capability(struct client *client)
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainen{
306b3f41b05da642d87e7ca7a1496efce9f5902fTimo Sirainen struct imap_client *imap_client = (struct imap_client *)client;
306b3f41b05da642d87e7ca7a1496efce9f5902fTimo Sirainen string_t *cap_str = t_str_new(256);
306b3f41b05da642d87e7ca7a1496efce9f5902fTimo Sirainen
306b3f41b05da642d87e7ca7a1496efce9f5902fTimo Sirainen if (*imap_client->set->imap_capability == '\0')
306b3f41b05da642d87e7ca7a1496efce9f5902fTimo Sirainen str_append(cap_str, CAPABILITY_BANNER_STRING);
306b3f41b05da642d87e7ca7a1496efce9f5902fTimo Sirainen else if (*imap_client->set->imap_capability != '+')
306b3f41b05da642d87e7ca7a1496efce9f5902fTimo Sirainen str_append(cap_str, imap_client->set->imap_capability);
306b3f41b05da642d87e7ca7a1496efce9f5902fTimo Sirainen else {
306b3f41b05da642d87e7ca7a1496efce9f5902fTimo Sirainen str_append(cap_str, CAPABILITY_BANNER_STRING);
306b3f41b05da642d87e7ca7a1496efce9f5902fTimo Sirainen str_append_c(cap_str, ' ');
306b3f41b05da642d87e7ca7a1496efce9f5902fTimo Sirainen str_append(cap_str, imap_client->set->imap_capability + 1);
97ae33602db7d5bc8eede82512a965d49ab8853bTimo Sirainen }
97ae33602db7d5bc8eede82512a965d49ab8853bTimo Sirainen
97ae33602db7d5bc8eede82512a965d49ab8853bTimo Sirainen if (client_is_tls_enabled(client) && !client->tls)
30d50c7e8706f2d750215e009504109ca19cd485Timo Sirainen str_append(cap_str, " STARTTLS");
30d50c7e8706f2d750215e009504109ca19cd485Timo Sirainen if (is_login_cmd_disabled(client))
97ae33602db7d5bc8eede82512a965d49ab8853bTimo Sirainen str_append(cap_str, " LOGINDISABLED");
97ae33602db7d5bc8eede82512a965d49ab8853bTimo Sirainen
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen client_authenticate_get_capabilities(client, cap_str);
57a8c6a95e4bce3eeaba36985adb81c07dd683ffTimo Sirainen return str_c(cap_str);
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainen}
afe1da042382720393eca6497253106e4eec75e0Timo Sirainen
afe1da042382720393eca6497253106e4eec75e0Timo Sirainenstatic int cmd_capability(struct imap_client *imap_client)
afe1da042382720393eca6497253106e4eec75e0Timo Sirainen{
afe1da042382720393eca6497253106e4eec75e0Timo Sirainen struct client *client = &imap_client->common;
afe1da042382720393eca6497253106e4eec75e0Timo Sirainen
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen /* Client is required to send CAPABILITY after STARTTLS, so the
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen capability resp-code workaround checks only pre-STARTTLS
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen CAPABILITY commands. */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (!client->starttls)
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen imap_client->client_ignores_capability_resp_code = TRUE;
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainen client_send_raw(client, t_strconcat(
420040a5930a2b497e79ff0b5f59ba4b764a5b39Timo Sirainen "* CAPABILITY ", get_capability(client), "\r\n", NULL));
420040a5930a2b497e79ff0b5f59ba4b764a5b39Timo Sirainen client_send_reply(client, IMAP_CMD_REPLY_OK,
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainen "Pre-login capabilities listed, post-login capabilities have more.");
420040a5930a2b497e79ff0b5f59ba4b764a5b39Timo Sirainen return 1;
420040a5930a2b497e79ff0b5f59ba4b764a5b39Timo Sirainen}
420040a5930a2b497e79ff0b5f59ba4b764a5b39Timo Sirainen
eecb235c14b49c01774134ea593c266f2d2c2be1Timo Sirainenstatic int cmd_starttls(struct imap_client *client)
eecb235c14b49c01774134ea593c266f2d2c2be1Timo Sirainen{
7900eb30bac4a46b259522c58362884661483d7cJosef 'Jeff' Sipek client_cmd_starttls(&client->common);
7900eb30bac4a46b259522c58362884661483d7cJosef 'Jeff' Sipek return 1;
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainen}
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen
98c217499d578495e982ea6010ebff831e9669aeMartti Rannanjärvistatic void
98c217499d578495e982ea6010ebff831e9669aeMartti Rannanjärviimap_client_notify_starttls(struct client *client,
98c217499d578495e982ea6010ebff831e9669aeMartti Rannanjärvi bool success, const char *text)
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen{
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen if (success)
97ae33602db7d5bc8eede82512a965d49ab8853bTimo Sirainen client_send_reply(client, IMAP_CMD_REPLY_OK, text);
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen else
f1743785713e7632459d623d5df2108f4b93accbTimo Sirainen client_send_reply(client, IMAP_CMD_REPLY_BAD, text);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen}
70ead6466f9baa8294e71fc2fba0a4f54f488b5eTimo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainenstatic void
ccc895c0358108d2304239063e940b7d75f364abTimo Sirainenclient_update_info(struct imap_client *client,
8d630c15a8ed6f85553467c3a231a273defca5f6Timo Sirainen const char *key, const char *value)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
ee116df08d0fdab703483e18fe8076b2ef9fd9d7Timo Sirainen if (strcasecmp(key, "x-originating-ip") == 0)
c5ab90cfad9cc3e33bcb1baeb30ffc82a7b7053aTimo Sirainen (void)net_addr2ip(value, &client->common.ip);
c5ab90cfad9cc3e33bcb1baeb30ffc82a7b7053aTimo Sirainen else if (strcasecmp(key, "x-originating-port") == 0)
306b3f41b05da642d87e7ca7a1496efce9f5902fTimo Sirainen client->common.remote_port = atoi(value);
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen else if (strcasecmp(key, "x-connected-ip") == 0)
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen (void)net_addr2ip(value, &client->common.local_ip);
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen else if (strcasecmp(key, "x-connected-port") == 0)
306b3f41b05da642d87e7ca7a1496efce9f5902fTimo Sirainen client->common.local_port = atoi(value);
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen else if (strcasecmp(key, "x-proxy-ttl") == 0)
4ee00532a265bdfb38539d811fcd12d51210ac35Timo Sirainen client->common.proxy_ttl = atoi(value);
c6afd726060aae56b6622c6c52aec10231c4bf1cTimo Sirainen else if (strcasecmp(key, "x-session-id") == 0 ||
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen strcasecmp(key, "x-session-ext-id") == 0) {
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen if (strlen(value) <= LOGIN_MAX_SESSION_ID_LEN) {
98c217499d578495e982ea6010ebff831e9669aeMartti Rannanjärvi client->common.session_id =
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen p_strdup(client->common.pool, value);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen }
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen}
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainenstatic void cmd_id_handle_keyvalue(struct imap_client *client,
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen const char *key, const char *value)
aa41b2e17912d6cad3151babea6a85dd88539d28Timo Sirainen{
aa41b2e17912d6cad3151babea6a85dd88539d28Timo Sirainen if (client->common.trusted && !client->id_logged)
aa41b2e17912d6cad3151babea6a85dd88539d28Timo Sirainen client_update_info(client, key, value);
aa41b2e17912d6cad3151babea6a85dd88539d28Timo Sirainen
aa41b2e17912d6cad3151babea6a85dd88539d28Timo Sirainen if (client->cmd_id->log_reply != NULL &&
aa41b2e17912d6cad3151babea6a85dd88539d28Timo Sirainen (client->cmd_id->log_keys == NULL ||
aa41b2e17912d6cad3151babea6a85dd88539d28Timo Sirainen str_array_icase_find((void *)client->cmd_id->log_keys, key)))
aa41b2e17912d6cad3151babea6a85dd88539d28Timo Sirainen imap_id_log_reply_append(client->cmd_id->log_reply, key, value);
aa41b2e17912d6cad3151babea6a85dd88539d28Timo Sirainen}
aa41b2e17912d6cad3151babea6a85dd88539d28Timo Sirainen
aa41b2e17912d6cad3151babea6a85dd88539d28Timo Sirainenstatic int cmd_id_handle_args(struct imap_client *client,
aa41b2e17912d6cad3151babea6a85dd88539d28Timo Sirainen const struct imap_arg *arg)
aa41b2e17912d6cad3151babea6a85dd88539d28Timo Sirainen{
aa41b2e17912d6cad3151babea6a85dd88539d28Timo Sirainen struct imap_client_cmd_id *id = client->cmd_id;
aa41b2e17912d6cad3151babea6a85dd88539d28Timo Sirainen const char *key, *value;
aa41b2e17912d6cad3151babea6a85dd88539d28Timo Sirainen
aa41b2e17912d6cad3151babea6a85dd88539d28Timo Sirainen switch (id->state) {
aa41b2e17912d6cad3151babea6a85dd88539d28Timo Sirainen case IMAP_CLIENT_ID_STATE_LIST:
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen if (arg->type == IMAP_ARG_NIL)
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen return 1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (arg->type != IMAP_ARG_LIST)
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen return -1;
cff1f182205e674285cf3ff446a0dcf7afea277dTimo Sirainen if (client->set->imap_id_log[0] == '\0') {
cff1f182205e674285cf3ff446a0dcf7afea277dTimo Sirainen /* no ID logging */
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen } else if (client->id_logged) {
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen /* already logged the ID reply */
e03d986a74128f5ba30fcfda9f6e36578f5d8decTimo Sirainen } else {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen id->log_reply = str_new(default_pool, 64);
f318b3dbe2acc177b8ee1c160e4b5b14e7f2cd41Timo Sirainen if (strcmp(client->set->imap_id_log, "*") == 0) {
f318b3dbe2acc177b8ee1c160e4b5b14e7f2cd41Timo Sirainen /* log all keys */
f318b3dbe2acc177b8ee1c160e4b5b14e7f2cd41Timo Sirainen } else {
f318b3dbe2acc177b8ee1c160e4b5b14e7f2cd41Timo Sirainen /* log only specified keys */
f318b3dbe2acc177b8ee1c160e4b5b14e7f2cd41Timo Sirainen id->log_keys = p_strsplit_spaces(default_pool,
f318b3dbe2acc177b8ee1c160e4b5b14e7f2cd41Timo Sirainen client->set->imap_id_log, " ");
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen }
d3280fe317a4598c0868cc440e7a1191c06d0db3Timo Sirainen }
d3280fe317a4598c0868cc440e7a1191c06d0db3Timo Sirainen id->state = IMAP_CLIENT_ID_STATE_KEY;
51327f2489a4e0e615eb9f7d921473cf8512bb79Timo Sirainen break;
51327f2489a4e0e615eb9f7d921473cf8512bb79Timo Sirainen case IMAP_CLIENT_ID_STATE_KEY:
51327f2489a4e0e615eb9f7d921473cf8512bb79Timo Sirainen if (!imap_arg_get_string(arg, &key))
6469cf211a57433335641725dc236ebb2b9fdd3bTimo Sirainen return -1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (i_strocpy(id->key, key, sizeof(id->key)) < 0)
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen return -1;
6cc4cce2078aca138fbce19305e69e77edcee614Timo Sirainen id->state = IMAP_CLIENT_ID_STATE_VALUE;
bd6a8056771b6150685dea319ab5a94e021d17f1Josef 'Jeff' Sipek break;
9f37ef2a9192e7d47e3d7ac959080fd01120f2e9Aki Tuomi case IMAP_CLIENT_ID_STATE_VALUE:
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen if (!imap_arg_get_nstring(arg, &value))
bd6a8056771b6150685dea319ab5a94e021d17f1Josef 'Jeff' Sipek return -1;
62041dfb7d6ac6e9c633a557075999cdfcff7bd5Timo Sirainen cmd_id_handle_keyvalue(client, id->key, value);
62041dfb7d6ac6e9c633a557075999cdfcff7bd5Timo Sirainen id->state = IMAP_CLIENT_ID_STATE_KEY;
62041dfb7d6ac6e9c633a557075999cdfcff7bd5Timo Sirainen break;
62041dfb7d6ac6e9c633a557075999cdfcff7bd5Timo Sirainen }
62041dfb7d6ac6e9c633a557075999cdfcff7bd5Timo Sirainen return 0;
62041dfb7d6ac6e9c633a557075999cdfcff7bd5Timo Sirainen}
62041dfb7d6ac6e9c633a557075999cdfcff7bd5Timo Sirainen
d3442384ca53d4b18a493db7dd0b000f470419cfTimo Sirainenstatic void cmd_id_finish(struct imap_client *client)
aa47c9bd1d1fc70cd699c49fd1ca92dbc7615953Timo Sirainen{
aa47c9bd1d1fc70cd699c49fd1ca92dbc7615953Timo Sirainen /* finished handling the parameters */
d3442384ca53d4b18a493db7dd0b000f470419cfTimo Sirainen if (!client->id_logged) {
d3442384ca53d4b18a493db7dd0b000f470419cfTimo Sirainen client->id_logged = TRUE;
aa47c9bd1d1fc70cd699c49fd1ca92dbc7615953Timo Sirainen
c0d069950af1dbc6a4e5c3de3bf2e437796e3ae0Timo Sirainen if (client->cmd_id->log_reply != NULL) {
c0d069950af1dbc6a4e5c3de3bf2e437796e3ae0Timo Sirainen client_log(&client->common, t_strdup_printf(
c0d069950af1dbc6a4e5c3de3bf2e437796e3ae0Timo Sirainen "ID sent: %s", str_c(client->cmd_id->log_reply)));
c0d069950af1dbc6a4e5c3de3bf2e437796e3ae0Timo Sirainen }
d3442384ca53d4b18a493db7dd0b000f470419cfTimo Sirainen }
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen client_send_raw(&client->common,
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen t_strdup_printf("* ID %s\r\n",
c979eeda1f46483d9c963e265786b701d7683d77Timo Sirainen imap_id_reply_generate(client->set->imap_id_send)));
c979eeda1f46483d9c963e265786b701d7683d77Timo Sirainen client_send_reply(&client->common, IMAP_CMD_REPLY_OK, "ID completed.");
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen}
2584e86cc2d8c31ba30a4109cf4ba09d1e37e28aTimo Sirainen
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainenstatic void cmd_id_free(struct imap_client *client)
4b41116563110d00330896a568eff1078c382827Timo Sirainen{
4b41116563110d00330896a568eff1078c382827Timo Sirainen struct imap_client_cmd_id *id = client->cmd_id;
4b41116563110d00330896a568eff1078c382827Timo Sirainen
5137d2d80255938a0f5fb8f3c1a21b34cf11ada3Timo Sirainen if (id->log_reply != NULL)
5137d2d80255938a0f5fb8f3c1a21b34cf11ada3Timo Sirainen str_free(&id->log_reply);
5137d2d80255938a0f5fb8f3c1a21b34cf11ada3Timo Sirainen if (id->log_keys != NULL)
f81f4bc282cd1944cec187bae89c0701a416ed2aTimo Sirainen p_strsplit_free(default_pool, id->log_keys);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen imap_parser_unref(&id->parser);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen i_free_and_null(client->cmd_id);
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen client->skip_line = TRUE;
b2c1349cf07410aefab0f5b17153af9e5cfcf48fTimo Sirainen}
96308127e006bb3b1108093bcf4cc1fd9481cb7aTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic int cmd_id(struct imap_client *client)
dbe64f3893616a4005c8946be75d2dc8f6823d72Timo Sirainen{
8a13b020f90e080570658b18c042e7e352c8b14fTimo Sirainen struct imap_client_cmd_id *id;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen enum imap_parser_flags parser_flags;
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen const struct imap_arg *args;
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen int ret;
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen if (client->cmd_id == NULL) {
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen client->cmd_id = id = i_new(struct imap_client_cmd_id, 1);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen id->parser = imap_parser_create(client->common.input,
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen client->common.output,
c4b376dd6e0c423006d7ac83a39253bcaf8e7c47Timo Sirainen MAX_IMAP_LINE);
eef4ba0cc3e78f8c26804c1c9251a76580a41f0cTimo Sirainen parser_flags = IMAP_PARSE_FLAG_STOP_AT_LIST;
eef4ba0cc3e78f8c26804c1c9251a76580a41f0cTimo Sirainen } else {
eef4ba0cc3e78f8c26804c1c9251a76580a41f0cTimo Sirainen id = client->cmd_id;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen parser_flags = IMAP_PARSE_FLAG_INSIDE_LIST;
f3bb2fbe87425dc89a839908985af496f7f65702Timo Sirainen }
eef4ba0cc3e78f8c26804c1c9251a76580a41f0cTimo Sirainen
a3ee5ce6ecc8e228ee69300fdd562d7ac8be89a7Timo Sirainen while ((ret = imap_parser_read_args(id->parser, 1, parser_flags, &args)) > 0) {
bd1b2615928a1e8be190cb0405754f0aec8cac2fTimo Sirainen i_assert(ret == 1);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
e3aeeb634245e80d4f643f8d2eea11d6b72336d8Timo Sirainen if ((ret = cmd_id_handle_args(client, args)) < 0) {
e3aeeb634245e80d4f643f8d2eea11d6b72336d8Timo Sirainen client_send_reply(&client->common,
e3aeeb634245e80d4f643f8d2eea11d6b72336d8Timo Sirainen IMAP_CMD_REPLY_BAD,
a423d985ba7261661475811c22b21b80ec765a71Timo Sirainen "Invalid ID parameters");
2ebeb22b9a8a8bb7fbe2f2e2908478a220792b87Timo Sirainen cmd_id_free(client);
a423d985ba7261661475811c22b21b80ec765a71Timo Sirainen return -1;
bd4d0a1a7c0626452b8d82f37e3ec07267ac9896Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (ret > 0) {
1460ef7a18c53216ddb4a94bb62fba96076aae8eTimo Sirainen /* NIL parameter */
1460ef7a18c53216ddb4a94bb62fba96076aae8eTimo Sirainen ret = 0;
1460ef7a18c53216ddb4a94bb62fba96076aae8eTimo Sirainen break;
1460ef7a18c53216ddb4a94bb62fba96076aae8eTimo Sirainen }
1460ef7a18c53216ddb4a94bb62fba96076aae8eTimo Sirainen imap_parser_reset(id->parser);
1460ef7a18c53216ddb4a94bb62fba96076aae8eTimo Sirainen parser_flags = IMAP_PARSE_FLAG_INSIDE_LIST;
1460ef7a18c53216ddb4a94bb62fba96076aae8eTimo Sirainen }
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen if (ret == 0) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* finished the line */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen cmd_id_finish(client);
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen cmd_id_free(client);
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen return 1;
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen } else if (ret == -1) {
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen if (!client_handle_parser_error(client, id->parser))
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen return 0;
0177594fa5217b02001f4ec8752154fd2b05c545Timo Sirainen cmd_id_free(client);
0177594fa5217b02001f4ec8752154fd2b05c545Timo Sirainen return -1;
0177594fa5217b02001f4ec8752154fd2b05c545Timo Sirainen } else {
0177594fa5217b02001f4ec8752154fd2b05c545Timo Sirainen i_assert(ret == -2);
0177594fa5217b02001f4ec8752154fd2b05c545Timo Sirainen return 0;
0177594fa5217b02001f4ec8752154fd2b05c545Timo Sirainen }
2c70086138fe7ac9abf52cd4223c224fe0bbb488Timo Sirainen}
2c70086138fe7ac9abf52cd4223c224fe0bbb488Timo Sirainen
2c70086138fe7ac9abf52cd4223c224fe0bbb488Timo Sirainenstatic int cmd_noop(struct imap_client *client)
2c70086138fe7ac9abf52cd4223c224fe0bbb488Timo Sirainen{
2c70086138fe7ac9abf52cd4223c224fe0bbb488Timo Sirainen client_send_reply(&client->common, IMAP_CMD_REPLY_OK,
2c70086138fe7ac9abf52cd4223c224fe0bbb488Timo Sirainen "NOOP completed.");
2b9dbb270ad82e58d5f3581436e6f143176d5819Timo Sirainen return 1;
2b9dbb270ad82e58d5f3581436e6f143176d5819Timo Sirainen}
2b9dbb270ad82e58d5f3581436e6f143176d5819Timo Sirainen
2b9dbb270ad82e58d5f3581436e6f143176d5819Timo Sirainenstatic int cmd_logout(struct imap_client *client)
1ae5d61ec366fdb2f3c5b150ca378d6141b0f4bdTimo Sirainen{
1ae5d61ec366fdb2f3c5b150ca378d6141b0f4bdTimo Sirainen client_send_reply(&client->common, IMAP_CMD_REPLY_BYE, "Logging out");
1ae5d61ec366fdb2f3c5b150ca378d6141b0f4bdTimo Sirainen client_send_reply(&client->common, IMAP_CMD_REPLY_OK,
1ae5d61ec366fdb2f3c5b150ca378d6141b0f4bdTimo Sirainen "Logout completed.");
1ae5d61ec366fdb2f3c5b150ca378d6141b0f4bdTimo Sirainen client_destroy(&client->common, "Aborted login");
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen return 1;
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen}
df00412606a00714a6e85383fa87fbdc7cc1fb5bTimo Sirainen
df00412606a00714a6e85383fa87fbdc7cc1fb5bTimo Sirainenstatic int cmd_enable(struct imap_client *client)
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen{
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen client_send_raw(&client->common, "* ENABLED\r\n");
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen client_send_reply(&client->common, IMAP_CMD_REPLY_OK,
aa41b2e17912d6cad3151babea6a85dd88539d28Timo Sirainen "ENABLE ignored in non-authenticated state.");
aa41b2e17912d6cad3151babea6a85dd88539d28Timo Sirainen return 1;
aa41b2e17912d6cad3151babea6a85dd88539d28Timo Sirainen}
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen
d938e9e4ec4c0f326dffd5ebe42c1ad893ce7e52Timo Sirainenstatic int client_command_execute(struct imap_client *client, const char *cmd,
eecb235c14b49c01774134ea593c266f2d2c2be1Timo Sirainen const struct imap_arg *args)
eecb235c14b49c01774134ea593c266f2d2c2be1Timo Sirainen{
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen cmd = t_str_ucase(cmd);
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen if (strcmp(cmd, "LOGIN") == 0)
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen return cmd_login(client, args);
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen if (strcmp(cmd, "CAPABILITY") == 0)
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen return cmd_capability(client);
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen if (strcmp(cmd, "STARTTLS") == 0)
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen return cmd_starttls(client);
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen if (strcmp(cmd, "NOOP") == 0)
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen return cmd_noop(client);
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen if (strcmp(cmd, "LOGOUT") == 0)
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen return cmd_logout(client);
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen if (strcmp(cmd, "ENABLE") == 0)
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen return cmd_enable(client);
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen return -2;
546335814920fb6b5b44c68c7803e654eefeae9dTimo Sirainen}
546335814920fb6b5b44c68c7803e654eefeae9dTimo Sirainen
546335814920fb6b5b44c68c7803e654eefeae9dTimo Sirainenstatic bool imap_is_valid_tag(const char *tag)
4b41218f9e09386ad5d8f279355aad1dfb64392dTimo Sirainen{
4b41218f9e09386ad5d8f279355aad1dfb64392dTimo Sirainen for (; *tag != '\0'; tag++) {
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen switch (*tag) {
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen case '+':
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen /* atom-specials: */
eb1572d7c44ebc7b0b039d085c3dbab2ef7043ddTimo Sirainen case '(':
eb1572d7c44ebc7b0b039d085c3dbab2ef7043ddTimo Sirainen case ')':
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen case '{':
bd4e36a8cd7257cca7d1434c49a1e343ed7c5100Timo Sirainen case '/':
bd4e36a8cd7257cca7d1434c49a1e343ed7c5100Timo Sirainen case ' ':
bd4e36a8cd7257cca7d1434c49a1e343ed7c5100Timo Sirainen /* list-wildcards: */
bd4e36a8cd7257cca7d1434c49a1e343ed7c5100Timo Sirainen case '%':
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen case '*':
df00412606a00714a6e85383fa87fbdc7cc1fb5bTimo Sirainen /* quoted-specials: */
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen case '"':
42507d758b053bb483de58fba55c73a9eb5d3fbaTimo Sirainen case '\\':
c0c346d0e6a76137ba5006857ed03b1227804170Timo Sirainen return FALSE;
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen default:
0177594fa5217b02001f4ec8752154fd2b05c545Timo Sirainen if (*tag < ' ') /* CTL */
382f23541ce657be87b079abd6784d376fb4eb43Timo Sirainen return FALSE;
2b9dbb270ad82e58d5f3581436e6f143176d5819Timo Sirainen break;
97a5e150cacf7da9dd200e317b75460352038d65Timo Sirainen }
3743948b65bd079cd6f2502d35bd21666c1a2f5aAki Tuomi }
134987bc3b685d7ec71c04e9337f7125cff0698fTimo Sirainen return TRUE;
42507d758b053bb483de58fba55c73a9eb5d3fbaTimo Sirainen}
817d027593510c3ba70ad542ce0011f5f6916d1eTimo Sirainen
817d027593510c3ba70ad542ce0011f5f6916d1eTimo Sirainenstatic int client_parse_command(struct imap_client *client,
817d027593510c3ba70ad542ce0011f5f6916d1eTimo Sirainen const struct imap_arg **args_r)
817d027593510c3ba70ad542ce0011f5f6916d1eTimo Sirainen{
817d027593510c3ba70ad542ce0011f5f6916d1eTimo Sirainen switch (imap_parser_read_args(client->parser, 0, 0, args_r)) {
6ae329de09afb7214c906d762320847e05469d53Timo Sirainen case -1:
6ae329de09afb7214c906d762320847e05469d53Timo Sirainen /* error */
f81f4bc282cd1944cec187bae89c0701a416ed2aTimo Sirainen if (!client_handle_parser_error(client, client->parser)) {
f81f4bc282cd1944cec187bae89c0701a416ed2aTimo Sirainen /* client destroyed */
f81f4bc282cd1944cec187bae89c0701a416ed2aTimo Sirainen return 0;
7e2671b295927b461adc8b6c4ed6a1c4761fb323Timo Sirainen }
7e2671b295927b461adc8b6c4ed6a1c4761fb323Timo Sirainen return -1;
f81f4bc282cd1944cec187bae89c0701a416ed2aTimo Sirainen case -2:
fcfe85637e1ee14a9fc39c41fd6ceca106301542Timo Sirainen /* not enough data */
fcfe85637e1ee14a9fc39c41fd6ceca106301542Timo Sirainen return 0;
fcfe85637e1ee14a9fc39c41fd6ceca106301542Timo Sirainen default:
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen /* we read the entire line - skip over the CRLF */
4ee00532a265bdfb38539d811fcd12d51210ac35Timo Sirainen if (!client_skip_line(client))
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen i_unreached();
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen return 1;
4ee00532a265bdfb38539d811fcd12d51210ac35Timo Sirainen }
5fb3bff645380804c9db2510940c41db6b8fdb01Timo Sirainen}
5fb3bff645380804c9db2510940c41db6b8fdb01Timo Sirainen
5fb3bff645380804c9db2510940c41db6b8fdb01Timo Sirainenstatic bool client_handle_input(struct imap_client *client)
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen{
4bbd396aa6198c84f3f7763b6e8a63a26e97e141Timo Sirainen const struct imap_arg *args;
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen bool parsed;
7baab0b0b60df7ce9093d0881cd322dff1e79491Timo Sirainen int ret;
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen
3f91e60401495a4046c73992fabaa5e77200a451Timo Sirainen i_assert(!client->common.authenticating);
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen
3857e2945a3b6744d603f0f5a656849ed8436ba3Timo Sirainen if (client->cmd_finished) {
3857e2945a3b6744d603f0f5a656849ed8436ba3Timo Sirainen /* clear the previous command from memory. don't do this
f90cbe597c41d5cc91debd371f8648bd8e6ffbc2Timo Sirainen immediately after handling command since we need the
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen cmd_tag to stay some time after authentication commands. */
33b469d1ca66dd2cc496d2d990b8b98e72952a29Timo Sirainen client->cmd_tag = NULL;
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen client->cmd_name = NULL;
58ba0fe5a6904d3a65cfe268411f4cbb881234eeTimo Sirainen imap_parser_reset(client->parser);
58ba0fe5a6904d3a65cfe268411f4cbb881234eeTimo Sirainen
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen /* remove \r\n */
6b0d8106ae51ffc6ce45636b34d2e21cbefca7fdTimo Sirainen if (client->skip_line) {
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen if (!client_skip_line(client))
eb64c3586d854cddd693f0b811d897399076a441Timo Sirainen return FALSE;
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen client->skip_line = FALSE;
eb64c3586d854cddd693f0b811d897399076a441Timo Sirainen }
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen
7f735cb86b2d8abd8f230089065eacfc24e9e5d6Timo Sirainen client->cmd_finished = FALSE;
7f735cb86b2d8abd8f230089065eacfc24e9e5d6Timo Sirainen }
7f735cb86b2d8abd8f230089065eacfc24e9e5d6Timo Sirainen
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen if (client->cmd_tag == NULL) {
b3484b5b1f47e4cf112f0e371478a2d7794b31bbTimo Sirainen client->cmd_tag = imap_parser_read_word(client->parser);
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen if (client->cmd_tag == NULL)
d81131d3bbb4f0befb62a661d1785cf8c84a17e2Timo Sirainen return FALSE; /* need more data */
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen if (!imap_is_valid_tag(client->cmd_tag) ||
9456a4a3e74929f9d3d5b00b93be6d8eb69bc52aTimo Sirainen strlen(client->cmd_tag) > IMAP_TAG_MAX_LEN) {
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen /* the tag is invalid, don't allow it and don't
4e3bcf7fdaeef92dd07a2acb1ded58422a907e87Timo Sirainen send it back. this attempts to prevent any
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen potentially dangerous replies in case someone tries
19e161dd9e2c3a2ffc96ee8852bec0720cb30d1cTimo Sirainen to access us using HTTP protocol. */
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen client->cmd_tag = "";
540555c5b435203e1c26c8e7b924b2643ae07ae3Timo Sirainen }
540555c5b435203e1c26c8e7b924b2643ae07ae3Timo Sirainen }
540555c5b435203e1c26c8e7b924b2643ae07ae3Timo Sirainen
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen if (client->cmd_name == NULL) {
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen client->cmd_name = imap_parser_read_word(client->parser);
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen if (client->cmd_name == NULL)
0d86aa0d47f7393c669c084b34c0537b193688adTimo Sirainen return FALSE; /* need more data */
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen }
7631f16156aca373004953fe6b01a7f343fb47e0Timo Sirainen
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen if (strcasecmp(client->cmd_name, "AUTHENTICATE") == 0) {
aa247243412a49f9bdebf7255e131dc6ece4ed46Timo Sirainen /* SASL-IR may need more space than input buffer's size,
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen so we'll handle it as a special case. */
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen ret = cmd_authenticate(client, &parsed);
ecd69c4e8371853667e01b0c16d436ef7f7393e2Timo Sirainen if (ret == 0 && !parsed)
ecd69c4e8371853667e01b0c16d436ef7f7393e2Timo Sirainen return FALSE;
ecd69c4e8371853667e01b0c16d436ef7f7393e2Timo Sirainen } else if (strcasecmp(client->cmd_name, "ID") == 0) {
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen /* ID extensions allows max. 30 parameters,
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen each max. 1024 bytes long. that brings us over the input
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen buffer's size, so handle the parameters one at a time */
a757f31393b9d6fc7760a9dec8363404ab3ae576Timo Sirainen ret = cmd_id(client);
a757f31393b9d6fc7760a9dec8363404ab3ae576Timo Sirainen if (ret == 0)
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen return FALSE;
f46885a5b78b15a8d2419f6e5d13b643bd85e41fTimo Sirainen if (ret < 0)
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen ret = 1; /* don't send the error reply again */
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen } else {
c0225f7f6b43d34dc58c17d3304f0fd60ab89894Timo Sirainen ret = client_parse_command(client, &args);
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen if (ret < 0)
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen return TRUE;
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen if (ret == 0)
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen return FALSE;
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen ret = *client->cmd_tag == '\0' ? -1 :
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen client_command_execute(client, client->cmd_name, args);
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen }
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen client->cmd_finished = TRUE;
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen if (ret == -2 && strcasecmp(client->cmd_tag, "LOGIN") == 0) {
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen client_send_reply(&client->common, IMAP_CMD_REPLY_BAD,
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen "First parameter in line is IMAP's command tag, "
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen "not the command name. Add that before the command, "
6df0ab0c1ab91f06b6418cb30eff44405a1b8f02Timo Sirainen "like: a login user pass");
6df0ab0c1ab91f06b6418cb30eff44405a1b8f02Timo Sirainen } else if (ret < 0) {
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen if (*client->cmd_tag == '\0')
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen client->cmd_tag = "*";
306b3f41b05da642d87e7ca7a1496efce9f5902fTimo Sirainen if (++client->common.bad_counter >= CLIENT_MAX_BAD_COMMANDS) {
306b3f41b05da642d87e7ca7a1496efce9f5902fTimo Sirainen client_send_reply(&client->common, IMAP_CMD_REPLY_BYE,
306b3f41b05da642d87e7ca7a1496efce9f5902fTimo Sirainen "Too many invalid IMAP commands.");
e53ab6c7081246c865917f9aa0eff031a08ad1e7Timo Sirainen client_destroy(&client->common,
e53ab6c7081246c865917f9aa0eff031a08ad1e7Timo Sirainen "Disconnected: Too many invalid commands");
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen return FALSE;
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen }
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen client_send_reply(&client->common, IMAP_CMD_REPLY_BAD,
21aaa6affb9f134112b75b5db737309fc35ef1cfMartti Rannanjärvi "Error in IMAP command received by server.");
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen }
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen return ret != 0 && !client->common.destroyed;
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen}
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainenstatic void imap_client_input(struct client *client)
f46885a5b78b15a8d2419f6e5d13b643bd85e41fTimo Sirainen{
225e82df5dd1e765f4e52b80c954558f00e5a7dfTimo Sirainen struct imap_client *imap_client = (struct imap_client *)client;
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen
838e367716bbd5e44b4a1691db9cbf72af53e9f0Timo Sirainen if (!client_read(client))
0206dc57f2c04da69599dea5816235cfeb2b897aMartti Rannanjärvi return;
0206dc57f2c04da69599dea5816235cfeb2b897aMartti Rannanjärvi
6564208826b0f46a00f010d1b5711d85944c3c88Timo Sirainen client_ref(client);
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen o_stream_cork(imap_client->common.output);
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen for (;;) {
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen if (!auth_client_is_connected(auth_client)) {
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen /* we're not currently connected to auth process -
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen don't allow any commands */
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen client_notify_status(client, FALSE,
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen AUTH_SERVER_WAITING_MSG);
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen if (client->to_auth_waiting != NULL)
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen timeout_remove(&client->to_auth_waiting);
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen
13e130c3af3032982de6b1d13c6dcddda9164848Timo Sirainen client->input_blocked = TRUE;
13e130c3af3032982de6b1d13c6dcddda9164848Timo Sirainen break;
13e130c3af3032982de6b1d13c6dcddda9164848Timo Sirainen } else {
13e130c3af3032982de6b1d13c6dcddda9164848Timo Sirainen if (!client_handle_input(imap_client))
13e130c3af3032982de6b1d13c6dcddda9164848Timo Sirainen break;
13e130c3af3032982de6b1d13c6dcddda9164848Timo Sirainen }
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen }
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen o_stream_uncork(imap_client->common.output);
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen client_unref(&client);
ecd69c4e8371853667e01b0c16d436ef7f7393e2Timo Sirainen}
310767ca33e7636d40ec45dee68a2c319a5fa3c0Timo Sirainen
310767ca33e7636d40ec45dee68a2c319a5fa3c0Timo Sirainenstatic struct client *imap_client_alloc(pool_t pool)
310767ca33e7636d40ec45dee68a2c319a5fa3c0Timo Sirainen{
5f44975ec6c5755dd74bcd4c47a123a7242ecab3Timo Sirainen struct imap_client *imap_client;
4ee00532a265bdfb38539d811fcd12d51210ac35Timo Sirainen
2c8ca7e88ec881c473fb90e5f647c1f563877164Timo Sirainen imap_client = p_new(pool, struct imap_client, 1);
2c8ca7e88ec881c473fb90e5f647c1f563877164Timo Sirainen return &imap_client->common;
6c51e3c3dc8dc5dc6fef2280b7c2c9ebef3de8f0Aki Tuomi}
6c51e3c3dc8dc5dc6fef2280b7c2c9ebef3de8f0Aki Tuomi
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainenstatic void imap_client_create(struct client *client, void **other_sets)
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct imap_client *imap_client = (struct imap_client *)client;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
e4c90f0b88e40a8f92b8f5e1f1a3ea701e5c965cTimo Sirainen imap_client->set = other_sets[0];
defb12ecd360df672ffb2f4dbf4d1218a0a9549cTimo Sirainen imap_client->parser =
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen imap_parser_create(imap_client->common.input,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen imap_client->common.output, MAX_IMAP_LINE);
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen client->io = io_add(client->fd, IO_READ, client_input, client);
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen}
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainenstatic void imap_client_destroy(struct client *client)
2d01cc1880cf2afd4fb1c8ad7fa6ce78e562e71eTimo Sirainen{
2d01cc1880cf2afd4fb1c8ad7fa6ce78e562e71eTimo Sirainen struct imap_client *imap_client = (struct imap_client *)client;
2d01cc1880cf2afd4fb1c8ad7fa6ce78e562e71eTimo Sirainen
2d01cc1880cf2afd4fb1c8ad7fa6ce78e562e71eTimo Sirainen i_free_and_null(imap_client->proxy_backend_capability);
2d01cc1880cf2afd4fb1c8ad7fa6ce78e562e71eTimo Sirainen imap_parser_unref(&imap_client->parser);
2d01cc1880cf2afd4fb1c8ad7fa6ce78e562e71eTimo Sirainen}
2d01cc1880cf2afd4fb1c8ad7fa6ce78e562e71eTimo Sirainen
2d01cc1880cf2afd4fb1c8ad7fa6ce78e562e71eTimo Sirainenstatic void imap_client_notify_auth_ready(struct client *client)
2d01cc1880cf2afd4fb1c8ad7fa6ce78e562e71eTimo Sirainen{
2d01cc1880cf2afd4fb1c8ad7fa6ce78e562e71eTimo Sirainen string_t *greet;
2d01cc1880cf2afd4fb1c8ad7fa6ce78e562e71eTimo Sirainen
2d01cc1880cf2afd4fb1c8ad7fa6ce78e562e71eTimo Sirainen greet = t_str_new(128);
e2d268e9531227ead6a98466ecf3c046c857ef70Timo Sirainen str_append(greet, "* OK ");
e2d268e9531227ead6a98466ecf3c046c857ef70Timo Sirainen str_printfa(greet, "[CAPABILITY %s] ", get_capability(client));
e2d268e9531227ead6a98466ecf3c046c857ef70Timo Sirainen str_append(greet, client->set->login_greeting);
e2d268e9531227ead6a98466ecf3c046c857ef70Timo Sirainen str_append(greet, "\r\n");
e2d268e9531227ead6a98466ecf3c046c857ef70Timo Sirainen
e2d268e9531227ead6a98466ecf3c046c857ef70Timo Sirainen client_send_raw(client, str_c(greet));
e2d268e9531227ead6a98466ecf3c046c857ef70Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic void imap_client_starttls(struct client *client)
194603b35061fea1ee8d171a7104b6985c610966Timo Sirainen{
d1fbd2c264368d8b4c7139b96e3b21f45930b857Timo Sirainen struct imap_client *imap_client = (struct imap_client *)client;
194603b35061fea1ee8d171a7104b6985c610966Timo Sirainen
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainen imap_parser_unref(&imap_client->parser);
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainen imap_client->parser =
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainen imap_parser_create(imap_client->common.input,
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainen imap_client->common.output, MAX_IMAP_LINE);
cd83124e5d070a016c590bb0b1096d7828c7b6adTimo Sirainen
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen /* CRLF is lost from buffer when streams are reopened. */
cd83124e5d070a016c590bb0b1096d7828c7b6adTimo Sirainen imap_client->skip_line = FALSE;
cd83124e5d070a016c590bb0b1096d7828c7b6adTimo Sirainen}
cd83124e5d070a016c590bb0b1096d7828c7b6adTimo Sirainen
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainenstatic void ATTR_NULL(3)
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainenclient_send_reply_raw(struct client *client,
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen const char *prefix, const char *resp_code,
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen const char *text, bool tagged)
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainen{
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainen struct imap_client *imap_client = (struct imap_client *)client;
c04f9a724a7b3cc649485a61b0a540868d25d71bTimo Sirainen
96308127e006bb3b1108093bcf4cc1fd9481cb7aTimo Sirainen T_BEGIN {
4ee00532a265bdfb38539d811fcd12d51210ac35Timo Sirainen string_t *line = t_str_new(256);
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen
2b9dbb270ad82e58d5f3581436e6f143176d5819Timo Sirainen if (tagged)
2b9dbb270ad82e58d5f3581436e6f143176d5819Timo Sirainen str_append(line, imap_client->cmd_tag);
2b9dbb270ad82e58d5f3581436e6f143176d5819Timo Sirainen else
eb0816090cf5a549280ad783b9aa6fec199d36baTimo Sirainen str_append_c(line, '*');
e2d268e9531227ead6a98466ecf3c046c857ef70Timo Sirainen str_append_c(line, ' ');
e2d268e9531227ead6a98466ecf3c046c857ef70Timo Sirainen str_append(line, prefix);
e2d268e9531227ead6a98466ecf3c046c857ef70Timo Sirainen str_append_c(line, ' ');
e2d268e9531227ead6a98466ecf3c046c857ef70Timo Sirainen if (resp_code != NULL)
e2d268e9531227ead6a98466ecf3c046c857ef70Timo Sirainen str_printfa(line, "[%s] ", resp_code);
1eaaa2c9003cf3fbf672d597473e3f84e70d2ee6Timo Sirainen str_append(line, text);
1eaaa2c9003cf3fbf672d597473e3f84e70d2ee6Timo Sirainen str_append(line, "\r\n");
2d01cc1880cf2afd4fb1c8ad7fa6ce78e562e71eTimo Sirainen
1eaaa2c9003cf3fbf672d597473e3f84e70d2ee6Timo Sirainen client_send_raw_data(client, str_data(line), str_len(line));
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen } T_END;
900bb5e316d030cdebff7ee128ce65881dfb27f7Timo Sirainen}
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainenvoid client_send_reply_code(struct client *client, enum imap_cmd_reply reply,
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen const char *resp_code, const char *text)
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen{
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen const char *prefix = "NO";
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen bool tagged = TRUE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen switch (reply) {
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen case IMAP_CMD_REPLY_OK:
e63bdfedcf61e1a9ee21990140cbd0d0638da7e1Timo Sirainen prefix = "OK";
c4b376dd6e0c423006d7ac83a39253bcaf8e7c47Timo Sirainen break;
e63bdfedcf61e1a9ee21990140cbd0d0638da7e1Timo Sirainen case IMAP_CMD_REPLY_NO:
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen break;
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen case IMAP_CMD_REPLY_BAD:
d9076f5939edf5d20a261494b1a861dcbb0d32e2Timo Sirainen prefix = "BAD";
e63bdfedcf61e1a9ee21990140cbd0d0638da7e1Timo Sirainen break;
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen case IMAP_CMD_REPLY_BYE:
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen prefix = "BYE";
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen tagged = FALSE;
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen break;
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen }
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen client_send_reply_raw(client, prefix, resp_code, text, tagged);
4ee00532a265bdfb38539d811fcd12d51210ac35Timo Sirainen}
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen
a3ee5ce6ecc8e228ee69300fdd562d7ac8be89a7Timo Sirainenvoid client_send_reply(struct client *client, enum imap_cmd_reply reply,
f4616f1875297fb2f583d913c0f01b075bdecd5bTimo Sirainen const char *text)
f4616f1875297fb2f583d913c0f01b075bdecd5bTimo Sirainen{
4ee00532a265bdfb38539d811fcd12d51210ac35Timo Sirainen client_send_reply_code(client, reply, NULL, text);
4321f6c969e7b8f6b243ff5bb6b8d297921676f6Timo Sirainen}
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainenstatic void
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenimap_client_notify_status(struct client *client, bool bad, const char *text)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
99695d99930b35c2bac85d52e976b44cf8485d83Timo Sirainen if (bad)
e3aeeb634245e80d4f643f8d2eea11d6b72336d8Timo Sirainen client_send_reply_raw(client, "BAD", "ALERT", text, FALSE);
e2d268e9531227ead6a98466ecf3c046c857ef70Timo Sirainen else
e3aeeb634245e80d4f643f8d2eea11d6b72336d8Timo Sirainen client_send_reply_raw(client, "OK", NULL, text, FALSE);
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen}
e3aeeb634245e80d4f643f8d2eea11d6b72336d8Timo Sirainen
0cce885512b836ce021260a58e7b4f099b36d0f1Timo Sirainenstatic void
e3aeeb634245e80d4f643f8d2eea11d6b72336d8Timo Sirainenimap_client_notify_disconnect(struct client *client,
e3aeeb634245e80d4f643f8d2eea11d6b72336d8Timo Sirainen enum client_disconnect_reason reason,
61cae213dc69070c1cef266578057710e34e0d12Timo Sirainen const char *text)
0cce885512b836ce021260a58e7b4f099b36d0f1Timo Sirainen{
9617ac7078a17bd346fed69526861c3e7fd9d809Timo Sirainen if (reason == CLIENT_DISCONNECT_INTERNAL_ERROR) {
4d527c363482be2b65dd0573d878ecda86cbb0bbTimo Sirainen client_send_reply_code(client, IMAP_CMD_REPLY_BYE,
99695d99930b35c2bac85d52e976b44cf8485d83Timo Sirainen IMAP_RESP_CODE_UNAVAILABLE, text);
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen } else {
99695d99930b35c2bac85d52e976b44cf8485d83Timo Sirainen client_send_reply_code(client, IMAP_CMD_REPLY_BYE, NULL, text);
99695d99930b35c2bac85d52e976b44cf8485d83Timo Sirainen }
99695d99930b35c2bac85d52e976b44cf8485d83Timo Sirainen}
99695d99930b35c2bac85d52e976b44cf8485d83Timo Sirainen
99695d99930b35c2bac85d52e976b44cf8485d83Timo Sirainenstatic void imap_login_preinit(void)
d0d37a769d7e54646de025a43d2cb888478cb218Timo Sirainen{
d0d37a769d7e54646de025a43d2cb888478cb218Timo Sirainen login_set_roots = imap_login_setting_roots;
d0d37a769d7e54646de025a43d2cb888478cb218Timo Sirainen}
d0d37a769d7e54646de025a43d2cb888478cb218Timo Sirainen
99695d99930b35c2bac85d52e976b44cf8485d83Timo Sirainenstatic void imap_login_init(void)
99695d99930b35c2bac85d52e976b44cf8485d83Timo Sirainen{
99695d99930b35c2bac85d52e976b44cf8485d83Timo Sirainen}
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen
b62140c5849297a800fee942026d9c3cb8c60206Timo Sirainenstatic void imap_login_deinit(void)
b62140c5849297a800fee942026d9c3cb8c60206Timo Sirainen{
b62140c5849297a800fee942026d9c3cb8c60206Timo Sirainen clients_destroy_all();
b62140c5849297a800fee942026d9c3cb8c60206Timo Sirainen}
b09eaeb9a81e5b58c6e605eb762573a2b4a69e0eTimo Sirainen
b09eaeb9a81e5b58c6e605eb762573a2b4a69e0eTimo Sirainenstatic struct client_vfuncs imap_client_vfuncs = {
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen imap_client_alloc,
ba8ff75a149d6936f769a2d1dfceaab9da87863bTimo Sirainen imap_client_create,
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen imap_client_destroy,
05150df8fbda6b8fdfafcfb0aa9003f1da4ecacaTimo Sirainen imap_client_notify_auth_ready,
05150df8fbda6b8fdfafcfb0aa9003f1da4ecacaTimo Sirainen imap_client_notify_disconnect,
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen imap_client_notify_status,
05150df8fbda6b8fdfafcfb0aa9003f1da4ecacaTimo Sirainen imap_client_notify_starttls,
05150df8fbda6b8fdfafcfb0aa9003f1da4ecacaTimo Sirainen imap_client_starttls,
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen imap_client_input,
05150df8fbda6b8fdfafcfb0aa9003f1da4ecacaTimo Sirainen NULL,
05150df8fbda6b8fdfafcfb0aa9003f1da4ecacaTimo Sirainen NULL,
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen imap_client_auth_result,
05150df8fbda6b8fdfafcfb0aa9003f1da4ecacaTimo Sirainen imap_proxy_reset,
05150df8fbda6b8fdfafcfb0aa9003f1da4ecacaTimo Sirainen imap_proxy_parse_line,
05150df8fbda6b8fdfafcfb0aa9003f1da4ecacaTimo Sirainen imap_proxy_error
897368f75a68f97e172ba76540759a10c557f1c3Timo Sirainen};
897368f75a68f97e172ba76540759a10c557f1c3Timo Sirainen
a423d985ba7261661475811c22b21b80ec765a71Timo Sirainenstatic const struct login_binary imap_login_binary = {
a423d985ba7261661475811c22b21b80ec765a71Timo Sirainen .protocol = "imap",
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen .process_name = "imap-login",
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen .default_port = 143,
64b61cd24d630223478ccbe1934b9f60f0881f59Timo Sirainen .default_ssl_port = 993,
4906f652013f9f9ea806602b5cd677ef0d039d62Timo Sirainen
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen .client_vfuncs = &imap_client_vfuncs,
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen .preinit = imap_login_preinit,
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen .init = imap_login_init,
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen .deinit = imap_login_deinit,
a4f09749814b93e8ad3ec8a0dc18885b874d6f8cTimo Sirainen
de58be41126e5d68008d2ea706d62ccdc1f29337Timo Sirainen .sasl_support_final_reply = FALSE
a4f09749814b93e8ad3ec8a0dc18885b874d6f8cTimo Sirainen};
a4f09749814b93e8ad3ec8a0dc18885b874d6f8cTimo Sirainen
a4f09749814b93e8ad3ec8a0dc18885b874d6f8cTimo Sirainenint main(int argc, char *argv[])
a4f09749814b93e8ad3ec8a0dc18885b874d6f8cTimo Sirainen{
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen return login_binary_run(&imap_login_binary, argc, argv);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen}
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen