security: Introduce hierarchical validator
Change-Id: Ie99abc2b8de4ff227c21e34fef19544c01a9f5dd
diff --git a/security/anchor.cert b/security/anchor.cert
index 6eeaef4..32a7523 100644
--- a/security/anchor.cert
+++ b/security/anchor.cert
@@ -1,16 +1,13 @@
-Bv0C2gcvCANuZG4IA0tFWQgRa3NrLTEzOTMzNzgwNTI0MDkIB0lELUNFUlQIB/0B
-RGvNyo0UAxgBAhX9AW0wggFpMCIYDzIwMTQwMjI2MDEyNzMyWhgPMjAxNDAzMDUw
-ODM5MzJaMB8wHQYDVQQpExYvbmRuL2tzay0xMzkzMzc4MDUyNDA5MIIBIDANBgkq
-hkiG9w0BAQEFAAOCAQ0AMIIBCAKCAQEAyfBfMsDEKjn5sEF/2B5uUvojnpUvh8/r
-rF5nDVdG7faJVjWkrdnPYweUQItnNRDfiTPYoAINfFdlSdtsCV3gMQjXvrJa5pFP
-Ha4M7nZ9YVExXAnYTSdHAqwFi2bfNJMNUvME7R0lVhjDcyJAdB4IjMc+W7s80rOr
-1BFo3Jf66HE+hLnQsHWC/L3AxR5IYJ7laubDeQBUCJWfbQ+xbM8cb8y39O7ONyhw
-hbJ4hGqel6wvffsGVNzQcZkkGFvpns8FTMrYdhV3rYbmRKxSy09Xh6qDkkuCvgf7
-zZHDZvJGIibEKlfjHD82EJn+V4Ib7PDFAy9le/rissmyZ3gBI7QcqwIBERYtGwEB
-HCgHJggDbmRuCANLRVkIEWtzay0xMzkzMzc4MDUyNDA5CAdJRC1DRVJUF/0BABlT
-1uvcHSjoMNnaeuK73LeI93OqZwOK3Prtl6KNYG/p6ob8uue0pU6x9u8YIu8qj1Gt
-1uIvFhgOqlkbBMUebCjFeRTwlddXnyCWaWH7oJMYZbEjuCyv3498xgEV+4K5fF/x
-BePjfFVD70Vfh3gMUqR2L3ktXzXcLyemT/PvLMXWJ6iQXX4FNLbpAx2EdMzwfFbE
-uPK9/QUBJIG92ks44e9M9iD7meiW+nLjKi4ebiCWYOVcoIazfEi13ZCiBXwbXTNv
-HM0wp7ODHf0CUz3cKfl9pLl8bC9UNEIxFi2b9Vr5UpCy2i8xiTGaxJpvICSFYGFg
-Z7eA1LjpBYouO/4W7+w=
+Bv0C1QcwCANuZG4IA0tFWQgRa3NrLTEzOTc1MzcyMjg2NDkIB0lELUNFUlQICAAAAUVjtyQUFAMY
+AQIV/QFnMIIBYzAiGA8yMDE0MDQxNDAwMDAwMFoYDzIwMTgxMjMxMjM1OTU5WjAZMBcGA1UEKRMQ
+TkROIFRlc3RiZWQgUm9vdDCCASAwDQYJKoZIhvcNAQEBBQADggENADCCAQgCggEBAL/XonINE4KB
+IC5G3Aab3uJmz9nf/4nTRa2/tWDPn5Notqs/+h4i/xF7LusKbBXkugLRjYcJsO1bIVf597921U8L
+pCfQdhaxBWfr26M4ZsZ3i2cVanBvxTneZQWYahsg8M0gA+jMFbSkpgVhMsAfVR+UCPhcvPkZ/94V
+HoOq3Nae36RRW64pa0QKCuUluFRVrAhZD9zj+QJHM8faOlOJTLnss9vjggb5MWu/dS8cYEfY9o/O
+oVlpbeCbCoQJdhGc0NWhEmpTx/UZHSUEDKRV6643ETx63yQtT99WIp4+VVBAoxh1Dz8i4ePBjgBs
+DJTW7p3xxreOxeW/ndIKNpUzv/UCAREWLRsBARwoByYIA25kbggDS0VZCBFrc2stMTM5NzUzNzIy
+ODY0OQgHSUQtQ0VSVBf9AQAhyPUjSO3lCt1XDWSAsTiw7M454QlyUIXWvS5WqIXGE9zJgIMxt0OL
+ec6o6rg5LZyH+hh6MSoK9ItUvQDVA/FXyQdTfKZAshGhx7ejEmKwU5yCt3PXfprfwQZwuImjkFo2
+QpgrwN/cToXGkiEOQ/7r5qXCSAEagmIWiLncefixfTopK7mGW+ADQryvChtTeiXawWuq0xPC45wm
+wzkoEyE2cGuEbgdyQoHTB0i/75nJVmQOc6iJbgAfxrdLIC53krKe5QRX8H1GDf5IrELmwC7kKa0b
+b06RJ+hLLGEKa286IOHeAJAFsQu3wnoThWBFvUDegt41zF50awzgosHLrZRD
\ No newline at end of file
diff --git a/src/chat-dialog-backend.cpp b/src/chat-dialog-backend.cpp
index 2644006..f175615 100644
--- a/src/chat-dialog-backend.cpp
+++ b/src/chat-dialog-backend.cpp
@@ -10,8 +10,11 @@
#include "chat-dialog-backend.hpp"
+#include <QFile>
+
#ifndef Q_MOC_RUN
#include <ndn-cxx/util/io.hpp>
+#include <ndn-cxx/security/validator-regex.hpp>
#include "logging.h"
#endif
@@ -29,6 +32,7 @@
const Name& routingPrefix,
const std::string& chatroomName,
const std::string& nick,
+ const Name& signingId,
QObject* parent)
: QThread(parent)
, m_localRoutingPrefix(routingPrefix)
@@ -36,6 +40,7 @@
, m_userChatPrefix(userChatPrefix)
, m_chatroomName(chatroomName)
, m_nick(nick)
+ , m_signingId(signingId)
{
updatePrefixes();
}
@@ -74,14 +79,38 @@
{
BOOST_ASSERT(m_sock == nullptr);
- m_face = unique_ptr<ndn::Face>(new ndn::Face);
+ m_face = make_shared<ndn::Face>();
m_scheduler = unique_ptr<ndn::Scheduler>(new ndn::Scheduler(m_face->getIoService()));
+ // initialize validator
+ shared_ptr<ndn::IdentityCertificate> anchor = loadTrustAnchor();
+
+ if (static_cast<bool>(anchor)) {
+ shared_ptr<ndn::ValidatorRegex> validator =
+ make_shared<ndn::ValidatorRegex>(m_face.get()); // TODO: Change to Face*
+ validator->addDataVerificationRule(
+ make_shared<ndn::SecRuleRelative>("^<>*<%F0.>(<>*)$",
+ "^([^<KEY>]*)<KEY>(<>*)<ksk-.*><ID-CERT>$",
+ ">", "\\1", "\\1\\2", true));
+ validator->addDataVerificationRule(
+ make_shared<ndn::SecRuleRelative>("(<>*)$",
+ "^([^<KEY>]*)<KEY>(<>*)<ksk-.*><ID-CERT>$",
+ ">", "\\1", "\\1\\2", true));
+ validator->addTrustAnchor(anchor);
+
+ m_validator = validator;
+ }
+ else
+ m_validator = shared_ptr<ndn::Validator>();
+
+
// create a new SyncSocket
m_sock = make_shared<chronosync::Socket>(m_chatroomPrefix,
m_routableUserChatPrefix,
ref(*m_face),
- bind(&ChatDialogBackend::processSyncUpdate, this, _1));
+ bind(&ChatDialogBackend::processSyncUpdate, this, _1),
+ m_signingId,
+ m_validator);
// schedule a new join event
m_scheduler->scheduleEvent(time::milliseconds(600),
@@ -94,6 +123,40 @@
}
}
+class IoDeviceSource
+{
+public:
+ typedef char char_type;
+ typedef boost::iostreams::source_tag category;
+
+ explicit
+ IoDeviceSource(QIODevice& source)
+ : m_source(source)
+ {
+ }
+
+ std::streamsize
+ read(char* buffer, std::streamsize n)
+ {
+ return m_source.read(buffer, n);
+ }
+private:
+ QIODevice& m_source;
+};
+
+shared_ptr<ndn::IdentityCertificate>
+ChatDialogBackend::loadTrustAnchor()
+{
+ QFile anchorFile(":/security/anchor.cert");
+
+ if (!anchorFile.open(QIODevice::ReadOnly)) {
+ return {};
+ }
+
+ boost::iostreams::stream<IoDeviceSource> anchorFileStream(anchorFile);
+ return ndn::io::load<ndn::IdentityCertificate>(anchorFileStream);
+}
+
void
ChatDialogBackend::close()
{
@@ -105,6 +168,7 @@
m_scheduler->cancelAllEvents();
m_helloEventId.reset();
m_roster.clear();
+ m_validator.reset();
m_sock.reset();
}
@@ -131,7 +195,13 @@
if (updates[i].high - updates[i].low < 3) {
for (chronosync::SeqNo seq = updates[i].low; seq <= updates[i].high; ++seq) {
m_sock->fetchData(updates[i].session, seq,
- bind(&ChatDialogBackend::processChatData, this, _1, true),
+ [this] (const shared_ptr<const ndn::Data>& data) {
+ this->processChatData(data, true, true);
+ },
+ [this] (const shared_ptr<const ndn::Data>& data, const std::string& msg) {
+ this->processChatData(data, true, false);
+ },
+ ndn::OnTimeout(),
2);
_LOG_DEBUG("<<< Fetching " << updates[i].session << "/" << seq);
}
@@ -139,7 +209,13 @@
else {
// There are too many msgs to fetch, let's just fetch the latest one
m_sock->fetchData(updates[i].session, updates[i].high,
- bind(&ChatDialogBackend::processChatData, this, _1, false),
+ [this] (const shared_ptr<const ndn::Data>& data) {
+ this->processChatData(data, false, true);
+ },
+ [this] (const shared_ptr<const ndn::Data>& data, const std::string& msg) {
+ this->processChatData(data, false, false);
+ },
+ ndn::OnTimeout(),
2);
}
@@ -156,7 +232,9 @@
}
void
-ChatDialogBackend::processChatData(const ndn::shared_ptr<const ndn::Data>& data, bool needDisplay)
+ChatDialogBackend::processChatData(const ndn::shared_ptr<const ndn::Data>& data,
+ bool needDisplay,
+ bool isValidated)
{
SyncDemo::ChatMessage msg;
@@ -223,10 +301,16 @@
this, remoteSessionPrefix));
// If chat message, notify the frontend
- if (msg.type() == SyncDemo::ChatMessage::CHAT)
- emit chatMessageReceived(QString::fromStdString(msg.from()),
- QString::fromStdString(msg.data()),
- msg.timestamp());
+ if (msg.type() == SyncDemo::ChatMessage::CHAT) {
+ if (isValidated)
+ emit chatMessageReceived(QString::fromStdString(msg.from()),
+ QString::fromStdString(msg.data()),
+ msg.timestamp());
+ else
+ emit chatMessageReceived(QString::fromStdString(msg.from() + " (Unverified)"),
+ QString::fromStdString(msg.data()),
+ msg.timestamp());
+ }
// Notify frontend to plot notification on DigestTree.
emit messageReceived(QString::fromStdString(remoteSessionPrefix.toUri()));
diff --git a/src/chat-dialog-backend.hpp b/src/chat-dialog-backend.hpp
index 051a35e..f01c015 100644
--- a/src/chat-dialog-backend.hpp
+++ b/src/chat-dialog-backend.hpp
@@ -46,6 +46,7 @@
const Name& routingPrefix,
const std::string& chatroomName,
const std::string& nick,
+ const Name& signingId = Name(),
QObject* parent = 0);
~ChatDialogBackend();
@@ -58,6 +59,9 @@
void
initializeSync();
+ shared_ptr<ndn::IdentityCertificate>
+ loadTrustAnchor();
+
void
close();
@@ -65,7 +69,9 @@
processSyncUpdate(const std::vector<chronosync::MissingDataInfo>& updates);
void
- processChatData(const ndn::shared_ptr<const ndn::Data>& data, bool needDisplay);
+ processChatData(const ndn::shared_ptr<const ndn::Data>& data,
+ bool needDisplay,
+ bool isValidated);
void
remoteSessionTimeout(const Name& sessionPrefix);
@@ -132,7 +138,7 @@
private:
typedef std::map<ndn::Name, UserInfo> BackendRoster;
- unique_ptr<ndn::Face> m_face;
+ shared_ptr<ndn::Face> m_face;
Name m_localRoutingPrefix; // routable local prefix
Name m_chatroomPrefix; // chatroom sync prefix
@@ -142,6 +148,8 @@
std::string m_chatroomName; // chatroom name
std::string m_nick; // user nick
+ Name m_signingId; // signing identity
+ shared_ptr<ndn::Validator> m_validator;// validator
shared_ptr<chronosync::Socket> m_sock; // SyncSocket
unique_ptr<ndn::Scheduler> m_scheduler;// scheduler
diff --git a/src/chat-dialog.cpp b/src/chat-dialog.cpp
index 9c74715..776e076 100644
--- a/src/chat-dialog.cpp
+++ b/src/chat-dialog.cpp
@@ -32,10 +32,11 @@
const std::string& chatroomName,
const std::string& nick,
bool isSecured,
+ const Name& signingId,
QWidget* parent)
: QDialog(parent)
, ui(new Ui::ChatDialog)
- , m_backend(chatroomPrefix, userChatPrefix, routingPrefix, chatroomName, nick)
+ , m_backend(chatroomPrefix, userChatPrefix, routingPrefix, chatroomName, nick, signingId)
, m_chatroomName(chatroomName)
, m_nick(nick.c_str())
, m_isSecured(isSecured)
@@ -186,7 +187,7 @@
}
if (m_isSecured)
- chatroomInfo->setTrustModel(ChatroomInfo::TRUST_MODEL_WEBOFTRUST);
+ chatroomInfo->setTrustModel(ChatroomInfo::TRUST_MODEL_HIERARCHICAL);
else
chatroomInfo->setTrustModel(ChatroomInfo::TRUST_MODEL_NONE);
return chatroomInfo;
diff --git a/src/chat-dialog.hpp b/src/chat-dialog.hpp
index 3568750..74dd76d 100644
--- a/src/chat-dialog.hpp
+++ b/src/chat-dialog.hpp
@@ -48,6 +48,7 @@
const std::string& chatroomName,
const std::string& nick,
bool isSecured = false,
+ const Name& signingId = Name(),
QWidget* parent = 0);
~ChatDialog();
diff --git a/src/controller.cpp b/src/controller.cpp
index a21a621..f716ada 100644
--- a/src/controller.cpp
+++ b/src/controller.cpp
@@ -630,7 +630,9 @@
chatPrefix,
m_localPrefix,
chatroomName.toStdString(),
- m_nick);
+ m_nick,
+ true,
+ m_identity);
addChatDialog(chatroomName, chatDialog);
chatDialog->show();