unofficial mirror of notmuch@notmuchmail.org
 help / color / mirror / code / Atom feed
* [PATCH] cli/insert: do not lose the SMTP envelope
@ 2016-01-01 11:21 J Farkas
  2016-01-02 11:28 ` Tomi Ollila
  2016-01-03 16:04 ` [PATCH] " Jani Nikula
  0 siblings, 2 replies; 6+ messages in thread
From: J Farkas @ 2016-01-01 11:21 UTC (permalink / raw)
  To: notmuch

From: Janos Farkas <chexum+dev@gmail.com>
Subject: [PATCH] cli/insert: do not lose the SMTP envelope

Make sure we store the envelope sender/recipient if provided by
qmail-command(8) in $RPLINE and $DTLINE.
---

I just realised that the messages delivered directly into maildir don't have
the usual envelope addresses that qmail provides.  This is a piece of
information that's important to (at least my) troubleshooting, so I created a
patch that seems to work well, applies cleanly to master (and 0.21), and
provided a NEWS entry should it be necessary.

 NEWS             |  9 +++++++++
 notmuch-insert.c | 28 ++++++++++++++++++++++++++++
 2 files changed, 37 insertions(+)

diff --git a/NEWS b/NEWS
index 6681699..13d45c8 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,12 @@
+
+
+`notmuch insert` records the envelope addresses if available
+
+  If the caller provides this information as qmail-command(8) does in
+  the RPLINE and DTLINE environment variables, then notmuch insert will
+  record it in the maildir file.
+
+
 Notmuch 0.21 (2015-10-29)
 =========================
 
diff --git a/notmuch-insert.c b/notmuch-insert.c
index 5205c17..ecc0fa0 100644
--- a/notmuch-insert.c
+++ b/notmuch-insert.c
@@ -284,6 +284,26 @@ copy_fd (int fdout, int fdin)
 }
 
 /*
+ * Write zero (and LF) terminated string to the output fd.  It's expected to
+ * come from getenv(), so it's not checked for correctness.  NULL or empty
+ * string is ignored, successfully.
+ * Return TRUE on success, FALSE on errors.
+ */
+static notmuch_bool_t
+write_header (int fdout, const char *hdr)
+{
+    ssize_t written,to_write;
+
+    if (hdr && (to_write = strlen (hdr))) {
+        written = write (fdout, hdr, to_write);
+	if (written != to_write)
+	    return FALSE;
+    }
+
+    return TRUE;
+}
+
+/*
  * Write fdin to a new temp file in maildir/tmp, return full path to
  * the file, or NULL on errors.
  */
@@ -297,6 +317,14 @@ maildir_write_tmp (const void *ctx, int fdin, const char *maildir)
     if (fdout < 0)
 	return NULL;
 
+    /* maildir(5) suggests the message should start with a Return-Path
+     * and Delivered-To lines.  qmail-local(8) supplies these.
+     */
+    if (! write_header(fdout, getenv("RPLINE")))
+	goto FAIL;
+    if (! write_header(fdout, getenv("DTLINE")))
+	goto FAIL;
+
     if (! copy_fd (fdout, fdin))
 	goto FAIL;
 
-- 
2.6.3

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH] cli/insert: do not lose the SMTP envelope
  2016-01-01 11:21 [PATCH] cli/insert: do not lose the SMTP envelope J Farkas
