blob: 76d0b97dae3e5dc08750cacdcec888b52e13f655 [file] [log] [blame]
Alexander Afanasyev7e721412017-01-11 13:36:08 -08001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
3 * Copyright (c) 2013-2017 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 "validation-state.hpp"
23#include "validator.hpp"
24#include "../verification-helpers.hpp"
25#include "util/logger.hpp"
26
27namespace ndn {
28namespace security {
29namespace v2 {
30
31NDN_LOG_INIT(ndn.security.v2.ValidationState);
32
33#define NDN_LOG_DEBUG_DEPTH(x) NDN_LOG_DEBUG(std::string(this->getDepth() + 1, '>') << " " << x)
34#define NDN_LOG_TRACE_DEPTH(x) NDN_LOG_TRACE(std::string(this->getDepth() + 1, '>') << " " << x)
35
36ValidationState::ValidationState()
Junxiao Shi830ba972017-06-23 22:44:41 +000037 : m_outcome(boost::logic::indeterminate)
Alexander Afanasyev7e721412017-01-11 13:36:08 -080038{
39}
40
41ValidationState::~ValidationState()
42{
43 NDN_LOG_TRACE(__func__);
Junxiao Shi830ba972017-06-23 22:44:41 +000044 BOOST_ASSERT(!boost::logic::indeterminate(m_outcome));
Alexander Afanasyev7e721412017-01-11 13:36:08 -080045}
46
47size_t
48ValidationState::getDepth() const
49{
50 return m_certificateChain.size();
51}
52
53bool
54ValidationState::hasSeenCertificateName(const Name& certName)
55{
56 return !m_seenCertificateNames.insert(certName).second;
57}
58
59void
60ValidationState::addCertificate(const Certificate& cert)
61{
62 m_certificateChain.push_front(cert);
63}
64
65const Certificate*
66ValidationState::verifyCertificateChain(const Certificate& trustedCert)
67{
68 const Certificate* validatedCert = &trustedCert;
69 for (auto it = m_certificateChain.begin(); it != m_certificateChain.end(); ++it) {
70 const auto& certToValidate = *it;
71
72 if (!verifySignature(certToValidate, *validatedCert)) {
73 this->fail({ValidationError::Code::INVALID_SIGNATURE, "Invalid signature of certificate `" +
74 certToValidate.getName().toUri() + "`"});
75 m_certificateChain.erase(it, m_certificateChain.end());
76 return nullptr;
77 }
78 else {
79 NDN_LOG_TRACE_DEPTH("OK signature for certificate `" << certToValidate.getName() << "`");
80 validatedCert = &certToValidate;
81 }
82 }
83 return validatedCert;
84}
85
86/////// DataValidationState
87
88DataValidationState::DataValidationState(const Data& data,
89 const DataValidationSuccessCallback& successCb,
90 const DataValidationFailureCallback& failureCb)
91 : m_data(data)
92 , m_successCb(successCb)
93 , m_failureCb(failureCb)
94{
95 BOOST_ASSERT(m_successCb != nullptr);
96 BOOST_ASSERT(m_failureCb != nullptr);
97}
98
99DataValidationState::~DataValidationState()
100{
Junxiao Shi830ba972017-06-23 22:44:41 +0000101 if (boost::logic::indeterminate(m_outcome)) {
Alexander Afanasyev7e721412017-01-11 13:36:08 -0800102 this->fail({ValidationError::Code::IMPLEMENTATION_ERROR,
103 "Validator/policy did not invoke success or failure callback"});
104 }
105}
106
107void
108DataValidationState::verifyOriginalPacket(const Certificate& trustedCert)
109{
110 if (verifySignature(m_data, trustedCert)) {
111 NDN_LOG_TRACE_DEPTH("OK signature for data `" << m_data.getName() << "`");
112 m_successCb(m_data);
Junxiao Shi830ba972017-06-23 22:44:41 +0000113 BOOST_ASSERT(boost::logic::indeterminate(m_outcome));
114 m_outcome = true;
Alexander Afanasyev7e721412017-01-11 13:36:08 -0800115 }
116 else {
117 this->fail({ValidationError::Code::INVALID_SIGNATURE, "Invalid signature of data `" +
118 m_data.getName().toUri() + "`"});
119 }
120}
121
122void
123DataValidationState::bypassValidation()
124{
125 NDN_LOG_TRACE_DEPTH("Signature verification bypassed for data `" << m_data.getName() << "`");
126 m_successCb(m_data);
Junxiao Shi830ba972017-06-23 22:44:41 +0000127 BOOST_ASSERT(boost::logic::indeterminate(m_outcome));
128 m_outcome = true;
Alexander Afanasyev7e721412017-01-11 13:36:08 -0800129}
130
131void
132DataValidationState::fail(const ValidationError& error)
133{
134 NDN_LOG_DEBUG_DEPTH(error);
135 m_failureCb(m_data, error);
Junxiao Shi830ba972017-06-23 22:44:41 +0000136 BOOST_ASSERT(boost::logic::indeterminate(m_outcome));
137 m_outcome = false;
Alexander Afanasyev7e721412017-01-11 13:36:08 -0800138}
139
140const Data&
141DataValidationState::getOriginalData() const
142{
143 return m_data;
144}
145
146/////// InterestValidationState
147
148InterestValidationState::InterestValidationState(const Interest& interest,
149 const InterestValidationSuccessCallback& successCb,
150 const InterestValidationFailureCallback& failureCb)
151 : m_interest(interest)
Alexander Afanasyev7e721412017-01-11 13:36:08 -0800152 , m_failureCb(failureCb)
153{
Alexander Afanasyev93338872017-01-30 22:37:00 -0800154 afterSuccess.connect(successCb);
155 BOOST_ASSERT(successCb != nullptr);
Alexander Afanasyev7e721412017-01-11 13:36:08 -0800156 BOOST_ASSERT(m_failureCb != nullptr);
157}
158
159InterestValidationState::~InterestValidationState()
160{
Junxiao Shi830ba972017-06-23 22:44:41 +0000161 if (boost::logic::indeterminate(m_outcome)) {
Alexander Afanasyev7e721412017-01-11 13:36:08 -0800162 this->fail({ValidationError::Code::IMPLEMENTATION_ERROR,
163 "Validator/policy did not invoke success or failure callback"});
164 }
165}
166
167void
168InterestValidationState::verifyOriginalPacket(const Certificate& trustedCert)
169{
170 if (verifySignature(m_interest, trustedCert)) {
171 NDN_LOG_TRACE_DEPTH("OK signature for interest `" << m_interest.getName() << "`");
Alexander Afanasyev93338872017-01-30 22:37:00 -0800172 this->afterSuccess(m_interest);
Junxiao Shi830ba972017-06-23 22:44:41 +0000173 BOOST_ASSERT(boost::logic::indeterminate(m_outcome));
174 m_outcome = true;
Alexander Afanasyev7e721412017-01-11 13:36:08 -0800175 }
176 else {
177 this->fail({ValidationError::Code::INVALID_SIGNATURE, "Invalid signature of interest `" +
178 m_interest.getName().toUri() + "`"});
179 }
180}
181
182void
183InterestValidationState::bypassValidation()
184{
185 NDN_LOG_TRACE_DEPTH("Signature verification bypassed for interest `" << m_interest.getName() << "`");
Alexander Afanasyev93338872017-01-30 22:37:00 -0800186 this->afterSuccess(m_interest);
Junxiao Shi830ba972017-06-23 22:44:41 +0000187 BOOST_ASSERT(boost::logic::indeterminate(m_outcome));
188 m_outcome = true;
Alexander Afanasyev7e721412017-01-11 13:36:08 -0800189}
190
191void
192InterestValidationState::fail(const ValidationError& error)
193{
194 NDN_LOG_DEBUG_DEPTH(error);
195 m_failureCb(m_interest, error);
Junxiao Shi830ba972017-06-23 22:44:41 +0000196 BOOST_ASSERT(boost::logic::indeterminate(m_outcome));
197 m_outcome = false;
Alexander Afanasyev7e721412017-01-11 13:36:08 -0800198}
199
200const Interest&
201InterestValidationState::getOriginalInterest() const
202{
203 return m_interest;
204}
205
206} // namespace v2
207} // namespace security
208} // namespace ndn