8 changed files with 40 additions and 399 deletions
@ -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 |
||||
|
||||
@ -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
|
||||
@ -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 |
||||
Loading…
Reference in new issue