diff --git a/node/BlobArray.hpp b/node/BlobArray.hpp deleted file mode 100644 index d78bcffa9..000000000 --- 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 . - * - * -- - * - * 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 -#include -#include - -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 -{ -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. - * - * -- - * - * 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 -#include -#include -#include "Pack.hpp" -#include "BlobArray.hpp" -#include "Utils.hpp" - -#include - -namespace ZeroTier { - -std::vector Pack::getAll() const -{ - std::vector v; - for(std::map::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::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::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::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 Pack::verifyAll(const Identity &id,bool mandatory) const -{ - std::vector bad; - for(std::map::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 a0aecd6e0..000000000 --- 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 . - * - * -- - * - * 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 -#include -#include -#include -#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 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 verifyAll(const Identity &id,bool mandatory) const; - -private: - std::map _entries; -}; - -} // namespace ZeroTier - -#endif diff --git a/node/Packet.cpp b/node/Packet.cpp index d12f396d5..4728609d6 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 5ccfae459..86d94e1d2 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 493129944..c6fab0b60 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 \