bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2013-2018 Dovecot authors, see the included COPYING file */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch#include "lib.h"
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch#include "llist.h"
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch#include "str.h"
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch#include "str-sanitize.h"
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch#include "strescape.h"
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch#include "ioloop.h"
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch#include "safe-mkstemp.h"
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch#include "hostpid.h"
bdd36cfdba3ff66d25570a9ff568d69e1eb543cfTimo Sirainen#include "net.h"
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch#include "istream.h"
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch#include "ostream.h"
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch#include "write-full.h"
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch#include "array.h"
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch#include "aqueue.h"
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch#include "mail-user.h"
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch#include "imap-urlauth-fetch.h"
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch#include "imap-urlauth-connection.h"
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschenum imap_urlauth_state {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch IMAP_URLAUTH_STATE_DISCONNECTED = 0,
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch IMAP_URLAUTH_STATE_AUTHENTICATING,
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch IMAP_URLAUTH_STATE_AUTHENTICATED,
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch IMAP_URLAUTH_STATE_SELECTING_TARGET,
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch IMAP_URLAUTH_STATE_UNSELECTING_TARGET,
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch IMAP_URLAUTH_STATE_READY,
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch IMAP_URLAUTH_STATE_REQUEST_PENDING,
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch IMAP_URLAUTH_STATE_REQUEST_WAIT,
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch};
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstruct imap_urlauth_request {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch struct imap_urlauth_target *target;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch struct imap_urlauth_request *prev, *next;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch char *url;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch enum imap_urlauth_fetch_flags flags;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch char *bodypartstruct;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch imap_urlauth_request_callback_t *callback;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch void *context;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
d9a7e950a9cd21f2b4a90ec7759fca9e8fcc7995Timo Sirainen bool binary_has_nuls;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch};
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstruct imap_urlauth_target {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch struct imap_urlauth_target *prev, *next;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch char *userid;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch struct imap_urlauth_request *requests_head, *requests_tail;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch};
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstruct imap_urlauth_connection {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch int refcount;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f1edf7f20661ef9627acbf4054acddcba4d2eb3fStephan Bosch char *path, *service, *session_id;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch struct mail_user *user;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch int fd;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch struct istream *input;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch struct ostream *output;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch struct io *io;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch struct timeout *to_reconnect, *to_idle, *to_response;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch time_t last_reconnect;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch unsigned int reconnect_attempts;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch unsigned int idle_timeout_msecs;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch char *literal_temp_path;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch int literal_fd;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch buffer_t *literal_buf;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch uoff_t literal_size, literal_bytes_left;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch enum imap_urlauth_state state;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* userid => target struct */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch struct imap_urlauth_target *targets_head, *targets_tail;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen bool reading_literal:1;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch};
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch#define IMAP_URLAUTH_RECONNECT_MIN_SECS 2
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch#define IMAP_URLAUTH_RECONNECT_MAX_ATTEMPTS 3
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch#define IMAP_URLAUTH_RESPONSE_TIMEOUT_MSECS 2*60*1000
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f1edf7f20661ef9627acbf4054acddcba4d2eb3fStephan Bosch#define IMAP_URLAUTH_HANDSHAKE "VERSION\timap-urlauth\t2\t0\n"
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch#define IMAP_URLAUTH_MAX_INLINE_LITERAL_SIZE (1024*32)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstatic void imap_urlauth_connection_disconnect
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch (struct imap_urlauth_connection *conn, const char *reason);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstatic void imap_urlauth_connection_abort
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch (struct imap_urlauth_connection *conn, const char *reason);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstatic void imap_urlauth_connection_reconnect
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch (struct imap_urlauth_connection *conn);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstatic void imap_urlauth_connection_idle_disconnect
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch (struct imap_urlauth_connection *conn);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstatic void imap_urlauth_connection_timeout_abort
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch (struct imap_urlauth_connection *conn);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstatic void imap_urlauth_connection_fail
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch (struct imap_urlauth_connection *conn);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstruct imap_urlauth_connection *
f1edf7f20661ef9627acbf4054acddcba4d2eb3fStephan Boschimap_urlauth_connection_init(const char *path, const char *service,
f1edf7f20661ef9627acbf4054acddcba4d2eb3fStephan Bosch struct mail_user *user, const char *session_id,
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch unsigned int idle_timeout_msecs)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch{
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch struct imap_urlauth_connection *conn;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch conn = i_new(struct imap_urlauth_connection, 1);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch conn->refcount = 1;
f1edf7f20661ef9627acbf4054acddcba4d2eb3fStephan Bosch conn->service = i_strdup(service);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch conn->path = i_strdup(path);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (session_id != NULL)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch conn->session_id = i_strdup(session_id);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch conn->user = user;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch conn->fd = -1;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch conn->literal_fd = -1;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch conn->idle_timeout_msecs = idle_timeout_msecs;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return conn;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch}
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschvoid imap_urlauth_connection_deinit(struct imap_urlauth_connection **_conn)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch{
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch struct imap_urlauth_connection *conn = *_conn;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch *_conn = NULL;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch imap_urlauth_connection_abort(conn, NULL);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_free(conn->path);
f1edf7f20661ef9627acbf4054acddcba4d2eb3fStephan Bosch i_free(conn->service);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (conn->session_id != NULL)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_free(conn->session_id);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_assert(conn->to_idle == NULL);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_assert(conn->to_reconnect == NULL);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_assert(conn->to_response == NULL);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_free(conn);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch}
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstatic void
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschimap_urlauth_stop_response_timeout(struct imap_urlauth_connection *conn)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch{
0d1b8b6bec79746c5d89d57dd8c1688946bd9237Josef 'Jeff' Sipek timeout_remove(&conn->to_response);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch}
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstatic void
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschimap_urlauth_start_response_timeout(struct imap_urlauth_connection *conn)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch{
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch imap_urlauth_stop_response_timeout(conn);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch conn->to_response = timeout_add(IMAP_URLAUTH_RESPONSE_TIMEOUT_MSECS,
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch imap_urlauth_connection_timeout_abort, conn);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch}
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstatic struct imap_urlauth_target *
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschimap_urlauth_connection_get_target(struct imap_urlauth_connection *conn,
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch const char *target_user)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch{
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch struct imap_urlauth_target *target = conn->targets_head;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch while (target != NULL) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (strcmp(target->userid, target_user) == 0)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return target;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch target = target->next;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch target = i_new(struct imap_urlauth_target, 1);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch target->userid = i_strdup(target_user);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch DLLIST2_APPEND(&conn->targets_head, &conn->targets_tail, target);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return target;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch}
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstatic void
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschimap_urlauth_target_free(struct imap_urlauth_connection *conn,
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch struct imap_urlauth_target *target)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch{
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch DLLIST2_REMOVE(&conn->targets_head, &conn->targets_tail, target);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_free(target->userid);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_free(target);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch}
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstatic void
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschimap_urlauth_connection_select_target(struct imap_urlauth_connection *conn)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch{
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch struct imap_urlauth_target *target = conn->targets_head;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch const char *cmd;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (target == NULL || conn->state != IMAP_URLAUTH_STATE_AUTHENTICATED)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (conn->user->mail_debug)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_debug("imap-urlauth: Selecting target user `%s'", target->userid);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch conn->state = IMAP_URLAUTH_STATE_SELECTING_TARGET;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch cmd = t_strdup_printf("USER\t%s\n", str_tabescape(target->userid));
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (o_stream_send_str(conn->output, cmd) < 0) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_warning("Error sending USER request to imap-urlauth server: %m");
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch imap_urlauth_connection_fail(conn);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch imap_urlauth_start_response_timeout(conn);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch}
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstatic void
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschimap_urlauth_connection_send_request(struct imap_urlauth_connection *conn)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch{
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch struct imap_urlauth_request *urlreq;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch string_t *cmd;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (conn->targets_head == NULL ||
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch (conn->targets_head->requests_head == NULL &&
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch conn->targets_head->next == NULL &&
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch conn->state == IMAP_URLAUTH_STATE_READY)) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (conn->user->mail_debug)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_debug("imap-urlauth: No more requests pending; scheduling disconnect");
0d1b8b6bec79746c5d89d57dd8c1688946bd9237Josef 'Jeff' Sipek timeout_remove(&conn->to_idle);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (conn->idle_timeout_msecs > 0) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch conn->to_idle = timeout_add(conn->idle_timeout_msecs,
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch imap_urlauth_connection_idle_disconnect, conn);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (conn->state == IMAP_URLAUTH_STATE_AUTHENTICATED) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch imap_urlauth_connection_select_target(conn);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (conn->state != IMAP_URLAUTH_STATE_READY)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch urlreq = conn->targets_head->requests_head;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (urlreq == NULL) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (conn->targets_head->next == NULL)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch conn->state = IMAP_URLAUTH_STATE_UNSELECTING_TARGET;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch imap_urlauth_target_free(conn, conn->targets_head);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (o_stream_send_str(conn->output, "END\n") < 0) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_warning("Error sending END request to imap-urlauth server: %m");
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch imap_urlauth_connection_fail(conn);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch imap_urlauth_start_response_timeout(conn);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (conn->user->mail_debug)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_debug("imap-urlauth: Fetching URL `%s'", urlreq->url);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch cmd = t_str_new(128);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch str_append(cmd, "URL\t");
d03a871a77f8ec36f48f5fea98d810e51b186fdbTimo Sirainen str_append_tabescaped(cmd, urlreq->url);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if ((urlreq->flags & IMAP_URLAUTH_FETCH_FLAG_BODYPARTSTRUCTURE) != 0)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch str_append(cmd, "\tbpstruct");
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if ((urlreq->flags & IMAP_URLAUTH_FETCH_FLAG_BINARY) != 0)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch str_append(cmd, "\tbinary");
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch else if ((urlreq->flags & IMAP_URLAUTH_FETCH_FLAG_BODY) != 0)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch str_append(cmd, "\tbody");
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch str_append_c(cmd, '\n');
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch conn->state = IMAP_URLAUTH_STATE_REQUEST_PENDING;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (o_stream_send(conn->output, str_data(cmd), str_len(cmd)) < 0) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_warning("Error sending URL request to imap-urlauth server: %m");
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch imap_urlauth_connection_fail(conn);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch imap_urlauth_start_response_timeout(conn);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch}
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstruct imap_urlauth_request *
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschimap_urlauth_request_new(struct imap_urlauth_connection *conn,
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch const char *target_user, const char *url,
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch enum imap_urlauth_fetch_flags flags,
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch imap_urlauth_request_callback_t *callback,
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch void *context)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch{
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch struct imap_urlauth_request *urlreq;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch struct imap_urlauth_target *target;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch target = imap_urlauth_connection_get_target(conn, target_user);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch urlreq = i_new(struct imap_urlauth_request, 1);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch urlreq->url = i_strdup(url);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch urlreq->flags = flags;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch urlreq->target = target;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch urlreq->callback = callback;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch urlreq->context = context;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch DLLIST2_APPEND(&target->requests_head, &target->requests_tail, urlreq);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
0d1b8b6bec79746c5d89d57dd8c1688946bd9237Josef 'Jeff' Sipek timeout_remove(&conn->to_idle);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (conn->user->mail_debug) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_debug("imap-urlauth: Added request for URL `%s' from user `%s'",
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch url, target_user);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch imap_urlauth_connection_send_request(conn);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return urlreq;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch}
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstatic void imap_urlauth_request_free(struct imap_urlauth_request *urlreq)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch{
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch struct imap_urlauth_target *target = urlreq->target;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch DLLIST2_REMOVE(&target->requests_head, &target->requests_tail, urlreq);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_free(urlreq->url);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_free(urlreq->bodypartstruct);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_free(urlreq);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch}
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
7cf790002e2fc9c260776862123d7af67032ad61Stephan Boschstatic void imap_urlauth_request_drop(struct imap_urlauth_connection *conn,
7cf790002e2fc9c260776862123d7af67032ad61Stephan Bosch struct imap_urlauth_request *urlreq)
7cf790002e2fc9c260776862123d7af67032ad61Stephan Bosch{
7cf790002e2fc9c260776862123d7af67032ad61Stephan Bosch if ((conn->state == IMAP_URLAUTH_STATE_REQUEST_PENDING ||
7cf790002e2fc9c260776862123d7af67032ad61Stephan Bosch conn->state == IMAP_URLAUTH_STATE_REQUEST_WAIT) &&
7cf790002e2fc9c260776862123d7af67032ad61Stephan Bosch conn->targets_head != NULL &&
7cf790002e2fc9c260776862123d7af67032ad61Stephan Bosch conn->targets_head->requests_head == urlreq) {
7cf790002e2fc9c260776862123d7af67032ad61Stephan Bosch /* cannot just drop pending request without breaking
7cf790002e2fc9c260776862123d7af67032ad61Stephan Bosch protocol state */
7cf790002e2fc9c260776862123d7af67032ad61Stephan Bosch return;
7cf790002e2fc9c260776862123d7af67032ad61Stephan Bosch }
7cf790002e2fc9c260776862123d7af67032ad61Stephan Bosch imap_urlauth_request_free(urlreq);
7cf790002e2fc9c260776862123d7af67032ad61Stephan Bosch
7cf790002e2fc9c260776862123d7af67032ad61Stephan Bosch}
7cf790002e2fc9c260776862123d7af67032ad61Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschvoid imap_urlauth_request_abort(struct imap_urlauth_connection *conn,
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch struct imap_urlauth_request *urlreq)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch{
76e3f370791fc63e4c176432fe2e6b77f400f862Stephan Bosch imap_urlauth_request_callback_t *callback;
76e3f370791fc63e4c176432fe2e6b77f400f862Stephan Bosch
76e3f370791fc63e4c176432fe2e6b77f400f862Stephan Bosch callback = urlreq->callback;
76e3f370791fc63e4c176432fe2e6b77f400f862Stephan Bosch urlreq->callback = NULL;
76e3f370791fc63e4c176432fe2e6b77f400f862Stephan Bosch if (callback != NULL) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch T_BEGIN {
76e3f370791fc63e4c176432fe2e6b77f400f862Stephan Bosch callback(NULL, urlreq->context);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch } T_END;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
7cf790002e2fc9c260776862123d7af67032ad61Stephan Bosch imap_urlauth_request_drop(conn, urlreq);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch}
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstatic void
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschimap_urlauth_request_fail(struct imap_urlauth_connection *conn,
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch struct imap_urlauth_request *urlreq,
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch const char *error)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch{
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch struct imap_urlauth_fetch_reply reply;
76e3f370791fc63e4c176432fe2e6b77f400f862Stephan Bosch imap_urlauth_request_callback_t *callback;
7cf790002e2fc9c260776862123d7af67032ad61Stephan Bosch int ret = 1;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
76e3f370791fc63e4c176432fe2e6b77f400f862Stephan Bosch callback = urlreq->callback;
76e3f370791fc63e4c176432fe2e6b77f400f862Stephan Bosch urlreq->callback = NULL;
76e3f370791fc63e4c176432fe2e6b77f400f862Stephan Bosch if (callback != NULL) {
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch i_zero(&reply);
76e3f370791fc63e4c176432fe2e6b77f400f862Stephan Bosch reply.url = urlreq->url;
76e3f370791fc63e4c176432fe2e6b77f400f862Stephan Bosch reply.flags = urlreq->flags;
76e3f370791fc63e4c176432fe2e6b77f400f862Stephan Bosch reply.succeeded = FALSE;
76e3f370791fc63e4c176432fe2e6b77f400f862Stephan Bosch reply.error = error;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
76e3f370791fc63e4c176432fe2e6b77f400f862Stephan Bosch T_BEGIN {
7cf790002e2fc9c260776862123d7af67032ad61Stephan Bosch ret = callback(&reply, urlreq->context);
76e3f370791fc63e4c176432fe2e6b77f400f862Stephan Bosch } T_END;
76e3f370791fc63e4c176432fe2e6b77f400f862Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
b804e2b1744ef1616626dd7b8b8ff6cb83cfb2dfTimo Sirainen void *urlreq_context = urlreq->context;
7cf790002e2fc9c260776862123d7af67032ad61Stephan Bosch imap_urlauth_request_drop(conn, urlreq);
7cf790002e2fc9c260776862123d7af67032ad61Stephan Bosch
7cf790002e2fc9c260776862123d7af67032ad61Stephan Bosch if (ret < 0) {
7cf790002e2fc9c260776862123d7af67032ad61Stephan Bosch /* Drop any related requests upon error */
b804e2b1744ef1616626dd7b8b8ff6cb83cfb2dfTimo Sirainen imap_urlauth_request_abort_by_context(conn, urlreq_context);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
7cf790002e2fc9c260776862123d7af67032ad61Stephan Bosch if (ret != 0)
7cf790002e2fc9c260776862123d7af67032ad61Stephan Bosch imap_urlauth_connection_continue(conn);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch}
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstatic void
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschimap_urlauth_target_abort(struct imap_urlauth_connection *conn,
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch struct imap_urlauth_target *target)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch{
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch struct imap_urlauth_request *urlreq, *next;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch urlreq = target->requests_head;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch while (urlreq != NULL) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch next = urlreq->next;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch imap_urlauth_request_abort(conn, urlreq);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch urlreq = next;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch imap_urlauth_target_free(conn, target);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch}
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstatic void
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschimap_urlauth_target_fail(struct imap_urlauth_connection *conn,
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch struct imap_urlauth_target *target, const char *error)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch{
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch struct imap_urlauth_request *urlreq, *next;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch urlreq = target->requests_head;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch while (urlreq != NULL) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch next = urlreq->next;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch imap_urlauth_request_fail(conn, urlreq, error);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch urlreq = next;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch imap_urlauth_target_free(conn, target);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch}
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstatic void
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschimap_urlauth_target_abort_by_context(struct imap_urlauth_connection *conn,
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch struct imap_urlauth_target *target,
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch void *context)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch{
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch struct imap_urlauth_request *urlreq, *next;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* abort all matching requests */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch urlreq = target->requests_head;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch while (urlreq != NULL) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch next = urlreq->next;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (urlreq->context == context)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch imap_urlauth_request_abort(conn, urlreq);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch urlreq = next;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (target->requests_head == NULL)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch imap_urlauth_target_free(conn, target);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch}
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstatic void
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschimap_urlauth_connection_abort(struct imap_urlauth_connection *conn,
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch const char *reason)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch{
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch struct imap_urlauth_target *target, *next;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (reason == NULL)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch reason = "Aborting due to error";
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch imap_urlauth_connection_disconnect(conn, reason);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* abort all requests */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch target = conn->targets_head;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch while (target != NULL) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch next = target->next;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch imap_urlauth_target_abort(conn, target);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch target = next;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch}
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschvoid imap_urlauth_request_abort_by_context(struct imap_urlauth_connection *conn,
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch void *context)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch{
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch struct imap_urlauth_target *target, *next;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* abort all matching requests */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch target = conn->targets_head;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch while (target != NULL) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch next = target->next;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch imap_urlauth_target_abort_by_context(conn, target, context);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch target = next;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch}
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstatic void imap_urlauth_connection_fail(struct imap_urlauth_connection *conn)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch{
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (conn->reconnect_attempts > IMAP_URLAUTH_RECONNECT_MAX_ATTEMPTS) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch imap_urlauth_connection_abort(conn,
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch "Connection failed and connection attempts exhausted");
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch } else {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch imap_urlauth_connection_reconnect(conn);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch}
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstatic int
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschimap_urlauth_connection_create_temp_fd(struct imap_urlauth_connection *conn,
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch const char **path_r)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch{
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch string_t *path;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch int fd;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch path = t_str_new(128);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch mail_user_set_get_temp_prefix(path, conn->user->set);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch fd = safe_mkstemp(path, 0600, (uid_t)-1, (gid_t)-1);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (fd == -1) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_error("safe_mkstemp(%s) failed: %m", str_c(path));
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return -1;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* we just want the fd, unlink it */
46b823ac3bce2c0f9f0fc73911e48d3a77b04fbeTimo Sirainen if (i_unlink(str_c(path)) < 0) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* shouldn't happen.. */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_close_fd(&fd);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return -1;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch *path_r = str_c(path);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return fd;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch}
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstatic int
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschimap_urlauth_connection_read_literal_init(struct imap_urlauth_connection *conn,
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch uoff_t size)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch{
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch const char *path;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_assert(conn->literal_fd == -1 && conn->literal_buf == NULL);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (size <= IMAP_URLAUTH_MAX_INLINE_LITERAL_SIZE) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* read the literal directly */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (size > 0) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch conn->literal_buf =
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch buffer_create_dynamic(default_pool, size);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch } else {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* read it into a file */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch conn->literal_fd =
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch imap_urlauth_connection_create_temp_fd(conn, &path);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (conn->literal_fd == -1)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return -1;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch conn->literal_temp_path = i_strdup(path);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch conn->literal_size = size;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch conn->literal_bytes_left = size;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch conn->reading_literal = TRUE;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return 1;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch}
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschvoid imap_urlauth_connection_continue(struct imap_urlauth_connection *conn)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch{
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_assert(conn->targets_head != NULL);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_assert(conn->targets_head->requests_head != NULL);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (conn->state != IMAP_URLAUTH_STATE_REQUEST_WAIT)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch conn->state = IMAP_URLAUTH_STATE_READY;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch imap_urlauth_request_free(conn->targets_head->requests_head);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch imap_urlauth_connection_send_request(conn);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch}
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstatic int
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschimap_urlauth_connection_read_literal_data(struct imap_urlauth_connection *conn)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch{
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch const unsigned char *data;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch size_t size;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* read data */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch data = i_stream_get_data(conn->input, &size);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (size > conn->literal_bytes_left)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch size = conn->literal_bytes_left;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* write to buffer or file */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (size > 0) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (conn->literal_fd >= 0) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (write_full(conn->literal_fd, data, size) < 0) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_error("imap-urlauth: write(%s) failed: %m",
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch conn->literal_temp_path);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return -1;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch } else {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_assert(conn->literal_buf != NULL);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch buffer_append(conn->literal_buf, data, size);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_stream_skip(conn->input, size);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch conn->literal_bytes_left -= size;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* exit if not finished */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (conn->literal_bytes_left > 0)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return 0;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* read LF guard */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch data = i_stream_get_data(conn->input, &size);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (size < 1)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return 0;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* check LF guard */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (data[0] != '\n') {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_error("imap-urlauth: no LF at end of literal (found 0x%x)",
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch data[0]);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return -1;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_stream_skip(conn->input, 1);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return 1;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch}
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstatic void literal_stream_destroy(buffer_t *buffer)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch{
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch buffer_free(&buffer);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch}
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstatic int
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschimap_urlauth_fetch_reply_set_literal_stream(struct imap_urlauth_connection *conn,
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch struct imap_urlauth_fetch_reply *reply)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch{
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch const unsigned char *data;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch size_t size;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch uoff_t fd_size;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (conn->literal_fd != -1) {
bace943c67e6cd14ce6c994f533d82a3caad5bf1Timo Sirainen reply->input = i_stream_create_fd_autoclose(&conn->literal_fd,
bace943c67e6cd14ce6c994f533d82a3caad5bf1Timo Sirainen (size_t)-1);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (i_stream_get_size(reply->input, TRUE, &fd_size) < 1 ||
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch fd_size != conn->literal_size) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_stream_unref(&reply->input);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_error("imap-urlauth: Failed to obtain proper size from literal stream");
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch imap_urlauth_connection_abort(conn,
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch "Failed during literal transfer");
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return -1;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch } else {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch data = buffer_get_data(conn->literal_buf, &size);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_assert(size == conn->literal_size);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch reply->input = i_stream_create_from_data(data, size);
1a0ece3e873e3864269ed7eaed957dc10c56d25fTimo Sirainen i_stream_add_destroy_callback(reply->input,
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch literal_stream_destroy,
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch conn->literal_buf);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch reply->size = conn->literal_size;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return 0;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch}
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstatic int
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschimap_urlauth_connection_read_literal(struct imap_urlauth_connection *conn)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch{
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch struct imap_urlauth_request *urlreq = conn->targets_head->requests_head;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch struct imap_urlauth_fetch_reply reply;
76e3f370791fc63e4c176432fe2e6b77f400f862Stephan Bosch imap_urlauth_request_callback_t *callback;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch int ret;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_assert(conn->reading_literal);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_assert(urlreq != NULL);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (conn->literal_size > 0) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch ret = imap_urlauth_connection_read_literal_data(conn);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (ret <= 0)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return ret;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_assert(conn->literal_bytes_left == 0);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* reply */
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch i_zero(&reply);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch reply.url = urlreq->url;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch reply.flags = urlreq->flags;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch reply.bodypartstruct = urlreq->bodypartstruct;
f0339f522dc9c8e2e8a29ef9a3f937c431c6bd1bTimo Sirainen reply.binary_has_nuls = urlreq->binary_has_nuls ? 1 : 0;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (conn->literal_size > 0) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (imap_urlauth_fetch_reply_set_literal_stream(conn, &reply) < 0)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return -1;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch reply.succeeded = TRUE;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch ret = 1;
76e3f370791fc63e4c176432fe2e6b77f400f862Stephan Bosch callback = urlreq->callback;
76e3f370791fc63e4c176432fe2e6b77f400f862Stephan Bosch urlreq->callback = NULL;
76e3f370791fc63e4c176432fe2e6b77f400f862Stephan Bosch if (callback != NULL) T_BEGIN {
76e3f370791fc63e4c176432fe2e6b77f400f862Stephan Bosch ret = callback(&reply, urlreq->context);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch } T_END;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (reply.input != NULL)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_stream_unref(&reply.input);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (ret < 0) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* Drop any related requests upon error */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch imap_urlauth_request_abort_by_context(conn, urlreq->context);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch conn->state = IMAP_URLAUTH_STATE_REQUEST_WAIT;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (ret != 0)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch imap_urlauth_connection_continue(conn);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* finished */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_free_and_null(conn->literal_temp_path);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch conn->literal_fd = -1;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch conn->literal_buf = NULL;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch conn->reading_literal = FALSE;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return 1;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch}
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstatic int imap_urlauth_input_pending(struct imap_urlauth_connection *conn)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch{
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch struct imap_urlauth_request *urlreq;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch const char *response, *const *args, *bpstruct = NULL;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch uoff_t literal_size;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_assert(conn->targets_head != NULL);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_assert(conn->targets_head->requests_head != NULL);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch urlreq = conn->targets_head->requests_head;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (conn->reading_literal) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* Read pending literal; may callback */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return imap_urlauth_connection_read_literal(conn);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* "OK"[<metadata-items>]"\t"<literal-size>"\n" or
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch "NO"["\terror="<error>]"\n" */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if ((response = i_stream_next_line(conn->input)) == NULL)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return 0;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch imap_urlauth_stop_response_timeout(conn);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch args = t_strsplit_tabescaped(response);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (args[0] == NULL) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_error("imap-urlauth: Empty URL response: %s",
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch str_sanitize(response, 80));
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return -1;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (strcmp(args[0], "OK") != 0 || args[1] == NULL) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (strcmp(args[0], "NO") == 0) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch const char *param = args[1], *error = NULL;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (param != NULL &&
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch strncasecmp(param, "error=", 6) == 0 &&
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch param[6] != '\0') {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch error = param+6;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
7cf790002e2fc9c260776862123d7af67032ad61Stephan Bosch conn->state = IMAP_URLAUTH_STATE_REQUEST_WAIT;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch imap_urlauth_request_fail(conn,
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch conn->targets_head->requests_head, error);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return 1;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_error("imap-urlauth: Unexpected URL response: %s",
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch str_sanitize(response, 80));
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return -1;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* read metadata */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch args++;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch for (; args[1] != NULL; args++) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch const char *param = args[0];
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (strcasecmp(param, "hasnuls") == 0) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch urlreq->binary_has_nuls = TRUE;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch } else if (strncasecmp(param, "bpstruct=", 9) == 0 &&
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch param[9] != '\0') {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch bpstruct = param+9;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* read literal size */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (str_to_uoff(args[0], &literal_size) < 0) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_error("imap-urlauth: "
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch "Overflowing unsigned integer value for literal size: %s",
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch args[1]);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return -1;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* read literal */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (imap_urlauth_connection_read_literal_init(conn, literal_size) < 0)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return -1;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch urlreq->bodypartstruct = i_strdup(bpstruct);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return imap_urlauth_connection_read_literal(conn);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch}
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstatic int imap_urlauth_input_next(struct imap_urlauth_connection *conn)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch{
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch const char *response;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch int ret;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch switch (conn->state) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch case IMAP_URLAUTH_STATE_AUTHENTICATING:
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch case IMAP_URLAUTH_STATE_UNSELECTING_TARGET:
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if ((response = i_stream_next_line(conn->input)) == NULL)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return 0;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch imap_urlauth_stop_response_timeout(conn);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (strcasecmp(response, "OK") != 0) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (conn->state == IMAP_URLAUTH_STATE_AUTHENTICATING)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_error("imap-urlauth: Failed to authenticate to service: "
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch "Got unexpected response: %s", str_sanitize(response, 80));
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch else
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_error("imap-urlauth: Failed to unselect target user: "
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch "Got unexpected response: %s", str_sanitize(response, 80));
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch imap_urlauth_connection_abort(conn, NULL);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return -1;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (conn->user->mail_debug) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (conn->state == IMAP_URLAUTH_STATE_AUTHENTICATING)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_debug("imap-urlauth: Successfully authenticated to service");
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch else
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_debug("imap-urlauth: Successfully unselected target user");
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch conn->state = IMAP_URLAUTH_STATE_AUTHENTICATED;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch imap_urlauth_connection_select_target(conn);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return 0;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch case IMAP_URLAUTH_STATE_SELECTING_TARGET:
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if ((response = i_stream_next_line(conn->input)) == NULL)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return 0;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch imap_urlauth_stop_response_timeout(conn);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_assert(conn->targets_head != NULL);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (strcasecmp(response, "NO") == 0) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (conn->user->mail_debug) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_debug("imap-urlauth: Failed to select target user %s",
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch conn->targets_head->userid);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch imap_urlauth_target_fail(conn, conn->targets_head, NULL);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch conn->state = IMAP_URLAUTH_STATE_AUTHENTICATED;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch imap_urlauth_connection_select_target(conn);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return 0;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (strcasecmp(response, "OK") != 0) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_error("imap-urlauth: Failed to select target user %s: "
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch "Got unexpected response: %s", conn->targets_head->userid,
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch str_sanitize(response, 80));
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch imap_urlauth_connection_abort(conn, NULL);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return -1;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (conn->user->mail_debug) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_debug("imap-urlauth: Successfully selected target user %s",
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch conn->targets_head->userid);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch conn->state = IMAP_URLAUTH_STATE_READY;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch imap_urlauth_connection_send_request(conn);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return 0;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch case IMAP_URLAUTH_STATE_AUTHENTICATED:
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch case IMAP_URLAUTH_STATE_READY:
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch case IMAP_URLAUTH_STATE_REQUEST_WAIT:
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if ((response = i_stream_next_line(conn->input)) == NULL)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return 0;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
c1dbcb60868c4e8e523fcf409b5b7539f58945d7Phil Carmody i_error("imap-urlauth: Received input while no requests were pending: %s",
c1dbcb60868c4e8e523fcf409b5b7539f58945d7Phil Carmody str_sanitize(response, 80));
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch imap_urlauth_connection_abort(conn, NULL);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return -1;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch case IMAP_URLAUTH_STATE_REQUEST_PENDING:
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if ((ret = imap_urlauth_input_pending(conn)) < 0)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch imap_urlauth_connection_fail(conn);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return ret;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch case IMAP_URLAUTH_STATE_DISCONNECTED:
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch break;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_unreached();
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch}
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstatic void imap_urlauth_input(struct imap_urlauth_connection *conn)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch{
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch int ret;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_assert(conn->state != IMAP_URLAUTH_STATE_DISCONNECTED);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (conn->input->closed) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* disconnected */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_error("imap-urlauth: Service disconnected unexpectedly");
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch imap_urlauth_connection_fail(conn);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch switch (i_stream_read(conn->input)) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch case -1:
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* disconnected */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_error("imap-urlauth: Service disconnected unexpectedly");
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch imap_urlauth_connection_fail(conn);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch case -2:
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* input buffer full */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_error("imap-urlauth: Service sent too large input");
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch imap_urlauth_connection_abort(conn, NULL);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch while (!conn->input->closed) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if ((ret = imap_urlauth_input_next(conn)) <= 0)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch break;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch}
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstatic int
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschimap_urlauth_connection_do_connect(struct imap_urlauth_connection *conn)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch{
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch string_t *str;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch int fd;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (conn->state != IMAP_URLAUTH_STATE_DISCONNECTED) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch imap_urlauth_connection_send_request(conn);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return 1;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (conn->user->auth_token == NULL) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_error("imap-urlauth: cannot authenticate because no auth token "
f1edf7f20661ef9627acbf4054acddcba4d2eb3fStephan Bosch "is available for this session (running standalone?).");
f82dfbdcc736987b8da09b75408393f2e074b891Stephan Bosch imap_urlauth_connection_abort(conn, NULL);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return -1;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (conn->user->mail_debug)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_debug("imap-urlauth: Connecting to service at %s", conn->path);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_assert(conn->fd == -1);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch fd = net_connect_unix(conn->path);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (fd == -1) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_error("imap-urlauth: net_connect_unix(%s) failed: %m",
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch conn->path);
f82dfbdcc736987b8da09b75408393f2e074b891Stephan Bosch imap_urlauth_connection_abort(conn, NULL);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return -1;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
0d1b8b6bec79746c5d89d57dd8c1688946bd9237Josef 'Jeff' Sipek timeout_remove(&conn->to_reconnect);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch conn->fd = fd;
e93184a9055c2530366dfe617e07199603c399ddMartti Rannanjärvi conn->input = i_stream_create_fd(fd, (size_t)-1);
e93184a9055c2530366dfe617e07199603c399ddMartti Rannanjärvi conn->output = o_stream_create_fd(fd, (size_t)-1);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch conn->io = io_add(fd, IO_READ, imap_urlauth_input, conn);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch conn->state = IMAP_URLAUTH_STATE_AUTHENTICATING;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch str = t_str_new(128);
f1edf7f20661ef9627acbf4054acddcba4d2eb3fStephan Bosch str_printfa(str, IMAP_URLAUTH_HANDSHAKE"AUTH\t%s\t%s\t",
f1edf7f20661ef9627acbf4054acddcba4d2eb3fStephan Bosch conn->service, my_pid);
d03a871a77f8ec36f48f5fea98d810e51b186fdbTimo Sirainen str_append_tabescaped(str, conn->user->username);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch str_append_c(str, '\t');
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (conn->session_id != NULL)
d03a871a77f8ec36f48f5fea98d810e51b186fdbTimo Sirainen str_append_tabescaped(str, conn->session_id);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch str_append_c(str, '\t');
d03a871a77f8ec36f48f5fea98d810e51b186fdbTimo Sirainen str_append_tabescaped(str, conn->user->auth_token);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch str_append_c(str, '\n');
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (o_stream_send(conn->output, str_data(str), str_len(str)) < 0) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_warning("Error sending handshake to imap-urlauth server: %m");
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch imap_urlauth_connection_abort(conn, NULL);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return -1;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch imap_urlauth_start_response_timeout(conn);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return 0;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch}
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschint imap_urlauth_connection_connect(struct imap_urlauth_connection *conn)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch{
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch conn->reconnect_attempts = 0;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (conn->to_reconnect == NULL)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return imap_urlauth_connection_do_connect(conn);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return 0;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch}
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstatic void imap_urlauth_connection_disconnect
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch(struct imap_urlauth_connection *conn, const char *reason)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch{
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch conn->state = IMAP_URLAUTH_STATE_DISCONNECTED;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (conn->fd != -1) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (conn->user->mail_debug) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (reason == NULL)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_debug("imap-urlauth: Disconnecting from service");
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch else
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_debug("imap-urlauth: Disconnected: %s", reason);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch io_remove(&conn->io);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_stream_destroy(&conn->input);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch o_stream_destroy(&conn->output);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch net_disconnect(conn->fd);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch conn->fd = -1;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch conn->reading_literal = FALSE;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (conn->literal_fd != -1) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (close(conn->literal_fd) < 0)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_error("imap-urlauth: close(%s) failed: %m", conn->literal_temp_path);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_free_and_null(conn->literal_temp_path);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch conn->literal_fd = -1;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
6307d76096764e66bddc63d4a3e5a1aa19cc528fJosef 'Jeff' Sipek buffer_free(&conn->literal_buf);
0d1b8b6bec79746c5d89d57dd8c1688946bd9237Josef 'Jeff' Sipek timeout_remove(&conn->to_reconnect);
0d1b8b6bec79746c5d89d57dd8c1688946bd9237Josef 'Jeff' Sipek timeout_remove(&conn->to_idle);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch imap_urlauth_stop_response_timeout(conn);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch}
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstatic void
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschimap_urlauth_connection_do_reconnect(struct imap_urlauth_connection *conn)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch{
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (conn->reconnect_attempts >= IMAP_URLAUTH_RECONNECT_MAX_ATTEMPTS) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch imap_urlauth_connection_abort(conn,
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch "Connection failed and connection attempts exhausted");
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (ioloop_time - conn->last_reconnect < IMAP_URLAUTH_RECONNECT_MIN_SECS) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (conn->user->mail_debug)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_debug("imap-urlauth: Scheduling reconnect");
0d1b8b6bec79746c5d89d57dd8c1688946bd9237Josef 'Jeff' Sipek timeout_remove(&conn->to_reconnect);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch conn->to_reconnect =
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch timeout_add(IMAP_URLAUTH_RECONNECT_MIN_SECS*1000,
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch imap_urlauth_connection_do_reconnect, conn);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch } else {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch conn->reconnect_attempts++;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch conn->last_reconnect = ioloop_time;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch (void)imap_urlauth_connection_do_connect(conn);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch}
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstatic void
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschimap_urlauth_connection_reconnect(struct imap_urlauth_connection *conn)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch{
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch imap_urlauth_connection_disconnect(conn, NULL);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* don't reconnect if there are no requests */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (conn->targets_head == NULL)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch imap_urlauth_connection_do_reconnect(conn);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch}
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstatic void
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschimap_urlauth_connection_idle_disconnect(struct imap_urlauth_connection *conn)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch{
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch imap_urlauth_connection_disconnect(conn, "Idle timeout");
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch}
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstatic void
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschimap_urlauth_connection_timeout_abort(struct imap_urlauth_connection *conn)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch{
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch imap_urlauth_connection_abort(conn, "Service is not responding");
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch}
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschbool imap_urlauth_connection_is_connected(struct imap_urlauth_connection *conn)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch{
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return conn->fd != -1 && conn->state != IMAP_URLAUTH_STATE_DISCONNECTED;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch}