On 10/4/19 10:03 AM, [email protected] wrote:
> October 4, 2019 9:55 AM, "Martijn van Duren"
> <[email protected]> wrote:
>>
>> This is similar to the diff I send a few months ago, but still doesn't
>> fix the case when someone sends a standalone '\n' as line-ending.
>>
>
> Unsure I understand that, can you elaborate ?
I send the diff below to you and Eric back in April, but it was dropped
in favour of forbidding the <CR> totally (the thing being discussed
now).
>
>
>> I'd prefer if we go with reverting (=my previous diff) until we have
>> something that definitively fixes things. If people send broken mails
>> they get broken signatures until that time.
>
> Fine by me
>
Index: bounce.c
===================================================================
RCS file: /cvs/src/usr.sbin/smtpd/bounce.c,v
retrieving revision 1.80
diff -u -p -r1.80 bounce.c
--- bounce.c 8 Dec 2018 08:01:15 -0000 1.80
+++ bounce.c 24 Apr 2019 09:33:35 -0000
@@ -718,7 +718,7 @@ bounce_io(struct io *io, int evt, void *
switch (evt) {
case IO_DATAIN:
nextline:
- line = io_getline(s->io, &len);
+ line = io_getline_rn(s->io, &len);
if (line == NULL && io_datalen(s->io) >= LINE_MAX) {
bounce_status(s, "Input too long");
bounce_free(s);
Index: iobuf.c
===================================================================
RCS file: /cvs/src/usr.sbin/smtpd/iobuf.c,v
retrieving revision 1.10
diff -u -p -r1.10 iobuf.c
--- iobuf.c 17 Mar 2017 20:56:04 -0000 1.10
+++ iobuf.c 24 Apr 2019 09:33:35 -0000
@@ -156,7 +156,35 @@ iobuf_drop(struct iobuf *io, size_t n)
}
char *
-iobuf_getline(struct iobuf *iobuf, size_t *rlen)
+iobuf_getline_n(struct iobuf *iobuf, size_t *rlen)
+{
+ char *buf;
+ size_t len, i;
+
+ buf = iobuf_data(iobuf);
+ len = iobuf_len(iobuf);
+
+ for (i = 0; i + 1 <= len; i++)
+ if (buf[i] == '\n') {
+ /* Note: the returned address points into the iobuf
+ * buffer. We NUL-end it for convenience, and discard
+ * the data from the iobuf, so that the caller doesn't
+ * have to do it. The data remains "valid" as long
+ * as the iobuf does not overwrite it, that is until
+ * the next call to iobuf_normalize() or iobuf_extend().
+ */
+ iobuf_drop(iobuf, i + 1);
+ buf[i] = '\0';
+ if (rlen)
+ *rlen = i;
+ return (buf);
+ }
+
+ return (NULL);
+}
+
+char *
+iobuf_getline_rn(struct iobuf *iobuf, size_t *rlen)
{
char *buf;
size_t len, i;
Index: iobuf.h
===================================================================
RCS file: /cvs/src/usr.sbin/smtpd/iobuf.h,v
retrieving revision 1.4
diff -u -p -r1.4 iobuf.h
--- iobuf.h 20 Jan 2015 17:37:54 -0000 1.4
+++ iobuf.h 24 Apr 2019 09:33:35 -0000
@@ -51,7 +51,8 @@ size_t iobuf_space(struct iobuf *);
size_t iobuf_len(struct iobuf *);
size_t iobuf_left(struct iobuf *);
char *iobuf_data(struct iobuf *);
-char *iobuf_getline(struct iobuf *, size_t *);
+char *iobuf_getline_n(struct iobuf *, size_t *);
+char *iobuf_getline_rn(struct iobuf *, size_t *);
ssize_t iobuf_read(struct iobuf *, int);
ssize_t iobuf_read_ssl(struct iobuf *, void *);
Index: ioev.c
===================================================================
RCS file: /cvs/src/usr.sbin/smtpd/ioev.c,v
retrieving revision 1.41
diff -u -p -r1.41 ioev.c
--- ioev.c 17 May 2017 14:00:06 -0000 1.41
+++ ioev.c 24 Apr 2019 09:33:35 -0000
@@ -501,9 +501,15 @@ io_datalen(struct io *io)
}
char *
-io_getline(struct io *io, size_t *sz)
+io_getline_n(struct io *io, size_t *sz)
{
- return iobuf_getline(&io->iobuf, sz);
+ return iobuf_getline_n(&io->iobuf, sz);
+}
+
+char *
+io_getline_rn(struct io *io, size_t *sz)
+{
+ return iobuf_getline_rn(&io->iobuf, sz);
}
void
Index: ioev.h
===================================================================
RCS file: /cvs/src/usr.sbin/smtpd/ioev.h,v
retrieving revision 1.16
diff -u -p -r1.16 ioev.h
--- ioev.h 30 Nov 2016 17:43:32 -0000 1.16
+++ ioev.h 24 Apr 2019 09:33:35 -0000
@@ -65,5 +65,6 @@ size_t io_queued(struct io *);
/* Buffered input functions */
void* io_data(struct io *);
size_t io_datalen(struct io *);
-char* io_getline(struct io *, size_t *);
+char* io_getline_n(struct io *, size_t *);
+char* io_getline_rn(struct io *, size_t *);
void io_drop(struct io *, size_t);
Index: lka_filter.c
===================================================================
RCS file: /cvs/src/usr.sbin/smtpd/lka_filter.c,v
retrieving revision 1.35
diff -u -p -r1.35 lka_filter.c
--- lka_filter.c 8 Apr 2019 07:44:45 -0000 1.35
+++ lka_filter.c 24 Apr 2019 09:33:35 -0000
@@ -393,7 +393,7 @@ filter_session_io(struct io *io, int evt
switch (evt) {
case IO_DATAIN:
nextline:
- line = io_getline(fs->io, &len);
+ line = io_getline_rn(fs->io, &len);
/* No complete line received */
if (line == NULL)
return;
Index: lka_proc.c
===================================================================
RCS file: /cvs/src/usr.sbin/smtpd/lka_proc.c,v
retrieving revision 1.6
diff -u -p -r1.6 lka_proc.c
--- lka_proc.c 21 Dec 2018 19:07:47 -0000 1.6
+++ lka_proc.c 24 Apr 2019 09:33:35 -0000
@@ -124,7 +124,7 @@ processor_io(struct io *io, int evt, voi
switch (evt) {
case IO_DATAIN:
nextline:
- line = io_getline(io, &len);
+ line = io_getline_n(io, &len);
/* No complete line received */
if (line == NULL)
return;
Index: mta_session.c
===================================================================
RCS file: /cvs/src/usr.sbin/smtpd/mta_session.c,v
retrieving revision 1.115
diff -u -p -r1.115 mta_session.c
--- mta_session.c 23 Dec 2018 16:37:53 -0000 1.115
+++ mta_session.c 24 Apr 2019 09:33:35 -0000
@@ -1111,7 +1111,7 @@ mta_io(struct io *io, int evt, void *arg
case IO_DATAIN:
nextline:
- line = io_getline(s->io, &len);
+ line = io_getline_rn(s->io, &len);
if (line == NULL) {
if (io_datalen(s->io) >= LINE_MAX) {
mta_error(s, "Input too long");
Index: smtp_client.c
===================================================================
RCS file: /cvs/src/usr.sbin/smtpd/smtp_client.c,v
retrieving revision 1.8
diff -u -p -r1.8 smtp_client.c
--- smtp_client.c 20 Sep 2018 11:42:28 -0000 1.8
+++ smtp_client.c 24 Apr 2019 09:33:35 -0000
@@ -667,7 +667,7 @@ smtp_client_readline(struct smtp_client
char *line, *msg, *p;
int cont;
- line = io_getline(proto->io, &len);
+ line = io_getline_rn(proto->io, &len);
if (line == NULL) {
if (io_datalen(proto->io) >= proto->params.linemax)
smtp_client_abort(proto, FAIL_PROTO, "Line too long");
Index: smtp_session.c
===================================================================
RCS file: /cvs/src/usr.sbin/smtpd/smtp_session.c,v
retrieving revision 1.389
diff -u -p -r1.389 smtp_session.c
--- smtp_session.c 20 Feb 2019 11:56:27 -0000 1.389
+++ smtp_session.c 24 Apr 2019 09:33:35 -0000
@@ -1078,7 +1078,7 @@ smtp_io(struct io *io, int evt, void *ar
case IO_DATAIN:
nextline:
- line = io_getline(s->io, &len);
+ line = io_getline_rn(s->io, &len);
if ((line == NULL && io_datalen(s->io) >= SMTP_LINE_MAX) ||
(line && len >= SMTP_LINE_MAX)) {
s->flags |= SF_BADINPUT;
@@ -2727,7 +2727,7 @@ filter_session_io(struct io *io, int evt
switch (evt) {
case IO_DATAIN:
nextline:
- line = io_getline(tx->filter, &len);
+ line = io_getline_rn(tx->filter, &len);
/* No complete line received */
if (line == NULL)
return;