]> git.ipfire.org Git - thirdparty/pdns.git/blame - pdns/test-dnscrypt_cc.cc
rec: ensure correct service user on debian
[thirdparty/pdns.git] / pdns / test-dnscrypt_cc.cc
CommitLineData
11e1e08b 1/*
6edbf68a
PL
2 * This file is part of PowerDNS or dnsdist.
3 * Copyright -- PowerDNS.COM B.V. and its contributors
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * In addition, for the avoidance of any doubt, permission is granted to
10 * link this program with OpenSSL and to (re)distribute the binaries
11 * produced as the result of such linking.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 */
11e1e08b
RG
22#define BOOST_TEST_DYN_LINK
23#define BOOST_TEST_NO_MAIN
24
25#include <boost/test/unit_test.hpp>
26
27#include "dnscrypt.hh"
28#include "dnsname.hh"
29#include "dnsparser.hh"
30#include "dnswriter.hh"
31#include <unistd.h>
32
33bool g_verbose{true};
bbfaaa6f 34bool g_syslog{true};
11e1e08b 35
c7f29d3e 36BOOST_AUTO_TEST_SUITE(test_dnscrypt_cc)
11e1e08b
RG
37
38#ifdef HAVE_DNSCRYPT
39
40// plaintext query for cert
41BOOST_AUTO_TEST_CASE(DNSCryptPlaintextQuery) {
43234e76
RG
42 DNSCryptPrivateKey resolverPrivateKey;
43 DNSCryptCert resolverCert;
11e1e08b
RG
44 unsigned char providerPublicKey[DNSCRYPT_PROVIDER_PUBLIC_KEY_SIZE];
45 unsigned char providerPrivateKey[DNSCRYPT_PROVIDER_PRIVATE_KEY_SIZE];
43234e76
RG
46 time_t now = time(nullptr);
47 DNSCryptContext::generateProviderKeys(providerPublicKey, providerPrivateKey);
48 DNSCryptContext::generateCertificate(1, now, now + (24 * 60 * 3600), DNSCryptExchangeVersion::VERSION1, providerPrivateKey, resolverPrivateKey, resolverCert);
49 auto ctx = std::make_shared<DNSCryptContext>("2.name", resolverCert, resolverPrivateKey);
11e1e08b
RG
50
51 DNSName name("2.name.");
52 vector<uint8_t> plainQuery;
53 DNSPacketWriter pw(plainQuery, name, QType::TXT, QClass::IN, 0);
54 pw.getHeader()->rd = 0;
55 uint16_t len = plainQuery.size();
56
43234e76 57 std::shared_ptr<DNSCryptQuery> query = std::make_shared<DNSCryptQuery>(ctx);
11e1e08b
RG
58 uint16_t decryptedLen = 0;
59
43234e76 60 query->parsePacket((char*) plainQuery.data(), len, false, &decryptedLen, now);
11e1e08b 61
43234e76
RG
62 BOOST_CHECK_EQUAL(query->isValid(), true);
63 BOOST_CHECK_EQUAL(query->isEncrypted(), false);
11e1e08b
RG
64
65 std::vector<uint8_t> response;
66
43234e76 67 query->getCertificateResponse(now, response);
11e1e08b 68
27c0050c 69 MOADNSParser mdp(false, (char*) response.data(), response.size());
11e1e08b
RG
70
71 BOOST_CHECK_EQUAL(mdp.d_header.qdcount, 1);
72 BOOST_CHECK_EQUAL(mdp.d_header.ancount, 1);
73 BOOST_CHECK_EQUAL(mdp.d_header.nscount, 0);
74 BOOST_CHECK_EQUAL(mdp.d_header.arcount, 0);
75
76 BOOST_CHECK_EQUAL(mdp.d_qname.toString(), "2.name.");
bd64cc44
RG
77 BOOST_CHECK(mdp.d_qclass == QClass::IN);
78 BOOST_CHECK(mdp.d_qtype == QType::TXT);
11e1e08b
RG
79}
80
81// invalid plaintext query (A)
82BOOST_AUTO_TEST_CASE(DNSCryptPlaintextQueryInvalidA) {
43234e76
RG
83 DNSCryptPrivateKey resolverPrivateKey;
84 DNSCryptCert resolverCert;
11e1e08b
RG
85 unsigned char providerPublicKey[DNSCRYPT_PROVIDER_PUBLIC_KEY_SIZE];
86 unsigned char providerPrivateKey[DNSCRYPT_PROVIDER_PRIVATE_KEY_SIZE];
43234e76
RG
87 time_t now = time(nullptr);
88 DNSCryptContext::generateProviderKeys(providerPublicKey, providerPrivateKey);
89 DNSCryptContext::generateCertificate(1, now, now + (24 * 60 * 3600), DNSCryptExchangeVersion::VERSION1, providerPrivateKey, resolverPrivateKey, resolverCert);
90 auto ctx = std::make_shared<DNSCryptContext>("2.name", resolverCert, resolverPrivateKey);
11e1e08b
RG
91
92 DNSName name("2.name.");
93
94 vector<uint8_t> plainQuery;
95 DNSPacketWriter pw(plainQuery, name, QType::A, QClass::IN, 0);
96 pw.getHeader()->rd = 0;
97 uint16_t len = plainQuery.size();
98
43234e76 99 std::shared_ptr<DNSCryptQuery> query = std::make_shared<DNSCryptQuery>(ctx);
11e1e08b
RG
100 uint16_t decryptedLen = 0;
101
43234e76 102 query->parsePacket((char*) plainQuery.data(), len, false, &decryptedLen, now);
11e1e08b 103
43234e76 104 BOOST_CHECK_EQUAL(query->isValid(), false);
11e1e08b
RG
105}
106
107// invalid plaintext query (wrong provider name)
108BOOST_AUTO_TEST_CASE(DNSCryptPlaintextQueryInvalidProviderName) {
43234e76
RG
109 DNSCryptPrivateKey resolverPrivateKey;
110 DNSCryptCert resolverCert;
11e1e08b
RG
111 unsigned char providerPublicKey[DNSCRYPT_PROVIDER_PUBLIC_KEY_SIZE];
112 unsigned char providerPrivateKey[DNSCRYPT_PROVIDER_PRIVATE_KEY_SIZE];
43234e76
RG
113 time_t now = time(nullptr);
114 DNSCryptContext::generateProviderKeys(providerPublicKey, providerPrivateKey);
115 DNSCryptContext::generateCertificate(1, now, now + (24 * 60 * 3600), DNSCryptExchangeVersion::VERSION1, providerPrivateKey, resolverPrivateKey, resolverCert);
116 auto ctx = std::make_shared<DNSCryptContext>("2.name", resolverCert, resolverPrivateKey);
11e1e08b
RG
117
118 DNSName name("2.WRONG.name.");
119
120 vector<uint8_t> plainQuery;
121 DNSPacketWriter pw(plainQuery, name, QType::TXT, QClass::IN, 0);
122 pw.getHeader()->rd = 0;
123 uint16_t len = plainQuery.size();
124
43234e76 125 std::shared_ptr<DNSCryptQuery> query = std::make_shared<DNSCryptQuery>(ctx);
11e1e08b
RG
126 uint16_t decryptedLen = 0;
127
43234e76 128 query->parsePacket((char*) plainQuery.data(), len, false, &decryptedLen, now);
11e1e08b 129
43234e76 130 BOOST_CHECK_EQUAL(query->isValid(), false);
11e1e08b
RG
131}
132
133// valid encrypted query
134BOOST_AUTO_TEST_CASE(DNSCryptEncryptedQueryValid) {
43234e76
RG
135 DNSCryptPrivateKey resolverPrivateKey;
136 DNSCryptCert resolverCert;
11e1e08b
RG
137 unsigned char providerPublicKey[DNSCRYPT_PROVIDER_PUBLIC_KEY_SIZE];
138 unsigned char providerPrivateKey[DNSCRYPT_PROVIDER_PRIVATE_KEY_SIZE];
43234e76
RG
139 time_t now = time(nullptr);
140 DNSCryptContext::generateProviderKeys(providerPublicKey, providerPrivateKey);
141 DNSCryptContext::generateCertificate(1, now, now + (24 * 60 * 3600), DNSCryptExchangeVersion::VERSION1, providerPrivateKey, resolverPrivateKey, resolverCert);
142 auto ctx = std::make_shared<DNSCryptContext>("2.name", resolverCert, resolverPrivateKey);
11e1e08b 143
43234e76 144 DNSCryptPrivateKey clientPrivateKey;
11e1e08b
RG
145 unsigned char clientPublicKey[DNSCRYPT_PUBLIC_KEY_SIZE];
146
43234e76 147 DNSCryptContext::generateResolverKeyPair(clientPrivateKey, clientPublicKey);
11e1e08b
RG
148
149 unsigned char clientNonce[DNSCRYPT_NONCE_SIZE / 2] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x08, 0x09, 0x0A, 0x0B };
150
151 DNSName name("www.powerdns.com.");
152 vector<uint8_t> plainQuery;
153 DNSPacketWriter pw(plainQuery, name, QType::AAAA, QClass::IN, 0);
154 pw.getHeader()->rd = 1;
43234e76
RG
155 size_t requiredSize = plainQuery.size() + sizeof(DNSCryptQueryHeader) + DNSCRYPT_MAC_SIZE;
156 if (requiredSize < DNSCryptQuery::s_minUDPLength) {
157 requiredSize = DNSCryptQuery::s_minUDPLength;
11e1e08b
RG
158 }
159
160 plainQuery.reserve(requiredSize);
161 uint16_t len = plainQuery.size();
162 uint16_t encryptedResponseLen = 0;
163
43234e76 164 int res = ctx->encryptQuery((char*) plainQuery.data(), len, plainQuery.capacity(), clientPublicKey, clientPrivateKey, clientNonce, false, &encryptedResponseLen, std::make_shared<DNSCryptCert>(resolverCert));
11e1e08b
RG
165
166 BOOST_CHECK_EQUAL(res, 0);
167 BOOST_CHECK(encryptedResponseLen > len);
168
43234e76 169 std::shared_ptr<DNSCryptQuery> query = std::make_shared<DNSCryptQuery>(ctx);
11e1e08b
RG
170 uint16_t decryptedLen = 0;
171
43234e76 172 query->parsePacket((char*) plainQuery.data(), encryptedResponseLen, false, &decryptedLen, now);
11e1e08b 173
43234e76
RG
174 BOOST_CHECK_EQUAL(query->isValid(), true);
175 BOOST_CHECK_EQUAL(query->isEncrypted(), true);
11e1e08b 176
27c0050c 177 MOADNSParser mdp(true, (char*) plainQuery.data(), decryptedLen);
11e1e08b
RG
178
179 BOOST_CHECK_EQUAL(mdp.d_header.qdcount, 1);
180 BOOST_CHECK_EQUAL(mdp.d_header.ancount, 0);
181 BOOST_CHECK_EQUAL(mdp.d_header.nscount, 0);
182 BOOST_CHECK_EQUAL(mdp.d_header.arcount, 0);
183
184 BOOST_CHECK_EQUAL(mdp.d_qname, name);
bd64cc44
RG
185 BOOST_CHECK(mdp.d_qclass == QClass::IN);
186 BOOST_CHECK(mdp.d_qtype == QType::AAAA);
11e1e08b
RG
187}
188
189// valid encrypted query with not enough room
190BOOST_AUTO_TEST_CASE(DNSCryptEncryptedQueryValidButShort) {
43234e76
RG
191 DNSCryptPrivateKey resolverPrivateKey;
192 DNSCryptCert resolverCert;
11e1e08b
RG
193 unsigned char providerPublicKey[DNSCRYPT_PROVIDER_PUBLIC_KEY_SIZE];
194 unsigned char providerPrivateKey[DNSCRYPT_PROVIDER_PRIVATE_KEY_SIZE];
43234e76
RG
195 time_t now = time(nullptr);
196 DNSCryptContext::generateProviderKeys(providerPublicKey, providerPrivateKey);
197 DNSCryptContext::generateCertificate(1, now, now + (24 * 60 * 3600), DNSCryptExchangeVersion::VERSION1, providerPrivateKey, resolverPrivateKey, resolverCert);
198 auto ctx = std::make_shared<DNSCryptContext>("2.name", resolverCert, resolverPrivateKey);
11e1e08b 199
43234e76 200 DNSCryptPrivateKey clientPrivateKey;
11e1e08b
RG
201 unsigned char clientPublicKey[DNSCRYPT_PUBLIC_KEY_SIZE];
202
43234e76 203 DNSCryptContext::generateResolverKeyPair(clientPrivateKey, clientPublicKey);
11e1e08b
RG
204
205 unsigned char clientNonce[DNSCRYPT_NONCE_SIZE / 2] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x08, 0x09, 0x0A, 0x0B };
206
207 DNSName name("www.powerdns.com.");
208 vector<uint8_t> plainQuery;
209 DNSPacketWriter pw(plainQuery, name, QType::AAAA, QClass::IN, 0);
210 pw.getHeader()->rd = 1;
211
212 uint16_t len = plainQuery.size();
213 uint16_t encryptedResponseLen = 0;
214
43234e76 215 int res = ctx->encryptQuery((char*) plainQuery.data(), len, plainQuery.capacity(), clientPublicKey, clientPrivateKey, clientNonce, false, &encryptedResponseLen, std::make_shared<DNSCryptCert>(resolverCert));
11e1e08b
RG
216
217 BOOST_CHECK_EQUAL(res, ENOBUFS);
218}
219
220// valid encrypted query with old key
221BOOST_AUTO_TEST_CASE(DNSCryptEncryptedQueryValidWithOldKey) {
43234e76
RG
222 DNSCryptPrivateKey resolverPrivateKey;
223 DNSCryptCert resolverCert;
11e1e08b
RG
224 unsigned char providerPublicKey[DNSCRYPT_PROVIDER_PUBLIC_KEY_SIZE];
225 unsigned char providerPrivateKey[DNSCRYPT_PROVIDER_PRIVATE_KEY_SIZE];
43234e76
RG
226 time_t now = time(nullptr);
227 DNSCryptContext::generateProviderKeys(providerPublicKey, providerPrivateKey);
228 DNSCryptContext::generateCertificate(1, now, now + (24 * 60 * 3600), DNSCryptExchangeVersion::VERSION1, providerPrivateKey, resolverPrivateKey, resolverCert);
229 auto ctx = std::make_shared<DNSCryptContext>("2.name", resolverCert, resolverPrivateKey);
11e1e08b 230
43234e76 231 DNSCryptPrivateKey clientPrivateKey;
11e1e08b
RG
232 unsigned char clientPublicKey[DNSCRYPT_PUBLIC_KEY_SIZE];
233
43234e76 234 DNSCryptContext::generateResolverKeyPair(clientPrivateKey, clientPublicKey);
11e1e08b
RG
235
236 unsigned char clientNonce[DNSCRYPT_NONCE_SIZE / 2] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x08, 0x09, 0x0A, 0x0B };
237
238 DNSName name("www.powerdns.com.");
239 vector<uint8_t> plainQuery;
240 DNSPacketWriter pw(plainQuery, name, QType::AAAA, QClass::IN, 0);
241 pw.getHeader()->rd = 1;
242
43234e76
RG
243 size_t requiredSize = plainQuery.size() + sizeof(DNSCryptQueryHeader) + DNSCRYPT_MAC_SIZE;
244 if (requiredSize < DNSCryptQuery::s_minUDPLength) {
245 requiredSize = DNSCryptQuery::s_minUDPLength;
11e1e08b
RG
246 }
247
248 plainQuery.reserve(requiredSize);
249
250 uint16_t len = plainQuery.size();
251 uint16_t encryptedResponseLen = 0;
252
43234e76 253 int res = ctx->encryptQuery((char*) plainQuery.data(), len, plainQuery.capacity(), clientPublicKey, clientPrivateKey, clientNonce, false, &encryptedResponseLen, std::make_shared<DNSCryptCert>(resolverCert));
11e1e08b
RG
254
255 BOOST_CHECK_EQUAL(res, 0);
256 BOOST_CHECK(encryptedResponseLen > len);
257
43234e76
RG
258 DNSCryptCert newResolverCert;
259 DNSCryptContext::generateCertificate(2, now, now + (24 * 60 * 3600), DNSCryptExchangeVersion::VERSION1, providerPrivateKey, resolverPrivateKey, newResolverCert);
260 ctx->addNewCertificate(newResolverCert, resolverPrivateKey);
261 ctx->markInactive(resolverCert.getSerial());
11e1e08b 262
43234e76 263 std::shared_ptr<DNSCryptQuery> query = std::make_shared<DNSCryptQuery>(ctx);
11e1e08b
RG
264 uint16_t decryptedLen = 0;
265
43234e76 266 query->parsePacket((char*) plainQuery.data(), encryptedResponseLen, false, &decryptedLen, now);
11e1e08b 267
43234e76
RG
268 BOOST_CHECK_EQUAL(query->isValid(), true);
269 BOOST_CHECK_EQUAL(query->isEncrypted(), true);
11e1e08b 270
27c0050c 271 MOADNSParser mdp(true, (char*) plainQuery.data(), decryptedLen);
11e1e08b
RG
272
273 BOOST_CHECK_EQUAL(mdp.d_header.qdcount, 1);
274 BOOST_CHECK_EQUAL(mdp.d_header.ancount, 0);
275 BOOST_CHECK_EQUAL(mdp.d_header.nscount, 0);
276 BOOST_CHECK_EQUAL(mdp.d_header.arcount, 0);
277
278 BOOST_CHECK_EQUAL(mdp.d_qname, name);
bd64cc44
RG
279 BOOST_CHECK(mdp.d_qclass == QClass::IN);
280 BOOST_CHECK(mdp.d_qtype == QType::AAAA);
11e1e08b
RG
281}
282
283// valid encrypted query with wrong key
284BOOST_AUTO_TEST_CASE(DNSCryptEncryptedQueryInvalidWithWrongKey) {
43234e76
RG
285 DNSCryptPrivateKey resolverPrivateKey;
286 DNSCryptCert resolverCert;
11e1e08b
RG
287 unsigned char providerPublicKey[DNSCRYPT_PROVIDER_PUBLIC_KEY_SIZE];
288 unsigned char providerPrivateKey[DNSCRYPT_PROVIDER_PRIVATE_KEY_SIZE];
43234e76
RG
289 time_t now = time(nullptr);
290 DNSCryptContext::generateProviderKeys(providerPublicKey, providerPrivateKey);
291 DNSCryptContext::generateCertificate(1, now, now + (24 * 60 * 3600), DNSCryptExchangeVersion::VERSION1, providerPrivateKey, resolverPrivateKey, resolverCert);
292 auto ctx = std::make_shared<DNSCryptContext>("2.name", resolverCert, resolverPrivateKey);
11e1e08b 293
43234e76 294 DNSCryptPrivateKey clientPrivateKey;
11e1e08b
RG
295 unsigned char clientPublicKey[DNSCRYPT_PUBLIC_KEY_SIZE];
296
43234e76 297 DNSCryptContext::generateResolverKeyPair(clientPrivateKey, clientPublicKey);
11e1e08b
RG
298
299 unsigned char clientNonce[DNSCRYPT_NONCE_SIZE / 2] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x08, 0x09, 0x0A, 0x0B };
300
301 DNSName name("www.powerdns.com.");
302 vector<uint8_t> plainQuery;
303 DNSPacketWriter pw(plainQuery, name, QType::AAAA, QClass::IN, 0);
304 pw.getHeader()->rd = 1;
305
43234e76
RG
306 size_t requiredSize = plainQuery.size() + sizeof(DNSCryptQueryHeader) + DNSCRYPT_MAC_SIZE;
307 if (requiredSize < DNSCryptQuery::s_minUDPLength) {
308 requiredSize = DNSCryptQuery::s_minUDPLength;
11e1e08b
RG
309 }
310
311 plainQuery.reserve(requiredSize);
312
313 uint16_t len = plainQuery.size();
314 uint16_t encryptedResponseLen = 0;
315
43234e76 316 int res = ctx->encryptQuery((char*) plainQuery.data(), len, plainQuery.capacity(), clientPublicKey, clientPrivateKey, clientNonce, false, &encryptedResponseLen, std::make_shared<DNSCryptCert>(resolverCert));
11e1e08b
RG
317
318 BOOST_CHECK_EQUAL(res, 0);
319 BOOST_CHECK(encryptedResponseLen > len);
320
43234e76
RG
321 DNSCryptCert newResolverCert;
322 DNSCryptContext::generateCertificate(2, now, now + (24 * 60 * 3600), DNSCryptExchangeVersion::VERSION1, providerPrivateKey, resolverPrivateKey, newResolverCert);
323 ctx->addNewCertificate(newResolverCert, resolverPrivateKey);
324 ctx->markInactive(resolverCert.getSerial());
325 ctx->removeInactiveCertificate(resolverCert.getSerial());
11e1e08b 326
43234e76 327 /* we have removed the old certificate, we can't decrypt this query */
11e1e08b 328
43234e76 329 std::shared_ptr<DNSCryptQuery> query = std::make_shared<DNSCryptQuery>(ctx);
11e1e08b
RG
330 uint16_t decryptedLen = 0;
331
43234e76 332 query->parsePacket((char*) plainQuery.data(), encryptedResponseLen, false, &decryptedLen, now);
11e1e08b 333
43234e76 334 BOOST_CHECK_EQUAL(query->isValid(), false);
11e1e08b
RG
335}
336
337#endif
338
339BOOST_AUTO_TEST_SUITE_END();