Add an echoed 32-bit token field to command packets.

This commit is contained in:
Adam Ierymenko 2013-07-17 17:35:19 -04:00
parent 2e85cf18c1
commit 1fce55fab1
2 changed files with 25 additions and 8 deletions

View File

@ -156,30 +156,30 @@ void NodeConfig::_CBcontrolPacketHandler(UdpSocket *sock,void *arg,const InetAdd
try { try {
// Minimum length // Minimum length
if (len < 24) if (len < 28)
return; return;
if (len >= sizeof(buf)) // only up to len - 24 bytes are used on receive/decrypt if (len >= sizeof(buf)) // only up to len - 28 bytes are used on receive/decrypt
return; return;
// Compare first 16 bytes of HMAC, which is after IV in packet // Compare first 16 bytes of HMAC, which is after IV in packet
memcpy(hmacKey,nc->_keys + 32,32); memcpy(hmacKey,nc->_keys + 32,32);
*((uint64_t *)hmacKey) ^= *((const uint64_t *)data); // include IV in HMAC *((uint64_t *)hmacKey) ^= *((const uint64_t *)data); // include IV in HMAC
HMAC::sha256(hmacKey,32,((const unsigned char *)data) + 24,len - 24,hmac); HMAC::sha256(hmacKey,32,((const unsigned char *)data) + 28,len - 28,hmac);
if (memcmp(hmac,((const unsigned char *)data) + 8,16)) if (memcmp(hmac,((const unsigned char *)data) + 8,16))
return; return;
// Decrypt payload if we passed HMAC // Decrypt payload if we passed HMAC
Salsa20 s20(nc->_keys,256,data); // first 64 bits of data are IV Salsa20 s20(nc->_keys,256,data); // first 64 bits of data are IV
s20.decrypt(((const unsigned char *)data) + 24,buf,len - 24); s20.decrypt(((const unsigned char *)data) + 28,buf,len - 28);
// Null-terminate string for execute() // Null-terminate string for execute()
buf[len - 24] = (char)0; buf[len - 28] = (char)0;
// Execute command // Execute command
std::vector<std::string> r(nc->execute(buf)); std::vector<std::string> r(nc->execute(buf));
// Result packet contains a series of null-terminated results // Result packet contains a series of null-terminated results
unsigned int resultLen = 24; unsigned int resultLen = 28;
for(std::vector<std::string>::iterator i(r.begin());i!=r.end();++i) { for(std::vector<std::string>::iterator i(r.begin());i!=r.end();++i) {
if ((resultLen + i->length() + 1) >= sizeof(buf)) if ((resultLen + i->length() + 1) >= sizeof(buf))
return; // result too long return; // result too long
@ -193,9 +193,12 @@ void NodeConfig::_CBcontrolPacketHandler(UdpSocket *sock,void *arg,const InetAdd
// Generate result packet HMAC // Generate result packet HMAC
memcpy(hmacKey,nc->_keys + 32,32); memcpy(hmacKey,nc->_keys + 32,32);
*((uint64_t *)hmacKey) ^= *((const uint64_t *)buf); // include IV in HMAC *((uint64_t *)hmacKey) ^= *((const uint64_t *)buf); // include IV in HMAC
HMAC::sha256(hmacKey,32,((const unsigned char *)buf) + 24,resultLen - 24,hmac); HMAC::sha256(hmacKey,32,((const unsigned char *)buf) + 28,resultLen - 28,hmac);
memcpy(buf + 8,hmac,16); memcpy(buf + 8,hmac,16);
// Copy arbitrary tag from original packet
memcpy(buf + 24,((const unsigned char *)data) + 24,4);
// Send encrypted result back to requester // Send encrypted result back to requester
sock->send(remoteAddr,buf,resultLen,-1); sock->send(remoteAddr,buf,resultLen,-1);
} catch ( ... ) { } catch ( ... ) {

View File

@ -33,6 +33,7 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include <stdexcept> #include <stdexcept>
#include <stdint.h> #include <stdint.h>
#include "SharedPtr.hpp" #include "SharedPtr.hpp"
#include "Network.hpp" #include "Network.hpp"
@ -45,7 +46,20 @@ namespace ZeroTier {
class RuntimeEnvironment; class RuntimeEnvironment;
/** /**
* Node configuration holder and fetcher * Node configuration endpoint
*
* Packet format for local UDP configuration packets:
* [8] random initialization vector
* [16] first 16 bytes of HMAC-SHA-256 of payload
* [4] arbitrary tag, echoed in response
* [...] payload
*
* For requests, the payload consists of a single ASCII command. For
* responses, the payload consists of one or more response lines delimited
* by NULL (0) characters. The tag field is replicated in the result
* packet.
*
* TODO: further document use of keys, encryption...
*/ */
class NodeConfig class NodeConfig
{ {