@ 2016-01-02 11:28 ` Tomi Ollila
  2016-01-02 11:50   ` J Farkas
  2016-01-03 16:04 ` [PATCH] " Jani Nikula
  1 sibling, 1 reply; 6+ messages in thread
From: Tomi Ollila @ 2016-01-02 11:28 UTC (permalink / raw)
  To: J Farkas, notmuch

On Fri, Jan 01 2016, J Farkas <jf.hyqohaczlksw4tx6ae@l2015aftruuq.dns007.net> wrote:

> From: Janos Farkas <chexum+dev@gmail.com>
> Subject: [PATCH] cli/insert: do not lose the SMTP envelope
>
> Make sure we store the envelope sender/recipient if provided by
> qmail-command(8) in $RPLINE and $DTLINE.
> ---

Probably good feature, but like
http://www.qmail.org/man/man8/qmail-command.html 
says:

          qmail-local supplies several useful environment variables to
          command.  WARNING: These environment variables are not
          quoted.  They may contain special characters.  They are
          under the control of a possibly malicious remote user.

Should we check that the contents of RPLINE and DTLINE are well-formed
before writing these to the mail files ?

Tomi


> I just realised that the messages delivered directly into maildir don't have
> the usual envelope addresses that qmail provides.  This is a piece of
> information that's important to (at least my) troubleshooting, so I created a
> patch that seems to work well, applies cleanly to master (and 0.21), and
> provided a NEWS entry should it be necessary.
>
>  NEWS             |  9 +++++++++
>  notmuch-insert.c | 28 ++++++++++++++++++++++++++++
>  2 files changed, 37 insertions(+)
>
> diff --git a/NEWS b/NEWS
> index 6681699..13d45c8 100644
> --- a/NEWS
> +++ b/NEWS
> @@ -1,3 +1,12 @@
> +
> +
> +`notmuch insert` records the envelope addresses if available
> +
> +  If the caller provides this information as qmail-command(8) does in
> +  the RPLINE and DTLINE environment variables, then notmuch insert will
> +  record it in the maildir file.
> +
> +
>  Notmuch 0.21 (2015-10-29)
>  =========================
>  
> diff --git a/notmuch-insert.c b/notmuch-insert.c
> index 5205c17..ecc0fa0 100644
> --- a/notmuch-insert.c
> +++ b/notmuch-insert.c
> @@ -284,6 +284,26 @@ copy_fd (int fdout, int fdin)
>  }
>  
>  /*
> + * Write zero (and LF) terminated string to the output fd.  It's expected to
> + * come from getenv(), so it's not checked for correctness.  NULL or empty
> + * string is ignored, successfully.
> + * Return TRUE on success, FALSE on errors.
> + */
> +static notmuch_bool_t
> +write_header (int fdout, const char *hdr)
> +{
> +    ssize_t written,to_write;
> +
> +    if (hdr && (to_write = strlen (hdr))) {
> +        written = write (fdout, hdr, to_write);
> +	if (written != to_write)
> +	    return FALSE;
> +    }
> +
> +    return TRUE;
> +}
> +
> +/*
>   * Write fdin to a new temp file in maildir/tmp, return full path to
>   * the file, or NULL on errors.
>   */
> @@ -297,6 +317,14 @@ maildir_write_tmp (const void *ctx, int fdin, const char *maildir)
>      if (fdout < 0)
>  	return NULL;
>  
> +    /* maildir(5) suggests the message should start with a Return-Path
> +     * and Delivered-To lines.  qmail-local(8) supplies these.
> +     */
> +    if (! write_header(fdout, getenv("RPLINE")))
> +	goto FAIL;
> +    if (! write_header(fdout, getenv("DTLINE")))
> +	goto FAIL;
> +
>      if (! copy_fd (fdout, fdin))
>  	goto FAIL;
>  
> -- 
> 2.6.3
>
> _______________________________________________
> notmuch mailing list
> notmuch@notmuchmail.org
> https://notmuchmail.org/mailman/listinfo/notmuch

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: cli/insert: do not lose the SMTP envelope
  2016-01-02 11:28 ` Tomi Ollila
@ 2016-01-02 11:50   ` J Farkas
  2016-01-03 16:15     ` Jani Nikula
  0 siblings, 1 reply; 6+ messages in thread
From: J Farkas @ 2016-01-02 11:50 UTC (permalink / raw)
  To: notmuch; +Cc: Tomi Ollila

