Package: release.debian.org Severity: normal User: release.debian....@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 <dbuer...@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 <m...@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 <m...@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 <m...@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