Yingdi Yu | 0eee600 | 2014-02-11 15:54:17 -0800 | [diff] [blame] | 1 | /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */ |
| 2 | /* |
| 3 | * Copyright (c) 2013, Regents of the University of California |
| 4 | * Yingdi Yu |
| 5 | * |
| 6 | * BSD license, See the LICENSE file for more information |
| 7 | * |
| 8 | * Author: Yingdi Yu <yingdi@cs.ucla.edu> |
| 9 | */ |
| 10 | |
| 11 | #include "sync-validator.h" |
| 12 | #include "sync-logging.h" |
| 13 | #include <ndn-cpp-dev/security/certificate-cache-ttl.hpp> |
| 14 | #include <queue> |
| 15 | |
| 16 | using namespace ndn; |
Yingdi Yu | 0eee600 | 2014-02-11 15:54:17 -0800 | [diff] [blame] | 17 | |
| 18 | INIT_LOGGER ("SyncValidator"); |
| 19 | |
| 20 | namespace Sync { |
| 21 | |
Yingdi Yu | 68bc51a | 2014-03-25 16:02:12 -0700 | [diff] [blame] | 22 | using ndn::shared_ptr; |
| 23 | |
Yingdi Yu | 0eee600 | 2014-02-11 15:54:17 -0800 | [diff] [blame] | 24 | const shared_ptr<CertificateCache> SyncValidator::DefaultCertificateCache = shared_ptr<CertificateCache>(); |
| 25 | const shared_ptr<SecRuleRelative> SyncValidator::DefaultDataRule = shared_ptr<SecRuleRelative>(); |
| 26 | |
| 27 | SyncValidator::SyncValidator(const Name& prefix, |
| 28 | const IdentityCertificate& anchor, |
Yingdi Yu | a873d64 | 2014-04-15 21:31:33 -0700 | [diff] [blame^] | 29 | Face& face, |
Yingdi Yu | 3da10fe | 2014-02-27 16:37:34 -0800 | [diff] [blame] | 30 | const PublishCertCallback& publishCertCallback, |
Yingdi Yu | 0eee600 | 2014-02-11 15:54:17 -0800 | [diff] [blame] | 31 | shared_ptr<SecRuleRelative> rule, |
Yingdi Yu | a873d64 | 2014-04-15 21:31:33 -0700 | [diff] [blame^] | 32 | shared_ptr<CertificateCache> certificateCache, |
Yingdi Yu | 0eee600 | 2014-02-11 15:54:17 -0800 | [diff] [blame] | 33 | const int stepLimit) |
| 34 | : Validator(face) |
| 35 | , m_prefix(prefix) |
| 36 | , m_anchor(anchor) |
| 37 | , m_stepLimit(stepLimit) |
| 38 | , m_certificateCache(certificateCache) |
Yingdi Yu | 3da10fe | 2014-02-27 16:37:34 -0800 | [diff] [blame] | 39 | , m_publishCertCallback(publishCertCallback) |
Yingdi Yu | 0eee600 | 2014-02-11 15:54:17 -0800 | [diff] [blame] | 40 | , m_dataRule(rule) |
| 41 | { |
Yingdi Yu | 0eee600 | 2014-02-11 15:54:17 -0800 | [diff] [blame] | 42 | if(!static_cast<bool>(m_certificateCache)) |
Yingdi Yu | a873d64 | 2014-04-15 21:31:33 -0700 | [diff] [blame^] | 43 | m_certificateCache = make_shared<CertificateCacheTtl>(m_face.ioService()); |
Yingdi Yu | 0eee600 | 2014-02-11 15:54:17 -0800 | [diff] [blame] | 44 | |
| 45 | Name certPrefix = prefix; |
Yingdi Yu | 3da10fe | 2014-02-27 16:37:34 -0800 | [diff] [blame] | 46 | certPrefix.append("CHRONOS-INTRO-CERT"); |
Yingdi Yu | a873d64 | 2014-04-15 21:31:33 -0700 | [diff] [blame^] | 47 | m_prefixId = m_face.setInterestFilter(certPrefix, |
| 48 | bind(&SyncValidator::onCertInterest, this, _1, _2), |
Yingdi Yu | 3da10fe | 2014-02-27 16:37:34 -0800 | [diff] [blame] | 49 | bind(&SyncValidator::onCertRegisterFailed, this, _1, _2)); |
Yingdi Yu | 0eee600 | 2014-02-11 15:54:17 -0800 | [diff] [blame] | 50 | |
| 51 | setAnchor(m_anchor); |
| 52 | } |
| 53 | |
| 54 | void |
| 55 | SyncValidator::deriveTrustNodes() |
| 56 | { |
Yingdi Yu | 68bc51a | 2014-03-25 16:02:12 -0700 | [diff] [blame] | 57 | std::queue<Name> nodeQueue; |
Yingdi Yu | 0eee600 | 2014-02-11 15:54:17 -0800 | [diff] [blame] | 58 | |
| 59 | // Clear existing trust nodes. |
| 60 | m_trustedNodes.clear(); |
| 61 | |
| 62 | // Add the trust anchor. |
| 63 | IntroNode origin(m_anchor); |
| 64 | m_trustedNodes[origin.name()] = m_anchor.getPublicKeyInfo(); |
| 65 | nodeQueue.push(origin.name()); |
| 66 | |
| 67 | // BFS trusted nodes. |
| 68 | while(!nodeQueue.empty()) |
| 69 | { |
| 70 | // Get next trusted node to process. |
| 71 | Nodes::const_iterator it = m_introNodes.find(nodeQueue.front()); |
| 72 | const PublicKey& publicKey = m_trustedNodes[nodeQueue.front()]; |
| 73 | |
| 74 | if(it != m_introNodes.end()) |
| 75 | { |
| 76 | // If the trusted node exists in the graph. |
| 77 | IntroNode::const_iterator eeIt = it->second.introduceeBegin(); |
| 78 | IntroNode::const_iterator eeEnd = it->second.introduceeEnd(); |
| 79 | for(; eeIt != eeEnd; eeIt++) |
| 80 | { |
| 81 | // Check the nodes introduced by the trusted node. |
| 82 | Edges::const_iterator edgeIt = m_introCerts.find(*eeIt); |
Yingdi Yu | a873d64 | 2014-04-15 21:31:33 -0700 | [diff] [blame^] | 83 | if(edgeIt != m_introCerts.end() |
Yingdi Yu | 3da10fe | 2014-02-27 16:37:34 -0800 | [diff] [blame] | 84 | && m_trustedNodes.find(edgeIt->second.getIntroduceeCertName()) == m_trustedNodes.end() |
Yingdi Yu | 0eee600 | 2014-02-11 15:54:17 -0800 | [diff] [blame] | 85 | && verifySignature(edgeIt->second, publicKey)) |
| 86 | { |
| 87 | // If the introduced node can be validated, add it into trusted node set and the node queue. |
Yingdi Yu | 3da10fe | 2014-02-27 16:37:34 -0800 | [diff] [blame] | 88 | m_trustedNodes[edgeIt->second.getIntroduceeCertName()] = edgeIt->second.getIntroduceeCert().getPublicKeyInfo(); |
| 89 | nodeQueue.push(edgeIt->second.getIntroduceeCertName()); |
Yingdi Yu | 0eee600 | 2014-02-11 15:54:17 -0800 | [diff] [blame] | 90 | } |
| 91 | } |
| 92 | } |
| 93 | nodeQueue.pop(); |
| 94 | } |
| 95 | } |
| 96 | |
| 97 | void |
Yingdi Yu | a873d64 | 2014-04-15 21:31:33 -0700 | [diff] [blame^] | 98 | SyncValidator::checkPolicy (const Data& data, |
| 99 | int stepCount, |
| 100 | const OnDataValidated& onValidated, |
Yingdi Yu | 0eee600 | 2014-02-11 15:54:17 -0800 | [diff] [blame] | 101 | const OnDataValidationFailed& onValidationFailed, |
| 102 | std::vector<shared_ptr<ValidationRequest> >& nextSteps) |
| 103 | { |
| 104 | if(m_stepLimit == stepCount) |
Yingdi Yu | a873d64 | 2014-04-15 21:31:33 -0700 | [diff] [blame^] | 105 | return onValidationFailed(data.shared_from_this(), |
Yingdi Yu | 0eee600 | 2014-02-11 15:54:17 -0800 | [diff] [blame] | 106 | "Maximum steps of validation reached: " + data.getName().toUri()); |
| 107 | |
Yingdi Yu | 3da10fe | 2014-02-27 16:37:34 -0800 | [diff] [blame] | 108 | if(m_prefix.isPrefixOf(data.getName()) || (static_cast<bool>(m_dataRule) && m_dataRule->satisfy(data))) |
Yingdi Yu | 0eee600 | 2014-02-11 15:54:17 -0800 | [diff] [blame] | 109 | { |
| 110 | try |
| 111 | { |
| 112 | SignatureSha256WithRsa sig(data.getSignature()); |
| 113 | Name keyLocatorName = sig.getKeyLocator().getName(); |
| 114 | |
| 115 | TrustNodes::const_iterator it = m_trustedNodes.find(keyLocatorName); |
| 116 | if(m_trustedNodes.end() != it) |
| 117 | { |
| 118 | if(verifySignature(data, sig, it->second)) |
| 119 | return onValidated(data.shared_from_this()); |
| 120 | else |
Yingdi Yu | a873d64 | 2014-04-15 21:31:33 -0700 | [diff] [blame^] | 121 | return onValidationFailed(data.shared_from_this(), |
Yingdi Yu | 0eee600 | 2014-02-11 15:54:17 -0800 | [diff] [blame] | 122 | "Cannot verify signature: " + data.getName().toUri()); |
| 123 | } |
| 124 | else |
| 125 | { |
Yingdi Yu | a873d64 | 2014-04-15 21:31:33 -0700 | [diff] [blame^] | 126 | _LOG_DEBUG("I am: " << m_anchor.getName().get(0).toEscapedString() << " for " << data.getName()); |
Yingdi Yu | 3da10fe | 2014-02-27 16:37:34 -0800 | [diff] [blame] | 127 | |
Yingdi Yu | 0eee600 | 2014-02-11 15:54:17 -0800 | [diff] [blame] | 128 | Name interestName = m_prefix; |
Yingdi Yu | 3da10fe | 2014-02-27 16:37:34 -0800 | [diff] [blame] | 129 | interestName.append("CHRONOS-INTRO-CERT").append(keyLocatorName.wireEncode()); |
Yingdi Yu | 0eee600 | 2014-02-11 15:54:17 -0800 | [diff] [blame] | 130 | Interest interest(interestName); |
Yingdi Yu | 6e1c9cd | 2014-03-25 10:26:54 -0700 | [diff] [blame] | 131 | interest.setInterestLifetime(time::milliseconds(500)); |
Yingdi Yu | 0eee600 | 2014-02-11 15:54:17 -0800 | [diff] [blame] | 132 | |
Yingdi Yu | a873d64 | 2014-04-15 21:31:33 -0700 | [diff] [blame^] | 133 | OnDataValidated onKeyValidated = bind(&SyncValidator::onCertificateValidated, this, |
Yingdi Yu | 0eee600 | 2014-02-11 15:54:17 -0800 | [diff] [blame] | 134 | _1, data.shared_from_this(), onValidated, onValidationFailed); |
Yingdi Yu | 0eee600 | 2014-02-11 15:54:17 -0800 | [diff] [blame] | 135 | |
Yingdi Yu | a873d64 | 2014-04-15 21:31:33 -0700 | [diff] [blame^] | 136 | OnDataValidationFailed onKeyValidationFailed = bind(&SyncValidator::onCertificateValidationFailed, this, |
| 137 | _1, _2, data.shared_from_this(), onValidationFailed); |
| 138 | |
| 139 | shared_ptr<ValidationRequest> nextStep = make_shared<ValidationRequest>(interest, |
Yingdi Yu | 0eee600 | 2014-02-11 15:54:17 -0800 | [diff] [blame] | 140 | onKeyValidated, |
| 141 | onKeyValidationFailed, |
| 142 | 1, |
| 143 | stepCount + 1); |
| 144 | nextSteps.push_back(nextStep); |
| 145 | |
| 146 | return; |
| 147 | } |
| 148 | } |
| 149 | catch(SignatureSha256WithRsa::Error& e) |
| 150 | { |
Yingdi Yu | a873d64 | 2014-04-15 21:31:33 -0700 | [diff] [blame^] | 151 | return onValidationFailed(data.shared_from_this(), |
Yingdi Yu | 68bc51a | 2014-03-25 16:02:12 -0700 | [diff] [blame] | 152 | "Not SignatureSha256WithRsa signature: " + std::string(e.what())); |
Yingdi Yu | 0eee600 | 2014-02-11 15:54:17 -0800 | [diff] [blame] | 153 | } |
| 154 | catch(KeyLocator::Error& e) |
| 155 | { |
| 156 | return onValidationFailed(data.shared_from_this(), |
| 157 | "Key Locator is not a name: " + data.getName().toUri()); |
| 158 | } |
| 159 | } |
Yingdi Yu | 0eee600 | 2014-02-11 15:54:17 -0800 | [diff] [blame] | 160 | else |
| 161 | return onValidationFailed(data.shared_from_this(), |
Yingdi Yu | 3da10fe | 2014-02-27 16:37:34 -0800 | [diff] [blame] | 162 | "No rule or rule is not satisfied: " + data.getName().toUri()); |
Yingdi Yu | 0eee600 | 2014-02-11 15:54:17 -0800 | [diff] [blame] | 163 | } |
| 164 | |
| 165 | void |
Yingdi Yu | a873d64 | 2014-04-15 21:31:33 -0700 | [diff] [blame^] | 166 | SyncValidator::checkPolicy (const Interest& interest, |
| 167 | int stepCount, |
| 168 | const OnInterestValidated& onValidated, |
Yingdi Yu | 0eee600 | 2014-02-11 15:54:17 -0800 | [diff] [blame] | 169 | const OnInterestValidationFailed& onValidationFailed, |
| 170 | std::vector<shared_ptr<ValidationRequest> >& nextSteps) |
| 171 | { |
| 172 | onValidationFailed(interest.shared_from_this(), "No policy for signed interest checking"); |
| 173 | } |
| 174 | |
| 175 | void |
Yingdi Yu | a873d64 | 2014-04-15 21:31:33 -0700 | [diff] [blame^] | 176 | SyncValidator::onCertificateValidated(const shared_ptr<const Data>& signCertificate, |
| 177 | const shared_ptr<const Data>& data, |
| 178 | const OnDataValidated& onValidated, |
Yingdi Yu | 0eee600 | 2014-02-11 15:54:17 -0800 | [diff] [blame] | 179 | const OnDataValidationFailed& onValidationFailed) |
| 180 | { |
| 181 | try |
| 182 | { |
| 183 | IntroCertificate introCert(*signCertificate); |
| 184 | addParticipant(introCert); |
Yingdi Yu | a873d64 | 2014-04-15 21:31:33 -0700 | [diff] [blame^] | 185 | |
Yingdi Yu | 0eee600 | 2014-02-11 15:54:17 -0800 | [diff] [blame] | 186 | if(verifySignature(*data, introCert.getIntroduceeCert().getPublicKeyInfo())) |
| 187 | return onValidated(data); |
| 188 | else |
Yingdi Yu | a873d64 | 2014-04-15 21:31:33 -0700 | [diff] [blame^] | 189 | return onValidationFailed(data, |
Yingdi Yu | 0eee600 | 2014-02-11 15:54:17 -0800 | [diff] [blame] | 190 | "Cannot verify signature: " + data->getName().toUri()); |
| 191 | } |
| 192 | catch(IntroCertificate::Error& e) |
| 193 | { |
Yingdi Yu | a873d64 | 2014-04-15 21:31:33 -0700 | [diff] [blame^] | 194 | return onValidationFailed(data, |
Yingdi Yu | 68bc51a | 2014-03-25 16:02:12 -0700 | [diff] [blame] | 195 | "Intro cert decoding error: " + std::string(e.what())); |
Yingdi Yu | 0eee600 | 2014-02-11 15:54:17 -0800 | [diff] [blame] | 196 | } |
| 197 | } |
| 198 | |
| 199 | void |
Yingdi Yu | a873d64 | 2014-04-15 21:31:33 -0700 | [diff] [blame^] | 200 | SyncValidator::onCertificateValidationFailed(const shared_ptr<const Data>& signCertificate, |
Yingdi Yu | 68bc51a | 2014-03-25 16:02:12 -0700 | [diff] [blame] | 201 | const std::string& failureInfo, |
Yingdi Yu | a873d64 | 2014-04-15 21:31:33 -0700 | [diff] [blame^] | 202 | const shared_ptr<const Data>& data, |
Yingdi Yu | 0eee600 | 2014-02-11 15:54:17 -0800 | [diff] [blame] | 203 | const OnDataValidationFailed& onValidationFailed) |
| 204 | { |
| 205 | onValidationFailed(data, failureInfo); |
| 206 | } |
| 207 | |
| 208 | void |
| 209 | SyncValidator::onCertInterest(const Name& prefix, const Interest& interest) |
| 210 | { |
Yingdi Yu | a873d64 | 2014-04-15 21:31:33 -0700 | [diff] [blame^] | 211 | Name name = interest.getName(); |
Yingdi Yu | 0eee600 | 2014-02-11 15:54:17 -0800 | [diff] [blame] | 212 | Edges::const_iterator it = m_introCerts.begin(); |
| 213 | for(; it != m_introCerts.end(); it++) |
| 214 | { |
| 215 | if(name.isPrefixOf(it->first)) |
| 216 | { |
Yingdi Yu | a873d64 | 2014-04-15 21:31:33 -0700 | [diff] [blame^] | 217 | m_face.put(it->second); |
Yingdi Yu | 0eee600 | 2014-02-11 15:54:17 -0800 | [diff] [blame] | 218 | return; |
| 219 | } |
| 220 | } |
| 221 | } |
| 222 | |
| 223 | void |
Yingdi Yu | 68bc51a | 2014-03-25 16:02:12 -0700 | [diff] [blame] | 224 | SyncValidator::onCertRegisterFailed(const Name& prefix, const std::string& msg) |
Yingdi Yu | 0eee600 | 2014-02-11 15:54:17 -0800 | [diff] [blame] | 225 | { |
| 226 | _LOG_DEBUG("SyncValidator::onCertRegisterFailed: " << msg); |
| 227 | } |
| 228 | |
| 229 | } // namespace Sync |