imap-urlauth-connection.c revision 7cf790002e2fc9c260776862123d7af67032ad61
/* Copyright (c) 2013 Dovecot authors, see the included COPYING file */
#include "lib.h"
#include "llist.h"
#include "str.h"
#include "str-sanitize.h"
#include "strescape.h"
#include "ioloop.h"
#include "safe-mkstemp.h"
#include "hostpid.h"
#include "net.h"
#include "istream.h"
#include "ostream.h"
#include "write-full.h"
#include "array.h"
#include "aqueue.h"
#include "mail-user.h"
#include "imap-urlauth-fetch.h"
#include "imap-urlauth-connection.h"
enum imap_urlauth_state {
};
struct imap_urlauth_request {
struct imap_urlauth_target *target;
char *url;
char *bodypartstruct;
void *context;
unsigned int binary_has_nuls;
};
struct imap_urlauth_target {
char *userid;
};
struct imap_urlauth_connection {
int refcount;
char *path, *session_id;
int fd;
unsigned int reconnect_attempts;
unsigned int idle_timeout_msecs;
char *literal_temp_path;
int literal_fd;
enum imap_urlauth_state state;
/* userid => target struct */
unsigned int reading_literal:1;
};
#define IMAP_URLAUTH_RECONNECT_MIN_SECS 2
#define IMAP_URLAUTH_RECONNECT_MAX_ATTEMPTS 3
#define IMAP_URLAUTH_HANDSHAKE "VERSION\timap-urlauth\t1\t0\n"
static void imap_urlauth_connection_disconnect
static void imap_urlauth_connection_abort
static void imap_urlauth_connection_reconnect
(struct imap_urlauth_connection *conn);
static void imap_urlauth_connection_idle_disconnect
(struct imap_urlauth_connection *conn);
static void imap_urlauth_connection_timeout_abort
(struct imap_urlauth_connection *conn);
static void imap_urlauth_connection_fail
(struct imap_urlauth_connection *conn);
struct imap_urlauth_connection *
const char *session_id,
unsigned int idle_timeout_msecs)
{
struct imap_urlauth_connection *conn;
if (session_id != NULL)
return conn;
}
{
}
static void
{
}
static void
{
}
static struct imap_urlauth_target *
const char *target_user)
{
return target;
}
return target;
}
static void
struct imap_urlauth_target *target)
{
}
static void
{
const char *cmd;
return;
i_warning("Error sending USER request to imap-urlauth server: %m");
}
}
static void
{
struct imap_urlauth_request *urlreq;
i_debug("imap-urlauth: No more requests pending; scheduling disconnect");
if (conn->idle_timeout_msecs > 0) {
}
return;
}
return;
}
return;
return;
i_warning("Error sending END request to imap-urlauth server: %m");
}
return;
}
i_warning("Error sending URL request to imap-urlauth server: %m");
}
}
struct imap_urlauth_request *
const char *target_user, const char *url,
void *context)
{
struct imap_urlauth_request *urlreq;
struct imap_urlauth_target *target;
i_debug("imap-urlauth: Added request for URL `%s' from user `%s'",
url, target_user);
}
return urlreq;
}
{
}
struct imap_urlauth_request *urlreq)
{
/* cannot just drop pending request without breaking
protocol state */
return;
}
}
struct imap_urlauth_request *urlreq)
{
T_BEGIN {
} T_END;
}
}
static void
struct imap_urlauth_request *urlreq,
const char *error)
{
struct imap_urlauth_fetch_reply reply;
int ret = 1;
T_BEGIN {
} T_END;
}
if (ret < 0) {
/* Drop any related requests upon error */
}
if (ret != 0)
}
static void
struct imap_urlauth_target *target)
{
}
}
static void
{
}
}
static void
struct imap_urlauth_target *target,
void *context)
{
/* abort all matching requests */
}
}
static void
const char *reason)
{
reason = "Aborting due to error";
/* abort all requests */
}
}
void *context)
{
/* abort all matching requests */
}
}
{
"Connection failed and connection attempts exhausted");
} else {
}
}
static int
const char **path_r)
{
int fd;
if (fd == -1) {
return -1;
}
/* we just want the fd, unlink it */
/* shouldn't happen.. */
i_close_fd(&fd);
return -1;
}
return fd;
}
static int
{
const char *path;
if (size <= IMAP_URLAUTH_MAX_INLINE_LITERAL_SIZE) {
/* read the literal directly */
if (size > 0) {
conn->literal_buf =
}
} else {
/* read it into a file */
conn->literal_fd =
return -1;
}
return 1;
}
{
return;
}
static int
{
const unsigned char *data;
/* read data */
/* write to buffer or file */
if (size > 0) {
if (conn->literal_fd >= 0) {
i_error("imap-urlauth: write(%s) failed: %m",
return -1;
}
} else {
}
}
/* exit if not finished */
if (conn->literal_bytes_left > 0)
return 0;
/* read LF guard */
if (size < 1)
return 0;
/* check LF guard */
if (data[0] != '\n') {
i_error("imap-urlauth: no LF at end of literal (found 0x%x)",
data[0]);
return -1;
}
return 1;
}
{
}
static int
struct imap_urlauth_fetch_reply *reply)
{
const unsigned char *data;
i_error("imap-urlauth: Failed to obtain proper size from literal stream");
"Failed during literal transfer");
return -1;
}
} else {
conn->literal_buf);
}
return 0;
}
static int
{
struct imap_urlauth_fetch_reply reply;
int ret;
if (conn->literal_size > 0) {
if (ret <= 0)
return ret;
}
/* reply */
if (conn->literal_size > 0) {
return -1;
}
ret = 1;
} T_END;
if (ret < 0) {
/* Drop any related requests upon error */
}
if (ret != 0)
/* finished */
return 1;
}
{
struct imap_urlauth_request *urlreq;
if (conn->reading_literal) {
/* Read pending literal; may callback */
return imap_urlauth_connection_read_literal(conn);
}
/* "OK"[<metadata-items>]"\t"<literal-size>"\n" or
"NO"["\terror="<error>]"\n" */
return 0;
i_error("imap-urlauth: Empty URL response: %s",
return -1;
}
}
return 1;
}
i_error("imap-urlauth: Unexpected URL response: %s",
return -1;
}
/* read metadata */
args++;
}
}
/* read literal size */
i_error("imap-urlauth: "
"Overflowing unsigned integer value for literal size: %s",
args[1]);
return -1;
}
/* read literal */
return -1;
return imap_urlauth_connection_read_literal(conn);
}
{
const char *response;
int ret;
return 0;
i_error("imap-urlauth: Failed to authenticate to service: "
else
i_error("imap-urlauth: Failed to unselect target user: "
return -1;
}
i_debug("imap-urlauth: Successfully authenticated to service");
else
i_debug("imap-urlauth: Successfully unselected target user");
}
return 0;
return 0;
i_debug("imap-urlauth: Failed to select target user %s",
}
return 0;
}
i_error("imap-urlauth: Failed to select target user %s: "
return -1;
}
i_debug("imap-urlauth: Successfully selected target user %s",
}
return 0;
case IMAP_URLAUTH_STATE_READY:
return 0;
i_error("imap-urlauth: Received input while no requests were pending");
return -1;
return ret;
break;
}
i_unreached();
}
{
int ret;
/* disconnected */
i_error("imap-urlauth: Service disconnected unexpectedly");
return;
}
case -1:
/* disconnected */
i_error("imap-urlauth: Service disconnected unexpectedly");
return;
case -2:
/* input buffer full */
i_error("imap-urlauth: Service sent too large input");
return;
}
break;
}
}
static int
{
int fd;
return 1;
}
i_error("imap-urlauth: cannot authenticate because no auth token "
"is available for this session (standalone IMAP?).");
return -1;
}
if (fd == -1) {
i_error("imap-urlauth: net_connect_unix(%s) failed: %m",
return -1;
}
i_warning("Error sending handshake to imap-urlauth server: %m");
return -1;
}
return 0;
}
{
conn->reconnect_attempts = 0;
return imap_urlauth_connection_do_connect(conn);
return 0;
}
static void imap_urlauth_connection_disconnect
{
i_debug("imap-urlauth: Disconnecting from service");
else
}
}
}
}
static void
{
"Connection failed and connection attempts exhausted");
return;
}
i_debug("imap-urlauth: Scheduling reconnect");
conn->to_reconnect =
} else {
}
}
static void
{
/* don't reconnect if there are no requests */
return;
}
static void
{
}
static void
{
}
{
}