summaryrefslogtreecommitdiff
path: root/node/Pack.cpp
diff options
context:
space:
mode:
authorAdam Ierymenko <adam.ierymenko@gmail.com>2013-07-04 16:56:19 -0400
committerAdam Ierymenko <adam.ierymenko@gmail.com>2013-07-04 16:56:19 -0400
commit150850b80012f852521c9935145cf966946334d5 (patch)
treec082369f2fef2515cfa2e4acf1b83250a3963158 /node/Pack.cpp
downloadinfinitytier-150850b80012f852521c9935145cf966946334d5.tar.gz
infinitytier-150850b80012f852521c9935145cf966946334d5.zip
New git repository for release - version 0.2.0 tagged
Diffstat (limited to 'node/Pack.cpp')
-rw-r--r--node/Pack.cpp159
1 files changed, 159 insertions, 0 deletions
diff --git a/node/Pack.cpp b/node/Pack.cpp
new file mode 100644
index 00000000..8bac1300
--- /dev/null
+++ b/node/Pack.cpp
@@ -0,0 +1,159 @@
+/*
+ * 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.zero();
+ 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(std::string((const char *)e->second.signedBy.data(),e->second.signedBy.size()));
+ 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 = entry[3].data();
+ else e.signedBy.zero();
+ 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