/* Copyright (c) 2005-2018 Dovecot authors, see the included COPYING file */
#include "lib.h"
#include "lib-signals.h"
#include "ioloop.h"
#include "env-util.h"
#include "istream.h"
#include "istream-seekable.h"
#include "path-util.h"
#include "safe-mkstemp.h"
#include "eacces-error.h"
#include "ipwd.h"
#include "str.h"
#include "str-sanitize.h"
#include "strescape.h"
#include "unichar.h"
#include "rfc822-parser.h"
#include "message-address.h"
#include "smtp-address.h"
#include "settings-parser.h"
#include "master-service.h"
#include "master-service-settings.h"
#include "mail-storage-service.h"
#include "mail-namespace.h"
#include "raw-storage.h"
#include "mail-deliver.h"
#include "mail-send.h"
#include "mbox-from.h"
#include "smtp-submit-settings.h"
#include "lda-settings.h"
#include <stdio.h>
#include <sysexits.h>
#define DEFAULT_ENVELOPE_SENDER \
/* After buffer grows larger than this, create a temporary file to /tmp
where to read the mail. */
static const char *wanted_headers[] = {
"From", "To", "Message-ID", "Subject", "Return-Path",
};
{
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 struct istream *
{
const unsigned char *data;
const char *error;
/* If input begins with a From-line, drop it */
/* skip until the first LF */
for (i = 0; i < size; i++) {
if (data[i] == '\n')
break;
}
if (i != size) {
&sender);
break;
}
}
}
/* use the envelope sender from From_-line, but only if it
hasn't been specified with -f already. */
i_warning("Failed to parse address from `From_'-line: %s",
error);
}
}
} else {
}
return input;
}
static struct mail *
{
struct mailbox_transaction_context *t;
void **sets;
int ret;
} else {
}
if (ret < 0) {
i_fatal("Can't open delivery mail as raw: %s",
}
return mail;
}
static void
const char *rcpt_to_source)
{
const char *error;
}
"Cannot obtain SMTP address from username `%s': %s",
}
rcpt_to_source = "user@hostname";
}
i_debug("Destination address: %s (source: %s)",
}
}
{
/* we want all our exit codes to be sysexits.h compatible.
if we failed because of a logging related error, we most likely
aren't writing to stderr, so try writing there to give some kind of
a clue what's wrong. FATAL_LOGOPEN failure already wrote to
stderr, so don't duplicate it. */
switch (*status) {
case FATAL_LOGWRITE:
break;
case FATAL_LOGERROR:
break;
case FATAL_LOGOPEN:
case FATAL_OUTOFMEM:
case FATAL_EXEC:
case FATAL_DEFAULT:
break;
default:
return;
}
*status = EX_TEMPFAIL;
}
static void print_help(void)
{
"Usage: dovecot-lda [-c <config file>] [-a <address>] [-d <username>] [-p <path>]\n"
" [-f <envelope sender>] [-m <mailbox>] [-e] [-k]\n");
}
{
};
int ret, c;
/* running setuid - don't allow this if the binary is
executable by anyone */
return EX_TEMPFAIL;
"and setuid-root. This allows root exploits. "
"See http://wiki2.dovecot.org/LDA#multipleuids\n",
argv[0]);
return EX_TEMPFAIL;
}
}
while ((c = master_getopt(master_service)) > 0) {
switch (c) {
case 'a':
/* original recipient address */
"Invalid -a parameter: %s", errstr);
}
rcpt_to_source = "-a parameter";
break;
case 'd':
/* destination user */
break;
case 'e':
break;
case 'f':
/* envelope sender address */
"Invalid -f parameter: %s", errstr);
}
break;
case 'm':
/* destination mailbox.
Ignore -m "". This allows doing -m ${extension}
in Postfix to handle user+mailbox */
if (!uni_utf8_str_is_valid(optarg)) {
i_fatal("Mailbox name not UTF-8: %s",
optarg);
}
} T_END;
break;
case 'p':
/* input path */
i_fatal("t_abspath(%s) failed: %s",
}
break;
case 'r':
/* final recipient address */
&final_rcpt_to, &errstr) < 0) {
"Invalid -a parameter: %s", errstr);
}
break;
default:
print_help();
return EX_USAGE;
}
}
print_help();
}
process_euid = geteuid();
if ((service_flags & MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP) != 0)
;
else if (process_euid != 0) {
/* we're non-root. get our username and possibly our home. */
const char *home;
/* no need for a pw lookup */
user_source = "USER environment";
user_source = "passwd lookup for process euid";
} else if (ret < 0) {
/* temporary failure */
i_fatal("getpwuid() failed: %m");
"Couldn't lookup our username (uid=%s)",
}
} else {
"destination user parameter (-d user) not given");
}
/* set before looking up the user (or ideally we'd do this between
_lookup() and _next(), but don't bother) */
&errstr);
if (ret <= 0) {
if (ret < 0)
return EX_NOUSER;
}
#ifdef SIGXFSZ
#endif
&errstr);
if (ret > 0) {
&errstr);
}
if (ret <= 0)
i_debug("userdb lookup skipped, username taken from %s",
}
} else {
/* This shouldn't happen */
i_error("BUG: Saving failed to unknown storage");
return EX_TEMPFAIL;
}
if (stderr_rejection) {
/* write to stderr also for tempfails so that MTA
can log the reason if it wants to. */
}
if (error != MAIL_ERROR_NOQUOTA ||
/* Saving to INBOX should always work unless
we're over quota. If it didn't, it's probably a
configuration problem. */
return EX_TEMPFAIL;
}
/* we'll have to reply with permanent failure */
if (stderr_rejection)
return EX_NOPERM;
if (ret != 0)
/* ok, rejection sent */
}
{
struct mailbox_transaction_context *t =
mailbox_free(&box);
}
return EX_OK;
}