server-connection.c revision 1b7459fda7de40f963e64da1886af68ad05fd10d
/* Copyright (c) 2010-2017 Dovecot authors, see the included COPYING file */
#include "lib.h"
#include "array.h"
#include "base64.h"
#include "ioloop.h"
#include "net.h"
#include "istream.h"
#include "istream-multiplex.h"
#include "ostream.h"
#include "ostream-dot.h"
#include "str.h"
#include "strescape.h"
#include "iostream-ssl.h"
#include "master-service.h"
#include "master-service-settings.h"
#include "settings-parser.h"
#include "doveadm.h"
#include "doveadm-print.h"
#include "doveadm-util.h"
#include "doveadm-server.h"
#include "doveadm-settings.h"
#include "server-connection.h"
#include <sysexits.h>
#include <unistd.h>
#define DOVEADM_LOG_CHANNEL_ID 'L'
enum server_reply_state {
};
struct server_connection {
struct doveadm_server *server;
struct doveadm_settings *set;
int fd;
unsigned int minor;
struct ssl_iostream *ssl_iostream;
struct ostream *cmd_output;
const char *delayed_cmd;
void *context;
enum server_reply_state state;
bool handshaked:1;
bool authenticated:1;
bool streaming:1;
};
{
struct doveadm_server *const *serverp;
return;
}
}
{
struct server_connection *const *conns;
unsigned int i, count;
for (i = 0; i < count; i++) {
continue;
server_connection_input, conns[i]);
server_connection_input, conns[i]);
}
}
static void print_connection_released(void)
{
struct doveadm_server *const *serverp;
return;
}
{
int ret = -1;
/* ostream-dot writes only up to max buffer size, so keep it non-zero */
switch (res) {
break;
return 1;
return 0;
i_error("read(%s) failed: %s",
break;
i_error("write(%s) failed: %s",
break;
}
if (res == OSTREAM_SEND_ISTREAM_RESULT_FINISHED) {
return 0;
else if (ret < 0) {
i_error("write(%s) failed: %s",
}
}
return ret;
}
{
return;
}
{
int ret;
if (ret < 0)
return ret;
}
static void
{
}
{
str_truncate(str, 0);
}
{
if (size > 0)
doveadm_print_stream("", 0);
} else {
str_truncate(str, 0);
}
}
static void
{
if (printing_conn == conn) {
/* continue printing */
} else if (printing_conn == NULL) {
} else {
/* someone else is printing. don't continue until it
goes away */
return;
}
/* last character is an escape */
size--;
}
if (data[i] == '\n') {
if (i != start) {
i_error("doveadm server sent broken print input");
return;
}
return;
}
if (data[i] == '\t') {
start = i + 1;
}
}
}
}
{
}
}
static int
{
i_error("doveadm_password not set, "
"can't authenticate to remote server");
return -1;
}
return 0;
}
{
const char *error;
}
}
{
const char *line;
struct failure_context ctx;
/* skip empty lines */
if (*line == '\0') continue;
i_warning("Doveadm server sent invalid log type 0x%02x",
line[0]);
line++;
}
}
{
i_stream_unref(&is);
}
{
const char *line;
i_error("doveadm server not compatible with this client"
"(mixed old and new binaries?)");
return;
}
continue;
}
break;
if (!conn->handshaked &&
server_connection_authenticate(conn) < 0) {
return;
} else if (conn->handshaked) {
i_error("doveadm authentication failed (%s)",
line+1);
return;
}
} else {
i_error("doveadm server sent invalid handshake: %s",
line);
return;
}
}
}
}
return;
}
/* disconnected */
return;
}
while (server_connection_input_one(conn)) ;
}
{
const unsigned char *data;
const char *line;
int exit_code;
if (size == 0)
return FALSE;
/* check logs */
(void)server_connection_print_log(conn);
case SERVER_REPLY_STATE_DONE:
i_error("doveadm server sent unexpected input");
return FALSE;
case SERVER_REPLY_STATE_PRINT:
return FALSE;
/* fall through */
case SERVER_REPLY_STATE_RET:
return FALSE;
if (line[0] == '+')
else if (line[0] == '-') {
line++;
if (exit_code == DOVEADM_EX_UNKNOWN &&
/* old doveadm-server */
}
} else {
i_error("doveadm server sent broken input "
"(expected cmd reply): %s", line);
return FALSE;
}
/* we're finished, close the connection */
return FALSE;
}
return TRUE;
}
i_unreached();
}
{
const struct setting_parser_info *set_roots[] = {
};
struct master_service_settings_input input;
struct master_service_settings_output output;
const char *error;
void *set;
return -1;
}
return 0;
}
{
error_r) < 0)
return -1;
if (doveadm_debug)
return 0;
}
{
struct ssl_iostream_settings ssl_set;
const char *error;
return 0;
return -1;
}
conn);
i_error("SSL handshake failed: %s",
return -1;
}
return 0;
}
struct server_connection **conn_r)
{
struct server_connection *conn;
if (server_connection_read_settings(conn) < 0 ||
server_connection_init_ssl(conn) < 0) {
return -1;
}
return 0;
}
{
struct server_connection *const *conns;
const char *error;
unsigned int i, count;
for (i = 0; i < count; i++) {
break;
}
}
}
error);
}
if (printing_conn == conn)
/* close cmd_output after its parent, so the "." isn't sent */
/* make sure all logs got consumed */
}
struct doveadm_server *
{
}
{
}
if (!conn->authenticated)
else {
}
}
{
}
struct ssl_iostream **ssl_iostream_r)
{
}