blob: cc3464564b24872d1c71474ed7005814cfd2ca46 [file] [log] [blame]
Yingdi Yu77627ab2015-07-21 16:13:49 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
3 * Copyright (c) 2013-2015 Regents of the University of California.
4 *
5 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
6 *
7 * ndn-cxx library is free software: you can redistribute it and/or modify it under the
8 * terms of the GNU Lesser General Public License as published by the Free Software
9 * Foundation, either version 3 of the License, or (at your option) any later version.
10 *
11 * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
12 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
13 * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
14 *
15 * You should have received copies of the GNU General Public License and GNU Lesser
16 * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
17 * <http://www.gnu.org/licenses/>.
18 *
19 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
20 */
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