[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#989324: marked as done (unblock: opendmarc/1.4.0~beta1+dfsg-4)



Your message dated Wed, 02 Jun 2021 18:05:07 +0000
with message-id <E1loVEp-0004zh-6G@respighi.debian.org>
and subject line unblock opendmarc
has caused the Debian Bug report #989324,
regarding unblock: opendmarc/1.4.0~beta1+dfsg-4
to be marked as done.

This means that you claim that the problem has been dealt with.
If this is not the case it is now your responsibility to reopen the
Bug report if necessary, and/or fix the problem forthwith.

(NB: If you are a system administrator and have no idea what this
message is talking about, this may indicate a serious mail system
misconfiguration somewhere. Please contact owner@bugs.debian.org
immediately.)


-- 
989324: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=989324
Debian Bug Tracking System
Contact owner@bugs.debian.org with problems
--- Begin Message ---
Package: release.debian.org
Severity: normal
User: release.debian.org@packages.debian.org
Usertags: unblock

Please unblock package opendmarc

Fixes for three CVEs have recently been released by the OpenDMARC
developers. The fixes themselves are spread over more than a dozen
commits, so I referred to the final code from upstream version 1.4.1.1.
Detailed description of the CVEs and their resolution can be found at:
https://github.com/trusteddomainproject/OpenDMARC/tree/rel-opendmarc-1-4-1-1/SECURITY

[ Reason ]
Fixes for several CVEs have been released in OpenDMARC 1.4.1.1.

[ Impact ]
Current opendmarc 1.4.0~beta1+dfsg-3 contains vulnerabilities that need
patching.

[ Tests ]
Version 1.4.0~beta1+dfsg-4 is running ‘in production’ (on my small
personal mail server), rudimentary manual testing.

[ Risks ]
The patches are not small but relatively self-contained and easy to
read.

[ Checklist ]
  [x] all changes are documented in the d/changelog
  [x] I reviewed all changes and I approve them
  [x] attach debdiff against the package in testing

unblock opendmarc/1.4.0~beta1+dfsg-4
diff -Nru opendmarc-1.4.0~beta1+dfsg/debian/changelog opendmarc-1.4.0~beta1+dfsg/debian/changelog
--- opendmarc-1.4.0~beta1+dfsg/debian/changelog	2020-09-19 08:40:47.000000000 +0200
+++ opendmarc-1.4.0~beta1+dfsg/debian/changelog	2021-05-29 16:22:50.000000000 +0200
@@ -1,3 +1,12 @@
+opendmarc (1.4.0~beta1+dfsg-4) unstable; urgency=high
+
+  * Backport patches from upstream version 1.4.1.1 (Closes: #977766, #977767):
+    - CVE-2019-16378: Fix handling of multi-valued From headers
+    - CVE-2019-20790: Validate incoming SPF headers
+    - CVE-2020-12272: Check DKIM and SPF domain syntax
+
+ -- David Bürgin <dbuergin@gluet.ch>  Sat, 29 May 2021 16:22:50 +0200
+
 opendmarc (1.4.0~beta1+dfsg-3) unstable; urgency=high
 
   * Cherry-pick patch for CVE-2020-12460 from upstream:
diff -Nru opendmarc-1.4.0~beta1+dfsg/debian/libopendmarc2.symbols opendmarc-1.4.0~beta1+dfsg/debian/libopendmarc2.symbols
--- opendmarc-1.4.0~beta1+dfsg/debian/libopendmarc2.symbols	2020-06-16 20:41:13.000000000 +0200
+++ opendmarc-1.4.0~beta1+dfsg/debian/libopendmarc2.symbols	2021-05-29 15:03:47.000000000 +0200
@@ -1,5 +1,6 @@
 libopendmarc.so.2 libopendmarc2 #MINVER#
 * Build-Depends-Package: libopendmarc-dev
+ check_domain@Base 1.4.0~beta1+dfsg
  dmarc_dns_get_record@Base 1.1.0~beta2
  dmarc_strlcat@Base 1.1.0~beta2
  dmarc_strlcpy@Base 1.1.0~beta2
diff -Nru opendmarc-1.4.0~beta1+dfsg/debian/patches/cve-2019-16378.patch opendmarc-1.4.0~beta1+dfsg/debian/patches/cve-2019-16378.patch
--- opendmarc-1.4.0~beta1+dfsg/debian/patches/cve-2019-16378.patch	1970-01-01 01:00:00.000000000 +0100
+++ opendmarc-1.4.0~beta1+dfsg/debian/patches/cve-2019-16378.patch	2021-05-29 16:22:50.000000000 +0200
@@ -0,0 +1,321 @@
+Description: CVE-2019-16378: Handle multi-valued From header, add RejectMultiValueFrom parameter
+Author: Murray S. Kucherawy <msk@trusteddomain.org>
+Origin: backport, https://github.com/trusteddomainproject/OpenDMARC/releases/tag/rel-opendmarc-1-4-1-1
+
+--- a/opendmarc/parse.c
++++ b/opendmarc/parse.c
+@@ -12,10 +12,18 @@
+ #include <string.h>
+ #include <limits.h>
+ #include <stdio.h>
++#include <stdlib.h>
+ 
+ /* opendmarc includes */
+ #include "util.h"
+ 
++#ifndef FALSE
++# define FALSE	0
++#endif /* ! FALSE */
++#ifndef TRUE
++# define TRUE	1
++#endif /* ! TRUE */
++
+ /* types */
+ typedef unsigned long cmap_elem_type;
+ 
+@@ -24,6 +32,7 @@
+ #define MAILPARSE_ERR_PUNBALANCED	1	/* unbalanced parentheses */
+ #define MAILPARSE_ERR_QUNBALANCED	2	/* unbalanced quotes */
+ #define MAILPARSE_ERR_SUNBALANCED	3	/* unbalanced sq. brackets */
++#define MAILPARSE_ERR_MULTIVALUE	4	/* multiple possible values */
+ 
+ /* a bitmap for the "specials" character class */
+ #define	CMAP_NBITS	 	(sizeof(cmap_elem_type) * CHAR_BIT)
+@@ -466,6 +475,160 @@
+ 	}
+ }
+ 
++/*
++**  DMARCF_MAIL_PARSE_MULTI -- extract the local-part and hostname from a mail
++**                             header field that might contain multiple
++**                             values, e.g. "To:", "Cc:"
++**
++**  Parameters:
++**  	line -- input line
++**  	users_out -- array of pointers to "local-part" (returned)
++**  	domains_out -- array of pointers to hostname (returned)
++**
++**  Return value:
++**  	0 on success, or an DKIM_MAILPARSE_ERR_* on failure.
++**
++**  Notes:
++**  	Input string is modified.
++*/
++
++int
++dmarcf_mail_parse_multi(unsigned char *line, unsigned char ***users_out,
++                        unsigned char ***domains_out)
++{
++	_Bool escaped = FALSE;
++	_Bool quoted = FALSE;
++	_Bool done = FALSE;
++	int a = 0;
++	int n = 0;
++	int status;
++	int parens = 0;
++	char *p;
++	char *addr;
++	unsigned char **uout = NULL;
++	unsigned char **dout = NULL;
++	unsigned char *u;
++	unsigned char *d;
++
++	/* walk the input string looking for unenclosed commas */
++	addr = line;
++	for (p = line; !done; p++)
++	{
++		if (escaped)
++		{
++			escaped = FALSE;
++			continue;
++		}
++
++		switch (*p)
++		{
++		  case '\\':
++			escaped = TRUE;
++			continue;
++
++		  case '"':
++			quoted = !quoted;
++			continue;
++
++		  case '(':
++			parens++;
++			continue;
++
++		  case ')':
++			parens--;
++			continue;
++
++		  case ',':
++			/* skip it if it's quoted or in a comment */
++			if (parens != 0 || quoted)
++				continue;
++			/* FALLTHROUGH */
++
++		  case '\0':
++			if (*p == '\0')
++				done = TRUE;
++			else
++				*p = '\0';
++
++			status = dmarcf_mail_parse(addr, &u, &d);
++			if (status != 0)
++			{
++				if (uout != NULL)
++				{
++					free(uout);
++					free(dout);
++				}
++
++				return status;
++			}
++
++			if (n == 0)
++			{
++				size_t newsize = 2 * sizeof(unsigned char *);
++
++				uout = (unsigned char **) malloc(newsize);
++				if (uout == NULL)
++					return -1;
++
++				dout = (unsigned char **) malloc(newsize);
++				if (dout == NULL)
++				{
++					free(uout);
++					return -1;
++				}
++
++				a = 2;
++			}
++			else if (n + 1 == a)
++			{
++				unsigned char **new;
++
++				size_t newsize = a * 2 * sizeof(unsigned char *);
++
++				new = (unsigned char **) realloc(uout, newsize);
++				if (new == NULL)
++				{
++					free(uout);
++					free(dout);
++					return -1;
++				}
++
++				uout = new;
++
++				new = (unsigned char **) realloc(dout, newsize);
++				if (new == NULL)
++				{
++					free(uout);
++					free(dout);
++					return -1;
++				}
++
++				dout = new;
++
++				a *= 2;
++			}
++
++			uout[n] = u;
++			dout[n++] = d;
++
++			uout[n] = (char *) NULL;
++			dout[n] = (char *) NULL;
++
++			addr = p + 1;
++
++			break;
++
++		  default:
++			break;
++		}
++	}
++
++	*users_out = uout;
++	*domains_out = dout;
++
++	return 0;
++}
++
+ #ifdef MAILPARSE_TEST
+ int
+ main(int argc, char **argv)
+--- a/opendmarc/opendmarc.c
++++ b/opendmarc/opendmarc.c
+@@ -177,6 +177,7 @@
+ 	_Bool			conf_spfselfvalidate;
+ #endif /* WITH_SPF */
+ 	_Bool			conf_ignoreauthclients;
++	_Bool			conf_reject_multi_from;
+ 	unsigned int		conf_refcnt;
+ 	unsigned int		conf_dnstimeout;
+ 	struct config *		conf_data;
+@@ -1365,6 +1366,10 @@
+ 		                  &conf->conf_afrf,
+ 		                  sizeof conf->conf_afrf);
+ 
++		(void) config_get(data, "RejectMultiValueFrom",
++		                  &conf->conf_reject_multi_from,
++		                  sizeof conf->conf_reject_multi_from);
++
+ 		(void) config_get(data, "FailureReportsOnNone",
+ 		                  &conf->conf_afrfnone,
+ 		                  sizeof conf->conf_afrfnone);
+@@ -2291,8 +2296,10 @@
+ 	struct dmarcf_header *from;
+ 	struct arcseal_header *as_hdr;
+ 	u_char *reqhdrs_error = NULL;
+-	u_char *user;
+-	u_char *domain;
++	u_char *user = NULL;
++	u_char **users;
++	u_char *domain = NULL;
++	u_char **domains;
+ 	u_char *bang;
+ 	u_char **ruv;
+ 	unsigned char header[MAXHEADER + 1];
+@@ -2414,10 +2421,36 @@
+ 		return SMFIS_ACCEPT;
+ 	}
+ 
+-	/* extract From: domain */
++	/* extract From: addresses */
+ 	memset(addrbuf, '\0', sizeof addrbuf);
+ 	strncpy(addrbuf, from->hdr_value, sizeof addrbuf - 1);
+-	status = dmarcf_mail_parse(addrbuf, &user, &domain);
++	status = dmarcf_mail_parse_multi(addrbuf, &users, &domains);
++	if (status == 0 && (users[0] != NULL || domains[0] != NULL))
++	{
++		/*
++		**  Enact special handling for a multi-valued from if
++		**  the domains are not all the same.
++		*/
++
++		for (c = 1; users[c] != NULL; c++)
++		{
++			if (strcasecmp(domains[0], domains[c]) != 0)
++			{
++				syslog(LOG_ERR,
++				       "%s: multi-valued From field detected",
++				       dfc->mctx_jobid);
++			}
++
++			if (conf->conf_reject_multi_from)
++				return SMFIS_REJECT;
++			else
++				return SMFIS_ACCEPT;
++		}
++
++		user = users[0];
++		domain = domains[0];
++	}
++
+ 	if (status != 0 || user == NULL || domain == NULL)
+ 	{
+ 		if (conf->conf_dolog)
+--- a/opendmarc/opendmarc-config.h
++++ b/opendmarc/opendmarc-config.h
+@@ -46,6 +46,7 @@
+ 	{ "RecordAllMessages",		CONFIG_TYPE_BOOLEAN,	FALSE },
+ 	{ "RequiredHeaders",		CONFIG_TYPE_BOOLEAN,	FALSE },
+ 	{ "RejectFailures",		CONFIG_TYPE_BOOLEAN,	FALSE },
++	{ "RejectMultiValueFrom",	CONFIG_TYPE_BOOLEAN,	FALSE },
+         { "RejectString",		CONFIG_TYPE_STRING,	FALSE },
+ 	{ "ReportCommand",		CONFIG_TYPE_STRING,	FALSE },
+ 	{ "Socket",			CONFIG_TYPE_STRING,	FALSE },
+--- a/opendmarc/opendmarc.conf.5.in
++++ b/opendmarc/opendmarc.conf.5.in
+@@ -251,6 +251,12 @@
+ The default is "false".
+ 
+ .TP
++.I RejectMultiValueFrom (Boolean)
++If set, messages with multiple addresses in the From: field of the message
++will be rejected unless all domain names in that field are the same.  They
++will otherwise be ignored by the filter (the default).
++
++.TP
+ .I RejectString (string)
+ This string describes the reason of reject at SMTP level.
+ The message MUST contain the word "%s" once, which will be replaced by
+--- a/opendmarc/opendmarc.conf.sample
++++ b/opendmarc/opendmarc.conf.sample
+@@ -295,6 +295,15 @@
+ #
+ # RejectFailures false
+ 
++##  RejectMultiValueFrom { true | false }
++##  	default "false"
++##
++##  If set, messages with multiple addresses in the From: field of the message
++##  will be rejected unless all domains in the field are the same.  They will
++##  otherwise be ignored by the filter (the default).
++#
++# RejectMultiValueFrom false
++
+ ## RejectString string
+ ##	default ("rejected by DMARC policy for %s")
+ ##
+--- a/opendmarc/parse.h
++++ b/opendmarc/parse.h
+@@ -22,5 +22,8 @@
+ /* prototypes */
+ extern int dmarcf_mail_parse __P((unsigned char *, unsigned char **,
+                                   unsigned char **));
++extern int dmarcf_mail_parse_multi __P((char *, unsigned char ***,
++                                       unsigned char ***));
++
+ 
+ #endif /* ! _DMARCF_MAILPARSE_H_ */
diff -Nru opendmarc-1.4.0~beta1+dfsg/debian/patches/cve-2019-20790.patch opendmarc-1.4.0~beta1+dfsg/debian/patches/cve-2019-20790.patch
--- opendmarc-1.4.0~beta1+dfsg/debian/patches/cve-2019-20790.patch	1970-01-01 01:00:00.000000000 +0100
+++ opendmarc-1.4.0~beta1+dfsg/debian/patches/cve-2019-20790.patch	2021-05-29 16:22:50.000000000 +0200
@@ -0,0 +1,300 @@
+Description: CVE-2019-20790: Properly validate incoming headers that carry SPF results
+Author: Murray S. Kucherawy <msk@trusteddomain.org>
+Origin: backport, https://github.com/trusteddomainproject/OpenDMARC/releases/tag/rel-opendmarc-1-4-1-1
+
+--- a/opendmarc/opendmarc.c
++++ b/opendmarc/opendmarc.c
+@@ -435,25 +435,46 @@
+ **
+ **  Parameters:
+ **  	str -- the value of the Received-SPF field to analyze
++**  	envdomain -- envelope sender domain against which to test
+ **
+ **  Return value:
+ **  	A ARES_RESULT_* constant.
++**
++**  Notes:
++**  	We will not accept a result delivered via a discovered Received-SPF
++**  	header field unless (a) it includes the "identity" key and its
++**  	value is "mailfrom", AND (b) it includes the "envelope-from" key and
++**  	its value matches the envelope sender we got via milter.  If either
++**  	of those tests fails, a "pass" or a "fail" is interpreted as "neutral".
++**  	This is necessary to be compliant with RFC 7489 Section 4.1,
++**  	which says the SPF evaluation of MAIL FROM is what DMARC consumes.
+ */
+ 
+ int
+-dmarcf_parse_received_spf(char *str)
++dmarcf_parse_received_spf(char *str, char *envdomain)
+ {
+-	_Bool copying = FALSE;
++	_Bool in_result = TRUE;
+ 	_Bool escaped = FALSE;
++	_Bool quoting = FALSE;
+ 	int parens = 0;
+ 	char *p;
+ 	char *r;
+ 	char *end;
+ 	char result[MAXSPFRESULT + 1];
++	char spf_envdomain[BUFRSZ + 1];
++	char key[BUFRSZ + 1];
++	char value[BUFRSZ + 1];
++	char identity[BUFRSZ + 1];
+ 
+ 	assert(str != NULL);
+ 
++	memset(spf_envdomain, '\0', sizeof spf_envdomain);
++	memset(key, '\0', sizeof key);
++	memset(value, '\0', sizeof value);
++	memset(identity, '\0', sizeof identity);
+ 	memset(result, '\0', sizeof result);
++
++	/* first thing we get is the result token */
+ 	r = result;
+ 	end = &result[sizeof result - 1];
+ 
+@@ -461,33 +482,13 @@
+ 	{
+ 		if (escaped)
+ 		{
+-			if (copying)
+-			{
+-				if (r < end)
+-					*r++ = *p;
+-			}
+-
++			if (parens == 0 && r < end)
++				*r++ = *p;
+ 			escaped = FALSE;
+ 		}
+-		else if (copying)
++		else if (*p == '\\')
+ 		{
+-			if (!escaped && *p == '\\')
+-			{
+-				escaped = TRUE;
+-			}
+-			else if (*p == '(')
+-			{
+-				copying = FALSE;
+-				parens++;
+-			}
+- 			else if (isascii(*p) && isspace(*p))
+-			{
+-				copying = FALSE;
+-			}
+-			else if (r < end)
+-			{
+-				*r++ = *p;
+-			}
++			escaped = TRUE;
+ 		}
+ 		else if (*p == '(')
+ 		{
+@@ -499,35 +500,117 @@
+ 		}
+ 		else if (parens == 0)
+ 		{
++			if (*p == '"')
++			{
++				/* entering/leaving a quoted substring */
++				quoting = !quoting;
++				continue;
++			}
++
++			/* a possibly meaningful character */
+ 			if (isascii(*p) && isspace(*p))
++			{
++				/* a space while quoting; just continue */
++				if (quoting)
++					continue;
++
++				if (in_result)
++				{
++					in_result = FALSE;
++					r = key;
++					end = &key[sizeof key - 1];
++				}
+ 				continue;
++			}
+ 
+-			if (!copying)
++			if (!in_result && *p == '=')
+ 			{
+-				if (result[0] != '\0')
+-					break;
++				r = value;
++				end = &value[sizeof value - 1];
++			}
++			else if (!in_result && *p == ';')
++			{
++				if (strcasecmp(key, "identity") == 0)
++				{
++					strlcpy(identity, value,
++					        sizeof identity);
++				}
++
++				if (strcasecmp(key, "envelope-from") == 0)
++				{
++					strlcpy(spf_envdomain, value,
++					        sizeof spf_envdomain);
++				}
++
++				memset(key, '\0', sizeof key);
++				memset(value, '\0', sizeof value);
+ 
+-				copying = TRUE;
+-				if (r < end)
+-					*r++ = *p;
++				r = key;
++				end = &key[sizeof key - 1];
++			}
++			else if (r < end)
++			{
++				*r++ = *p;
+ 			}
+ 		}
+ 	}
+ 
+-	if (strcasecmp(result, "pass") == 0)
++	if (key[0] != '\0')
++	{
++		if (strcasecmp(key, "identity") == 0)
++			strlcpy(identity, value, sizeof identity);
++		if (strcasecmp(key, "envelope-from") == 0)
++			strlcpy(spf_envdomain, value, sizeof spf_envdomain);
++	}
++
++	p = strchr(spf_envdomain, '@');
++	if (p != NULL)
++	{
++		r = spf_envdomain;
++		p = p + 1;
++		for (;;)
++		{
++			*r = *p;
++			if (*p == '\0')
++				break;
++			r++;
++			p++;
++		}
++	}
++
++	if (strcasecmp(identity, "mailfrom") != 0 ||
++            strcasecmp(spf_envdomain, envdomain) != 0)
++	{
++		return ARES_RESULT_NEUTRAL;
++	}
++	else if (strcasecmp(result, "pass") == 0)
++	{
+ 		return ARES_RESULT_PASS;
++	}
+ 	else if (strcasecmp(result, "fail") == 0)
++	{
+ 		return ARES_RESULT_FAIL;
++	}
+ 	else if (strcasecmp(result, "softfail") == 0)
++	{
+ 		return ARES_RESULT_SOFTFAIL;
++	}
+ 	else if (strcasecmp(result, "neutral") == 0)
++	{
+ 		return ARES_RESULT_NEUTRAL;
++	}
+ 	else if (strcasecmp(result, "temperror") == 0)
++	{
+ 		return ARES_RESULT_TEMPERROR;
++	}
+ 	else if (strcasecmp(result, "none") == 0)
++	{
+ 		return ARES_RESULT_NONE;
++	}
+ 	else
++	{
+ 		return ARES_RESULT_PERMERROR;
++	}
+ }
+ 
+ /*
+@@ -2678,13 +2761,47 @@
+ #endif
+ 			)
+ 			{
++				_Bool envfrom_match = FALSE;
+ 				int spfmode;
++				int i;
+ 
+ 				dfc->mctx_spfresult = ar.ares_result[c].result_result;
+ 
+ 				if (ar.ares_result[c].result_result != ARES_RESULT_PASS)
+ 					continue;
+ 
++				/*
++				**  Confirm the method used was "smtp.mailfrom"
++				**  and it matches our envelope sender.
++				*/
++
++				for (i = 0;
++				     i < ar.ares_result[c].result_props;
++				     i++)
++				{
++					if (ar.ares_result[c].result_ptype[i] == ARES_PTYPE_SMTP &&
++					    strcasecmp(ar.ares_result[c].result_property[i],
++					               "mailfrom") == 0)
++					{
++						char *d;
++
++						d = strchr(ar.ares_result[c].result_value[i],
++						           '@');
++						if (d == NULL)
++							d = ar.ares_result[c].result_value[i];
++
++						if (strcasecmp(d,
++						               dfc->mctx_envdomain) == 0)
++						{
++							envfrom_match = TRUE;
++							break;
++						}
++					}
++				}
++
++				if (!envfrom_match)
++					continue;
++
+ 				spfaddr = NULL;
+ 				spfmode = DMARC_POLICY_SPF_ORIGIN_HELO;
+ 
+@@ -2928,7 +3045,8 @@
+ 				else
+ 					spfmode = DMARC_POLICY_SPF_ORIGIN_MAILFROM;
+ 
+-				spfres = dmarcf_parse_received_spf(hdr->hdr_value);
++				spfres = dmarcf_parse_received_spf(hdr->hdr_value,
++				                                   dfc->mctx_envdomain);
+ 
+ 				dmarcf_dstring_printf(dfc->mctx_histbuf,
+ 				                      "spf %d\n", spfres);
+@@ -3002,7 +3120,7 @@
+ 				&used_mfrom);
+ 			if (used_mfrom == TRUE)
+ 			{
+-				use_domain = dfc->mctx_envfrom;
++				use_domain = dfc->mctx_envdomain;
+ 				spf_mode   = DMARC_POLICY_SPF_ORIGIN_MAILFROM;
+ 			}
+ 			else
+@@ -3011,10 +3129,10 @@
+ 				spf_mode   = DMARC_POLICY_SPF_ORIGIN_HELO;
+ 			}
+ 			ostatus = opendmarc_policy_store_spf(cc->cctx_dmarc, 
+-				                                     use_domain,
+-				                                     spf_result,
+-				                                     spf_mode,
+-				                                     human);
++				                             use_domain,
++				                             spf_result,
++				                             spf_mode,
++				                             human);
+ 			switch (spf_result)
+ 			{
+ 			    case DMARC_POLICY_SPF_OUTCOME_PASS:
diff -Nru opendmarc-1.4.0~beta1+dfsg/debian/patches/cve-2020-12272.patch opendmarc-1.4.0~beta1+dfsg/debian/patches/cve-2020-12272.patch
--- opendmarc-1.4.0~beta1+dfsg/debian/patches/cve-2020-12272.patch	1970-01-01 01:00:00.000000000 +0100
+++ opendmarc-1.4.0~beta1+dfsg/debian/patches/cve-2020-12272.patch	2021-05-29 16:22:50.000000000 +0200
@@ -0,0 +1,67 @@
+Description: CVE-2020-12272: Check syntax of DKIM and SPF domain names
+Author: Murray S. Kucherawy <msk@trusteddomain.org>
+Origin: backport, https://github.com/trusteddomainproject/OpenDMARC/releases/tag/rel-opendmarc-1-4-1-1
+
+--- a/libopendmarc/opendmarc_policy.c
++++ b/libopendmarc/opendmarc_policy.c
+@@ -4,6 +4,8 @@
+ **  Copyright (c) 2012-2016, 2018, The Trusted Domain Project.  All rights reserved.
+ **************************************************************************/
+ 
++#include <ctype.h>
++
+ #include "opendmarc_internal.h"
+ #include "dmarc.h"
+ 
+@@ -22,6 +24,33 @@
+ # include <opendmarc_strl.h>
+ #endif /* USE_DMARCSTRL_H */
+ 
++/*
++**  CHECK_DOMAIN -- check for syntactical validity of a domain name
++**
++**  Parameters:
++**  	domain -- domain name to check
++**
++**  Return value:
++**  	TRUE if the syntax was fine, FALSE otherwise.
++*/
++
++bool check_domain(u_char *domain)
++{
++	u_char *dp;
++
++	for (dp = domain; *dp != '\0'; dp++)
++	{
++		if (!(isalpha(*dp) ||
++		      isdigit(*dp) ||
++		      *dp == '.' ||
++		      *dp == '-' ||
++		      *dp == '_'))
++			return FALSE;
++	}
++
++	return TRUE;
++}
++
+ /**************************************************************************
+ ** OPENDMARC_POLICY_LIBRARY_INIT -- Initialize The Library
+ **	Parameters:
+@@ -388,6 +417,8 @@
+ 	dp = opendmarc_util_finddomain(domain, domain_buf, sizeof domain_buf);
+ 	if (dp == NULL)
+ 		return DMARC_PARSE_ERROR_NO_DOMAIN;
++	if (!check_domain(dp))
++		return DMARC_PARSE_ERROR_BAD_VALUE;
+ 	if (human_readable != NULL)
+ 		pctx->spf_human_outcome = strdup((char *)human_readable);
+ 	pctx->spf_domain = strdup((char *)dp);
+@@ -454,6 +485,8 @@
+ 		return DMARC_PARSE_ERROR_NULL_CTX;
+ 	if (d_equal_domain == NULL || strlen((char *)d_equal_domain) == 0)
+ 		return DMARC_PARSE_ERROR_EMPTY;
++	if (!check_domain(d_equal_domain))
++		return DMARC_PARSE_ERROR_BAD_VALUE;
+ 
+ 	switch (dkim_result)
+ 	{
diff -Nru opendmarc-1.4.0~beta1+dfsg/debian/patches/series opendmarc-1.4.0~beta1+dfsg/debian/patches/series
--- opendmarc-1.4.0~beta1+dfsg/debian/patches/series	2020-09-19 08:34:33.000000000 +0200
+++ opendmarc-1.4.0~beta1+dfsg/debian/patches/series	2021-05-29 15:51:16.000000000 +0200
@@ -9,3 +9,6 @@
 ticket227.patch
 pull48.patch
 cve-2020-12460.patch
+cve-2019-16378.patch
+cve-2020-12272.patch
+cve-2019-20790.patch

--- End Message ---
--- Begin Message ---
Unblocked.

--- End Message ---

Reply to: