client.c revision 5a580c3a38ced62d4bcc95b8ac7c4f2935b5d294
/* Copyright (c) 2002-2013 Dovecot authors, see the included COPYING file */
#include "login-common.h"
#include "buffer.h"
#include "ioloop.h"
#include "istream.h"
#include "ostream.h"
#include "safe-memset.h"
#include "str.h"
#include "strescape.h"
#include "imap-parser.h"
#include "imap-id.h"
#include "imap-resp-code.h"
#include "master-service.h"
#include "master-auth.h"
#include "client.h"
#include "client-authenticate.h"
#include "auth-client.h"
#include "ssl-proxy.h"
#include "imap-proxy.h"
#include "imap-login-settings.h"
#include <stdlib.h>
/* maximum length for IMAP command line. */
#define MAX_IMAP_LINE 8192
/* Disconnect client when it sends too many bad commands */
#define CLIENT_MAX_BAD_COMMANDS 3
/* Skip incoming data until newline is found,
returns TRUE if newline was found. */
{
const unsigned char *data;
for (i = 0; i < data_size; i++) {
if (data[i] == '\n') {
return TRUE;
}
}
return FALSE;
}
{
else {
}
}
{
/* Client is required to send CAPABILITY after STARTTLS, so the
capability resp-code workaround checks only pre-STARTTLS
CAPABILITY commands. */
"Pre-login capabilities listed, post-login capabilities have more.");
return 1;
}
{
return 1;
}
static void
{
if (success)
else
}
static void
{
return;
}
args += 2;
}
}
{
const char *value;
}
}
t_strdup_printf("* ID %s\r\n",
return 1;
}
{
"NOOP completed.");
return 1;
}
{
"Logout completed.");
return 1;
}
{
"ENABLE ignored in non-authenticated state.");
return 1;
}
{
return cmd_capability(client);
return cmd_starttls(client);
return cmd_logout(client);
return cmd_enable(client);
return -2;
}
static bool imap_is_valid_tag(const char *tag)
{
switch (*tag) {
case '+':
/* atom-specials: */
case '(':
case ')':
case '{':
case '/':
case ' ':
/* list-wildcards: */
case '%':
case '*':
/* quoted-specials: */
case '"':
case '\\':
return FALSE;
default:
return FALSE;
break;
}
}
return TRUE;
}
{
const char *msg;
bool fatal;
case -1:
/* error */
if (fatal) {
return FALSE;
}
return -1;
case -2:
/* not enough data */
return 0;
default:
/* we read the entire line - skip over the CRLF */
if (!client_skip_line(client))
i_unreached();
return 1;
}
}
{
bool parsed;
int ret;
if (client->cmd_finished) {
/* clear the previous command from memory. don't do this
immediately after handling command since we need the
cmd_tag to stay some time after authentication commands. */
/* remove \r\n */
if (!client_skip_line(client))
return FALSE;
}
}
return FALSE; /* need more data */
/* the tag is invalid, don't allow it and don't
send it back. this attempts to prevent any
potentially dangerous replies in case someone tries
to access us using HTTP protocol. */
}
}
return FALSE; /* need more data */
}
/* SASL-IR may need more space than input buffer's size,
so we'll handle it as a special case. */
return FALSE;
} else {
if (ret < 0)
return TRUE;
if (ret == 0)
return FALSE;
}
"First parameter in line is IMAP's command tag, "
"not the command name. Add that before the command, "
"like: a login user pass");
} else if (ret < 0) {
"Too many invalid IMAP commands.");
"Disconnected: Too many invalid commands");
return FALSE;
}
"Error in IMAP command received by server.");
}
}
{
if (!client_read(client))
return;
for (;;) {
if (!auth_client_is_connected(auth_client)) {
/* we're not currently connected to auth process -
don't allow any commands */
break;
} else {
if (!client_handle_input(imap_client))
break;
}
}
}
{
struct imap_client *imap_client;
return &imap_client->common;
}
{
}
{
}
{
}
{
/* CRLF is lost from buffer when streams are reopened. */
}
static void ATTR_NULL(3)
{
T_BEGIN {
if (tagged)
else
} T_END;
}
{
const char *prefix = "NO";
switch (reply) {
case IMAP_CMD_REPLY_OK:
prefix = "OK";
break;
case IMAP_CMD_REPLY_NO:
break;
case IMAP_CMD_REPLY_BAD:
prefix = "BAD";
break;
case IMAP_CMD_REPLY_BYE:
prefix = "BYE";
break;
}
}
const char *text)
{
}
static void
{
if (bad)
else
}
static void
const char *text)
{
if (reason == CLIENT_DISCONNECT_INTERNAL_ERROR) {
} else {
}
}
static void imap_login_preinit(void)
{
}
static void imap_login_init(void)
{
}
static void imap_login_deinit(void)
{
}
static struct client_vfuncs imap_client_vfuncs = {
NULL,
NULL,
};
static const struct login_binary imap_login_binary = {
.protocol = "imap",
.process_name = "imap-login",
.default_port = 143,
.default_ssl_port = 993,
.init = imap_login_init,
};
{
}