pop3c-client.c revision 7a88e726e7300fb0273cb4e55b43c27fbd90bdbd
/* Copyright (c) 2011-2014 Dovecot authors, see the included COPYING file */
#include "lib.h"
#include "ioloop.h"
#include "net.h"
#include "istream.h"
#include "istream-dot.h"
#include "istream-seekable.h"
#include "ostream.h"
#include "iostream-rawlog.h"
#include "iostream-ssl.h"
#include "safe-mkstemp.h"
#include "base64.h"
#include "str.h"
#include "dns-lookup.h"
#include "pop3c-client.h"
#include <unistd.h>
enum pop3c_client_state {
/* No connection */
/* Trying to connect */
/* Connected, trying to authenticate */
/* Post-authentication, asking for capabilities */
/* Authenticated, ready to accept commands */
};
struct pop3c_client {
struct pop3c_client_settings set;
struct ssl_iostream_context *ssl_ctx;
int fd;
struct ssl_iostream *ssl_iostream;
struct dns_lookup *dns_lookup;
enum pop3c_client_state state;
enum pop3c_capability capabilities;
void *login_context;
unsigned int async_commands;
const char *input_line;
unsigned int running:1;
};
static void
struct pop3c_client *client);
struct pop3c_client *
{
struct pop3c_client *client;
struct ssl_iostream_settings ssl_set;
const char *error;
&error) < 0) {
i_error("pop3c(%s:%u): Couldn't initialize SSL context: %s",
}
}
return client;
}
static void
{
}
}
{
client->async_commands = 0;
i_error("close(pop3c) failed: %m");
}
"Disconnected");
}
{
}
{
}
{
i_error("pop3c(%s): connect(%s, %u) timed out after %u seconds",
break;
case POP3C_CLIENT_STATE_DONE:
i_error("pop3c(%s): Command timed out after %u seconds",
break;
default:
i_error("pop3c(%s): Authentication timed out after %u seconds",
break;
}
}
{
struct dns_lookup_settings dns_set;
unsigned int ips_count;
int ret;
if (ret != 0) {
i_error("pop3c(%s): net_gethostbyname() failed: %s",
return -1;
}
} else {
&client->dns_lookup) < 0)
return -1;
}
return 0;
}
{
ioloop = io_loop_create();
/* we're connecting, start DNS lookup after our ioloop
is created */
if (pop3c_client_dns_lookup(client) < 0)
}
if (!failed) {
}
}
{
i_debug("pop3c(%s): Authenticating as %s",
} else {
i_debug("pop3c(%s): Authenticating as %s for user %s",
}
}
} else {
}
}
static const char *
{
} else {
}
}
{
}
static int
{
const char *reply;
if (!success) {
i_error("pop3c(%s): Server sent invalid banner: %s",
return -1;
}
break;
case POP3C_CLIENT_STATE_USER:
if (!success) {
i_error("pop3c(%s): USER failed: %s",
return -1;
}
break;
case POP3C_CLIENT_STATE_AUTH:
if (line[0] != '+') {
i_error("pop3c(%s): AUTH PLAIN failed: %s",
return -1;
}
break;
case POP3C_CLIENT_STATE_PASS:
line;
} else if (!success) {
i_error("pop3c(%s): Authentication failed: %s",
}
if (!success)
return -1;
break;
case POP3C_CLIENT_STATE_CAPA:
/* CAPA command not supported. some commands still
support UIDL though. */
break;
break;
}
break;
case POP3C_CLIENT_STATE_DONE:
i_unreached();
}
return 0;
}
{
/* we need to read as much as we can with SSL streams to avoid
hanging */
return;
}
}
/* disconnected */
i_error("pop3c(%s): Server disconnected unexpectedly",
} else {
}
i_error("pop3c(%s): Server disconnected: %s",
}
}
}
{
const char *error;
i_debug("pop3c(%s): SSL handshake successful",
}
return 0;
i_debug("pop3c(%s): SSL handshake successful, "
"ignoring invalid certificate: %s",
}
return 0;
} else {
return -1;
}
}
{
struct ssl_iostream_settings ssl_set;
const char *error;
return -1;
}
}
/* recreate rawlog after STARTTLS */
}
i_error("pop3c(%s): Couldn't initialize SSL client: %s",
return -1;
}
client);
return -1;
}
}
return 0;
}
{
int err;
if (err != 0) {
i_error("pop3c(%s): connect(%s, %u) failed: %s",
return;
}
if (pop3c_client_ssl_init(client) < 0)
}
}
{
return;
}
}
}
}
static void
struct pop3c_client *client)
{
i_error("pop3c(%s): dns_lookup() failed: %s",
return;
}
}
{
return;
}
}
{
}
enum pop3c_capability
{
return client->capabilities;
}
{
/* disconnected */
i_error("pop3c(%s): Server disconnected unexpectedly",
}
}
static int
{
*error_r = "Disconnected";
return -1;
}
return 0;
}
static int
{
const char *line;
*error_r = "Disconnected";
return -1;
}
while (client->async_commands > 0) {
return -1;
client->async_commands--;
}
return 0;
}
const char **reply_r)
{
const char *line;
int ret;
return -1;
return -1;
ret = 0;
ret = -1;
} else {
ret = -1;
}
if (**reply_r == ' ')
*reply_r += 1;
return ret;
}
{
const char *error;
return;
}
return;
}
client->async_commands++;
}
{
int fd;
if (fd == -1) {
return -1;
}
/* we just want the fd, unlink it */
/* shouldn't happen.. */
i_close_fd(&fd);
return -1;
}
return fd;
}
{
}
if (ret != 0) {
i_error("pop3c(%s): Server disconnected unexpectedly",
}
}
}
{
/* read the +OK / -ERR */
return -1;
/* read the stream */
i_stream_unref(&inputs[0]);
/* read any pending data from the stream */
*error_r = "Disconnected";
return -1;
}
/* if this stream is used by some filter stream, make the filter
stream blocking */
return 0;
}