]> granicus.if.org Git - pdns/commitdiff
dnsdist: Merge the client and server nonces to prevent replay attacks
authorRemi Gacogne <remi.gacogne@powerdns.com>
Fri, 23 Dec 2016 10:52:43 +0000 (11:52 +0100)
committerRemi Gacogne <remi.gacogne@powerdns.com>
Thu, 5 Jan 2017 11:33:09 +0000 (12:33 +0100)
Instead of using the local nonce to send messages (and so the remote
one for received ones), split and merge the local and remote nonces
to create two new nonces, one for client to server and one for server
to client.

pdns/dnsdist-console.cc
pdns/sodcrypto.hh
regression-tests.dnsdist/dnsdisttests.py

index 45052f08db4997a28e8a44a9006a86186a6473b1..ad9c4bb3c642d1424f65d10ae319393f6993959d 100644 (file)
@@ -56,14 +56,16 @@ void doClient(ComboAddress server, const std::string& command)
   }
   SConnect(fd, server);
   setTCPNoDelay(fd);
-  SodiumNonce theirs, ours;
+  SodiumNonce theirs, ours, readingNonce, writingNonce;
   ours.init();
 
   writen2(fd, (const char*)ours.value, sizeof(ours.value));
   readn2(fd, (char*)theirs.value, sizeof(theirs.value));
+  readingNonce.merge(ours, theirs);
+  writingNonce.merge(theirs, ours);
 
   if(!command.empty()) {
-    string msg=sodEncryptSym(command, g_key, ours);
+    string msg=sodEncryptSym(command, g_key, writingNonce);
     putMsgLen32(fd, (uint32_t) msg.length());
     if(!msg.empty())
       writen2(fd, msg);
@@ -73,7 +75,7 @@ void doClient(ComboAddress server, const std::string& command)
         boost::scoped_array<char> resp(new char[len]);
         readn2(fd, resp.get(), len);
         msg.assign(resp.get(), len);
-        msg=sodDecryptSym(msg, g_key, theirs);
+        msg=sodDecryptSym(msg, g_key, readingNonce);
         cout<<msg;
         cout.flush();
       }
@@ -116,7 +118,7 @@ void doClient(ComboAddress server, const std::string& command)
     if(line.empty())
       continue;
 
-    string msg=sodEncryptSym(line, g_key, ours);
+    string msg=sodEncryptSym(line, g_key, writingNonce);
     putMsgLen32(fd, (uint32_t) msg.length());
     writen2(fd, msg);
     uint32_t len;
@@ -129,7 +131,7 @@ void doClient(ComboAddress server, const std::string& command)
       boost::scoped_array<char> resp(new char[len]);
       readn2(fd, resp.get(), len);
       msg.assign(resp.get(), len);
-      msg=sodDecryptSym(msg, g_key, theirs);
+      msg=sodDecryptSym(msg, g_key, readingNonce);
       cout<<msg;
       cout.flush();
     }
@@ -417,11 +419,12 @@ void controlClientThread(int fd, ComboAddress client)
 try
 {
   setTCPNoDelay(fd);
-  SodiumNonce theirs;
-  readn2(fd, (char*)theirs.value, sizeof(theirs.value));
-  SodiumNonce ours;
+  SodiumNonce theirs, ours, readingNonce, writingNonce;
   ours.init();
+  readn2(fd, (char*)theirs.value, sizeof(theirs.value));
   writen2(fd, (char*)ours.value, sizeof(ours.value));
+  readingNonce.merge(ours, theirs);
+  writingNonce.merge(theirs, ours);
 
   for(;;) {
     uint32_t len;
@@ -439,7 +442,7 @@ try
     readn2(fd, msg.get(), len);
     
     string line(msg.get(), len);
-    line = sodDecryptSym(line, g_key, theirs);
+    line = sodDecryptSym(line, g_key, readingNonce);
     //    cerr<<"Have decrypted line: "<<line<<endl;
     string response;
     try {
@@ -512,7 +515,7 @@ try
     catch(const LuaContext::SyntaxErrorException& e) {
       response = "Error: " + string(e.what()) + ": ";
     }
-    response = sodEncryptSym(response, g_key, ours);
+    response = sodEncryptSym(response, g_key, writingNonce);
     putMsgLen32(fd, response.length());
     writen2(fd, response.c_str(), response.length());
   }
index fce2164cea871dd898462177a175d0343717e36e..86d52b2f0c9cfc5d2408f4e02f5402401b750493 100644 (file)
 #ifndef HAVE_LIBSODIUM
 struct SodiumNonce
 {
-       void init(){};
-       void increment(){};
-       unsigned char value[1];
+  void init(){};
+  void merge(const SodiumNonce& lower, const SodiumNonce& higher) {};
+  void increment(){};
+  unsigned char value[1];
 };
 #else
 #include <sodium.h>
@@ -42,7 +43,14 @@ struct SodiumNonce
   {
     randombytes_buf(value, sizeof value);
   }
-  
+
+  void merge(const SodiumNonce& lower, const SodiumNonce& higher)
+  {
+    static const size_t halfSize = (sizeof value) / 2;
+    memcpy(value, lower.value, halfSize);
+    memcpy(value + halfSize, higher.value + halfSize, halfSize);
+  }
+
   void increment()
   {
     uint32_t* p = (uint32_t*)value;
index d04c247803db5428ec6a88a8a93112beb65ea2f3..9a649c583dea370d56c7ae46dda9b1a2988cd02b 100644 (file)
@@ -371,11 +371,15 @@ class DNSDistTest(unittest.TestCase):
         sock.send(ourNonce)
         theirNonce = sock.recv(len(ourNonce))
 
-        msg = cls._encryptConsole(command, ourNonce)
+        halfNonceSize = len(ourNonce) / 2
+        readingNonce = ourNonce[0:halfNonceSize] + theirNonce[halfNonceSize:]
+        writingNonce = theirNonce[0:halfNonceSize] + ourNonce[halfNonceSize:]
+
+        msg = cls._encryptConsole(command, writingNonce)
         sock.send(struct.pack("!I", len(msg)))
         sock.send(msg)
         data = sock.recv(4)
         (responseLen,) = struct.unpack("!I", data)
         data = sock.recv(responseLen)
-        response = cls._decryptConsole(data, theirNonce)
+        response = cls._decryptConsole(data, readingNonce)
         return response