#include "dma.h"
static int
-init_cert_file(struct qitem *it, SSL_CTX *ctx, const char *path)
+init_cert_file(SSL_CTX *ctx, const char *path)
{
int error;
/* Load certificate into ctx */
error = SSL_CTX_use_certificate_chain_file(ctx, path);
if (error < 1) {
- syslog(LOG_ERR, "%s: SSL: Cannot load certificate `%s': %s",
- it->queueid, path, ssl_errstr());
+ syslog(LOG_ERR, "SSL: Cannot load certificate `%s': %s", path, ssl_errstr());
return (-1);
}
/* Add private key to ctx */
error = SSL_CTX_use_PrivateKey_file(ctx, path, SSL_FILETYPE_PEM);
if (error < 1) {
- syslog(LOG_ERR, "%s: SSL: Cannot load private key `%s': %s",
- it->queueid, path, ssl_errstr());
+ syslog(LOG_ERR, "SSL: Cannot load private key `%s': %s", path, ssl_errstr());
return (-1);
}
*/
error = SSL_CTX_check_private_key(ctx);
if (error < 1) {
- syslog(LOG_ERR, "%s: SSL: Cannot check private key: %s",
- it->queueid, ssl_errstr());
+ syslog(LOG_ERR, "SSL: Cannot check private key: %s", ssl_errstr());
return (-1);
}
}
int
-smtp_init_crypto(struct qitem *it, int fd, int feature)
+smtp_init_crypto(int fd, int feature)
{
SSL_CTX *ctx = NULL;
SSL_METHOD *meth = NULL;
ctx = SSL_CTX_new(meth);
if (ctx == NULL) {
- syslog(LOG_WARNING, "%s: remote delivery deferred: SSL init failed: %s",
- it->queueid, ssl_errstr());
+ syslog(LOG_WARNING, "remote delivery deferred: SSL init failed: %s", ssl_errstr());
return (1);
}
/* User supplied a certificate */
if (config->certfile != NULL) {
- error = init_cert_file(it, ctx, config->certfile);
+ error = init_cert_file(ctx, config->certfile);
if (error) {
- syslog(LOG_WARNING, "%s: remote delivery deferred", it->queueid);
+ syslog(LOG_WARNING, "remote delivery deferred");
return (1);
}
}
if (read_remote(fd, 0, NULL) == 2) {
send_remote_command(fd, "STARTTLS");
if (read_remote(fd, 0, NULL) != 2) {
- syslog(LOG_ERR, "%s: remote delivery deferred:"
- " STARTTLS not available: %s", it->queueid,
- neterr);
+ syslog(LOG_ERR, "remote delivery deferred:"
+ " STARTTLS not available: %s", neterr);
config->features &= ~NOSSL;
return (1);
}
config->ssl = SSL_new(ctx);
if (config->ssl == NULL) {
- syslog(LOG_NOTICE, "%s: remote delivery deferred: SSL struct creation failed: %s",
- it->queueid, ssl_errstr());
+ syslog(LOG_NOTICE, "remote delivery deferred: SSL struct creation failed: %s",
+ ssl_errstr());
return (1);
}
/* Set fd for SSL in/output */
error = SSL_set_fd(config->ssl, fd);
if (error == 0) {
- syslog(LOG_NOTICE, "%s: remote delivery deferred: SSL set fd failed: %s",
- it->queueid, ssl_errstr());
+ syslog(LOG_NOTICE, "remote delivery deferred: SSL set fd failed: %s",
+ ssl_errstr());
return (1);
}
/* Open SSL connection */
error = SSL_connect(config->ssl);
if (error < 0) {
- syslog(LOG_ERR, "%s: remote delivery deferred: SSL handshake failed fatally: %s",
- it->queueid, ssl_errstr());
+ syslog(LOG_ERR, "remote delivery deferred: SSL handshake failed fatally: %s",
+ ssl_errstr());
return (1);
}
/* Get peer certificate */
cert = SSL_get_peer_certificate(config->ssl);
if (cert == NULL) {
- syslog(LOG_WARNING, "%s: remote delivery deferred: Peer did not provide certificate: %s",
- it->queueid, ssl_errstr());
+ syslog(LOG_WARNING, "remote delivery deferred: Peer did not provide certificate: %s",
+ ssl_errstr());
}
X509_free(cert);
* CRAM-MD5 authentication
*/
int
-smtp_auth_md5(struct qitem *it, int fd, char *login, char *password)
+smtp_auth_md5(int fd, char *login, char *password)
{
unsigned char buffer[BUF_SIZE], digest[BUF_SIZE], ascii_digest[33];
char *temp;
/* Send AUTH command according to RFC 2554 */
send_remote_command(fd, "AUTH CRAM-MD5");
if (read_remote(fd, sizeof(buffer), buffer) != 3) {
- syslog(LOG_DEBUG, "%s: smarthost authentification:"
- " AUTH cram-md5 not available: %s", it->queueid,
- neterr);
+ syslog(LOG_DEBUG, "smarthost authentification:"
+ " AUTH cram-md5 not available: %s", neterr);
/* if cram-md5 is not available */
return (-1);
}
/* encode answer */
len = base64_encode(buffer, strlen(buffer), &temp);
if (len < 0) {
- syslog(LOG_ERR, "%s: can not encode auth reply: %m",
- it->queueid);
+ syslog(LOG_ERR, "can not encode auth reply: %m");
return (-1);
}
send_remote_command(fd, "%s", temp);
free(temp);
if (read_remote(fd, 0, NULL) != 2) {
- syslog(LOG_WARNING, "%s: remote delivery deferred:"
- " AUTH cram-md5 failed: %s", it->queueid,
- neterr);
+ syslog(LOG_WARNING, "remote delivery deferred:"
+ " AUTH cram-md5 failed: %s", neterr);
return (-2);
}
struct config *config;
static const char *username;
static uid_t uid;
+static const char *logident_base;
const char *
return name;
}
+static void
+setlogident(const char *fmt, ...)
+{
+ char *tag = NULL;
+
+ if (fmt != NULL) {
+ va_list ap;
+ char *sufx;
+
+ va_start(ap, fmt);
+ vasprintf(&sufx, fmt, ap);
+ if (sufx != NULL) {
+ asprintf(&tag, "%s[%s]", logident_base, sufx);
+ free(sufx);
+ }
+ va_end(ap);
+ }
+ closelog();
+ openlog(tag != NULL ? tag : logident_base, 0, LOG_MAIL);
+}
+
static const char *
check_username(const char *name, uid_t ckuid)
{
error = snprintf(line, sizeof(line),
"Received: from %s (uid %d)\n"
"\t(envelope-from %s)\n"
- "\tid %"PRIxMAX"\n"
+ "\tid %s\n"
"\tby %s (%s)\n"
"\t%s\n",
username, uid,
} else if (!had_messagid) {
/* XXX better msgid, assign earlier and log? */
had_messagid = 1;
- snprintf(line, sizeof(line), "Message-Id: <%"PRIxMAX"@%s>\n",
+ snprintf(line, sizeof(line), "Message-Id: <%s@%s>\n",
queue->id, hostname());
} else if (!had_from) {
had_from = 1;
}
if (fsync(queue->mailfd) != 0)
return (-1);
+
+ syslog(LOG_INFO, "new mail from user=%s uid=%d envelope_from=<%s>",
+ username, uid, sender);
+
return (0);
}
LIST_FOREACH(it, &queue->queue, next) {
/* No need to fork for the last dest */
- if (LIST_NEXT(it, next) == NULL)
+ if (LIST_NEXT(it, next) == NULL) {
+ setlogident("%s", it->queueid);
return (it);
+ }
pid = fork();
switch (pid) {
*
* return and deliver mail
*/
+ setlogident("%s", it->queueid);
return (it);
default:
/* Don't bounce bounced mails */
if (it->sender[0] == 0) {
- syslog(LOG_INFO, "%s: can not bounce a bounce message, discarding",
- it->queueid);
+ syslog(LOG_INFO, "can not bounce a bounce message, discarding");
exit(1);
}
- syslog(LOG_ERR, "%s: delivery failed, bouncing",
- it->queueid);
-
LIST_INIT(&bounceq.queue);
if (add_recp(&bounceq, it->sender, "", 1) != 0)
goto fail;
if (newspoolf(&bounceq, "") != 0)
goto fail;
+
+ syslog(LOG_ERR, "delivery failed, bouncing as %s", bounceq.id);
+ setlogident("%s", bounceq.id);
+
bit = LIST_FIRST(&bounceq.queue);
error = fprintf(bit->mailf,
"Received: from MAILER-DAEMON\n"
- "\tid %"PRIxMAX"\n"
+ "\tid %s\n"
"\tby %s (%s)\n"
"\t%s\n"
"X-Original-To: <%s>\n"
"From: MAILER-DAEMON <>\n"
"To: %s\n"
"Subject: Mail delivery failed\n"
- "Message-Id: <%"PRIxMAX"@%s>\n"
+ "Message-Id: <%s@%s>\n"
"Date: %s\n"
"\n"
"This is the %s at %s.\n"
/* NOTREACHED */
fail:
- syslog(LOG_CRIT, "%s: error creating bounce: %m", it->queueid);
+ syslog(LOG_CRIT, "error creating bounce: %m");
delqueue(it);
exit(1);
}
struct timeval now;
struct stat st;
- syslog(LOG_INFO, "%s: mail from=<%s> to=<%s>",
- it->queueid, it->sender, it->addr);
-
retry:
- syslog(LOG_INFO, "%s: trying delivery",
- it->queueid);
+ syslog(LOG_INFO, "trying delivery");
if (it->remote)
error = deliver_remote(it, &errmsg);
switch (error) {
case 0:
delqueue(it);
- syslog(LOG_INFO, "%s: delivery successful",
- it->queueid);
+ syslog(LOG_INFO, "delivery successful");
exit(0);
case 1:
if (stat(it->queuefn, &st) != 0) {
- syslog(LOG_ERR, "%s: lost queue file `%s'",
- it->queueid, it->queuefn);
+ syslog(LOG_ERR, "lost queue file `%s'", it->queuefn);
exit(1);
}
if (gettimeofday(&now, NULL) == 0 &&
main(int argc, char **argv)
{
char *sender = NULL;
- const char *tag = "dma";
struct qitem *it;
struct queue queue;
struct queue lqueue;
daemonize = 0;
break;
case 'L':
- tag = optarg;
+ logident_base = optarg;
break;
case 'f':
case 'r':
errx(1, "conflicting queue operations");
skipopts:
- openlog(tag, LOG_PID, LOG_MAIL);
+ if (logident_base == NULL)
+ logident_base = "dma";
+ setlogident(NULL);
set_username();
/* XXX fork root here */
if (newspoolf(&queue, sender) != 0)
err(1, "can not create temp file");
+ setlogident("%s", queue.id);
+
if (readmail(&queue, sender, nodot) != 0)
err(1, "can not read mail");
struct queue {
struct queueh queue;
- uintmax_t id;
+ char *id;
int mailfd;
char *tmpf;
};
/* crypto.c */
void hmac_md5(unsigned char *, int, unsigned char *, int, caddr_t);
-int smtp_auth_md5(struct qitem *, int, char *, char *);
-int smtp_init_crypto(struct qitem *, int, int);
+int smtp_auth_md5(int, char *, char *);
+int smtp_init_crypto(int, int);
/* net.c */
char *ssl_errstr(void);
error = snprintf(fn, sizeof(fn), "%s/%s", _PATH_MAILDIR, it->addr);
if (error < 0 || (size_t)error >= sizeof(fn)) {
- syslog(LOG_NOTICE, "%s: local delivery deferred: %m",
- it->queueid);
+ syslog(LOG_NOTICE, "local delivery deferred: %m");
return (1);
}
/* mailx removes users mailspool file if empty, so open with O_CREAT */
mbox = open_locked(fn, O_WRONLY | O_APPEND | O_CREAT);
if (mbox < 0) {
- syslog(LOG_NOTICE, "%s: local delivery deferred: can not open `%s': %m",
- it->queueid, fn);
+ syslog(LOG_NOTICE, "local delivery deferred: can not open `%s': %m", fn);
return (1);
}
mboxlen = lseek(mbox, 0, SEEK_CUR);
if (fseek(it->mailf, it->hdrlen, SEEK_SET) != 0) {
- syslog(LOG_NOTICE, "%s: local delivery deferred: can not seek: %m",
- it->queueid);
+ syslog(LOG_NOTICE, "local delivery deferred: can not seek: %m");
return (1);
}
error = snprintf(line, sizeof(line), "From %s\t%s", it->sender, ctime(&now));
if (error < 0 || (size_t)error >= sizeof(line)) {
- syslog(LOG_NOTICE, "%s: local delivery deferred: can not write header: %m",
- it->queueid);
+ syslog(LOG_NOTICE, "local delivery deferred: can not write header: %m");
return (1);
}
if (write(mbox, line, error) != error)
break;
linelen = strlen(line);
if (linelen == 0 || line[linelen - 1] != '\n') {
- syslog(LOG_CRIT, "%s: local delivery failed: corrupted queue file",
- it->queueid);
+ syslog(LOG_CRIT, "local delivery failed: corrupted queue file");
*errmsg = "corrupted queue file";
error = -1;
goto chop;
return (0);
wrerror:
- syslog(LOG_ERR, "%s: local delivery failed: write error: %m",
- it->queueid);
+ syslog(LOG_ERR, "local delivery failed: write error: %m");
error = 1;
chop:
if (ftruncate(mbox, mboxlen) != 0)
- syslog(LOG_WARNING, "%s: error recovering mbox `%s': %m",
- it->queueid, fn);
+ syslog(LOG_WARNING, "error recovering mbox `%s': %m", fn);
close(mbox);
return (error);
}
* Handle SMTP authentication
*/
static int
-smtp_login(struct qitem *it, int fd, char *login, char* password)
+smtp_login(int fd, char *login, char* password)
{
char *temp;
int len, res = 0;
- res = smtp_auth_md5(it, fd, login, password);
+ res = smtp_auth_md5(fd, login, password);
if (res == 0) {
return (0);
} else if (res == -2) {
/* Send AUTH command according to RFC 2554 */
send_remote_command(fd, "AUTH LOGIN");
if (read_remote(fd, 0, NULL) != 3) {
- syslog(LOG_NOTICE, "%s: remote delivery deferred:"
+ syslog(LOG_NOTICE, "remote delivery deferred:"
" AUTH login not available: %s",
- it->queueid, neterr);
+ neterr);
return (1);
}
len = base64_encode(login, strlen(login), &temp);
if (len < 0) {
encerr:
- syslog(LOG_ERR, "%s: can not encode auth reply: %m",
- it->queueid);
+ syslog(LOG_ERR, "can not encode auth reply: %m");
return (1);
}
free(temp);
res = read_remote(fd, 0, NULL);
if (res != 3) {
- syslog(LOG_NOTICE, "%s: remote delivery %s: AUTH login failed: %s",
- it->queueid, res == 5 ? "failed" : "deferred", neterr);
+ syslog(LOG_NOTICE, "remote delivery %s: AUTH login failed: %s",
+ res == 5 ? "failed" : "deferred", neterr);
return (res == 5 ? -1 : 1);
}
free(temp);
res = read_remote(fd, 0, NULL);
if (res != 2) {
- syslog(LOG_NOTICE, "%s: remote delivery %s: Authentication failed: %s",
- it->queueid, res == 5 ? "failed" : "deferred", neterr);
+ syslog(LOG_NOTICE, "remote delivery %s: Authentication failed: %s",
+ res == 5 ? "failed" : "deferred", neterr);
return (res == 5 ? -1 : 1);
}
} else {
- syslog(LOG_WARNING, "%s: non-encrypted SMTP login is disabled in config, so skipping it. ",
- it->queueid);
+ syslog(LOG_WARNING, "non-encrypted SMTP login is disabled in config, so skipping it. ");
return (1);
}
}
static int
-open_connection(struct qitem *it, const char *host)
+open_connection(const char *host)
{
struct addrinfo hints, *res, *res0;
char servname[128];
snprintf(servname, sizeof(servname), "%d", port);
error = getaddrinfo(host, servname, &hints, &res0);
if (error) {
- syslog(LOG_NOTICE, "%s: remote delivery deferred: "
- "%s: %m", it->queueid, gai_strerror(error));
+ syslog(LOG_NOTICE, "remote delivery deferred: %s", gai_strerror(error));
return (-1);
}
fd = -1;
break;
}
if (fd < 0) {
- syslog(LOG_NOTICE, "%s: remote delivery deferred: %s (%s:%s)",
- it->queueid, errmsg, host, servname);
+ syslog(LOG_NOTICE, "remote delivery deferred: %s (%s:%s)",
+ errmsg, host, servname);
freeaddrinfo(res0);
return (-1);
}
/* Smarthost support? */
if (config->smarthost != NULL && strlen(config->smarthost) > 0) {
- syslog(LOG_INFO, "%s: using smarthost (%s:%i)",
- it->queueid, config->smarthost, config->port);
+ syslog(LOG_INFO, "using smarthost (%s:%i)",
+ config->smarthost, config->port);
host = config->smarthost;
}
- fd = open_connection(it, host);
+ fd = open_connection(host);
if (fd < 0)
return (1);
config->features |= NOSSL;
res = read_remote(fd, 0, NULL);
if (res != 2) {
- syslog(LOG_WARNING, "%s: Invalid initial response: %i",
- it->queueid, res);
+ syslog(LOG_WARNING, "Invalid initial response: %i", res);
return(1);
}
config->features &= ~NOSSL;
if ((config->features & SECURETRANS) != 0) {
- error = smtp_init_crypto(it, fd, config->features);
+ error = smtp_init_crypto(fd, config->features);
if (error >= 0)
- syslog(LOG_DEBUG, "%s: SSL initialization successful",
- it->queueid);
+ syslog(LOG_DEBUG, "SSL initialization successful");
else
goto out;
}
send_remote_command(fd, "EHLO %s", hostname());
if (read_remote(fd, 0, NULL) != 2) {
- syslog(LOG_WARNING, "%s: remote delivery deferred: "
- " EHLO failed: %s", it->queueid, neterr);
+ syslog(LOG_WARNING, "remote delivery deferred: EHLO failed: %s", neterr);
asprintf(errmsgc, "%s did not like our EHLO:\n%s",
host, neterr);
return (-1);
* Check if the user wants plain text login without using
* encryption.
*/
- syslog(LOG_INFO, "%s: Use SMTP authentication",
- it->queueid);
- error = smtp_login(it, fd, a->login, a->password);
+ syslog(LOG_INFO, "using SMTP authentication");
+ error = smtp_login(fd, a->login, a->password);
if (error < 0) {
- syslog(LOG_ERR, "%s: remote delivery failed:"
- " SMTP login failed: %m", it->queueid);
+ syslog(LOG_ERR, "remote delivery failed:"
+ " SMTP login failed: %m");
asprintf(errmsgc, "SMTP login to %s failed", host);
return (-1);
}
/* SMTP login is not available, so try without */
- else if (error > 0)
- syslog(LOG_WARNING, "%s: SMTP login not available."
- " Try without", it->queueid);
+ else if (error > 0) {
+ syslog(LOG_WARNING, "SMTP login not available. Trying without.");
+ }
}
#define READ_REMOTE_CHECK(c, exp) \
res = read_remote(fd, 0, NULL); \
if (res == 5) { \
- syslog(LOG_ERR, "%s: remote delivery failed: " \
- c " failed: %s", it->queueid, neterr); \
+ syslog(LOG_ERR, "remote delivery failed: " \
+ c " failed: %s", neterr); \
asprintf(errmsgc, "%s did not like our " c ":\n%s", \
host, neterr); \
return (-1); \
} else if (res != exp) { \
- syslog(LOG_NOTICE, "%s: remote delivery deferred: " \
- c " failed: %s", it->queueid, neterr); \
+ syslog(LOG_NOTICE, "remote delivery deferred: " \
+ c " failed: %s", neterr); \
return (1); \
}
READ_REMOTE_CHECK("DATA", 3);
if (fseek(it->mailf, it->hdrlen, SEEK_SET) != 0) {
- syslog(LOG_ERR, "%s: remote delivery deferred: cannot seek: %s",
- it->queueid, neterr);
+ syslog(LOG_ERR, "remote delivery deferred: cannot seek: %s", neterr);
return (1);
}
break;
linelen = strlen(line);
if (linelen == 0 || line[linelen - 1] != '\n') {
- syslog(LOG_CRIT, "%s: remote delivery failed:"
- "corrupted queue file", it->queueid);
+ syslog(LOG_CRIT, "remote delivery failed: corrupted queue file");
*errmsg = "corrupted queue file";
error = -1;
goto out;
linelen++;
if (send_remote_command(fd, "%s", line) != (ssize_t)linelen+1) {
- syslog(LOG_NOTICE, "%s: remote delivery deferred: "
- "write error", it->queueid);
+ syslog(LOG_NOTICE, "remote delivery deferred: write error");
error = 1;
goto out;
}
send_remote_command(fd, "QUIT");
if (read_remote(fd, 0, NULL) != 2)
- syslog(LOG_INFO, "%s: remote delivery succeeded but "
- "QUIT failed: %s", it->queueid, neterr);
+ syslog(LOG_INFO, "remote delivery succeeded but QUIT failed: %s", neterr);
out:
close_connection(fd);
#include <fcntl.h>
#include <inttypes.h>
#include <unistd.h>
+#include <syslog.h>
#include "dma.h"
{
char line[1000]; /* by RFC2822 */
char fn[PATH_MAX+1];
+ struct stat st;
struct stritem *t;
struct qitem *it;
FILE *mailf;
it->hdrlen = hdrlen;
}
+ /*
+ * Assign queue id
+ */
+ if (fstat(queue->mailfd, &st) != 0)
+ return (-1);
+ if (asprintf(&queue->id, "%"PRIxMAX, st.st_ino) < 0)
+ return (-1);
+
t = malloc(sizeof(*t));
if (t != NULL) {
t->str = queue->tmpf;
int queuefd;
struct qitem *it;
- /*
- * Assign queue id to each dest.
- */
- if (fstat(queue->mailfd, &st) != 0)
- return (-1);
- queue->id = st.st_ino;
-
- /* XXX put this to a better place
- syslog(LOG_INFO, "%"PRIxMAX": new mail from user=%s uid=%d envelope_from=<%s>",
- queue->id, username, uid, sender);
- */
-
LIST_FOREACH(it, &queue->queue, next) {
- if (asprintf(&it->queueid, "%"PRIxMAX".%"PRIxPTR, queue->id, (uintptr_t)it) <= 0)
+ if (asprintf(&it->queueid, "%s.%"PRIxPTR, queue->id, (uintptr_t)it) <= 0)
goto delfiles;
if (asprintf(&it->queuefn, "%s/Q%s", config->spooldir, it->queueid) <= 0)
goto delfiles;
goto delfiles;
}
- /* XXX
- syslog(LOG_INFO, "%"PRIxMAX": mail to=<%s> queued as %s",
- queue->id, it->addr, it->queueid);
- */
+ LIST_FOREACH(it, &queue->queue, next) {
+ syslog(LOG_INFO, "mail to=<%s> queued as %s",
+ it->addr, it->queueid);
+ }
unlink(queue->tmpf);
return (0);