bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2013-2018 Dovecot authors, see the included COPYING file */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch#include "lib.h"
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch#include "array.h"
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch#include "ioloop.h"
bdd36cfdba3ff66d25570a9ff568d69e1eb543cfTimo Sirainen#include "net.h"
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch#include "fdpass.h"
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch#include "istream.h"
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch#include "ostream.h"
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch#include "str.h"
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch#include "str-sanitize.h"
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch#include "strescape.h"
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch#include "llist.h"
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch#include "hostpid.h"
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch#include "var-expand.h"
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch#include "process-title.h"
70375a50991814959d061db0e2d4da35e542e437Timo Sirainen#include "randgen.h"
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch#include "restrict-access.h"
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch#include "settings-parser.h"
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch#include "master-service.h"
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch#include "master-interface.h"
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch#include "mail-storage.h"
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch#include "mail-storage-service.h"
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch#include "mail-namespace.h"
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch#include "imap-url.h"
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch#include "imap-msgpart-url.h"
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch#include "imap-urlauth.h"
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch#include "imap-urlauth-fetch.h"
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch#include "imap-urlauth-worker-settings.h"
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch#include <unistd.h>
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch#include <sysexits.h>
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch#define MAX_CTRL_HANDSHAKE 255
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch/* max. length of input lines (URLs) */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch#define MAX_INBUF_SIZE 2048
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch/* Disconnect client after idling this many milliseconds */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch#define CLIENT_IDLE_TIMEOUT_MSECS (10*60*1000)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch#define IS_STANDALONE() \
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch (getenv(MASTER_IS_PARENT_ENV) == NULL)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f1edf7f20661ef9627acbf4054acddcba4d2eb3fStephan Bosch#define IMAP_URLAUTH_WORKER_PROTOCOL_MAJOR_VERSION 2
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch#define IMAP_URLAUTH_WORKER_PROTOCOL_MINOR_VERSION 0
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstruct client {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch struct client *prev, *next;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch int fd_in, fd_out, fd_ctrl;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch struct io *io, *ctrl_io;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch struct istream *input, *ctrl_input;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch struct ostream *output, *ctrl_output;
2d8ff6cda406da5c53e635fe31dfadc3bdb05235Timo Sirainen struct timeout *to_idle;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f1edf7f20661ef9627acbf4054acddcba4d2eb3fStephan Bosch char *access_user, *access_service;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch ARRAY_TYPE(string) access_apps;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch struct mail_storage_service_user *service_user;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch struct mail_user *mail_user;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch struct imap_urlauth_context *urlauth_ctx;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch struct imap_msgpart_url *url;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch struct istream *msg_part_input;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch uoff_t msg_part_size;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* settings: */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch const struct imap_urlauth_worker_settings *set;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch const struct mail_storage_settings *mail_set;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen bool debug:1;
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen bool finished:1;
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen bool waiting_input:1;
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen bool version_received:1;
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen bool access_received:1;
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen bool access_anonymous:1;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch};
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstatic bool verbose_proctitle = FALSE;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstatic struct mail_storage_service_ctx *storage_service;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstruct client *imap_urlauth_worker_clients;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschunsigned int imap_urlauth_worker_client_count;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstatic void client_destroy(struct client *client);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstatic void client_abort(struct client *client, const char *reason);
4fa772eefd5a22a597601488be44997e788cb60dStephan Boschstatic int client_run_url(struct client *client);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstatic void client_input(struct client *client);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstatic bool client_handle_input(struct client *client);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstatic int client_output(struct client *client);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstatic void client_ctrl_input(struct client *client);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstatic void imap_urlauth_worker_refresh_proctitle(void)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch{
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch struct client *client = imap_urlauth_worker_clients;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch string_t *title;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (!verbose_proctitle)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch title = t_str_new(128);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch str_append_c(title, '[');
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch switch (imap_urlauth_worker_client_count) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch case 0:
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch str_append(title, "idling");
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch break;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch case 1:
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (client->mail_user == NULL)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch str_append(title, client->access_user);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch else {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch str_append(title, client->access_user);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch str_append(title, "->");
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch str_append(title, client->mail_user->username);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch break;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch default:
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch str_printfa(title, "%u connections",
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch imap_urlauth_worker_client_count);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch break;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch str_append_c(title, ']');
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch process_title_set(str_c(title));
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch}
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstatic void client_idle_timeout(struct client *client)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch{
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (client->url != NULL) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch client_abort(client,
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch "Session closed for inactivity in reading our output");
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch } else {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch client_destroy(client);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch}
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstatic struct client *client_create(int fd)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch{
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch struct client *client;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* always use nonblocking I/O */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch net_set_nonblock(fd, TRUE);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch client = i_new(struct client, 1);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_array_init(&client->access_apps, 16);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch client->fd_in = -1;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch client->fd_out = -1;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch client->fd_ctrl = fd;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch client->access_anonymous = TRUE; /* default until overridden */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch client->ctrl_io = io_add(fd, IO_READ, client_ctrl_input, client);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch client->to_idle = timeout_add(CLIENT_IDLE_TIMEOUT_MSECS,
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch client_idle_timeout, client);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch imap_urlauth_worker_client_count++;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch DLLIST_PREPEND(&imap_urlauth_worker_clients, client);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch imap_urlauth_worker_refresh_proctitle();
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return client;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch}
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstatic struct client *
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschclient_create_standalone(const char *access_user,
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch const char *const *access_applications,
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch int fd_in, int fd_out, bool debug)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch{
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch struct client *client;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* always use nonblocking I/O */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch net_set_nonblock(fd_in, TRUE);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch net_set_nonblock(fd_out, TRUE);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch client = i_new(struct client, 1);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_array_init(&client->access_apps, 16);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch client->fd_in = fd_in;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch client->fd_out = fd_out;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch client->fd_ctrl = -1;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (access_user != NULL && *access_user != '\0')
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch client->access_user = i_strdup(access_user);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch else {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch client->access_user = i_strdup("anonymous");
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch client->access_anonymous = TRUE;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (access_applications != NULL) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch const char *const *apps = access_applications;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch for (; *apps != NULL; apps++) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch char *app = i_strdup(*apps);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch array_append(&client->access_apps, &app, 1);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch client->debug = debug;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
e93184a9055c2530366dfe617e07199603c399ddMartti Rannanjärvi client->input = i_stream_create_fd(fd_in, MAX_INBUF_SIZE);
e93184a9055c2530366dfe617e07199603c399ddMartti Rannanjärvi client->output = o_stream_create_fd(fd_out, (size_t)-1);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch client->io = io_add(fd_in, IO_READ, client_input, client);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch client->to_idle = timeout_add(CLIENT_IDLE_TIMEOUT_MSECS,
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch client_idle_timeout, client);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch o_stream_set_flush_callback(client->output, client_output, client);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch imap_urlauth_worker_client_count++;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch DLLIST_PREPEND(&imap_urlauth_worker_clients, client);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
ca4526e3b5fbf5ea3dd477a2098522a44c9ac52cTimo Sirainen i_set_failure_prefix("imap-urlauth[%s](%s): ",
ca4526e3b5fbf5ea3dd477a2098522a44c9ac52cTimo Sirainen my_pid, client->access_user);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return client;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch}
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstatic void client_abort(struct client *client, const char *reason)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch{
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_error("%s", reason);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch client_destroy(client);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch}
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstatic void client_destroy(struct client *client)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch{
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch char **app;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
ca4526e3b5fbf5ea3dd477a2098522a44c9ac52cTimo Sirainen i_set_failure_prefix("imap-urlauth[%s](%s): ",
ca4526e3b5fbf5ea3dd477a2098522a44c9ac52cTimo Sirainen my_pid, client->access_user);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (client->url != NULL) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* deinitialize url */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_stream_close(client->input);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch o_stream_close(client->output);
4fa772eefd5a22a597601488be44997e788cb60dStephan Bosch (void)client_run_url(client);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_assert(client->url == NULL);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch imap_urlauth_worker_client_count--;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch DLLIST_REMOVE(&imap_urlauth_worker_clients, client);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (client->urlauth_ctx != NULL)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch imap_urlauth_deinit(&client->urlauth_ctx);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (client->mail_user != NULL)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch mail_user_unref(&client->mail_user);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
5f1d689131a75c39f064cbd4202373e7edf78f18Josef 'Jeff' Sipek io_remove(&client->io);
5f1d689131a75c39f064cbd4202373e7edf78f18Josef 'Jeff' Sipek io_remove(&client->ctrl_io);
0d1b8b6bec79746c5d89d57dd8c1688946bd9237Josef 'Jeff' Sipek timeout_remove(&client->to_idle);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
be5773cb4d6edae8a5d9f300c3c7375cdd33826eJosef 'Jeff' Sipek i_stream_destroy(&client->input);
be5773cb4d6edae8a5d9f300c3c7375cdd33826eJosef 'Jeff' Sipek o_stream_destroy(&client->output);
be5773cb4d6edae8a5d9f300c3c7375cdd33826eJosef 'Jeff' Sipek
be5773cb4d6edae8a5d9f300c3c7375cdd33826eJosef 'Jeff' Sipek i_stream_destroy(&client->ctrl_input);
be5773cb4d6edae8a5d9f300c3c7375cdd33826eJosef 'Jeff' Sipek o_stream_destroy(&client->ctrl_output);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
33a80622828063f5be6f743855d5273fabe8ae58Timo Sirainen fd_close_maybe_stdio(&client->fd_in, &client->fd_out);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (client->fd_ctrl >= 0)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch net_disconnect(client->fd_ctrl);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (client->service_user != NULL)
eb318ea05532d2e54ed3bfc89bc15dcf1adae838Timo Sirainen mail_storage_service_user_unref(&client->service_user);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_free(client->access_user);
f1edf7f20661ef9627acbf4054acddcba4d2eb3fStephan Bosch i_free(client->access_service);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch array_foreach_modifiable(&client->access_apps, app)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_free(*app);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch array_free(&client->access_apps);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_free(client);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch imap_urlauth_worker_refresh_proctitle();
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch master_service_client_connection_destroyed(master_service);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch}
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
4fa772eefd5a22a597601488be44997e788cb60dStephan Boschstatic int client_run_url(struct client *client)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch{
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch const unsigned char *data;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch size_t size;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch ssize_t ret = 0;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
3858a7a5da361c35f1e6e50c8e3214dc0cf379d6Phil Carmody while (i_stream_read_more(client->msg_part_input, &data, &size) > 0) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if ((ret = o_stream_send(client->output, data, size)) < 0)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch break;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_stream_skip(client->msg_part_input, ret);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (o_stream_get_buffer_used_size(client->output) >= 4096) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if ((ret = o_stream_flush(client->output)) < 0)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch break;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (ret == 0)
4fa772eefd5a22a597601488be44997e788cb60dStephan Bosch return 0;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (client->output->closed || ret < 0) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch imap_msgpart_url_free(&client->url);
4fa772eefd5a22a597601488be44997e788cb60dStephan Bosch return -1;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (client->msg_part_input->eof) {
963842c00ef1714db2855c8952f1b46d78cba1caTimo Sirainen (void)o_stream_send(client->output, "\n", 1);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch imap_msgpart_url_free(&client->url);
4fa772eefd5a22a597601488be44997e788cb60dStephan Bosch return 1;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
4fa772eefd5a22a597601488be44997e788cb60dStephan Bosch return 0;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch}
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstatic void clients_destroy_all(void)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch{
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch while (imap_urlauth_worker_clients != NULL)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch client_destroy(imap_urlauth_worker_clients);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch}
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstatic void ATTR_FORMAT(2, 3)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschclient_send_line(struct client *client, const char *fmt, ...)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch{
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch va_list va;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch ssize_t ret;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (client->output->closed)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch va_start(va, fmt);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch T_BEGIN {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch string_t *str;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch str = t_str_new(256);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch str_vprintfa(str, fmt, va);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch str_append(str, "\n");
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch ret = o_stream_send(client->output,
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch str_data(str), str_len(str));
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_assert(ret < 0 || (size_t)ret == str_len(str));
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch } T_END;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch va_end(va);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch}
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstatic int
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschclient_fetch_urlpart(struct client *client, const char *url,
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch enum imap_urlauth_fetch_flags url_flags,
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch const char **bpstruct_r, bool *binary_with_nuls_r,
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch const char **errormsg_r)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch{
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch const char *error;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch struct imap_msgpart_open_result mpresult;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch enum mail_error error_code;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch int ret;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch *bpstruct_r = NULL;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch *errormsg_r = NULL;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch *binary_with_nuls_r = FALSE;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch ret = imap_urlauth_fetch(client->urlauth_ctx, url,
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch &client->url, &error_code, &error);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (ret <= 0) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (ret < 0)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return -1;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch error = t_strdup_printf("Failed to fetch URLAUTH \"%s\": %s",
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch url, error);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (client->debug)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_debug("%s", error);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* don't leak info about existence/accessibility
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch of mailboxes */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (error_code == MAIL_ERROR_PARAMS)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch *errormsg_r = error;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return 0;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if ((url_flags & IMAP_URLAUTH_FETCH_FLAG_BINARY) != 0)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch imap_msgpart_url_set_decode_to_binary(client->url);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if ((url_flags & IMAP_URLAUTH_FETCH_FLAG_BODYPARTSTRUCTURE) != 0) {
2d72e8492960794037a1ca90df34f7ab2a170a81Timo Sirainen ret = imap_msgpart_url_get_bodypartstructure(client->url,
2d72e8492960794037a1ca90df34f7ab2a170a81Timo Sirainen bpstruct_r, &error);
2d72e8492960794037a1ca90df34f7ab2a170a81Timo Sirainen if (ret <= 0) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch *errormsg_r = t_strdup_printf(
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch "Failed to read URLAUTH \"%s\": %s", url, error);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (client->debug)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_debug("%s", *errormsg_r);
2d72e8492960794037a1ca90df34f7ab2a170a81Timo Sirainen return ret;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* if requested, read the message part the URL points to */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if ((url_flags & IMAP_URLAUTH_FETCH_FLAG_BODY) != 0 ||
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch (url_flags & IMAP_URLAUTH_FETCH_FLAG_BINARY) != 0) {
2d72e8492960794037a1ca90df34f7ab2a170a81Timo Sirainen ret = imap_msgpart_url_read_part(client->url, &mpresult, &error);
2d72e8492960794037a1ca90df34f7ab2a170a81Timo Sirainen if (ret <= 0) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch *errormsg_r = t_strdup_printf(
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch "Failed to read URLAUTH \"%s\": %s", url, error);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (client->debug)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_debug("%s", *errormsg_r);
2d72e8492960794037a1ca90df34f7ab2a170a81Timo Sirainen return ret;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch client->msg_part_size = mpresult.size;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch client->msg_part_input = mpresult.input;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch *binary_with_nuls_r = mpresult.binary_decoded_input_has_nuls;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return 1;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch}
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstatic int client_fetch_url(struct client *client, const char *url,
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch enum imap_urlauth_fetch_flags url_flags)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch{
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch string_t *response;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch const char *bpstruct, *errormsg;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch bool binary_with_nuls;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch int ret;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_assert(client->url == NULL);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch client->msg_part_size = 0;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch client->msg_part_input = NULL;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (client->debug)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_debug("Fetching URLAUTH %s", url);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* fetch URL */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch ret = client_fetch_urlpart(client, url, url_flags, &bpstruct,
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch &binary_with_nuls, &errormsg);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (ret <= 0) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* fetch failed */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (client->url != NULL)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch imap_msgpart_url_free(&client->url);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* don't send error details to anonymous users: just to be sure
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch that no information about the target user account is unduly
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch leaked. */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (client->access_anonymous || errormsg == NULL)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch client_send_line(client, "NO");
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch else {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch client_send_line(client, "NO\terror=%s",
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch str_tabescape(errormsg));
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (ret < 0) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* fetch failed badly */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch client_abort(client, "Session aborted: Fatal failure while fetching URL");
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return 0;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch response = t_str_new(256);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch str_append(response, "OK");
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (binary_with_nuls)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch str_append(response, "\thasnuls");
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (bpstruct != NULL) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch str_append(response, "\tbpstruct=");
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch str_append(response, str_tabescape(bpstruct));
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (client->debug) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_debug("Fetched URLAUTH yielded BODYPARTSTRUCTURE (%s)",
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch bpstruct);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* return content */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch o_stream_cork(client->output);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (client->msg_part_size == 0 || client->msg_part_input == NULL) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* empty */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch str_append(response, "\t0");
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch client_send_line(client, "%s", str_c(response));
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch imap_msgpart_url_free(&client->url);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch client->url = NULL;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (client->debug)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_debug("Fetched URLAUTH yielded empty result");
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch } else {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* actual content */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch str_printfa(response, "\t%"PRIuUOFF_T, client->msg_part_size);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch client_send_line(client, "%s", str_c(response));
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (client->debug) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_debug("Fetched URLAUTH yielded %"PRIuUOFF_T" bytes "
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch "of %smessage data", client->msg_part_size,
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch (binary_with_nuls ? "binary " : ""));
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
4fa772eefd5a22a597601488be44997e788cb60dStephan Bosch if (client_run_url(client) < 0) {
4fa772eefd5a22a597601488be44997e788cb60dStephan Bosch client_abort(client,
9008daea438f0e389b37aabbbde62a1f02725e32Timo Sirainen "Session aborted: Fatal failure while transferring URL");
4fa772eefd5a22a597601488be44997e788cb60dStephan Bosch return 0;
4fa772eefd5a22a597601488be44997e788cb60dStephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (client->url != NULL) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* URL not finished */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch o_stream_set_flush_pending(client->output, TRUE);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch client->waiting_input = TRUE;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch o_stream_uncork(client->output);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return client->url != NULL ? 0 : 1;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch}
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstatic int
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschclient_handle_command(struct client *client, const char *cmd,
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch const char *const *args, const char **error_r)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch{
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch int ret;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch *error_r = NULL;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* "URL"["\tbody"]["\tbinary"]["\tbpstruct"]"\t"<url>:
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch fetch URL (meta)data */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (strcmp(cmd, "URL") == 0) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch enum imap_urlauth_fetch_flags url_flags = 0;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch const char *url;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (*args == NULL) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch *error_r = "URL: Missing URL parameter";
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return -1;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch url = *args;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch args++;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch while (*args != NULL) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (strcasecmp(*args, "body") == 0)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch url_flags |= IMAP_URLAUTH_FETCH_FLAG_BODY;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch else if (strcasecmp(*args, "binary") == 0)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch url_flags |= IMAP_URLAUTH_FETCH_FLAG_BINARY;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch else if (strcasecmp(*args, "bpstruct") == 0)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch url_flags |= IMAP_URLAUTH_FETCH_FLAG_BODYPARTSTRUCTURE;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch args++;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (url_flags == 0)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch url_flags = IMAP_URLAUTH_FETCH_FLAG_BODY;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch T_BEGIN {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch ret = client_fetch_url(client, url, url_flags);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch } T_END;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return ret;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* "END": unselect current user (closes worker) */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (strcmp(cmd, "END") == 0) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (args[0] != NULL) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch *error_r = "END: Invalid number of parameters";
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return -1;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch client->finished = TRUE;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (client->ctrl_output != NULL)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch (void)o_stream_send_str(client->ctrl_output, "FINISHED\n");
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch client_destroy(client);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return 0;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch *error_r = t_strconcat("Unknown or inappropriate command: ", cmd, NULL);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return -1;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch}
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstatic int
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschclient_handle_user_command(struct client *client, const char *cmd,
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch const char *const *args, const char **error_r)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch{
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch struct mail_storage_service_input input;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch struct imap_urlauth_worker_settings *set;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch struct mail_storage_service_user *user;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch struct imap_urlauth_config config;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch struct mail_user *mail_user;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch const char *error;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch unsigned int count;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch int ret;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* "USER\t"<username> */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch *error_r = NULL;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* check command syntax */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (strcmp(cmd, "USER") != 0) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch *error_r = t_strconcat("Unknown or inappropriate command: ",
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch cmd, NULL);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return -1;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (args[0] == NULL || args[1] != NULL) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch *error_r = "USER: Invalid number of parameters";
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return -1;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* lookup user */
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch i_zero(&input);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch input.module = "imap-urlauth-worker";
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch input.service = "imap-urlauth-worker";
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch input.username = args[0];
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (client->debug)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_debug("Looking up user %s", input.username);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch ret = mail_storage_service_lookup_next(storage_service, &input,
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch &user, &mail_user, &error);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (ret < 0) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_error("Failed to lookup user %s: %s", input.username, error);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch client_abort(client, "Session aborted: Failed to lookup user");
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return 0;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch } else if (ret == 0) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (client->debug)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_debug("User %s doesn't exist", input.username);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch client_send_line(client, "NO");
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return 1;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch client->debug = mail_user->mail_debug =
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch client->debug || mail_user->mail_debug;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* drop privileges */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch restrict_access_allow_coredumps(TRUE);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch set = mail_storage_service_user_get_set(user)[1];
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen if (settings_var_expand(&imap_urlauth_worker_setting_parser_info, set,
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen mail_user->pool,
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen mail_user_var_expand_table(mail_user),
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen &error) <= 0) {
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen client_send_line(client, "NO");
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen client_abort(client, t_strdup_printf(
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen "Session aborted: Failed to expand settings: %s", error));
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen return 0;
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (set->verbose_proctitle) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch verbose_proctitle = TRUE;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch imap_urlauth_worker_refresh_proctitle();
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch client->service_user = user;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch client->mail_user = mail_user;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch client->set = set;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (client->debug) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_debug("Found user account `%s' on behalf of user `%s'",
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch mail_user->username, client->access_user);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* initialize urlauth context */
4abdade2cb09266ea3d063d5cb6893cb0583f20eTimo Sirainen if (*set->imap_urlauth_host == '\0') {
4abdade2cb09266ea3d063d5cb6893cb0583f20eTimo Sirainen i_error("imap_urlauth_host setting is not configured for user %s",
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch mail_user->username);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch client_send_line(client, "NO");
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch client_abort(client, "Session aborted: URLAUTH not configured");
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return 0;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch i_zero(&config);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch config.url_host = set->imap_urlauth_host;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch config.url_port = set->imap_urlauth_port;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch config.access_user = client->access_user;
f1edf7f20661ef9627acbf4054acddcba4d2eb3fStephan Bosch config.access_service = client->access_service;
6541da94741ea43514cdac3dd2ebbcf839ffb783Stephan Bosch config.access_anonymous = client->access_anonymous;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch config.access_applications =
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch (const void *)array_get(&client->access_apps, &count);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
4abdade2cb09266ea3d063d5cb6893cb0583f20eTimo Sirainen client->urlauth_ctx = imap_urlauth_init(client->mail_user, &config);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (client->debug) {
f1edf7f20661ef9627acbf4054acddcba4d2eb3fStephan Bosch i_debug("Providing access to user account `%s' on behalf of user `%s' "
f1edf7f20661ef9627acbf4054acddcba4d2eb3fStephan Bosch "using service `%s'", mail_user->username, client->access_user,
f1edf7f20661ef9627acbf4054acddcba4d2eb3fStephan Bosch client->access_service);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
ca4526e3b5fbf5ea3dd477a2098522a44c9ac52cTimo Sirainen i_set_failure_prefix("imap-urlauth[%s](%s->%s): ",
ca4526e3b5fbf5ea3dd477a2098522a44c9ac52cTimo Sirainen my_pid, client->access_user, mail_user->username);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch client_send_line(client, "OK");
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return 1;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch}
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstatic bool client_handle_input(struct client *client)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch{
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch const char *line, *cmd, *error;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch int ret;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
2d8ff6cda406da5c53e635fe31dfadc3bdb05235Timo Sirainen if (client->url != NULL) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* we're still processing a URL. wait until it's
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch finished. */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch io_remove(&client->io);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch client->io = NULL;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch client->waiting_input = TRUE;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return TRUE;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (client->io == NULL) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch client->io = io_add(client->fd_in, IO_READ,
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch client_input, client);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch client->waiting_input = FALSE;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch timeout_reset(client->to_idle);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch switch (i_stream_read(client->input)) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch case -1:
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* disconnected */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (client->ctrl_output != NULL)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch (void)o_stream_send_str(client->ctrl_output, "DISCONNECTED\n");
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch client_destroy(client);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return FALSE;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch case -2:
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* line too long, kill it */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch client_abort(client, "Session aborted: Input line too long");
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return FALSE;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch while ((line = i_stream_next_line(client->input)) != NULL) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch const char *const *args = t_strsplit_tabescaped(line);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (args[0] == NULL)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch continue;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch cmd = args[0]; args++;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (client->mail_user == NULL)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch ret = client_handle_user_command(client, cmd, args, &error);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch else
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch ret = client_handle_command(client, cmd, args, &error);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (ret <= 0) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (ret == 0)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch break;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_error("Client input error: %s", error);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch client_abort(client, "Session aborted: Unexpected input");
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return FALSE;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return TRUE;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch}
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstatic void client_input(struct client *client)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch{
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch (void)client_handle_input(client);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch}
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstatic int client_output(struct client *client)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch{
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (o_stream_flush(client->output) < 0) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (client->ctrl_output != NULL)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch (void)o_stream_send_str(client->ctrl_output, "DISCONNECTED\n");
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch client_destroy(client);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return 1;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch timeout_reset(client->to_idle);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (client->url != NULL) {
4fa772eefd5a22a597601488be44997e788cb60dStephan Bosch if (client_run_url(client) < 0) {
4fa772eefd5a22a597601488be44997e788cb60dStephan Bosch client_destroy(client);
4fa772eefd5a22a597601488be44997e788cb60dStephan Bosch return 1;
4fa772eefd5a22a597601488be44997e788cb60dStephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (client->url == NULL && client->waiting_input) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (!client_handle_input(client)) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* client got destroyed */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return 1;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (client->url != NULL) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* url not finished yet */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return 0;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch } else if (client->io == NULL) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* data still in output buffer, get back here to add IO */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return 0;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch } else {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return 1;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch}
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstatic int
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschclient_ctrl_read_fds(struct client *client)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch{
0bb5699d56b7c9f897ee8e627ae4a8ba4fe0c21bTimo Sirainen unsigned char data = 0;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch ssize_t ret = 1;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (client->fd_in == -1) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch ret = fd_read(client->fd_ctrl, &data,
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch sizeof(data), &client->fd_in);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (ret > 0 && data == '0')
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch client->fd_out = client->fd_in;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (ret > 0 && client->fd_out == -1) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch ret = fd_read(client->fd_ctrl, &data,
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch sizeof(data), &client->fd_out);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (ret == 0) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* unexpectedly disconnected */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch client_destroy(client);
4fa772eefd5a22a597601488be44997e788cb60dStephan Bosch return 0;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch } else if (ret < 0) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (errno == EAGAIN)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return 0;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_error("fd_read() failed: %m");
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return -1;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch } else if (data != '0') {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_error("fd_read() returned invalid byte 0x%2x", data);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return -1;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (client->fd_in == -1 || client->fd_out == -1) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_error("Handshake is missing a file descriptor");
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return -1;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch client->ctrl_input =
e93184a9055c2530366dfe617e07199603c399ddMartti Rannanjärvi i_stream_create_fd(client->fd_ctrl, MAX_INBUF_SIZE);
e93184a9055c2530366dfe617e07199603c399ddMartti Rannanjärvi client->ctrl_output = o_stream_create_fd(client->fd_ctrl, (size_t)-1);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return 1;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch}
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstatic void client_ctrl_input(struct client *client)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch{
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch const char *const *args;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch const char *line;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch int ret;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch timeout_reset(client->to_idle);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (client->fd_in == -1 || client->fd_out == -1) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if ((ret = client_ctrl_read_fds(client)) <= 0) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (ret < 0)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch client_abort(client, "FD Transfer failed");
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch switch (i_stream_read(client->ctrl_input)) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch case -1:
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* disconnected */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch client_destroy(client);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch case -2:
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* line too long, kill it */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch client_abort(client,
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch "Control session aborted: Input line too long");
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (!client->version_received) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if ((line = i_stream_next_line(client->ctrl_input)) == NULL)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (!version_string_verify(line, "imap-urlauth-worker",
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch IMAP_URLAUTH_WORKER_PROTOCOL_MAJOR_VERSION)) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_error("imap-urlauth-worker client not compatible with this server "
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch "(mixed old and new binaries?) %s", line);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch client_abort(client, "Control session aborted: Version mismatch");
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch client->version_received = TRUE;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (o_stream_send_str(client->ctrl_output, "OK\n") < 0) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch client_destroy(client);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (client->access_received) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch client_abort(client, "Control session aborted: Unexpected input");
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if ((line = i_stream_next_line(client->ctrl_input)) == NULL)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch args = t_strsplit_tabescaped(line);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (*args == NULL || strcmp(*args, "ACCESS") != 0) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_error("Invalid control command: %s", str_sanitize(line, 80));
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch client_abort(client, "Control session aborted: Invalid command");
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch args++;
f1edf7f20661ef9627acbf4054acddcba4d2eb3fStephan Bosch if (args[0] == NULL || args[1] == NULL) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_error("Invalid ACCESS command: %s", str_sanitize(line, 80));
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch client_abort(client, "Control session aborted: Invalid command");
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_assert(client->access_user == NULL);
f1edf7f20661ef9627acbf4054acddcba4d2eb3fStephan Bosch i_assert(client->access_service == NULL);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (**args != '\0') {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch client->access_user = i_strdup(*args);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch client->access_anonymous = FALSE;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch } else {
6541da94741ea43514cdac3dd2ebbcf839ffb783Stephan Bosch client->access_user = i_strdup("anonymous");
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch client->access_anonymous = TRUE;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f1edf7f20661ef9627acbf4054acddcba4d2eb3fStephan Bosch args++;
f1edf7f20661ef9627acbf4054acddcba4d2eb3fStephan Bosch client->access_service = i_strdup(*args);
f1edf7f20661ef9627acbf4054acddcba4d2eb3fStephan Bosch
ca4526e3b5fbf5ea3dd477a2098522a44c9ac52cTimo Sirainen i_set_failure_prefix("imap-urlauth[%s](%s): ",
ca4526e3b5fbf5ea3dd477a2098522a44c9ac52cTimo Sirainen my_pid, client->access_user);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch args++;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch while (*args != NULL) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* debug */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (strcasecmp(*args, "debug") == 0) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch client->debug = TRUE;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* apps=<access-application>[,<access-application,...] */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch } else if (strncasecmp(*args, "apps=", 5) == 0 &&
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch (*args)[5] != '\0') {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch const char *const *apps = t_strsplit(*args+5, ",");
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch while (*apps != NULL) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch char *app = i_strdup(*apps);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch array_append(&client->access_apps, &app, 1);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (client->debug) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_debug("User %s has URLAUTH %s access",
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch client->access_user, app);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch apps++;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch } else {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_error("Invalid ACCESS parameter: %s", str_sanitize(*args, 80));
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch client_abort(client, "Control session aborted: Invalid command");
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch args++;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch client->access_received = TRUE;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (o_stream_send_str(client->ctrl_output, "OK\n") < 0) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch client_destroy(client);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
e93184a9055c2530366dfe617e07199603c399ddMartti Rannanjärvi client->input = i_stream_create_fd(client->fd_in, MAX_INBUF_SIZE);
e93184a9055c2530366dfe617e07199603c399ddMartti Rannanjärvi client->output = o_stream_create_fd(client->fd_out, (size_t)-1);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch client->io = io_add(client->fd_in, IO_READ, client_input, client);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch o_stream_set_flush_callback(client->output, client_output, client);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (client->debug) {
f1edf7f20661ef9627acbf4054acddcba4d2eb3fStephan Bosch i_debug("Worker activated for access by user `%s' using service `%s'",
f1edf7f20661ef9627acbf4054acddcba4d2eb3fStephan Bosch client->access_user, client->access_service);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch}
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstatic void imap_urlauth_worker_die(void)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch{
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* do nothing */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch}
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstatic void main_stdio_run(const char *access_user,
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch const char *const *access_applications)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch{
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch bool debug;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
01243115311a0da7c65bdce6d6e0b9632ff97186Timo Sirainen debug = getenv("DEBUG") != NULL;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch access_user = access_user != NULL ? access_user : getenv("USER");
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (access_user == NULL && IS_STANDALONE())
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch access_user = getlogin();
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (access_user == NULL)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_fatal("USER environment missing");
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch (void)client_create_standalone(access_user, access_applications,
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch STDIN_FILENO, STDOUT_FILENO, debug);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch}
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschstatic void client_connected(struct master_service_connection *conn)
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch{
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch master_service_client_connection_accept(conn);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch (void)client_create(conn->fd);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch}
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Boschint main(int argc, char *argv[])
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch{
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch static const struct setting_parser_info *set_roots[] = {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch &imap_urlauth_worker_setting_parser_info,
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch NULL
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch };
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch enum master_service_flags service_flags = 0;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch enum mail_storage_service_flags storage_service_flags =
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP |
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch MAIL_STORAGE_SERVICE_FLAG_NO_LOG_INIT;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch ARRAY_TYPE (const_string) access_apps;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch const char *access_user = NULL;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch int c;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (IS_STANDALONE()) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch service_flags |= MASTER_SERVICE_FLAG_STANDALONE |
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch MASTER_SERVICE_FLAG_STD_CLIENT;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch } else {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch service_flags |= MASTER_SERVICE_FLAG_KEEP_CONFIG_OPEN;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch master_service = master_service_init("imap-urlauth-worker", service_flags,
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch &argc, &argv, "a:");
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch t_array_init(&access_apps, 4);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch while ((c = master_getopt(master_service)) > 0) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch switch (c) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch case 'a': {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch const char *app = t_strdup(optarg);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch array_append(&access_apps, &app, 1);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch break;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch default:
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return FATAL_DEFAULT;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if ( optind < argc ) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch access_user = argv[optind++];
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (optind != argc) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch i_fatal_status(EX_USAGE, "Unknown argument: %s", argv[optind]);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch master_service_init_log(master_service,
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch t_strdup_printf("imap-urlauth[%s]: ", my_pid));
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch master_service_set_die_callback(master_service, imap_urlauth_worker_die);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch storage_service =
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch mail_storage_service_init(master_service,
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch set_roots, storage_service_flags);
d6b3cfd855c0eebed68be50d3111de1b5a6afeb0Timo Sirainen master_service_init_finish(master_service);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch /* fake that we're running, so we know if client was destroyed
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch while handling its initial input */
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch io_loop_set_running(current_ioloop);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (IS_STANDALONE()) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch T_BEGIN {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (array_count(&access_apps) > 0) {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch (void)array_append_space(&access_apps);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch main_stdio_run(access_user, array_idx(&access_apps,0));
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch } else {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch main_stdio_run(access_user, NULL);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch } T_END;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch } else {
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch io_loop_set_running(current_ioloop);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch }
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch if (io_loop_is_running(current_ioloop))
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch master_service_run(master_service, client_connected);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch clients_destroy_all();
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch mail_storage_service_deinit(&storage_service);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch master_service_deinit(&master_service);
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch return 0;
f9511e684858bf5f6ac77ab12254b85b737beae8Stephan Bosch}