bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2013-2018 Dovecot authors, see the included COPYING file */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch struct imap_urlauth_request *requests_head, *requests_tail;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch struct timeout *to_reconnect, *to_idle, *to_response;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* userid => target struct */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch struct imap_urlauth_target *targets_head, *targets_tail;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch#define IMAP_URLAUTH_RESPONSE_TIMEOUT_MSECS 2*60*1000
f1edf7f20661ef9627acbf4054acddcba4d2eb3fStephan Bosch#define IMAP_URLAUTH_HANDSHAKE "VERSION\timap-urlauth\t2\t0\n"
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch#define IMAP_URLAUTH_MAX_INLINE_LITERAL_SIZE (1024*32)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch (struct imap_urlauth_connection *conn, const char *reason);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch (struct imap_urlauth_connection *conn, const char *reason);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstatic void imap_urlauth_connection_idle_disconnect
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstatic void imap_urlauth_connection_timeout_abort
f1edf7f20661ef9627acbf4054acddcba4d2eb3fStephan Boschimap_urlauth_connection_init(const char *path, const char *service,
f1edf7f20661ef9627acbf4054acddcba4d2eb3fStephan Bosch struct mail_user *user, const char *session_id,
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch conn = i_new(struct imap_urlauth_connection, 1);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch conn->idle_timeout_msecs = idle_timeout_msecs;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschvoid imap_urlauth_connection_deinit(struct imap_urlauth_connection **_conn)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch struct imap_urlauth_connection *conn = *_conn;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschimap_urlauth_stop_response_timeout(struct imap_urlauth_connection *conn)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschimap_urlauth_start_response_timeout(struct imap_urlauth_connection *conn)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch conn->to_response = timeout_add(IMAP_URLAUTH_RESPONSE_TIMEOUT_MSECS,
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschimap_urlauth_connection_get_target(struct imap_urlauth_connection *conn,
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch struct imap_urlauth_target *target = conn->targets_head;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch target = i_new(struct imap_urlauth_target, 1);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch DLLIST2_APPEND(&conn->targets_head, &conn->targets_tail, target);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschimap_urlauth_target_free(struct imap_urlauth_connection *conn,
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch DLLIST2_REMOVE(&conn->targets_head, &conn->targets_tail, target);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschimap_urlauth_connection_select_target(struct imap_urlauth_connection *conn)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch struct imap_urlauth_target *target = conn->targets_head;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (target == NULL || conn->state != IMAP_URLAUTH_STATE_AUTHENTICATED)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_debug("imap-urlauth: Selecting target user `%s'", target->userid);
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 Boschimap_urlauth_connection_send_request(struct imap_urlauth_connection *conn)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_debug("imap-urlauth: No more requests pending; scheduling disconnect");
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch conn->to_idle = timeout_add(conn->idle_timeout_msecs,
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch imap_urlauth_connection_idle_disconnect, conn);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (conn->state == IMAP_URLAUTH_STATE_AUTHENTICATED) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch conn->state = IMAP_URLAUTH_STATE_UNSELECTING_TARGET;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch imap_urlauth_target_free(conn, conn->targets_head);
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 i_debug("imap-urlauth: Fetching URL `%s'", urlreq->url);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if ((urlreq->flags & IMAP_URLAUTH_FETCH_FLAG_BODYPARTSTRUCTURE) != 0)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if ((urlreq->flags & IMAP_URLAUTH_FETCH_FLAG_BINARY) != 0)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch else if ((urlreq->flags & IMAP_URLAUTH_FETCH_FLAG_BODY) != 0)
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 Boschimap_urlauth_request_new(struct imap_urlauth_connection *conn,
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch target = imap_urlauth_connection_get_target(conn, target_user);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch urlreq = i_new(struct imap_urlauth_request, 1);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch DLLIST2_APPEND(&target->requests_head, &target->requests_tail, urlreq);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_debug("imap-urlauth: Added request for URL `%s' from user `%s'",
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstatic void imap_urlauth_request_free(struct imap_urlauth_request *urlreq)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch struct imap_urlauth_target *target = urlreq->target;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch DLLIST2_REMOVE(&target->requests_head, &target->requests_tail, urlreq);
7cf790002e2fc9c260776862123d7af67032ad61Stephan Boschstatic void imap_urlauth_request_drop(struct imap_urlauth_connection *conn,
7cf790002e2fc9c260776862123d7af67032ad61Stephan Bosch if ((conn->state == IMAP_URLAUTH_STATE_REQUEST_PENDING ||
7cf790002e2fc9c260776862123d7af67032ad61Stephan Bosch conn->state == IMAP_URLAUTH_STATE_REQUEST_WAIT) &&
7cf790002e2fc9c260776862123d7af67032ad61Stephan Bosch conn->targets_head->requests_head == urlreq) {
7cf790002e2fc9c260776862123d7af67032ad61Stephan Bosch /* cannot just drop pending request without breaking
7cf790002e2fc9c260776862123d7af67032ad61Stephan Bosch protocol state */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschvoid imap_urlauth_request_abort(struct imap_urlauth_connection *conn,
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschimap_urlauth_request_fail(struct imap_urlauth_connection *conn,
7cf790002e2fc9c260776862123d7af67032ad61Stephan Bosch /* Drop any related requests upon error */
b804e2b1744ef1616626dd7b8b8ff6cb83cfb2dfTimo Sirainen imap_urlauth_request_abort_by_context(conn, urlreq_context);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschimap_urlauth_target_abort(struct imap_urlauth_connection *conn,
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschimap_urlauth_target_fail(struct imap_urlauth_connection *conn,
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch struct imap_urlauth_target *target, const char *error)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch imap_urlauth_request_fail(conn, urlreq, error);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschimap_urlauth_target_abort_by_context(struct imap_urlauth_connection *conn,
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* abort all matching requests */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschimap_urlauth_connection_abort(struct imap_urlauth_connection *conn,
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch imap_urlauth_connection_disconnect(conn, reason);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* abort all requests */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschvoid imap_urlauth_request_abort_by_context(struct imap_urlauth_connection *conn,
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* abort all matching requests */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch imap_urlauth_target_abort_by_context(conn, target, context);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstatic void imap_urlauth_connection_fail(struct imap_urlauth_connection *conn)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (conn->reconnect_attempts > IMAP_URLAUTH_RECONNECT_MAX_ATTEMPTS) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch "Connection failed and connection attempts exhausted");
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschimap_urlauth_connection_create_temp_fd(struct imap_urlauth_connection *conn,
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch const char **path_r)
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 i_error("safe_mkstemp(%s) failed: %m", str_c(path));
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* we just want the fd, unlink it */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* shouldn't happen.. */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschimap_urlauth_connection_read_literal_init(struct imap_urlauth_connection *conn,
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_assert(conn->literal_fd == -1 && conn->literal_buf == NULL);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (size <= IMAP_URLAUTH_MAX_INLINE_LITERAL_SIZE) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* read the literal directly */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* read it into a file */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch imap_urlauth_connection_create_temp_fd(conn, &path);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschvoid imap_urlauth_connection_continue(struct imap_urlauth_connection *conn)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_assert(conn->targets_head->requests_head != NULL);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (conn->state != IMAP_URLAUTH_STATE_REQUEST_WAIT)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch imap_urlauth_request_free(conn->targets_head->requests_head);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschimap_urlauth_connection_read_literal_data(struct imap_urlauth_connection *conn)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* read data */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* write to buffer or file */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (write_full(conn->literal_fd, data, size) < 0) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* exit if not finished */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* read LF guard */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* check LF guard */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_error("imap-urlauth: no LF at end of literal (found 0x%x)",
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstatic void literal_stream_destroy(buffer_t *buffer)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschimap_urlauth_fetch_reply_set_literal_stream(struct imap_urlauth_connection *conn,
bace943c67e6cd14ce6c994f533d82a3caad5bf1Timo Sirainen reply->input = i_stream_create_fd_autoclose(&conn->literal_fd,
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (i_stream_get_size(reply->input, TRUE, &fd_size) < 1 ||
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_error("imap-urlauth: Failed to obtain proper size from literal stream");
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch "Failed during literal transfer");
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch data = buffer_get_data(conn->literal_buf, &size);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch reply->input = i_stream_create_from_data(data, size);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschimap_urlauth_connection_read_literal(struct imap_urlauth_connection *conn)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch struct imap_urlauth_request *urlreq = conn->targets_head->requests_head;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch ret = imap_urlauth_connection_read_literal_data(conn);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch reply.bodypartstruct = urlreq->bodypartstruct;
f0339f522dc9c8e2e8a29ef9a3f937c431c6bd1bTimo Sirainen reply.binary_has_nuls = urlreq->binary_has_nuls ? 1 : 0;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (imap_urlauth_fetch_reply_set_literal_stream(conn, &reply) < 0)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* Drop any related requests upon error */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch imap_urlauth_request_abort_by_context(conn, urlreq->context);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch conn->state = IMAP_URLAUTH_STATE_REQUEST_WAIT;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* finished */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstatic int imap_urlauth_input_pending(struct imap_urlauth_connection *conn)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch const char *response, *const *args, *bpstruct = NULL;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_assert(conn->targets_head->requests_head != NULL);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* Read pending literal; may callback */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return imap_urlauth_connection_read_literal(conn);
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 i_error("imap-urlauth: Empty URL response: %s",
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (strcmp(args[0], "OK") != 0 || args[1] == NULL) {
7cf790002e2fc9c260776862123d7af67032ad61Stephan Bosch conn->state = IMAP_URLAUTH_STATE_REQUEST_WAIT;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_error("imap-urlauth: Unexpected URL response: %s",
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* read metadata */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch } else if (strncasecmp(param, "bpstruct=", 9) == 0 &&
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* read literal size */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (str_to_uoff(args[0], &literal_size) < 0) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch "Overflowing unsigned integer value for literal size: %s",
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* read literal */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (imap_urlauth_connection_read_literal_init(conn, literal_size) < 0)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return imap_urlauth_connection_read_literal(conn);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstatic int imap_urlauth_input_next(struct imap_urlauth_connection *conn)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if ((response = i_stream_next_line(conn->input)) == NULL)
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 i_error("imap-urlauth: Failed to unselect target user: "
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch "Got unexpected response: %s", str_sanitize(response, 80));
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (conn->state == IMAP_URLAUTH_STATE_AUTHENTICATING)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_debug("imap-urlauth: Successfully authenticated to service");
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_debug("imap-urlauth: Successfully unselected target user");
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch conn->state = IMAP_URLAUTH_STATE_AUTHENTICATED;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if ((response = i_stream_next_line(conn->input)) == NULL)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_debug("imap-urlauth: Failed to select target user %s",
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch imap_urlauth_target_fail(conn, conn->targets_head, NULL);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch conn->state = IMAP_URLAUTH_STATE_AUTHENTICATED;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_error("imap-urlauth: Failed to select target user %s: "
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch "Got unexpected response: %s", conn->targets_head->userid,
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_debug("imap-urlauth: Successfully selected target user %s",
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if ((response = i_stream_next_line(conn->input)) == NULL)
c1dbcb60868c4e8e523fcf409b5b7539f58945d7Phil Carmody i_error("imap-urlauth: Received input while no requests were pending: %s",
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if ((ret = imap_urlauth_input_pending(conn)) < 0)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstatic void imap_urlauth_input(struct imap_urlauth_connection *conn)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_assert(conn->state != IMAP_URLAUTH_STATE_DISCONNECTED);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* disconnected */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_error("imap-urlauth: Service disconnected unexpectedly");
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* disconnected */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_error("imap-urlauth: Service disconnected unexpectedly");
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* input buffer full */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_error("imap-urlauth: Service sent too large input");
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if ((ret = imap_urlauth_input_next(conn)) <= 0)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschimap_urlauth_connection_do_connect(struct imap_urlauth_connection *conn)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (conn->state != IMAP_URLAUTH_STATE_DISCONNECTED) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_error("imap-urlauth: cannot authenticate because no auth token "
f1edf7f20661ef9627acbf4054acddcba4d2eb3fStephan Bosch "is available for this session (running standalone?).");
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_debug("imap-urlauth: Connecting to service at %s", conn->path);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_error("imap-urlauth: net_connect_unix(%s) failed: %m",
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;
f1edf7f20661ef9627acbf4054acddcba4d2eb3fStephan Bosch str_printfa(str, IMAP_URLAUTH_HANDSHAKE"AUTH\t%s\t%s\t",
d03a871a77f8ec36f48f5fea98d810e51b186fdbTimo Sirainen str_append_tabescaped(str, conn->user->username);
d03a871a77f8ec36f48f5fea98d810e51b186fdbTimo Sirainen str_append_tabescaped(str, conn->user->auth_token);
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 Boschint imap_urlauth_connection_connect(struct imap_urlauth_connection *conn)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return imap_urlauth_connection_do_connect(conn);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch(struct imap_urlauth_connection *conn, const char *reason)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch conn->state = IMAP_URLAUTH_STATE_DISCONNECTED;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_debug("imap-urlauth: Disconnecting from service");
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_debug("imap-urlauth: Disconnected: %s", reason);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_error("imap-urlauth: close(%s) failed: %m", conn->literal_temp_path);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschimap_urlauth_connection_do_reconnect(struct imap_urlauth_connection *conn)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (conn->reconnect_attempts >= IMAP_URLAUTH_RECONNECT_MAX_ATTEMPTS) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch "Connection failed and connection attempts exhausted");
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (ioloop_time - conn->last_reconnect < IMAP_URLAUTH_RECONNECT_MIN_SECS) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_debug("imap-urlauth: Scheduling reconnect");
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch timeout_add(IMAP_URLAUTH_RECONNECT_MIN_SECS*1000,
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch (void)imap_urlauth_connection_do_connect(conn);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschimap_urlauth_connection_reconnect(struct imap_urlauth_connection *conn)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch imap_urlauth_connection_disconnect(conn, NULL);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* don't reconnect if there are no requests */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschimap_urlauth_connection_idle_disconnect(struct imap_urlauth_connection *conn)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch imap_urlauth_connection_disconnect(conn, "Idle timeout");
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschimap_urlauth_connection_timeout_abort(struct imap_urlauth_connection *conn)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch imap_urlauth_connection_abort(conn, "Service is not responding");
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschbool imap_urlauth_connection_is_connected(struct imap_urlauth_connection *conn)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return conn->fd != -1 && conn->state != IMAP_URLAUTH_STATE_DISCONNECTED;