summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdam Ierymenko <adam.ierymenko@gmail.com>2013-07-27 16:20:08 -0400
committerAdam Ierymenko <adam.ierymenko@gmail.com>2013-07-27 16:20:08 -0400
commit7a17f6ca80e3df9e1509dc99d0acdd00f12686e0 (patch)
tree1ab3bb43f16047f79fcb66fb46143703912d63a1
parentd35d322890a4a4c3ca85768ba2e16c47662c27c8 (diff)
downloadinfinitytier-7a17f6ca80e3df9e1509dc99d0acdd00f12686e0.tar.gz
infinitytier-7a17f6ca80e3df9e1509dc99d0acdd00f12686e0.zip
Add skeleton of certificate-based private network authentication. Also remove some old code.
-rw-r--r--node/BlobArray.hpp94
-rw-r--r--node/Network.hpp15
-rw-r--r--node/Node.cpp1
-rw-r--r--node/Pack.cpp159
-rw-r--r--node/Pack.hpp141
-rw-r--r--node/Packet.cpp3
-rw-r--r--node/Packet.hpp25
-rw-r--r--objects.mk1
8 files changed, 40 insertions, 399 deletions
diff --git a/node/BlobArray.hpp b/node/BlobArray.hpp
deleted file mode 100644
index d78bcffa..00000000
--- a/node/BlobArray.hpp
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * ZeroTier One - Global Peer to Peer Ethernet
- * Copyright (C) 2012-2013 ZeroTier Networks LLC
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- * --
- *
- * ZeroTier may be used and distributed under the terms of the GPLv3, which
- * are available at: http://www.gnu.org/licenses/gpl-3.0.html
- *
- * If you would like to embed ZeroTier into a commercial application or
- * redistribute it in a modified binary form, please contact ZeroTier Networks
- * LLC. Start here: http://www.zerotier.com/
- */
-
-#ifndef _ZT_BLOBARRAY_HPP
-#define _ZT_BLOBARRAY_HPP
-
-#include <vector>
-#include <string>
-#include <algorithm>
-
-namespace ZeroTier {
-
-/**
- * A vector of binary strings serializable in a packed format
- *
- * The format uses variable-length integers to indicate the length of each
- * field. Each byte of the length has another byte with seven more significant
- * bits if its 8th bit is set. Fields can be up to 2^28 in length.
- */
-class BlobArray : public std::vector<std::string>
-{
-public:
- inline std::string serialize() const
- {
- std::string r;
- for(BlobArray::const_iterator i=begin();i!=end();++i) {
- unsigned int flen = (unsigned int)i->length();
- do {
- unsigned char flenb = (unsigned char)(flen & 0x7f);
- flen >>= 7;
- flenb |= (flen) ? 0x80 : 0;
- r.push_back((char)flenb);
- } while (flen);
- r.append(*i);
- }
- return r;
- }
-
- /**
- * Deserialize, replacing the current contents of this array
- *
- * @param data Serialized binary data
- * @param len Length of serialized data
- */
- inline void deserialize(const void *data,unsigned int len)
- {
- clear();
- for(unsigned int i=0;i<len;) {
- unsigned int flen = 0;
- unsigned int chunk = 0;
- while (i < len) {
- flen |= ((unsigned int)(((const unsigned char *)data)[i] & 0x7f)) << (7 * chunk++);
- if (!(((const unsigned char *)data)[i++] & 0x80))
- break;
- }
- flen = std::min(flen,len - i);
- push_back(std::string(((const char *)data) + i,flen));
- i += flen;
- }
- }
- inline void deserialize(const std::string &data)
- {
- deserialize(data.data(),(unsigned int)data.length());
- }
-};
-
-} // namespace ZeroTier
-
-#endif
-
diff --git a/node/Network.hpp b/node/Network.hpp
index a95ae869..6263aa9b 100644
--- a/node/Network.hpp
+++ b/node/Network.hpp
@@ -49,7 +49,20 @@ namespace ZeroTier {
class NodeConfig;
/**
- * Local membership to a network
+ * A virtual LAN
+ *
+ * Networks can be open or closed.
+ *
+ * Open networks do not track membership. Anyone is allowed to communicate
+ * over them.
+ *
+ * Closed networks track membership by way of timestamped signatures. When
+ * the network requests its configuration, one of the fields returned is
+ * a signature for the identity of the peer on the network. This signature
+ * includes a timestamp. When a peer communicates with other peers on a
+ * closed network, it periodically (and pre-emptively) propagates this
+ * signature to the peers with which it is communicating. Peers reject
+ * packets with an error if no recent signature is on file.
*/
class Network : NonCopyable
{
diff --git a/node/Node.cpp b/node/Node.cpp
index 08b08fc1..827af23b 100644
--- a/node/Node.cpp
+++ b/node/Node.cpp
@@ -56,7 +56,6 @@
#include "Logger.hpp"
#include "Constants.hpp"
#include "InetAddress.hpp"
-#include "Pack.hpp"
#include "Salsa20.hpp"
#include "HMAC.hpp"
#include "RuntimeEnvironment.hpp"
diff --git a/node/Pack.cpp b/node/Pack.cpp
deleted file mode 100644
index 98686559..00000000
--- a/node/Pack.cpp
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * ZeroTier One - Global Peer to Peer Ethernet
- * Copyright (C) 2012-2013 ZeroTier Networks LLC
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- * --
- *
- * ZeroTier may be used and distributed under the terms of the GPLv3, which
- * are available at: http://www.gnu.org/licenses/gpl-3.0.html
- *
- * If you would like to embed ZeroTier into a commercial application or
- * redistribute it in a modified binary form, please contact ZeroTier Networks
- * LLC. Start here: http://www.zerotier.com/
- */
-
-#include <iostream>
-#include <string.h>
-#include <stdlib.h>
-#include "Pack.hpp"
-#include "BlobArray.hpp"
-#include "Utils.hpp"
-
-#include <openssl/sha.h>
-
-namespace ZeroTier {
-
-std::vector<const Pack::Entry *> Pack::getAll() const
-{
- std::vector<const Entry *> v;
- for(std::map<std::string,Entry>::const_iterator e=_entries.begin();e!=_entries.end();++e)
- v.push_back(&(e->second));
- return v;
-}
-
-const Pack::Entry *Pack::get(const std::string &name) const
-{
- std::map<std::string,Entry>::const_iterator e(_entries.find(name));
- return ((e == _entries.end()) ? (const Entry *)0 : &(e->second));
-}
-
-const Pack::Entry *Pack::put(const std::string &name,const std::string &content)
-{
- SHA256_CTX sha;
-
- Pack::Entry &e = _entries[name];
- e.name = name;
- e.content = content;
-
- SHA256_Init(&sha);
- SHA256_Update(&sha,content.data(),content.length());
- SHA256_Final(e.sha256,&sha);
-
- e.signedBy = 0;
- e.signature.assign((const char *)0,0);
-
- return &e;
-}
-
-void Pack::clear()
-{
- _entries.clear();
-}
-
-std::string Pack::serialize() const
-{
- BlobArray archive;
- for(std::map<std::string,Entry>::const_iterator e=_entries.begin();e!=_entries.end();++e) {
- BlobArray entry;
- entry.push_back(e->second.name);
- entry.push_back(e->second.content);
- entry.push_back(std::string((const char *)e->second.sha256,sizeof(e->second.sha256)));
- entry.push_back(e->second.signedBy.toBinaryString());
- entry.push_back(e->second.signature);
- archive.push_back(entry.serialize());
- }
-
- std::string ser(archive.serialize());
- std::string comp;
- Utils::compress(ser.begin(),ser.end(),Utils::StringAppendOutput(comp));
- return comp;
-}
-
-bool Pack::deserialize(const void *sd,unsigned int sdlen)
-{
- unsigned char dig[32];
- SHA256_CTX sha;
-
- std::string decomp;
- if (!Utils::decompress(((const char *)sd),((const char *)sd) + sdlen,Utils::StringAppendOutput(decomp)))
- return false;
-
- BlobArray archive;
- archive.deserialize(decomp.data(),decomp.length());
- clear();
- for(BlobArray::const_iterator i=archive.begin();i!=archive.end();++i) {
- BlobArray entry;
- entry.deserialize(i->data(),i->length());
-
- if (entry.size() != 5) return false;
- if (entry[2].length() != 32) return false; // SHA-256
- if (entry[3].length() != ZT_ADDRESS_LENGTH) return false; // Address
-
- Pack::Entry &e = _entries[entry[0]];
- e.name = entry[0];
- e.content = entry[1];
-
- SHA256_Init(&sha);
- SHA256_Update(&sha,e.content.data(),e.content.length());
- SHA256_Final(dig,&sha);
- if (memcmp(dig,entry[2].data(),32)) return false; // integrity check failed
- memcpy(e.sha256,dig,32);
-
- if (entry[3].length() == ZT_ADDRESS_LENGTH)
- e.signedBy.setTo(entry[3].data());
- else e.signedBy = 0;
- e.signature = entry[4];
- }
- return true;
-}
-
-bool Pack::signAll(const Identity &id)
-{
- for(std::map<std::string,Entry>::iterator e=_entries.begin();e!=_entries.end();++e) {
- e->second.signedBy = id.address();
- e->second.signature = id.sign(e->second.sha256);
- if (!e->second.signature.length())
- return false;
- }
- return true;
-}
-
-std::vector<const Pack::Entry *> Pack::verifyAll(const Identity &id,bool mandatory) const
-{
- std::vector<const Entry *> bad;
- for(std::map<std::string,Entry>::const_iterator e=_entries.begin();e!=_entries.end();++e) {
- if ((e->second.signedBy)&&(e->second.signature.length())) {
- if (id.address() != e->second.signedBy)
- bad.push_back(&(e->second));
- else if (!id.verifySignature(e->second.sha256,e->second.signature.data(),e->second.signature.length()))
- bad.push_back(&(e->second));
- } else if (mandatory)
- bad.push_back(&(e->second));
- }
- return bad;
-}
-
-} // namespace ZeroTier
diff --git a/node/Pack.hpp b/node/Pack.hpp
deleted file mode 100644
index a0aecd6e..00000000
--- a/node/Pack.hpp
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * ZeroTier One - Global Peer to Peer Ethernet
- * Copyright (C) 2012-2013 ZeroTier Networks LLC
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- * --
- *
- * ZeroTier may be used and distributed under the terms of the GPLv3, which
- * are available at: http://www.gnu.org/licenses/gpl-3.0.html
- *
- * If you would like to embed ZeroTier into a commercial application or
- * redistribute it in a modified binary form, please contact ZeroTier Networks
- * LLC. Start here: http://www.zerotier.com/
- */
-
-#ifndef _ZT_PACK_HPP
-#define _ZT_PACK_HPP
-
-#include <string>
-#include <map>
-#include <list>
-#include <stdexcept>
-#include "Address.hpp"
-#include "Identity.hpp"
-
-namespace ZeroTier {
-
-/**
- * A very simple archive format for distributing packs of files or resources
- *
- * This is used for things like the auto-updater. It's not suitable for huge
- * files, since at present it must work in memory. Packs support signing with
- * identities and signature verification.
- */
-class Pack
-{
-public:
- /**
- * Pack entry structure for looking up deserialized entries
- */
- struct Entry
- {
- std::string name;
- std::string content;
- unsigned char sha256[32];
- Address signedBy;
- std::string signature;
- };
-
- Pack() {}
- ~Pack() {}
-
- /**
- * @return Vector of all entries
- */
- std::vector<const Entry *> getAll() const;
-
- /**
- * Look up an entry
- *
- * @param name Name to look up
- * @return Pointer to entry if it exists or NULL if not found
- */
- const Entry *get(const std::string &name) const;
-
- /**
- * Add an entry to this pack
- *
- * @param name Entry to add
- * @param content Entry's contents
- * @return The new entry
- */
- const Entry *put(const std::string &name,const std::string &content);
-
- /**
- * Remove all entries
- */
- void clear();
-
- /**
- * @return Number of entries in pack
- */
- inline unsigned int numEntries() const { return (unsigned int)_entries.size(); }
-
- /**
- * Serialize this pack
- *
- * @return Serialized form (compressed with LZ4)
- */
- std::string serialize() const;
-
- /**
- * Deserialize this pack
- *
- * Any current contents are lost. This does not verify signatures,
- * but does check SHA256 hashes for entry integrity. If the return
- * value is false, the pack's contents are undefined.
- *
- * @param sd Serialized data
- * @param sdlen Length of serialized data
- * @return True on success, false on deserialization error
- */
- bool deserialize(const void *sd,unsigned int sdlen);
- inline bool deserialize(const std::string &sd) { return deserialize(sd.data(),sd.length()); }
-
- /**
- * Sign all entries in this pack with a given identity
- *
- * @param id Identity to sign with
- * @return True on signature success, false if error
- */
- bool signAll(const Identity &id);
-
- /**
- * Verify all signed entries
- *
- * @param id Identity to verify against
- * @param mandatory If true, require that all entries be signed and fail if no signature
- * @return Vector of entries that failed verification or empty vector if all passed
- */
- std::vector<const Entry *> verifyAll(const Identity &id,bool mandatory) const;
-
-private:
- std::map<std::string,Entry> _entries;
-};
-
-} // namespace ZeroTier
-
-#endif
diff --git a/node/Packet.cpp b/node/Packet.cpp
index d12f396d..4728609d 100644
--- a/node/Packet.cpp
+++ b/node/Packet.cpp
@@ -42,6 +42,7 @@ const char *Packet::verbString(Verb v)
case VERB_FRAME: return "FRAME";
case VERB_MULTICAST_FRAME: return "MULTICAST_FRAME";
case VERB_MULTICAST_LIKE: return "MULTICAST_LIKE";
+ case VERB_NETWORK_PERMISSION_CERTIFICATE: return "NETWORK_PERMISSION_CERTIFICATE";
}
return "(unknown)";
}
@@ -57,6 +58,8 @@ const char *Packet::errorString(ErrorCode e)
case ERROR_IDENTITY_COLLISION: return "IDENTITY_COLLISION";
case ERROR_IDENTITY_INVALID: return "IDENTITY_INVALID";
case ERROR_UNSUPPORTED_OPERATION: return "UNSUPPORTED_OPERATION";
+ case ERROR_NO_NETWORK_CERTIFICATE_ON_FILE: return "NO_NETWORK_CERTIFICATE_ON_FILE";
+ case ERROR_OBJECT_EXPIRED: return "OBJECT_EXPIRED";
}
return "(unknown)";
}
diff --git a/node/Packet.hpp b/node/Packet.hpp
index 5ccfae45..86d94e1d 100644
--- a/node/Packet.hpp
+++ b/node/Packet.hpp
@@ -463,7 +463,22 @@ public:
*
* No OK or ERROR is generated.
*/
- VERB_MULTICAST_FRAME = 9
+ VERB_MULTICAST_FRAME = 9,
+
+ /* Network permission certificate:
+ * <[8] 64-bit network ID>
+ * <[1] flags (currently unused, must be 0)>
+ * <[8] certificate timestamp>
+ * <[8] 16-bit length of signature>
+ * <[...] ECDSA signature of my binary serialized identity and timestamp>
+ *
+ * This message is used to send ahead of time a certificate proving
+ * this node has permission to communicate on a private network.
+ *
+ * OK is generated on acceptance. ERROR is returned on failure. In both
+ * cases the payload is the network ID.
+ */
+ VERB_NETWORK_PERMISSION_CERTIFICATE = 10
};
/**
@@ -490,7 +505,13 @@ public:
ERROR_IDENTITY_INVALID = 5,
/* Verb or use case not supported/enabled by this node */
- ERROR_UNSUPPORTED_OPERATION = 6
+ ERROR_UNSUPPORTED_OPERATION = 6,
+
+ /* Message to private network rejected -- no unexpired certificate on file */
+ ERROR_NO_NETWORK_CERTIFICATE_ON_FILE = 7,
+
+ /* Object is expired (e.g. network certificate) */
+ ERROR_OBJECT_EXPIRED = 8
};
/**
diff --git a/objects.mk b/objects.mk
index 49312994..c6fab0b6 100644
--- a/objects.mk
+++ b/objects.mk
@@ -18,7 +18,6 @@ OBJS=\
node/NodeConfig.o \
node/Packet.o \
node/PacketDecoder.o \
- node/Pack.o \
node/Peer.o \
node/Salsa20.o \
node/Switch.o \