On 2016-01-02 at 13:28:02, Tomi Ollila wrote:
> On Fri, Jan 01 2016, J Farkas <jf.hyqohaczlksw4tx6ae@l2015aftruuq.dns007.net> wrote:
> > Make sure we store the envelope sender/recipient if provided by
> > qmail-command(8) in $RPLINE and $DTLINE.
> > ---
> 
> Probably good feature, but like
> http://www.qmail.org/man/man8/qmail-command.html 
> says:
> 
>           qmail-local supplies several useful environment variables to
>           command.  WARNING: These environment variables are not
>           quoted.  They may contain special characters.  They are
>           under the control of a possibly malicious remote user.
> 
> Should we check that the contents of RPLINE and DTLINE are well-formed
> before writing these to the mail files ?

Thank you for reviewing and being so careful!

That warning is not applicable for the *LINE variables which are
supposed to end up in the message without further munging (they even
have the LF appended already).

The extra carefulness is only relevant for anyone trying to *parse*
those strings, like $EXT via unsafe languages, when EXT becomes the
part following the dash after the username (considering 
bgates-(){:;};shutdown@example.org for example)

It still should be what the envelope sender was, and what was considered
valid at the time.

I actually checked if there's any relevance for this warning: most
maildir delivering program does it already in one form or the other; in
fact, there is a command in the qmail distribution:
http://www.qmail.org/man/man1/preline.html which does the exact same
getenv and copy to the output.

If you'd liek to confirm, there's one repo for what seems to be the
original qmail source for this file shows even DJB does it the same way:

https://github.com/c-rack/qmail/blob/master/preline.c

I would think it's not worth the extra fork and pipe for this.  I don't
see how anyone could do without these headers saved, to be honest :)

Janos

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] cli/insert: do not lose the SMTP envelope
  2016-01-01 11:21 [PATCH] cli/insert: do not lose the SMTP envelope J Farkas
  2016-01-02 11:28 ` Tomi Ollila
@ 2016-01-03 16:04 ` Jani Nikula
  2016-01-03 20:27   ` J Farkas
  1 sibling, 1 reply; 6+ messages in thread
From: Jani Nikula @ 2016-01-03 16:04 UTC (permalink / raw)
  To: J Farkas, notmuch

On Fri, 01 Jan 2016, J Farkas <jf.hyqohaczlksw4tx6ae@l2015aftruuq.dns007.net> wrote:
> From: Janos Farkas <chexum+dev@gmail.com>
> Subject: [PATCH] cli/insert: do not lose the SMTP envelope
>
> Make sure we store the envelope sender/recipient if provided by
> qmail-command(8) in $RPLINE and $DTLINE.
> ---
>
> I just realised that the messages delivered directly into maildir don't have
> the usual envelope addresses that qmail provides.  This is a piece of
> information that's important to (at least my) troubleshooting, so I created a
> patch that seems to work well, applies cleanly to master (and 0.21), and
> provided a NEWS entry should it be necessary.

I'd be more interested in seeing some tests for this...

>
>  NEWS             |  9 +++++++++
>  notmuch-insert.c | 28 ++++++++++++++++++++++++++++
>  2 files changed, 37 insertions(+)
>
> diff --git a/NEWS b/NEWS
> index 6681699..13d45c8 100644
> --- a/NEWS
> +++ b/NEWS
> @@ -1,3 +1,12 @@
> +
> +
> +`notmuch insert` records the envelope addresses if available
> +
> +  If the caller provides this information as qmail-command(8) does in
> +  the RPLINE and DTLINE environment variables, then notmuch insert will
> +  record it in the maildir file.

We usually refer to message files. Perhaps you should also mention what
the RPLINE and DTLINE variables should contain.

> +
> +
>  Notmuch 0.21 (2015-10-29)
>  =========================
>  
> diff --git a/notmuch-insert.c b/notmuch-insert.c
> index 5205c17..ecc0fa0 100644
> --- a/notmuch-insert.c
> +++ b/notmuch-insert.c
> @@ -284,6 +284,26 @@ copy_fd (int fdout, int fdin)
>  }
>  
>  /*
> + * Write zero (and LF) terminated string to the output fd.  It's expected to
> + * come from getenv(), so it's not checked for correctness.  NULL or empty
> + * string is ignored, successfully.
> + * Return TRUE on success, FALSE on errors.
> + */
> +static notmuch_bool_t
> +write_header (int fdout, const char *hdr)
> +{
> +    ssize_t written,to_write;
> +
> +    if (hdr && (to_write = strlen (hdr))) {
> +        written = write (fdout, hdr, to_write);
> +	if (written != to_write)
> +	    return FALSE;
> +    }

It's not an error for write() to return prematurely with written <
to_write. Please see the write(2) man page and the copy_fd()
implementation in this file.

BR,
Jani.

> +
> +    return TRUE;
> +}
> +
> +/*
>   * Write fdin to a new temp file in maildir/tmp, return full path to
>   * the file, or NULL on errors.
>   */
> @@ -297,6 +317,14 @@ maildir_write_tmp (const void *ctx, int fdin, const char *maildir)
>      if (fdout < 0)
>  	return NULL;
>  
> +    /* maildir(5) suggests the message should start with a Return-Path
> +     * and Delivered-To lines.  qmail-local(8) supplies these.
> +     */
> +    if (! write_header(fdout, getenv("RPLINE")))
> +	goto FAIL;
> +    if (! write_header(fdout, getenv("DTLINE")))
> +	goto FAIL;
> +
>      if (! copy_fd (fdout, fdin))
>  	goto FAIL;
>  
> -- 
> 2.6.3
>
> _______________________________________________
> notmuch mailing list
> notmuch@notmuchmail.org
> https://notmuchmail.org/mailman/listinfo/notmuch

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: cli/insert: do not lose the SMTP envelope
  2016-01-02 11:50   ` J Farkas
