blob: 27b78730eed9451c1d52f8dd6300922b3b5a22ba [file] [log] [blame]
Yingdi Yu77627ab2015-07-21 16:13:49 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Yingdi Yu0a312e52015-07-22 13:14:53 -07003 * Copyright (c) 2014-2015, Regents of the University of California.
Yingdi Yu77627ab2015-07-21 16:13:49 -07004 *
Yingdi Yu0a312e52015-07-22 13:14:53 -07005 * This file is part of ndn-tools (Named Data Networking Essential Tools).
6 * See AUTHORS.md for complete list of ndn-tools authors and contributors.
Yingdi Yu77627ab2015-07-21 16:13:49 -07007 *
Yingdi Yu0a312e52015-07-22 13:14:53 -07008 * ndn-tools is free software: you can redistribute it and/or modify it under the terms
9 * of the GNU General Public License as published by the Free Software Foundation,
10 * either version 3 of the License, or (at your option) any later version.
Yingdi Yu77627ab2015-07-21 16:13:49 -070011 *
Yingdi Yu0a312e52015-07-22 13:14:53 -070012 * ndn-tools is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
13 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14 * PURPOSE. See the GNU General Public License for more details.
Yingdi Yu77627ab2015-07-21 16:13:49 -070015 *
Yingdi Yu0a312e52015-07-22 13:14:53 -070016 * You should have received a copy of the GNU General Public License along with
17 * ndn-tools, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
Yingdi Yu77627ab2015-07-21 16:13:49 -070018 *
Yingdi Yu0a312e52015-07-22 13:14:53 -070019 * @author Yingdi Yu <yingdi@cs.ucla.edu>
Yingdi Yu77627ab2015-07-21 16:13:49 -070020 */
21
22#include "pib-validator.hpp"
23#include "encoding/pib-common.hpp"
24#include "encoding/update-param.hpp"
25#include <set>
26#include <string>
27
28namespace ndn {
29namespace pib {
30
31using std::set;
32using std::string;
33
34PibValidator::PibValidator(const PibDb& db, size_t maxCacheSize)
35 : m_db(db)
36 , m_isMgmtReady(false)
37{
38 m_owner = m_db.getOwnerName();
39 m_mgmtCert = m_db.getMgmtCertificate();
40
41 if (!m_owner.empty() && m_mgmtCert != nullptr)
42 m_isMgmtReady = true;
43
44 m_mgmtChangeConnection =
45 const_cast<PibDb&>(m_db).mgmtCertificateChanged.connect([this] () {
46 m_owner = m_db.getOwnerName();
47 m_mgmtCert = m_db.getMgmtCertificate();
48 if (!m_owner.empty() && m_mgmtCert != nullptr)
49 m_isMgmtReady = true;
50 });
51
52 m_keyDeletedConnection =
53 const_cast<PibDb&>(m_db).keyDeleted.connect([this] (Name keyName) {
54 m_keyCache.erase(keyName);
55 });
56}
57
58PibValidator::~PibValidator()
59{
60}
61
62void
63PibValidator::checkPolicy(const Interest& interest,
64 int nSteps,
65 const OnInterestValidated& onValidated,
66 const OnInterestValidationFailed& onValidationFailed,
67 std::vector<shared_ptr<ValidationRequest>>& nextSteps)
68{
69 if (!m_isMgmtReady)
70 return onValidationFailed(interest.shared_from_this(), "PibDb is not initialized");
71
72 const Name& interestName = interest.getName();
73
74 if (interestName.size() != SIGNED_PIB_INTEREST_SIZE) {
75 return onValidationFailed(interest.shared_from_this(),
76 "Interest is not signed: " + interest.getName().toUri());
77 }
78
79 // Check if the user exists in PIB
80 string user = interestName.get(OFFSET_USER).toUri();
81 if (user != m_owner)
82 return onValidationFailed(interest.shared_from_this(), "Wrong user: " + user);
83
84 // Verify signature
85 try {
86 Signature signature(interestName[OFFSET_SIG_INFO].blockFromValue(),
87 interestName[OFFSET_SIG_VALUE].blockFromValue());
88 // KeyLocator is required to contain the name of signing certificate (w/o version)
89 if (!signature.hasKeyLocator())
90 return onValidationFailed(interest.shared_from_this(), "No valid KeyLocator");
91
92 const KeyLocator& keyLocator = signature.getKeyLocator();
93 if (keyLocator.getType() != KeyLocator::KeyLocator_Name)
94 return onValidationFailed(interest.shared_from_this(), "Key Locator is not a name");
95
96 // Check if PIB has the corresponding public key
97 shared_ptr<PublicKey> publicKey;
98
99 if (keyLocator.getName() == m_mgmtCert->getName().getPrefix(-1)) {
100 // the signing key is mgmt key.
101 publicKey = make_shared<PublicKey>(m_mgmtCert->getPublicKeyInfo());
102 }
103 else {
104 // the signing key is normal key.
105 Name keyName = IdentityCertificate::certificateNameToPublicKeyName(keyLocator.getName());
106
107 shared_ptr<PublicKey> key = m_keyCache.find(keyName);
108 if (key != nullptr) {
109 // the signing key is cached.
110 publicKey = key;
111 }
112 else {
113 // the signing key is not cached.
114 publicKey = m_db.getKey(keyName);
115 if (publicKey == nullptr) {
116 // the signing key does not exist in PIB.
117 return onValidationFailed(interest.shared_from_this(), "Public key is not trusted");
118 }
119 else {
120 // the signing key is retrieved from PIB.
121 m_keyCache.insert(keyName, publicKey);
122 }
123 }
124 }
125
126 if (verifySignature(interest, signature, *publicKey))
127 onValidated(interest.shared_from_this());
128 else
129 onValidationFailed(interest.shared_from_this(), "Cannot verify signature");
130
131 }
132 catch (KeyLocator::Error&) {
133 return onValidationFailed(interest.shared_from_this(),
134 "No valid KeyLocator");
135 }
136 catch (Signature::Error&) {
137 return onValidationFailed(interest.shared_from_this(),
138 "No valid signature");
139 }
140 catch (IdentityCertificate::Error&) {
141 return onValidationFailed(interest.shared_from_this(),
142 "Cannot determine the signing key");
143 }
144 catch (tlv::Error&) {
145 return onValidationFailed(interest.shared_from_this(),
146 "Cannot decode signature");
147 }
148}
149
150void
151PibValidator::checkPolicy(const Data& data,
152 int nSteps,
153 const OnDataValidated& onValidated,
154 const OnDataValidationFailed& onValidationFailed,
155 std::vector<shared_ptr<ValidationRequest>>& nextSteps)
156{
157 // Pib does not express any interest, therefor should not validate any data.
158 onValidationFailed(data.shared_from_this(),
159 "PibValidator should not receive data packet");
160}
161
162} // namespace pib
163} // namespace ndn