validity-period.cpp
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2013-2023 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 
24 
25 namespace ndn::security {
26 
27 using boost::chrono::time_point_cast;
28 
29 constexpr size_t ISO_DATETIME_SIZE = 15;
30 constexpr size_t NOT_BEFORE_OFFSET = 0;
31 constexpr size_t NOT_AFTER_OFFSET = 1;
32 
36 {
37  return ValidityPeriod(now + validFrom, now + validUntil);
38 }
39 
41  : ValidityPeriod(time::system_clock::time_point() + 1_ns,
42  time::system_clock::time_point())
43 {
44 }
45 
47  const time::system_clock::time_point& notAfter)
48  : m_notBefore(toTimePointCeil(notBefore))
49  , m_notAfter(toTimePointFloor(notAfter))
50 {
51 }
52 
54 {
55  wireDecode(block);
56 }
57 
58 template<encoding::Tag TAG>
59 size_t
61 {
62  size_t totalLength = 0;
63 
64  totalLength += prependStringBlock(encoder, tlv::NotAfter, time::toIsoString(m_notAfter));
65  totalLength += prependStringBlock(encoder, tlv::NotBefore, time::toIsoString(m_notBefore));
66 
67  totalLength += encoder.prependVarNumber(totalLength);
68  totalLength += encoder.prependVarNumber(tlv::ValidityPeriod);
69  return totalLength;
70 }
71 
73 
74 const Block&
76 {
77  if (m_wire.hasWire())
78  return m_wire;
79 
80  EncodingEstimator estimator;
81  size_t estimatedSize = wireEncode(estimator);
82 
83  EncodingBuffer buffer(estimatedSize, 0);
84  wireEncode(buffer);
85 
86  m_wire = buffer.block();
87  m_wire.parse();
88 
89  return m_wire;
90 }
91 
92 void
94 {
95  if (!wire.hasWire()) {
96  NDN_THROW(Error("The supplied block does not contain wire format"));
97  }
98 
99  m_wire = wire;
100  m_wire.parse();
101 
102  if (m_wire.type() != tlv::ValidityPeriod)
103  NDN_THROW(Error("ValidityPeriod", m_wire.type()));
104 
105  if (m_wire.elements_size() != 2)
106  NDN_THROW(Error("ValidityPeriod does not have two sub-TLVs"));
107 
108  if (m_wire.elements()[NOT_BEFORE_OFFSET].type() != tlv::NotBefore ||
109  m_wire.elements()[NOT_BEFORE_OFFSET].value_size() != ISO_DATETIME_SIZE ||
110  m_wire.elements()[NOT_AFTER_OFFSET].type() != tlv::NotAfter ||
111  m_wire.elements()[NOT_AFTER_OFFSET].value_size() != ISO_DATETIME_SIZE) {
112  NDN_THROW(Error("Invalid NotBefore or NotAfter field"));
113  }
114 
115  try {
116  m_notBefore = decodeTimePoint(m_wire.elements()[NOT_BEFORE_OFFSET]);
117  m_notAfter = decodeTimePoint(m_wire.elements()[NOT_AFTER_OFFSET]);
118  }
119  catch (const std::bad_cast&) {
120  NDN_THROW(Error("Invalid date format in NOT-BEFORE or NOT-AFTER field"));
121  }
122 }
123 
124 ValidityPeriod::TimePoint
125 ValidityPeriod::toTimePointFloor(const time::system_clock::time_point& t)
126 {
127  return TimePoint(boost::chrono::floor<TimePoint::duration>(t.time_since_epoch()));
128 }
129 
130 ValidityPeriod::TimePoint
131 ValidityPeriod::toTimePointCeil(const time::system_clock::time_point& t)
132 {
133  return TimePoint(boost::chrono::ceil<TimePoint::duration>(t.time_since_epoch()));
134 }
135 
136 ValidityPeriod::TimePoint
137 ValidityPeriod::decodeTimePoint(const Block& element)
138 {
139  // Bug #5176, prevent time::system_clock::time_point under/overflow
140  static const auto minTime = toTimePointCeil(time::system_clock::time_point::min());
141  static const auto maxTime = toTimePointFloor(time::system_clock::time_point::max());
142  static const auto minValue = time::toIsoString(minTime);
143  static const auto maxValue = time::toIsoString(maxTime);
144  BOOST_ASSERT(minValue.size() == ISO_DATETIME_SIZE);
145  BOOST_ASSERT(maxValue.size() == ISO_DATETIME_SIZE);
146 
147  auto value = readString(element);
148  BOOST_ASSERT(value.size() == ISO_DATETIME_SIZE);
149 
150  if (value < minValue) {
151  return minTime;
152  }
153  if (value > maxValue) {
154  return maxTime;
155  }
156  return time_point_cast<TimePoint::duration>(time::fromIsoString(value));
157 }
158 
161  const time::system_clock::time_point& notAfter)
162 {
163  m_wire.reset();
164  m_notBefore = toTimePointCeil(notBefore);
165  m_notAfter = toTimePointFloor(notAfter);
166  return *this;
167 }
168 
169 std::pair<time::system_clock::time_point, time::system_clock::time_point>
171 {
172  return {m_notBefore, m_notAfter};
173 }
174 
175 bool
177 {
178  return m_notBefore <= now && now <= m_notAfter;
179 }
180 
181 std::ostream&
182 operator<<(std::ostream& os, const ValidityPeriod& period)
183 {
184  os << "(" << time::toIsoString(period.getPeriod().first)
185  << ", " << time::toIsoString(period.getPeriod().second) << ")";
186  return os;
187 }
188 
189 } // namespace ndn::security
Represents a TLV element of the NDN packet format.
Definition: block.hpp:45
size_t elements_size() const noexcept
Equivalent to elements().size().
Definition: block.hpp:451
const element_container & elements() const noexcept
Get container of sub-elements.
Definition: block.hpp:424
bool hasWire() const noexcept
Check if the Block contains a fully encoded wire representation.
Definition: block.hpp:205
uint32_t type() const noexcept
Return the TLV-TYPE of the Block.
Definition: block.hpp:275
void reset() noexcept
Reset the Block to a default-constructed state.
Definition: block.cpp:293
void parse() const
Parse TLV-VALUE into sub-elements.
Definition: block.cpp:326
Represents a ValidityPeriod TLV element.
ValidityPeriod()
Create a validity period that is invalid for any timepoint.
static ValidityPeriod makeRelative(time::seconds validFrom, time::seconds validUntil, const time::system_clock::time_point &now=time::system_clock::now())
Construct ValidityPeriod relative to a timepoint.
std::pair< time::system_clock::time_point, time::system_clock::time_point > getPeriod() const
Get the stored validity period.
bool isValid(const time::system_clock::time_point &now=time::system_clock::now()) const
Check if now falls within the validity period.
void wireDecode(const Block &wire)
Decode ValidityPeriod from TLV block.
ValidityPeriod & setPeriod(const time::system_clock::time_point &notBefore, const time::system_clock::time_point &notAfter)
Set validity period [notBefore, notAfter].
const Block & wireEncode() const
Encode ValidityPeriod into TLV block.
::boost::chrono::time_point< system_clock > time_point
Definition: time.hpp:205
#define NDN_CXX_DEFINE_WIRE_ENCODE_INSTANTIATIONS(ClassName)
#define NDN_THROW(e)
Definition: exception.hpp:56
EncodingImpl< EstimatorTag > EncodingEstimator
size_t prependStringBlock(EncodingImpl< TAG > &encoder, uint32_t type, std::string_view value)
Prepend a TLV element containing a string.
std::string readString(const Block &block)
Read the TLV-VALUE of a TLV element as a string.
EncodingImpl< EncoderTag > EncodingBuffer
Contains the ndn-cxx security framework.
std::ostream & operator<<(std::ostream &os, const AdditionalDescription &desc)
constexpr size_t NOT_AFTER_OFFSET
constexpr size_t ISO_DATETIME_SIZE
constexpr size_t NOT_BEFORE_OFFSET
::boost::chrono::seconds seconds
Definition: time.hpp:51
std::string toIsoString(const system_clock::time_point &timePoint)
Convert to the ISO 8601 string representation, basic format (YYYYMMDDTHHMMSS,fffffffff).
Definition: time.cpp:130
system_clock::time_point fromIsoString(const std::string &isoString)
Convert from the ISO 8601 basic string format (YYYYMMDDTHHMMSS,fffffffff) to the internal time format...
Definition: time.cpp:155
@ ValidityPeriod
Definition: tlv.hpp:107
@ NotAfter
Definition: tlv.hpp:109
@ NotBefore
Definition: tlv.hpp:108