From patchwork Fri Jan 19 17:16:08 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kevin 'ldir' Darbyshire-Bryant X-Patchwork-Id: 863665 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.infradead.org (client-ip=65.50.211.133; helo=bombadil.infradead.org; envelope-from=lede-dev-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="JdPVIUxT"; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=darbyshire-bryant.me.uk header.i=@darbyshire-bryant.me.uk header.b="QeULcoF/"; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [65.50.211.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3zNSD04bDqz9s7G for ; Sat, 20 Jan 2018 04:16:32 +1100 (AEDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:Subject:MIME-Version:Message-Id:Date:To :From:Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To:References: List-Owner; bh=qJLXC1txN8rt6CCQp617neLKenOPeZR9+CwI3P12Ftg=; b=JdPVIUxTxsDS6t JH3we6IHwlZc95Xo5rY3DWGgQRDxeu+PoCvD4NfC23OHNs/oJ/BX+LGb126mdeBzfywlWd7lOU9xX oBeX3GkZWy+/L4+QnDkOnk41lbVVE4CeD2JLiXRYlcGbXkNZAevcafq9lvG5VaLQO2EOi2jTIMqjR lWGCaP1U2QMeYxrk4DKeZRG90fSRtL7MIil8wzBRgt7c15OK24zb5OqW2aV1y4tLeYrjfOqepAWMj WZsdvbNTOgjthf2hZDfbvu/3At6iHi2aGzzBbQ4PaMs/q9x7ltHGni0r1Xo8KLqXaYAcZcbEQDWqV hPaJSrCCAA6HNkj9V2mA==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.89 #1 (Red Hat Linux)) id 1ecaHG-0008CL-Qr; Fri, 19 Jan 2018 17:16:30 +0000 Received: from mail-ve1eur01on0088.outbound.protection.outlook.com ([104.47.1.88] helo=EUR01-VE1-obe.outbound.protection.outlook.com) by bombadil.infradead.org with esmtps (Exim 4.89 #1 (Red Hat Linux)) id 1ecaHC-00087j-Kv for lede-dev@lists.infradead.org; Fri, 19 Jan 2018 17:16:29 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=darbyshire-bryant.me.uk; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version; bh=E8y/ttIWyF/WOgfTjHIYqqtOphmqVcbp9dHFntT8Cj4=; b=QeULcoF/7Ef3tD5FjjW/vC5YoekO14/qwU+xjA/379YMedmFkotVfsAx2kje70jhq7qOK184dQsqqq5eFBNYG5fhPvRjoXDW9BHlwezUhvUY64/RIwNf4v8aFVNH/zTgkyXiWJF28oogdH8Aq4Z4RX+/c3BRCWeiTOmKrho28jY= Received: from Rowlf.darbyshire-bryant.me.uk (151.224.34.91) by VI1PR0702MB3741.eurprd07.prod.outlook.com (2603:10a6:803:7::31) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P256) id 15.20.444.5; Fri, 19 Jan 2018 17:16:12 +0000 From: Kevin Darbyshire-Bryant To: lede-dev@lists.infradead.org Date: Fri, 19 Jan 2018 17:16:08 +0000 Message-Id: <20180119171608.2970-1-ldir@darbyshire-bryant.me.uk> X-Mailer: git-send-email 2.14.3 (Apple Git-98) MIME-Version: 1.0 X-Originating-IP: [151.224.34.91] X-ClientProxiedBy: LO2P265CA0046.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:61::34) To VI1PR0702MB3741.eurprd07.prod.outlook.com (2603:10a6:803:7::31) X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 37f35cad-085d-4437-2fe7-08d55f6056fe X-Microsoft-Antispam: UriScan:; BCL:0; PCL:0; RULEID:(7020095)(4652020)(7021125)(5600026)(4604075)(4534125)(7022125)(4602075)(4603075)(4627221)(201702281549075)(7048125)(7024125)(7027125)(7028125)(7023125)(2017052603307)(7153060)(7193020); SRVR:VI1PR0702MB3741; X-Microsoft-Exchange-Diagnostics: 1; VI1PR0702MB3741; 3:ttCXr3RTh9LeZT9IgoqZfBN35w5C4SlufK6UWpkzpyfT1wzC55j1aBvV9RQDtG04PBIOW33oIbXGXGRJDJRzw4I05GyP74OSo+pHLVL3SaaA+TGQL8n0eP+/qxfV9Nguot8LbHSiQFoCAy8ogcSRWD+zE74oZpEqYXiq6X6VCJMxe/ivVlZX8wR9+F8Q10wftQzykUu85oFl+7oXGbV35fEQYsx7rhrZLWNlArcSDyTsSDa53IuMk1HvNyLZgyGi; 25:WLZPUEiSgudi12cpBpUnmmaV8ZBBhU6P1CRh8Xm0WmdN9C8ucFpxesPdC5nuVWQK/DTkwMoXLXSJaJzttXTjFweS/x5KB/hl1H3dHk9eyGH1F5gT5fzblFG0fC4uLN2AGSixfsOsUUjwsFbN5qvefbBGPpyjMC6jQtpLWajbRUgmM2b4zUSrUspnTi69nmmcMUYLE+gagszWviqovI+F8g94FNHQ75Evv0+56ouGG4kWWmkVUo7+CY7z7FIABPDdtY13c8A230mHjfUGjd0SXSDnzcbHN+NUMCQCvyBdHSUIpeHHxWgGQVcHiLVKyLFp8Zz2QRgYr+tbdtOBN1pPhw==; 31:SmjLYGuGguQADjFGkbgW7zLHXDbYIROE8SxEDkjXAOGTHQNULms6LRw+IPdUNOsmV4b0lMRgIxqjsWRoHUuQmgQa3Lk2SjWnCSLGstIfLb7ISPCVBP64R7r//1XkUzO7Go4lRqc8vbjL9waNr5tUrF3xJGoKpjqcJLB67VL/BP5cz22Gv8vwPL22aawsBQoZCabc59HiMUglujrhd1oB4WFjpwTnNTLkn2n1KsvP+Ts= X-MS-TrafficTypeDiagnostic: VI1PR0702MB3741: X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:(192374486261705)(150554046322364); X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:(6040495)(2401047)(8121501046)(5005006)(3002001)(93006095)(93001095)(3231046)(2400080)(944501161)(10201501046)(6041282)(2016111802025)(20161123558120)(20161123562045)(20161123564045)(20161123560045)(6043046)(6072148)(201708071742011); SRVR:VI1PR0702MB3741; BCL:0; PCL:0; RULEID:(100000803101)(100110400095); SRVR:VI1PR0702MB3741; X-Microsoft-Exchange-Diagnostics: 1; VI1PR0702MB3741; 4:JDjmkVjtLoOw70KSVvQZWcRdhbKLQp7tjykPZuHSC2on2eeDCkj3g3nFt0FSZQxoi5sbe6UiACe9XXQNTe11dwB5xGgImCp/IZl9OB+/oOTkBrnpaqZCqrGCSQBGHTu3/HNY9W4M5wuzAN+qxSnjEEVBiDOGVX2A6T9ZuzTC6Gw1eQFpkbvrNI1xEIyiN7JGeozI8wy0lF6+yWbcvnryH2MWzyjQF+EEfoJpeOAhDNBF+PHfm7zsBrfr6OXCn/ON5LcihTIipkJko2l5Q/w87YFTnyPmRG6Iq8vAzStR2ETwyO3AhW43bPKMJoCPZjySiroU0H6oaCRUVvBLi7w53+2kVf7RWCNc34ITlUkP+Uc= X-Forefront-PRVS: 0557CBAD84 X-Forefront-Antispam-Report: SFV:NSPM; SFS:(10009020)(346002)(366004)(39380400002)(39830400003)(376002)(396003)(288314003)(189003)(199004)(15650500001)(7696005)(16586007)(2906002)(48376002)(107886003)(81166006)(2420400007)(97736004)(50466002)(106356001)(478600001)(10710500007)(316002)(5660300001)(42882006)(53416004)(6916009)(386003)(8676002)(1076002)(105586002)(81156014)(52116002)(51416003)(3846002)(6666003)(59450400001)(47776003)(8936002)(7736002)(2361001)(6306002)(36756003)(6116002)(53936002)(69596002)(2351001)(25786009)(66066001)(4326008)(74482002)(16526018)(50226002)(6486002)(305945005)(26005)(6346003)(68736007); DIR:OUT; SFP:1101; SCL:1; SRVR:VI1PR0702MB3741; H:Rowlf.darbyshire-bryant.me.uk; FPR:; SPF:None; PTR:InfoNoRecords; MX:1; A:1; LANG:en; Received-SPF: None (protection.outlook.com: darbyshire-bryant.me.uk does not designate permitted sender hosts) Authentication-Results: spf=none (sender IP is ) smtp.mailfrom=kevin@darbyshire-bryant.me.uk; X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1; VI1PR0702MB3741; 23:u5S5I6sor4VlzVO9pY2k/pyGbAXPDkxE82VWwAh?= SG21wUHikP3T1A/cwE3UeJnyc2yzF+Qdoyif0voIkSZF8YHtIW5cZ7HUKinSAL5wblDQnpngeA3LQyASdxoh+oLPHGj0q3+nY0P6n9ORoZ+wXCXuUwFl1o7EqvnN6q67gd5wJEX1yikCbrIsFV9ESBz2Dcqlxc4KOg2cNJ4Is3rBzLReMHM1ZTuKoTaKAByiCVkMfDblOh8A/wntJJkXRUw1OKOfaqxA6MGSuKV6afHgO+5Cc3QazI+4jg26PGsUHsCQ5HJ+So09cyeEcehkmEOR0/WpdFOizxTo+Xbmm172Us5I/ML878F8N2fy9HQKpdk7XrdCNbdkOgx8nWcnvLbxJdYvzl7crb+2fvggwn5fvMjyoN5tRyuLuzO2VLm17jXcDDmPbqgfVVO1ZfK0AVMV/EOHpasMvgwr//1jwHBn27Bqxnig3NrHzuiWN7tDSBncpBMH6kf0Rgq17zDEk63d+m6tVKZUse4Jqwb7yf8Y9NwpoSWp9hJI+qHTRfvNCtfYYquzfxU15UMbYDRD/DjWPdq2Y04NI3mBrGgp1GY4/+LUmW6W7FHot+a/XBotmYw8JwFGHsyvrJUAJTpx31RP70Bt0lZAlbzWc68ieY2ZuSxNLUqIZ4GHNPwo2S7A43OQDDUJBI46oiqikzWuP3OHkp3Ox/v/v+rE+vOqa9zup7ULPEky/JcNwj5R4JCa2q5k9cEJFabz4UCs1eMXdIIJPNLkD44UYiRivOGpE2StLiNUTH8DBbZEpVG3T3QYaMP0SVM0S6uv19bqgF/6AvmSqbPYdEOEpEREfCda+8tj/xsJ4FlIHjAZvrcBnr0b4mR+sc6+Wwu2X49Nt2xfQrDNrxJaTx/sE0peBAJnwg9V+/DHGw1DD5PlEKUGOTOYaoQkHpIAtZs64fdurb6N4fkfhAahNDTOLsik+Bg1Pg7sClxPy6ugwN9s5LCSW/iPMY/HErW/fpJPct0f/57YFw1DJJyBBwJ27kAv1RjdnSHD01QdtRp1CaNLeWa/hPX657K9Rds9nbjzsGbGkepxq41xhtMTXt7tpDfR3H1OXymRG5LHvxQaddn1k+dGYF3cnotZQ/xgJVCJMjV84OLdB+Xq5DflCMhz1H4c/i8ftGV3JjbmBF+0ZLpzs94I1SvyjbOE/YhFHoPN99tRDlCAR57zqr6XRKNIEN2Sbca/dGNpd8s7ORmsEhplDt5+MaMZG2PItC2Vh/gyR1qaGUtRYx6J5XUdKynnD0fWvhSSesa6wqT8NNe/x91bAhhoE+pxyGmnPO80el2H1xubYHXKKkBzI X-Microsoft-Exchange-Diagnostics: 1; VI1PR0702MB3741; 6:Mexv2cvC7zCD8oIYpEKpcafhKQFSicYiLPuv5ZNNxDMivdzttDRVoEEbFAzGSSfEtqeoq0gFvdxoUPJXNPuBLgDob5NVaA/CHwUXvtf2CjkPFZYkrSqEJqF9bjIFeEheix3HTm9jDN2VuexIDNs3tSxV/t1N8bVlRKg7EHFas0X5j4tETKMth0JHy308w5maGzv2CKVeP9tsXwz60flnmPzepzESN9qUB5GqyE7kCIrY/rDXsunJ6I6PhnHNDZcyqUBxqYSWt6M2A/d/RkBx+sgaMaYYIj3QwfhyWm6aPVMtuTpxPXpgDg0Vqr/mtBHJj2vLLXSXmSfyx1vFi2P9hZagyp6SK+uWo7tulOhsiJk=; 5:+gWXrEV6umKZu4PfE00tW1dnz6gHlb5VC+YYPPjeLYaif0k+4ENq4maiaiXxukrEylpwXFNxCRuCaz9NQDbIzGss8vrI3eGREynDYQ854u9F9+5Z4nQOyWk5yFxkflcfolIxdKVNHVTVF6EBwOnSqn6eaTL/WE2V0kaGAzlDSjg=; 24:tceyPk1TO/IcY7mhaK74MYixhU1N+T8o3jXUyDNBLlFchWBiWPzw7zAwLQrJiSksD7sB0kdtrihX9hwll2YGUx+mbohBsIcHqwVrkn1hi7k=; 7:AihCZNCM5HBDD2cUDoJKz3L3lyz6zmFbQCmYNNyxY+bOqeFER6mPuDPvAwYnZyiQYThdc9z57Zm+BrakmnZNIgCEUna0M7McUgRMWo9hlCGlQmmP/R2hPzruZUGdBR2mOO/m73/mP4dBAFD3JH7UuOyBluJNgc1u5BA8NvG5Lu+Z2Vza+LRi8On7jFoQ0hOsbYXZpnKcPC5uPYQxZ3vgz23jgyArrjhaEPe6gMG90ewnxQhdrXfXQEnDSBP/WxqJ SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-OriginatorOrg: darbyshire-bryant.me.uk X-MS-Exchange-CrossTenant-OriginalArrivalTime: 19 Jan 2018 17:16:12.2228 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 37f35cad-085d-4437-2fe7-08d55f6056fe X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 9151708b-c553-406f-8e56-694f435154a4 X-MS-Exchange-Transport-CrossTenantHeadersStamped: VI1PR0702MB3741 X-Spam-Note: CRM114 invocation failed X-Spam-Score: -3.0 (---) X-Spam-Report: SpamAssassin version 3.4.1 on bombadil.infradead.org summary: Content analysis details: (-3.0 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at http://www.dnswl.org/, no trust [104.47.1.88 listed in list.dnswl.org] -1.0 RCVD_IN_MSPIKE_H5 RBL: Excellent reputation (+5) [104.47.1.88 listed in wl.mailspike.net] -0.0 SPF_PASS SPF: sender matches SPF record -0.0 SPF_HELO_PASS SPF: HELO matches SPF record -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature -0.0 RCVD_IN_MSPIKE_WL Mailspike good senders Subject: [LEDE-DEV] [PATCH v1] dnsmasq: backport dnssec security fix X-BeenThere: lede-dev@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Kevin Darbyshire-Bryant Sender: "Lede-dev" Errors-To: lede-dev-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org CVE-2017-15107 An interesting problem has turned up in DNSSEC validation. It turns out that NSEC records expanded from wildcards are allowed, so a domain can include an NSEC record for *.example.org and an actual query reply could expand that to anything in example.org and still have it signed by the signature for the wildcard. So, for example !.example.org NSEC zz.example.org is fine. The problem is that most implementers (your author included, but also the Google public DNS people, powerdns and Unbound) then took that record to prove the nothing exists between !.example.org and zz.example.org, whereas in fact it only provides that proof between *.example.org and zz.example.org. This gives an attacker a way to prove that anything between !.example.org and *.example.org doesn't exists, when it may well do so. Signed-off-by: Kevin Darbyshire-Bryant --- package/network/services/dnsmasq/Makefile | 2 +- .../dnsmasq/patches/270-dnssec-wildcards.patch | 202 +++++++++++++++++++++ 2 files changed, 203 insertions(+), 1 deletion(-) create mode 100644 package/network/services/dnsmasq/patches/270-dnssec-wildcards.patch diff --git a/package/network/services/dnsmasq/Makefile b/package/network/services/dnsmasq/Makefile index 1224ad86f8..3ef7a317d4 100644 --- a/package/network/services/dnsmasq/Makefile +++ b/package/network/services/dnsmasq/Makefile @@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=dnsmasq PKG_VERSION:=2.78 -PKG_RELEASE:=8 +PKG_RELEASE:=9 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz PKG_SOURCE_URL:=http://thekelleys.org.uk/dnsmasq/ diff --git a/package/network/services/dnsmasq/patches/270-dnssec-wildcards.patch b/package/network/services/dnsmasq/patches/270-dnssec-wildcards.patch new file mode 100644 index 0000000000..029e7ea7af --- /dev/null +++ b/package/network/services/dnsmasq/patches/270-dnssec-wildcards.patch @@ -0,0 +1,202 @@ +From 4fe6744a220eddd3f1749b40cac3dfc510787de6 Mon Sep 17 00:00:00 2001 +From: Simon Kelley +Date: Fri, 19 Jan 2018 12:26:08 +0000 +Subject: [PATCH] DNSSEC fix for wildcard NSEC records. CVE-2017-15107 + applies. + +It's OK for NSEC records to be expanded from wildcards, +but in that case, the proof of non-existence is only valid +starting at the wildcard name, *. NOT the name expanded +from the wildcard. Without this check it's possible for an +attacker to craft an NSEC which wrongly proves non-existence +in a domain which includes a wildcard for NSEC. +--- + src/dnssec.c | 117 +++++++++++++++++++++++++++++++++++++++++++++++++++------- + 2 files changed, 114 insertions(+), 15 deletions(-) + +--- a/src/dnssec.c ++++ b/src/dnssec.c +@@ -424,15 +424,17 @@ static void from_wire(char *name) + static int count_labels(char *name) + { + int i; +- ++ char *p; ++ + if (*name == 0) + return 0; + +- for (i = 0; *name; name++) +- if (*name == '.') ++ for (p = name, i = 0; *p; p++) ++ if (*p == '.') + i++; + +- return i+1; ++ /* Don't count empty first label. */ ++ return *name == '.' ? i : i+1; + } + + /* Implement RFC1982 wrapped compare for 32-bit numbers */ +@@ -1412,8 +1414,8 @@ static int hostname_cmp(const char *a, c + } + } + +-static int prove_non_existence_nsec(struct dns_header *header, size_t plen, unsigned char **nsecs, int nsec_count, +- char *workspace1, char *workspace2, char *name, int type, int *nons) ++static int prove_non_existence_nsec(struct dns_header *header, size_t plen, unsigned char **nsecs, unsigned char **labels, int nsec_count, ++ char *workspace1_in, char *workspace2, char *name, int type, int *nons) + { + int i, rc, rdlen; + unsigned char *p, *psave; +@@ -1426,6 +1428,9 @@ static int prove_non_existence_nsec(stru + /* Find NSEC record that proves name doesn't exist */ + for (i = 0; i < nsec_count; i++) + { ++ char *workspace1 = workspace1_in; ++ int sig_labels, name_labels; ++ + p = nsecs[i]; + if (!extract_name(header, plen, &p, workspace1, 1, 10)) + return 0; +@@ -1434,7 +1439,27 @@ static int prove_non_existence_nsec(stru + psave = p; + if (!extract_name(header, plen, &p, workspace2, 1, 10)) + return 0; +- ++ ++ /* If NSEC comes from wildcard expansion, use original wildcard ++ as name for computation. */ ++ sig_labels = *labels[i]; ++ name_labels = count_labels(workspace1); ++ ++ if (sig_labels < name_labels) ++ { ++ int k; ++ for (k = name_labels - sig_labels; k != 0; k--) ++ { ++ while (*workspace1 != '.' && *workspace1 != 0) ++ workspace1++; ++ if (k != 1 && *workspace1 == '.') ++ workspace1++; ++ } ++ ++ workspace1--; ++ *workspace1 = '*'; ++ } ++ + rc = hostname_cmp(workspace1, name); + + if (rc == 0) +@@ -1832,24 +1857,26 @@ static int prove_non_existence_nsec3(str + + static int prove_non_existence(struct dns_header *header, size_t plen, char *keyname, char *name, int qtype, int qclass, char *wildname, int *nons) + { +- static unsigned char **nsecset = NULL; +- static int nsecset_sz = 0; ++ static unsigned char **nsecset = NULL, **rrsig_labels = NULL; ++ static int nsecset_sz = 0, rrsig_labels_sz = 0; + + int type_found = 0; +- unsigned char *p = skip_questions(header, plen); ++ unsigned char *auth_start, *p = skip_questions(header, plen); + int type, class, rdlen, i, nsecs_found; + + /* Move to NS section */ + if (!p || !(p = skip_section(p, ntohs(header->ancount), header, plen))) + return 0; ++ ++ auth_start = p; + + for (nsecs_found = 0, i = ntohs(header->nscount); i != 0; i--) + { + unsigned char *pstart = p; + +- if (!(p = skip_name(p, header, plen, 10))) ++ if (!extract_name(header, plen, &p, daemon->workspacename, 1, 10)) + return 0; +- ++ + GETSHORT(type, p); + GETSHORT(class, p); + p += 4; /* TTL */ +@@ -1866,7 +1893,69 @@ static int prove_non_existence(struct dn + if (!expand_workspace(&nsecset, &nsecset_sz, nsecs_found)) + return 0; + +- nsecset[nsecs_found++] = pstart; ++ if (type == T_NSEC) ++ { ++ /* If we're looking for NSECs, find the corresponding SIGs, to ++ extract the labels value, which we need in case the NSECs ++ are the result of wildcard expansion. ++ Note that the NSEC may not have been validated yet ++ so if there are multiple SIGs, make sure the label value ++ is the same in all, to avoid be duped by a rogue one. ++ If there are no SIGs, that's an error */ ++ unsigned char *p1 = auth_start; ++ int res, j, rdlen1, type1, class1; ++ ++ if (!expand_workspace(&rrsig_labels, &rrsig_labels_sz, nsecs_found)) ++ return 0; ++ ++ rrsig_labels[nsecs_found] = NULL; ++ ++ for (j = ntohs(header->nscount); j != 0; j--) ++ { ++ if (!(res = extract_name(header, plen, &p1, daemon->workspacename, 0, 10))) ++ return 0; ++ ++ GETSHORT(type1, p1); ++ GETSHORT(class1, p1); ++ p1 += 4; /* TTL */ ++ GETSHORT(rdlen1, p1); ++ ++ if (!CHECK_LEN(header, p1, plen, rdlen1)) ++ return 0; ++ ++ if (res == 1 && class1 == qclass && type1 == T_RRSIG) ++ { ++ int type_covered; ++ unsigned char *psav = p1; ++ ++ if (rdlen < 18) ++ return 0; /* bad packet */ ++ ++ GETSHORT(type_covered, p1); ++ ++ if (type_covered == T_NSEC) ++ { ++ p1++; /* algo */ ++ ++ /* labels field must be the same in every SIG we find. */ ++ if (!rrsig_labels[nsecs_found]) ++ rrsig_labels[nsecs_found] = p1; ++ else if (*rrsig_labels[nsecs_found] != *p1) /* algo */ ++ return 0; ++ } ++ p1 = psav; ++ } ++ ++ if (!ADD_RDLEN(header, p1, plen, rdlen1)) ++ return 0; ++ } ++ ++ /* Must have found at least one sig. */ ++ if (!rrsig_labels[nsecs_found]) ++ return 0; ++ } ++ ++ nsecset[nsecs_found++] = pstart; + } + + if (!ADD_RDLEN(header, p, plen, rdlen)) +@@ -1874,7 +1963,7 @@ static int prove_non_existence(struct dn + } + + if (type_found == T_NSEC) +- return prove_non_existence_nsec(header, plen, nsecset, nsecs_found, daemon->workspacename, keyname, name, qtype, nons); ++ return prove_non_existence_nsec(header, plen, nsecset, rrsig_labels, nsecs_found, daemon->workspacename, keyname, name, qtype, nons); + else if (type_found == T_NSEC3) + return prove_non_existence_nsec3(header, plen, nsecset, nsecs_found, daemon->workspacename, keyname, name, qtype, wildname, nons); + else