@ 2016-01-03 16:15     ` Jani Nikula
  0 siblings, 0 replies; 6+ messages in thread
From: Jani Nikula @ 2016-01-03 16:15 UTC (permalink / raw)
  To: J Farkas, notmuch; +Cc: Tomi Ollila

On Sat, 02 Jan 2016, J Farkas <jf.hyqohaczlksw4tx6ae@l2015aftruuq.dns007.net> wrote:
> On 2016-01-02 at 13:28:02, Tomi Ollila wrote:
>> On Fri, Jan 01 2016, J Farkas <jf.hyqohaczlksw4tx6ae@l2015aftruuq.dns007.net> wrote:
>> > Make sure we store the envelope sender/recipient if provided by
>> > qmail-command(8) in $RPLINE and $DTLINE.
>> > ---
>> 
>> Probably good feature, but like
>> http://www.qmail.org/man/man8/qmail-command.html 
>> says:
>> 
>>           qmail-local supplies several useful environment variables to
>>           command.  WARNING: These environment variables are not
>>           quoted.  They may contain special characters.  They are
>>           under the control of a possibly malicious remote user.
>> 
>> Should we check that the contents of RPLINE and DTLINE are well-formed
>> before writing these to the mail files ?
>
> Thank you for reviewing and being so careful!
>
> That warning is not applicable for the *LINE variables which are
> supposed to end up in the message without further munging (they even
> have the LF appended already).
>
> The extra carefulness is only relevant for anyone trying to *parse*
> those strings, like $EXT via unsafe languages, when EXT becomes the
> part following the dash after the username (considering 
> bgates-(){:;};shutdown@example.org for example)

We should already assume that the messages can contain basically any
malicious content, and we should treat them like that. Adding malicious
content at this step should not trip us over.

The question is, could this make it easier for Mallory to inject
malicious content to otherwise good messages? The environment variables
in question could contain a whole message, hiding the actual
message. Not sure how one could control the environment without being
able to do a whole lot of other, potentially more malicious things.

BR,
Jani.


>
> It still should be what the envelope sender was, and what was considered
> valid at the time.
>
> I actually checked if there's any relevance for this warning: most
> maildir delivering program does it already in one form or the other; in
> fact, there is a command in the qmail distribution:
> http://www.qmail.org/man/man1/preline.html which does the exact same
> getenv and copy to the output.
>
> If you'd liek to confirm, there's one repo for what seems to be the
> original qmail source for this file shows even DJB does it the same way:
>
> https://github.com/c-rack/qmail/blob/master/preline.c
>
> I would think it's not worth the extra fork and pipe for this.  I don't
> see how anyone could do without these headers saved, to be honest :)
>
> Janos
>
> _______________________________________________
> notmuch mailing list
> notmuch@notmuchmail.org
> https://notmuchmail.org/mailman/listinfo/notmuch

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] cli/insert: do not lose the SMTP envelope
  2016-01-03 16:04 ` [PATCH] " Jani Nikula
