blob: 20d7116b079436778d7a268e19ba1184dda8b95c [file] [log] [blame]
Yingdi Yufa4ce792014-02-06 18:09:22 -08001/* -*- 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
Yingdi Yu0b0a7362014-08-05 16:31:30 -070011#include "validator-invitation.hpp"
12#include "invitation.hpp"
Yingdi Yufa4ce792014-02-06 18:09:22 -080013
14#include "logging.h"
15
Yingdi Yueb692ac2015-02-10 18:46:18 -080016namespace chronochat {
Yingdi Yufa4ce792014-02-06 18:09:22 -080017
Yingdi Yu0b0a7362014-08-05 16:31:30 -070018using std::vector;
Yingdi Yufa4ce792014-02-06 18:09:22 -080019
Yingdi Yu0b0a7362014-08-05 16:31:30 -070020using ndn::CertificateCache;
21using ndn::SecRuleRelative;
22using ndn::OnDataValidated;
23using ndn::OnDataValidationFailed;
24using ndn::OnInterestValidated;
25using ndn::OnInterestValidationFailed;
26using ndn::ValidationRequest;
27using ndn::IdentityCertificate;
Yingdi Yu17032f82014-03-25 15:48:23 -070028
Yingdi Yu0b0a7362014-08-05 16:31:30 -070029const shared_ptr<CertificateCache> ValidatorInvitation::DefaultCertificateCache =
30 shared_ptr<CertificateCache>();
Yingdi Yufa4ce792014-02-06 18:09:22 -080031
Yingdi Yu348f5ea2014-03-01 14:47:25 -080032ValidatorInvitation::ValidatorInvitation()
33 : Validator()
Yingdi Yufa0b6a02014-04-30 14:26:42 -070034 , m_invitationReplyRule("^([^<CHRONOCHAT-INVITATION>]*)<CHRONOCHAT-INVITATION>",
35 "^([^<KEY>]*)<KEY>(<>*)[<dsk-.*><ksk-.*>]<ID-CERT>$",
Yingdi Yu348f5ea2014-03-01 14:47:25 -080036 "==", "\\1", "\\1\\2", true)
37 , m_invitationInterestRule("^[^<CHRONOCHAT-INVITATION>]*<CHRONOCHAT-INVITATION><>{6}$")
38 , m_innerKeyRegex("^([^<KEY>]*)<KEY>(<>*)[<dsk-.*><ksk-.*>]<ID-CERT><>$", "\\1\\2")
Yingdi Yufa4ce792014-02-06 18:09:22 -080039{
Yingdi Yu348f5ea2014-03-01 14:47:25 -080040}
Yingdi Yufa4ce792014-02-06 18:09:22 -080041
42void
Yingdi Yu0b0a7362014-08-05 16:31:30 -070043ValidatorInvitation::addTrustAnchor(const Name& keyName, const ndn::PublicKey& key)
44{
45 m_trustAnchors[keyName] = key;
46}
47
48void
49ValidatorInvitation::removeTrustAnchor(const Name& keyName)
50{
51 m_trustAnchors.erase(keyName);
52}
53
54void
55ValidatorInvitation::cleanTrustAnchor()
56{
57 m_trustAnchors.clear();
58}
59
60void
Yingdi Yufa0b6a02014-04-30 14:26:42 -070061ValidatorInvitation::checkPolicy (const Data& data,
62 int stepCount,
63 const OnDataValidated& onValidated,
Yingdi Yufa4ce792014-02-06 18:09:22 -080064 const OnDataValidationFailed& onValidationFailed,
Yingdi Yu0b0a7362014-08-05 16:31:30 -070065 vector<shared_ptr<ValidationRequest> >& nextSteps)
Yingdi Yufa4ce792014-02-06 18:09:22 -080066{
Yingdi Yu0b0a7362014-08-05 16:31:30 -070067 const Signature& signature = data.getSignature();
Yingdi Yufa0b6a02014-04-30 14:26:42 -070068
Yingdi Yu0b0a7362014-08-05 16:31:30 -070069 if (signature.getKeyLocator().getType() != KeyLocator::KeyLocator_Name)
70 return onValidationFailed(data.shared_from_this(),
71 "Key Locator is not a name: " + data.getName().toUri());
Yingdi Yu348f5ea2014-03-01 14:47:25 -080072
Yingdi Yu0b0a7362014-08-05 16:31:30 -070073 const Name & keyLocatorName = signature.getKeyLocator().getName();
Yingdi Yufa0b6a02014-04-30 14:26:42 -070074
Yingdi Yu0b0a7362014-08-05 16:31:30 -070075 if (!m_invitationReplyRule.satisfy(data.getName(), keyLocatorName))
76 return onValidationFailed(data.shared_from_this(),
77 "Does not comply with the invitation rule: " +
78 data.getName().toUri() + " signed by: " +
79 keyLocatorName.toUri());
80
81 Data innerData;
82 innerData.wireDecode(data.getContent().blockFromValue());
83
84 return internalCheck(data.wireEncode().value(),
85 data.wireEncode().value_size() - data.getSignature().getValue().size(),
86 signature,
87 keyLocatorName,
88 innerData,
89 bind(onValidated, data.shared_from_this()),
90 bind(onValidationFailed, data.shared_from_this(), _1));
Yingdi Yufa4ce792014-02-06 18:09:22 -080091}
92
93void
Yingdi Yufa0b6a02014-04-30 14:26:42 -070094ValidatorInvitation::checkPolicy (const Interest& interest,
95 int stepCount,
96 const OnInterestValidated& onValidated,
Yingdi Yufa4ce792014-02-06 18:09:22 -080097 const OnInterestValidationFailed& onValidationFailed,
Yingdi Yu0b0a7362014-08-05 16:31:30 -070098 vector<shared_ptr<ValidationRequest> >& nextSteps)
Yingdi Yufa4ce792014-02-06 18:09:22 -080099{
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700100 const Name& interestName = interest.getName();
Yingdi Yufa0b6a02014-04-30 14:26:42 -0700101
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700102 if (!m_invitationInterestRule.match(interestName))
103 return onValidationFailed(interest.shared_from_this(),
104 "Invalid interest name: " + interest.getName().toUri());
Yingdi Yufa4ce792014-02-06 18:09:22 -0800105
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700106 Name signedName = interestName.getPrefix(-1);
Yingdi Yu6a614442014-10-31 17:42:43 -0700107 ndn::Buffer signedBlob = ndn::Buffer(signedName.wireEncode().value(),
108 signedName.wireEncode().value_size());
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800109
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700110 Block signatureBlock = interestName.get(Invitation::SIGNATURE).blockFromValue();
111 Block signatureInfo = interestName.get(Invitation::KEY_LOCATOR).blockFromValue();
112 Signature signature(signatureInfo, signatureBlock);
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800113
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700114 if (signature.getKeyLocator().getType() != KeyLocator::KeyLocator_Name)
115 return onValidationFailed(interest.shared_from_this(),
116 "KeyLocator is not a name: " + interest.getName().toUri());
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800117
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700118 const Name & keyLocatorName = signature.getKeyLocator().getName();
119
120 Data innerData;
121 innerData.wireDecode(interestName.get(Invitation::INVITER_CERT).blockFromValue());
122
123 return internalCheck(signedBlob.buf(), signedBlob.size(),
124 signature,
125 keyLocatorName,
126 innerData,
127 bind(onValidated, interest.shared_from_this()),
128 bind(onValidationFailed, interest.shared_from_this(), _1));
Yingdi Yufa4ce792014-02-06 18:09:22 -0800129}
130
131void
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800132ValidatorInvitation::internalCheck(const uint8_t* buf, size_t size,
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700133 const Signature& signature,
134 const Name& keyLocatorName,
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800135 const Data& innerData,
Yingdi Yufa0b6a02014-04-30 14:26:42 -0700136 const OnValidated& onValidated,
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800137 const OnValidationFailed& onValidationFailed)
138{
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700139 Name signingKeyName = IdentityCertificate::certificateNameToPublicKeyName(keyLocatorName);
Yingdi Yufa0b6a02014-04-30 14:26:42 -0700140
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700141 TrustAnchors::const_iterator keyIt = m_trustAnchors.find(signingKeyName);
142 if (keyIt == m_trustAnchors.end())
143 return onValidationFailed("Cannot reach any trust anchor");
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800144
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700145 if (!Validator::verifySignature(buf, size, signature, keyIt->second))
146 return onValidationFailed("Cannot verify outer signature");
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800147
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700148 // Temporarily disabled, we should get it back when we create a specific key for the chatroom.
149 // if(!Validator::verifySignature(innerData, m_trustAnchors[signingKeyName]))
150 // return onValidationFailed("Cannot verify inner signature");
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800151
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700152 if (!m_innerKeyRegex.match(innerData.getName()) ||
153 m_innerKeyRegex.expand() != signingKeyName.getPrefix(-1))
154 return onValidationFailed("Inner certificate does not comply with the rule");
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800155
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700156 return onValidated();
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800157}
158
Yingdi Yueb692ac2015-02-10 18:46:18 -0800159} // namespace chronochat