/* Copyright (c) 2013-2018 Dovecot authors, see the included COPYING file */
/*
The imap-urlauth service provides URLAUTH access between different accounts. If
user A has an URLAUTH that references a mail from user B, it makes a connection
to the imap-urlauth service to access user B's mail store to retrieve the
mail.
The authentication and authorization of the URLAUTH is performed within
this service. Because access to the mailbox and the associated mailbox keys is
necessary to retrieve the message and for verification of the URLAUTH, the
urlauth services need root privileges. To mitigate security concerns, the
retrieval and verification of the URLs is performed in a worker service that
drops root privileges and acts as target user B.
The imap-urlauth service thus consists of three separate stages:
- imap-urlauth-login:
This is the login service which operates identical to imap-login and
pop3-login equivalents, except for the fact that only token authentication is
allowed. It verifies that the connecting client is an IMAP service acting on
behaf of an authenticated user.
- imap-urlauth:
Once the client is authenticated, the connection gets passed to the
imap-urlauth service (as implemented here). The goal of this stage is
to prevent the need for re-authenticating to the imap-urlauth service when
the clients wants to switch to a different target user. It normally runs as
$default_internal_user and starts workers to perform the actual work. To start
a worker, the imap-urlauth service establishes a control connection to the
imap-urlauth-worker service. In the handshake phase of the control protocol,
the connection of the client is passed to the worker. Once the worker
finishes, a new worker is started and the client connection is transfered to
it, unless the client is disconnected.
- imap-urlauth-worker:
The worker handles the URLAUTH requests from the client, so this is where the
mail store of the target user is accessed. The worker starts as root. In the
protocol interaction the client first indicates what the target user is.
The worker then performs a userdb lookup and drops privileges. The client can
then submit URLAUTH requests, which are limited to that user. Once the client
wants to access a different user, the worker terminates and the imap-urlauth
service starts a new worker for the next target user.
*/
#include "imap-urlauth-common.h"
#include "lib-signals.h"
#include "ioloop.h"
#include "buffer.h"
#include "array.h"
#include "istream.h"
#include "ostream.h"
#include "path-util.h"
#include "base64.h"
#include "str.h"
#include "process-title.h"
#include "auth-master.h"
#include "master-service.h"
#include "master-service-settings.h"
#include "master-login.h"
#include "master-interface.h"
#include "var-expand.h"
#include <stdio.h>
#include <unistd.h>
#define IS_STANDALONE() \
void imap_urlauth_refresh_proctitle(void)
{
if (!verbose_proctitle)
return;
switch (imap_urlauth_client_count) {
case 0:
break;
case 1:
break;
default:
break;
}
}
static void imap_urlauth_die(void)
{
/* do nothing. imap_urlauth connections typically die pretty quick anyway. */
}
static int
{
imap_urlauth_settings, &client) < 0)
return -1;
if (!IS_STANDALONE())
return 0;
}
{
i_fatal("USER environment missing");
}
static void
const char *username, const char *const *extra_fields)
{
const char *const *fields;
unsigned int count, i;
/* check peer credentials if possible */
i_error("Peer's credentials (uid=%ld) do not match "
"the user that logged in (uid=%ld).",
/* ignored */
}
return;
}
for (i = 0; i < count; i++) {
break;
}
}
i_error("Auth did not yield required client_service field (BUG).");
/* ignored */
}
return;
}
}
const char *errormsg ATTR_UNUSED)
{
/* ignored */
}
}
{
/* when running standalone, we shouldn't even get here */
}
{
};
void **sets;
int c;
if (IS_STANDALONE() && getuid() == 0 &&
printf("NO imap_urlauth binary must not be started from "
"inetd, use imap-urlauth-login instead.\n");
return 1;
}
if (IS_STANDALONE()) {
} else {
}
while ((c = master_getopt(master_service)) > 0) {
switch (c) {
case 'a':
break;
default:
return FATAL_DEFAULT;
}
}
&error) < 0)
imap_urlauth_settings = sets[0];
}
/* fake that we're running, so we know if client was destroyed
while handling its initial input */
if (IS_STANDALONE()) {
T_BEGIN {
} T_END;
} else {
}
if (master_login != NULL)
return 0;
}