@ 2016-01-03 20:27   ` J Farkas
  0 siblings, 0 replies; 6+ messages in thread
From: J Farkas @ 2016-01-03 20:27 UTC (permalink / raw)
  To: Jani Nikula; +Cc: notmuch

On 2016-01-03 at 18:04:39, Jani Nikula wrote:
> On Fri, 01 Jan 2016, J Farkas <jf.hyqohaczlksw4tx6ae@l2015aftruuq.dns007.net> wrote:
> > From: Janos Farkas <chexum+dev@gmail.com>
> > Subject: [PATCH] cli/insert: do not lose the SMTP envelope
> >
> > Make sure we store the envelope sender/recipient if provided by
> > qmail-command(8) in $RPLINE and $DTLINE.
> > ---
> >
> > I just realised that the messages delivered directly into maildir don't have
> > the usual envelope addresses that qmail provides.  This is a piece of
> > information that's important to (at least my) troubleshooting, so I created a
> > patch that seems to work well, applies cleanly to master (and 0.21), and
> > provided a NEWS entry should it be necessary.
> 
> I'd be more interested in seeing some tests for this...

I was thinking of it, and it could be simply an assurance that the
functionality stays there after changes too.  To be honest, the only
reason I didn't because the test suite is not passing in my environment,
either because of some gdb peculiarity, or some differences with emacs.

Answering your comment about Mallory here -- the DTLINE and RPLINE are
practically qmail's way of splitting the first two headers that *should*
be written in the message, they can only be affected by someone who
is actually saying he wants to deliver a message, not for any other
deliveries.

All the data that is supplied this way to the MDA by qmail (or the local
MTA), is still something that was accepted during the SMTP conversation
and passed basic checks, for a locally acceptable recipient, and after
any possible blocking on the sender.

It's just done in this way because:

- DTLINE is the Delivered-To line and qmail at this point is not sure
  the file will be "delivered", or processed in some other way, only the
  delivering program can actually tell what recipient will it be
  delivered to.  qmail uses this series of headers for loop avoidance,
  so it's essential that all the checkpoints are present.

- RPLINE is the Return-Path header that should be the *first* header in
  the file; if it would become part of the stdio, now all delivering and
  non-delivering programs would have to parse, detach it, and reattach
  to the front after any headers added.

It's basically a way to keep the SMTP conversation details alive along
the delivery pipeline.  Throwing it away is incorrect.  If this is not
ending up in the message, all I lose is the SMTP envelope, that can tell
me what entity was directly responsible to pass this message to my SMTP
server - was it sent by a mailing list, or if it's a direct message.
Or, in some cases, *which* mailing list.  It's a much safer way than
parsing through the Received lines.

Feel free to let me know if it needs further clarification why it is to
be done this way.

> >  NEWS             |  9 +++++++++
> >  notmuch-insert.c | 28 ++++++++++++++++++++++++++++
> >  2 files changed, 37 insertions(+)
> >
> > diff --git a/NEWS b/NEWS
> > index 6681699..13d45c8 100644
> > --- a/NEWS
> > +++ b/NEWS
> > @@ -1,3 +1,12 @@
> > +
> > +
> > +`notmuch insert` records the envelope addresses if available
> > +
> > +  If the caller provides this information as qmail-command(8) does in
> > +  the RPLINE and DTLINE environment variables, then notmuch insert will
> > +  record it in the maildir file.
> 
> We usually refer to message files. Perhaps you should also mention what
> the RPLINE and DTLINE variables should contain.

I don't think it's worthy for a NEWS entry with an explanation for those
- perhaps you meant in the commit or comments?

> > +
> >  Notmuch 0.21 (2015-10-29)
> >  =========================
> >  
> > diff --git a/notmuch-insert.c b/notmuch-insert.c
> > index 5205c17..ecc0fa0 100644
> > --- a/notmuch-insert.c
> > +++ b/notmuch-insert.c
> > @@ -284,6 +284,26 @@ copy_fd (int fdout, int fdin)
> >  }
> >  
> >  /*
> > + * Write zero (and LF) terminated string to the output fd.  It's expected to
> > + * come from getenv(), so it's not checked for correctness.  NULL or empty
> > + * string is ignored, successfully.
> > + * Return TRUE on success, FALSE on errors.
> > + */
> > +static notmuch_bool_t
> > +write_header (int fdout, const char *hdr)
> > +{
> > +    ssize_t written,to_write;
> > +
> > +    if (hdr && (to_write = strlen (hdr))) {
> > +        written = write (fdout, hdr, to_write);
> > +	if (written != to_write)
> > +	    return FALSE;
> > +    }
> 
> It's not an error for write() to return prematurely with written <
> to_write. Please see the write(2) man page and the copy_fd()
> implementation in this file.

Yes, I considered it - I just couldn't see why any of the conditions
that can cause this, makes it worth to keep trying.

My manuals, and even the POSIX write()* description is only mentioning
error conditions (end of medium, file size limits) and signals that can
cause a split write().  In case of a hard error (which can be resolved
some time later, for sure), the best choice is to abort it anyway.
There's no other signal that can divert the execution, just ctrl-c, in
which case the user is already expecting the program to quit.

And - a "failure" in an MDA is not necessarily the worst way to handle
problems - the delivery is just deferred by the local queue, it will
only cause an error if it was persistently failing for a long time.

But if you think it should be more robust at this point, I'll be happy
to redo the error handling as expected.

* http://pubs.opengroup.org/onlinepubs/9699919799/functions/write.html


> Jani.
> 
> > +
> > +    return TRUE;
> > +}
> > +
> > +/*
> >   * Write fdin to a new temp file in maildir/tmp, return full path to
> >   * the file, or NULL on errors.
> >   */
> > @@ -297,6 +317,14 @@ maildir_write_tmp (const void *ctx, int fdin, const char *maildir)
> >      if (fdout < 0)
> >  	return NULL;
> >  
> > +    /* maildir(5) suggests the message should start with a Return-Path
> > +     * and Delivered-To lines.  qmail-local(8) supplies these.
> > +     */
> > +    if (! write_header(fdout, getenv("RPLINE")))
> > +	goto FAIL;
> > +    if (! write_header(fdout, getenv("DTLINE")))
> > +	goto FAIL;
> > +
> >      if (! copy_fd (fdout, fdin))
> >  	goto FAIL;

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2016-01-03 20:27 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-01-01 11:21 [PATCH] cli/insert: do not lose the SMTP envelope J Farkas
2016-01-02 11:28 ` Tomi Ollila
2016-01-02 11:50   ` J Farkas
2016-01-03 16:15     ` Jani Nikula
2016-01-03 16:04 ` [PATCH] " Jani Nikula
2016-01-03 20:27   ` J Farkas

Code repositories for project(s) associated with this public inbox

	https://yhetil.org/notmuch.git/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).