summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr.sbin/smtpd/bounce.c17
-rw-r--r--usr.sbin/smtpd/client.c121
-rw-r--r--usr.sbin/smtpd/client.h10
-rw-r--r--usr.sbin/smtpd/enqueue.c16
-rw-r--r--usr.sbin/smtpd/mta.c7
5 files changed, 87 insertions, 84 deletions
diff --git a/usr.sbin/smtpd/bounce.c b/usr.sbin/smtpd/bounce.c
index 52feb25ad5a..a313b8503a5 100644
--- a/usr.sbin/smtpd/bounce.c
+++ b/usr.sbin/smtpd/bounce.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: bounce.c,v 1.13 2009/12/12 10:33:11 jacekm Exp $ */
+/* $OpenBSD: bounce.c,v 1.14 2009/12/12 14:03:59 jacekm Exp $ */
/*
* Copyright (c) 2009 Gilles Chehade <gilles@openbsd.org>
@@ -58,10 +58,14 @@ bounce_session(struct smtpd *env, int fd, struct message *messagep)
int msgfd = -1;
char *reason;
+ /* get message content */
+ if ((msgfd = queue_open_message_file(messagep->message_id)) == -1)
+ goto fail;
+
/* init smtp session */
if ((cc = calloc(1, sizeof(*cc))) == NULL)
goto fail;
- cc->pcb = client_init(fd, env->sc_hostname, 1);
+ cc->pcb = client_init(fd, msgfd, env->sc_hostname, 1);
cc->m = *messagep;
client_ssl_optional(cc->pcb);
@@ -77,7 +81,7 @@ bounce_session(struct smtpd *env, int fd, struct message *messagep)
/* create message header */
/* XXX - The Date: header should be added during SMTP pickup. */
- client_data_printf(cc->pcb,
+ client_printf(cc->pcb,
"Subject: Delivery status notification\n"
"From: Mailer Daemon <MAILER-DAEMON@%s>\n"
"To: %s@%s\n"
@@ -100,13 +104,6 @@ bounce_session(struct smtpd *env, int fd, struct message *messagep)
messagep->recipient.user, messagep->recipient.domain,
reason);
- /* append original message */
- if ((msgfd = queue_open_message_file(messagep->message_id)) == -1)
- goto fail;
- client_data_fd(cc->pcb, msgfd);
- close(msgfd);
- msgfd = -1;
-
/* setup event */
session_socket_blockmode(fd, BM_NONBLOCK);
event_set(&cc->ev, fd, EV_WRITE, bounce_event, cc);
diff --git a/usr.sbin/smtpd/client.c b/usr.sbin/smtpd/client.c
index e00bf48b7ab..ab55f29d5c2 100644
--- a/usr.sbin/smtpd/client.c
+++ b/usr.sbin/smtpd/client.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: client.c,v 1.18 2009/12/12 10:33:11 jacekm Exp $ */
+/* $OpenBSD: client.c,v 1.19 2009/12/12 14:03:59 jacekm Exp $ */
/*
* Copyright (c) 2009 Jacek Masiulaniec <jacekm@dobremiasto.net>
@@ -45,7 +45,7 @@ void client_status(struct smtp_client *, char *, ...);
int client_getln(struct smtp_client *);
void client_putln(struct smtp_client *, char *, ...);
-void client_data_add(struct smtp_client *, char *, size_t);
+void client_body(struct msgbuf *, FILE *);
#ifndef CLIENT_NO_SSL
int client_ssl_connect(struct smtp_client *);
@@ -65,7 +65,7 @@ void fatalx(const char *); /* XXX */
* Initialize SMTP session.
*/
struct smtp_client *
-client_init(int fd, char *ehlo, int verbose)
+client_init(int fd, int body, char *ehlo, int verbose)
{
struct smtp_client *sp = NULL;
@@ -92,8 +92,8 @@ client_init(int fd, char *ehlo, int verbose)
sp->verbose = stdout;
else if ((sp->verbose = fopen("/dev/null", "a")) == NULL)
fatal("client_init: fopen");
- if ((sp->data = buf_dynamic(0, SIZE_T_MAX)) == NULL)
- fatal(NULL);
+ if ((sp->body = fdopen(body, "r")) == NULL)
+ fatal("client_init: fdopen");
sp->state = CLIENT_INIT;
sp->handler = client_write;
sp->timeout.tv_sec = 300;
@@ -208,44 +208,41 @@ client_rcpt(struct smtp_client *sp, void *p, char *fmt, ...)
}
/*
- * Append file referenced by fd to the data buffer.
- */
-void
-client_data_fd(struct smtp_client *sp, int fd)
-{
- struct stat sb;
- char *map;
-
- if (fstat(fd, &sb) == -1)
- fatal("client_data_fd: fstat");
- if ((size_t)sb.st_size > SIZE_T_MAX)
- fatalx("client_data_fd: file too large");
- if (!S_ISREG(sb.st_mode))
- fatalx("client_data_fd: non-regular file");
- map = mmap(NULL, sb.st_size, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd,
- (off_t)0);
- if (map == MAP_FAILED)
- fatal("client_data_fd: mmap failed");
- madvise(map, sb.st_size, MADV_SEQUENTIAL);
- client_data_add(sp, map, sb.st_size);
- munmap(map, sb.st_size);
-}
-
-/*
* Append string to the data buffer.
*/
void
-client_data_printf(struct smtp_client *sp, char *fmt, ...)
+client_printf(struct smtp_client *sp, char *fmt, ...)
{
va_list ap;
- char *p = NULL;
+ char *p, *ln, *tmp;
int len;
+ if (sp->head == NULL)
+ sp->head = buf_dynamic(0, SIZE_T_MAX);
+ if (sp->head == NULL)
+ fatal(NULL);
+
va_start(ap, fmt);
if ((len = vasprintf(&p, fmt, ap)) == -1)
fatal("client_data_printf: vasprintf");
va_end(ap);
- client_data_add(sp, p, len);
+
+ /* must end with a newline */
+ if (len == 0 || p[len - 1] != '\n')
+ fatalx("client_printf: invalid use");
+ p[len - 1] = '\0';
+
+ /* split into lines, deal with dot escaping etc. */
+ tmp = p;
+ while ((ln = strsep(&tmp, "\n"))) {
+ if (*ln == '.' && buf_add(sp->head, ".", 1))
+ fatal(NULL);
+ if (buf_add(sp->head, ln, strlen(ln)))
+ fatal(NULL);
+ if (buf_add(sp->head, "\r\n", 2))
+ fatal(NULL);
+ }
+
free(p);
}
@@ -503,10 +500,11 @@ client_write(struct smtp_client *sp)
case CLIENT_DATA_BODY:
sp->timeout.tv_sec = 180;
- if (buf_add(sp->data, ".\r\n", 3) < 0)
- fatal("client_write: buf_add failed");
- buf_close(&sp->w, sp->data);
- sp->data = NULL;
+ if (sp->head) {
+ buf_close(&sp->w, sp->head);
+ sp->head = NULL;
+ }
+ client_body(&sp->w, sp->body);
break;
case CLIENT_QUIT:
@@ -545,11 +543,12 @@ write:
}
}
- /*
- * Extend timeout after having sent final "." character.
- */
- if (sp->state == CLIENT_DATA_BODY && sp->w.queued == 0)
- sp->timeout.tv_sec = 600;
+ if (sp->state == CLIENT_DATA_BODY) {
+ if (!feof(sp->body))
+ return (CLIENT_WANT_WRITE);
+ else
+ sp->timeout.tv_sec = 600;
+ }
return (sp->w.queued ? CLIENT_WANT_WRITE : CLIENT_WANT_READ);
}
@@ -616,8 +615,8 @@ client_close(struct smtp_client *sp)
free(sp->auth.plain);
free(sp->auth.cert);
free(sp->auth.key);
- if (sp->data)
- buf_free(sp->data);
+ if (sp->head)
+ buf_free(sp->head);
msgbuf_clear(&sp->w);
while ((rp = TAILQ_FIRST(&sp->recipients))) {
TAILQ_REMOVE(&sp->recipients, rp, entry);
@@ -775,9 +774,9 @@ client_putln(struct smtp_client *sp, char *fmt, ...)
if ((cmd = buf_open(len + 2)) == NULL)
fatal(NULL);
- if (buf_add(cmd, p, len) < 0)
+ if (buf_add(cmd, p, len))
fatal(NULL);
- if (buf_add(cmd, "\r\n", 2) < 0)
+ if (buf_add(cmd, "\r\n", 2))
fatal(NULL);
buf_close(&sp->w, cmd);
@@ -785,27 +784,35 @@ client_putln(struct smtp_client *sp, char *fmt, ...)
}
/*
- * Append buffer to the data buffer, performing necessary transformations.
+ * Put chunk of message content to output buffer.
*/
void
-client_data_add(struct smtp_client *sp, char *buf, size_t len)
+client_body(struct msgbuf *out, FILE *fp)
{
- char *ln;
+ struct buf *b;
+ char *ln;
+ size_t len, total = 0;
- /* must end with a newline */
- if (len == 0 || buf[len - 1] != '\n')
- fatalx("client_data_add: bad buffer");
- buf[len - 1] = '\0';
+ if ((b = buf_dynamic(0, SIZE_T_MAX)) == NULL)
+ fatal(NULL);
- /* split into lines, deal with dot escaping etc. */
- while ((ln = strsep(&buf, "\n"))) {
- if (*ln == '.' && buf_add(sp->data, ".", 1) < 0)
+ while ((ln = fgetln(fp, &len)) && total < 4096) {
+ if (ln[len - 1] == '\n')
+ len--;
+ if (*ln == '.' && buf_add(b, ".", 1))
fatal(NULL);
- if (buf_add(sp->data, ln, strlen(ln)) < 0)
+ if (buf_add(b, ln, len))
fatal(NULL);
- if (buf_add(sp->data, "\r\n", 2) < 0)
+ if (buf_add(b, "\r\n", 2))
fatal(NULL);
+ total += len;
}
+ if (ferror(fp))
+ fatal("client_body: fgetln");
+ if (feof(fp) && buf_add(b, ".\r\n", 3))
+ fatal(NULL);
+
+ buf_close(out, b);
}
/*
diff --git a/usr.sbin/smtpd/client.h b/usr.sbin/smtpd/client.h
index d038ab0acc4..f81832e819f 100644
--- a/usr.sbin/smtpd/client.h
+++ b/usr.sbin/smtpd/client.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: client.h,v 1.5 2009/12/12 10:33:11 jacekm Exp $ */
+/* $OpenBSD: client.h,v 1.6 2009/12/12 14:03:59 jacekm Exp $ */
/*
* Copyright (c) 2009 Jacek Masiulaniec <jacekm@dobremiasto.net>
@@ -81,7 +81,8 @@ struct smtp_client {
size_t rcptokay;
struct buf_read r;
struct msgbuf w;
- struct buf *data;
+ struct buf *head;
+ FILE *body;
struct client_ext exts[CLIENT_EXT_MAX];
int (*handler)(struct smtp_client *);
void *ssl_state;
@@ -92,7 +93,7 @@ struct smtp_client {
FILE *verbose;
};
-struct smtp_client *client_init(int, char *, int);
+struct smtp_client *client_init(int, int, char *, int);
void client_ssl_smtps(struct smtp_client *);
void client_ssl_optional(struct smtp_client *);
void client_certificate(struct smtp_client *, char *,
@@ -100,7 +101,6 @@ void client_certificate(struct smtp_client *, char *,
void client_auth(struct smtp_client *, char *);
void client_sender(struct smtp_client *, char *, ...);
void client_rcpt(struct smtp_client *, void *, char *, ...);
-void client_data_fd(struct smtp_client *, int);
-void client_data_printf(struct smtp_client *, char *, ...);
+void client_printf(struct smtp_client *, char *, ...);
int client_talk(struct smtp_client *);
void client_close(struct smtp_client *);
diff --git a/usr.sbin/smtpd/enqueue.c b/usr.sbin/smtpd/enqueue.c
index f5f6c949f95..251a2346c1f 100644
--- a/usr.sbin/smtpd/enqueue.c
+++ b/usr.sbin/smtpd/enqueue.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: enqueue.c,v 1.28 2009/12/12 10:33:11 jacekm Exp $ */
+/* $OpenBSD: enqueue.c,v 1.29 2009/12/12 14:03:59 jacekm Exp $ */
/*
* Copyright (c) 2005 Henning Brauer <henning@bulabula.org>
@@ -27,6 +27,7 @@
#include <err.h>
#include <errno.h>
#include <event.h>
+#include <fcntl.h>
#include <netdb.h>
#include <pwd.h>
#include <signal.h>
@@ -190,7 +191,8 @@ enqueue(int argc, char *argv[])
msg.fd = open_connection();
/* init session */
- pcb = client_init(msg.fd, "localhost", verbose);
+ pcb = client_init(msg.fd, open("/dev/null", O_RDONLY), "localhost",
+ verbose);
/* parse message */
if ((body = buf_dynamic(0, SIZE_T_MAX)) < 0)
@@ -208,25 +210,25 @@ enqueue(int argc, char *argv[])
/* add From */
if (!msg.saw_from)
- client_data_printf(pcb, "From: %s%s<%s>\n",
+ client_printf(pcb, "From: %s%s<%s>\n",
msg.fromname ? msg.fromname : "",
msg.fromname ? " " : "",
msg.from);
/* add Date */
if (!msg.saw_date)
- client_data_printf(pcb, "Date: %s\n", time_to_text(timestamp));
+ client_printf(pcb, "Date: %s\n", time_to_text(timestamp));
/* add Message-Id */
if (!msg.saw_msgid)
- client_data_printf(pcb, "Message-Id: <%llu.enqueue@%s>\n",
+ client_printf(pcb, "Message-Id: <%llu.enqueue@%s>\n",
generate_uid(), host);
/* add separating newline */
if (noheader)
- client_data_printf(pcb, "\n");
+ client_printf(pcb, "\n");
- client_data_printf(pcb, "%.*s", buf_size(body), body->buf);
+ client_printf(pcb, "%.*s", buf_size(body), body->buf);
buf_free(body);
/* run the protocol engine */
diff --git a/usr.sbin/smtpd/mta.c b/usr.sbin/smtpd/mta.c
index 99ecc7ccd3f..660fd113afd 100644
--- a/usr.sbin/smtpd/mta.c
+++ b/usr.sbin/smtpd/mta.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: mta.c,v 1.80 2009/12/12 10:33:11 jacekm Exp $ */
+/* $OpenBSD: mta.c,v 1.81 2009/12/12 14:03:59 jacekm Exp $ */
/*
* Copyright (c) 2008 Pierre-Yves Ritschard <pyr@openbsd.org>
@@ -636,7 +636,7 @@ mta_enter_state(struct mta_session *s, int newstate, void *p)
*/
log_debug("mta: entering smtp phase");
- pcb = client_init(s->fd, s->env->sc_hostname, 1);
+ pcb = client_init(s->fd, s->datafd, s->env->sc_hostname, 1);
/* lookup SSL certificate */
if (s->cert) {
@@ -679,9 +679,6 @@ mta_enter_state(struct mta_session *s, int newstate, void *p)
client_rcpt(pcb, m, "%s@%s", m->recipient.user,
m->recipient.domain);
- /* load message body */
- client_data_fd(pcb, s->datafd);
-
s->pcb = pcb;
event_set(&s->ev, s->fd, EV_WRITE, mta_event, s);
event_add(&s->ev, &pcb->timeout);