Sorry to shamelessly "bump" this, but any way to get this integrated
into upstream, eventually?
We used the original patch from Frank Scholl and then this improved one
in production now for like a year, now, and didn't experience issues. In
our case it is specifically needed for a client that uses GroupWise[0]
internally to send mails (which seems to always generate mails with an
"xtext" ORCPT param).
Thanks!
[0] https://www.microfocus.com/products/groupwise/
On Fri, Oct 28, 2022 at 04:16:36PM +0200, Tim Kuijsten wrote:
I have refined and more thoroughly tested a previous patch that
relaxes the ORCPT address check.
Over the years mail has been rejected by senders that use RCPT TO
commands like:
RCPT TO:<i...@exmpale.com> ORCPT=rfc822;groupwise-i...@example.com:0:0 or
RCPT TO:<i...@exmpale.com> ORCPT=rfc822;groupwise-i...@example.com:0:0
NOTIFY=SUCCESS,FAILURE
In the above the domain part of the ORCPT address resolves to
example.com:0:0 which is rejected by smtpd with the message:
smtpd[20797]: 1a3a396cd4c57d05 smtp failed-command command="RCPT
TO:<i...@example.com> ORCPT=rfc822;groupwise-i...@example.com:0:0
NOTIFY=SUCCESS,FAILURE" result="553 ORCPT address syntax error"
I've studied RFC 3461 section 4 and 4.2 but it's not entirely clear to
me if the above ORCPT command is valid or not. The encoding adheres to
the spec, which says it must be valid xtext.
With this patch smtpd accepts any ORCPT that is valid xtext as defined
in the RFC (and logs on informational message when it consists of an
invalid user or domain name).
Cheers,
Tim
---
usr.sbin/smtpd/smtp_session.c | 22 ++++++++++++++++++----
usr.sbin/smtpd/smtpd.h | 1 +
usr.sbin/smtpd/util.c | 32 ++++++++++++++++++++++++++++++++
3 files changed, 51 insertions(+), 4 deletions(-)
diff --git a/usr.sbin/smtpd/smtp_session.c b/usr.sbin/smtpd/smtp_session.c
index 72e13e8fd8d..c0c29d4a695 100644
--- a/usr.sbin/smtpd/smtp_session.c
+++ b/usr.sbin/smtpd/smtp_session.c
@@ -2415,6 +2415,7 @@ smtp_tx_create_message(struct smtp_tx *tx)
static void
smtp_tx_rcpt_to(struct smtp_tx *tx, const char *line)
{
+ struct mailaddr orcptaddr;
char *opt, *p;
char *copy;
char tmp[SMTP_LINE_MAX];
@@ -2469,10 +2470,23 @@ smtp_tx_rcpt_to(struct smtp_tx *tx, const char
*line)
if (strncasecmp(opt, "rfc822;", 7) == 0)
opt += 7;
- if (!text_to_mailaddr(&tx->evp.dsn_orcpt, opt) ||
- !valid_localpart(tx->evp.dsn_orcpt.user) ||
- (strlen(tx->evp.dsn_orcpt.domain) != 0 &&
- !valid_domainpart(tx->evp.dsn_orcpt.domain))) {
+ if (!text_to_mailaddr(&orcptaddr, opt)) {
+ smtp_reply(tx->session,
+ "553 ORCPT address syntax error");
+ return;
+ }
+
+ if (valid_localpart(orcptaddr.user) &&
+ (strlen(orcptaddr.domain) != 0 &&
+ valid_domainpart(orcptaddr.domain))) {
+ tx->evp.dsn_orcpt = orcptaddr;
+ } else if (valid_xtext(opt)) {
+ log_info("%016"PRIx64" smtp "
+ "uncommon ORCPT: \"%s\", u:\"%s\",
d:\"%s\"",
+ tx->session->id,
+ opt, orcptaddr.user, orcptaddr.domain);
+ tx->evp.dsn_orcpt = orcptaddr;
+ } else {
smtp_reply(tx->session,
"553 ORCPT address syntax error");
return;
diff --git a/usr.sbin/smtpd/smtpd.h b/usr.sbin/smtpd/smtpd.h
index 125a6a5dfbe..c59706885e2 100644
--- a/usr.sbin/smtpd/smtpd.h
+++ b/usr.sbin/smtpd/smtpd.h
@@ -1702,6 +1702,7 @@ int mailaddr_match(const struct mailaddr *,
const struct mailaddr *);
int valid_localpart(const char *);
int valid_domainpart(const char *);
int valid_domainname(const char *);
+int valid_xtext(const char *s);
int valid_smtp_response(const char *);
int secure_file(int, char *, char *, uid_t, int);
int lowercase(char *, const char *, size_t);
diff --git a/usr.sbin/smtpd/util.c b/usr.sbin/smtpd/util.c
index feb663cc61e..0c4d0015fa4 100644
--- a/usr.sbin/smtpd/util.c
+++ b/usr.sbin/smtpd/util.c
@@ -515,6 +515,38 @@ valid_domainname(const char *str)
return 1;
}
+int
+valid_xtext(const char *s)
+{
+ while (*s != '\0') {
+ if (*s == '=')
+ return 0;
+
+ if (*s < '\x21' || *s > '\x7e')
+ return 0;
+
+ if (*s == '+') {
+ /* expect hexchar "+XX" RFC 3461 4. */
+ if (strnlen(s, 3) != 3)
+ return 0;
+
+ s++;
+
+ if (!isdigit(*s) && !isupper(*s))
+ return 0;
+
+ s++;
+
+ if (!isdigit(*s) && !isupper(*s))
+ return 0;
+ }
+
+ s++;
+ }
+
+ return 1;
+}
+
int
valid_smtp_response(const char *s)
{
--
2.37.3