blob: 3b53e26ca42a9b48d6de7b5db123d62fc3483210 [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 Yufa4ce792014-02-06 18:09:22 -080016using namespace ndn;
17
Yingdi Yu0b0a7362014-08-05 16:31:30 -070018namespace chronos {
Yingdi Yufa4ce792014-02-06 18:09:22 -080019
Yingdi Yu0b0a7362014-08-05 16:31:30 -070020using std::vector;
Yingdi Yufa4ce792014-02-06 18:09:22 -080021
Yingdi Yu0b0a7362014-08-05 16:31:30 -070022using ndn::CertificateCache;
23using ndn::SecRuleRelative;
24using ndn::OnDataValidated;
25using ndn::OnDataValidationFailed;
26using ndn::OnInterestValidated;
27using ndn::OnInterestValidationFailed;
28using ndn::ValidationRequest;
29using ndn::IdentityCertificate;
Yingdi Yu17032f82014-03-25 15:48:23 -070030
Yingdi Yu0b0a7362014-08-05 16:31:30 -070031const shared_ptr<CertificateCache> ValidatorInvitation::DefaultCertificateCache =
32 shared_ptr<CertificateCache>();
Yingdi Yufa4ce792014-02-06 18:09:22 -080033
Yingdi Yu348f5ea2014-03-01 14:47:25 -080034ValidatorInvitation::ValidatorInvitation()
35 : Validator()
Yingdi Yufa0b6a02014-04-30 14:26:42 -070036 , m_invitationReplyRule("^([^<CHRONOCHAT-INVITATION>]*)<CHRONOCHAT-INVITATION>",
37 "^([^<KEY>]*)<KEY>(<>*)[<dsk-.*><ksk-.*>]<ID-CERT>$",
Yingdi Yu348f5ea2014-03-01 14:47:25 -080038 "==", "\\1", "\\1\\2", true)
39 , m_invitationInterestRule("^[^<CHRONOCHAT-INVITATION>]*<CHRONOCHAT-INVITATION><>{6}$")
40 , m_innerKeyRegex("^([^<KEY>]*)<KEY>(<>*)[<dsk-.*><ksk-.*>]<ID-CERT><>$", "\\1\\2")
Yingdi Yufa4ce792014-02-06 18:09:22 -080041{
Yingdi Yu348f5ea2014-03-01 14:47:25 -080042}
Yingdi Yufa4ce792014-02-06 18:09:22 -080043
44void
Yingdi Yu0b0a7362014-08-05 16:31:30 -070045ValidatorInvitation::addTrustAnchor(const Name& keyName, const ndn::PublicKey& key)
46{
47 m_trustAnchors[keyName] = key;
48}
49
50void
51ValidatorInvitation::removeTrustAnchor(const Name& keyName)
52{
53 m_trustAnchors.erase(keyName);
54}
55
56void
57ValidatorInvitation::cleanTrustAnchor()
58{
59 m_trustAnchors.clear();
60}
61
62void
Yingdi Yufa0b6a02014-04-30 14:26:42 -070063ValidatorInvitation::checkPolicy (const Data& data,
64 int stepCount,
65 const OnDataValidated& onValidated,
Yingdi Yufa4ce792014-02-06 18:09:22 -080066 const OnDataValidationFailed& onValidationFailed,
Yingdi Yu0b0a7362014-08-05 16:31:30 -070067 vector<shared_ptr<ValidationRequest> >& nextSteps)
Yingdi Yufa4ce792014-02-06 18:09:22 -080068{
Yingdi Yu0b0a7362014-08-05 16:31:30 -070069 const Signature& signature = data.getSignature();
Yingdi Yufa0b6a02014-04-30 14:26:42 -070070
Yingdi Yu0b0a7362014-08-05 16:31:30 -070071 if (signature.getKeyLocator().getType() != KeyLocator::KeyLocator_Name)
72 return onValidationFailed(data.shared_from_this(),
73 "Key Locator is not a name: " + data.getName().toUri());
Yingdi Yu348f5ea2014-03-01 14:47:25 -080074
Yingdi Yu0b0a7362014-08-05 16:31:30 -070075 const Name & keyLocatorName = signature.getKeyLocator().getName();
Yingdi Yufa0b6a02014-04-30 14:26:42 -070076
Yingdi Yu0b0a7362014-08-05 16:31:30 -070077 if (!m_invitationReplyRule.satisfy(data.getName(), keyLocatorName))
78 return onValidationFailed(data.shared_from_this(),
79 "Does not comply with the invitation rule: " +
80 data.getName().toUri() + " signed by: " +
81 keyLocatorName.toUri());
82
83 Data innerData;
84 innerData.wireDecode(data.getContent().blockFromValue());
85
86 return internalCheck(data.wireEncode().value(),
87 data.wireEncode().value_size() - data.getSignature().getValue().size(),
88 signature,
89 keyLocatorName,
90 innerData,
91 bind(onValidated, data.shared_from_this()),
92 bind(onValidationFailed, data.shared_from_this(), _1));
Yingdi Yufa4ce792014-02-06 18:09:22 -080093}
94
95void
Yingdi Yufa0b6a02014-04-30 14:26:42 -070096ValidatorInvitation::checkPolicy (const Interest& interest,
97 int stepCount,
98 const OnInterestValidated& onValidated,
Yingdi Yufa4ce792014-02-06 18:09:22 -080099 const OnInterestValidationFailed& onValidationFailed,
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700100 vector<shared_ptr<ValidationRequest> >& nextSteps)
Yingdi Yufa4ce792014-02-06 18:09:22 -0800101{
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700102 const Name& interestName = interest.getName();
Yingdi Yufa0b6a02014-04-30 14:26:42 -0700103
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700104 if (!m_invitationInterestRule.match(interestName))
105 return onValidationFailed(interest.shared_from_this(),
106 "Invalid interest name: " + interest.getName().toUri());
Yingdi Yufa4ce792014-02-06 18:09:22 -0800107
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700108 Name signedName = interestName.getPrefix(-1);
109 Buffer signedBlob = Buffer(signedName.wireEncode().value(),
110 signedName.wireEncode().value_size());
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800111
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700112 Block signatureBlock = interestName.get(Invitation::SIGNATURE).blockFromValue();
113 Block signatureInfo = interestName.get(Invitation::KEY_LOCATOR).blockFromValue();
114 Signature signature(signatureInfo, signatureBlock);
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800115
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700116 if (signature.getKeyLocator().getType() != KeyLocator::KeyLocator_Name)
117 return onValidationFailed(interest.shared_from_this(),
118 "KeyLocator is not a name: " + interest.getName().toUri());
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800119
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700120 const Name & keyLocatorName = signature.getKeyLocator().getName();
121
122 Data innerData;
123 innerData.wireDecode(interestName.get(Invitation::INVITER_CERT).blockFromValue());
124
125 return internalCheck(signedBlob.buf(), signedBlob.size(),
126 signature,
127 keyLocatorName,
128 innerData,
129 bind(onValidated, interest.shared_from_this()),
130 bind(onValidationFailed, interest.shared_from_this(), _1));
Yingdi Yufa4ce792014-02-06 18:09:22 -0800131}
132
133void
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800134ValidatorInvitation::internalCheck(const uint8_t* buf, size_t size,
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700135 const Signature& signature,
136 const Name& keyLocatorName,
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800137 const Data& innerData,
Yingdi Yufa0b6a02014-04-30 14:26:42 -0700138 const OnValidated& onValidated,
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800139 const OnValidationFailed& onValidationFailed)
140{
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700141 Name signingKeyName = IdentityCertificate::certificateNameToPublicKeyName(keyLocatorName);
Yingdi Yufa0b6a02014-04-30 14:26:42 -0700142
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700143 TrustAnchors::const_iterator keyIt = m_trustAnchors.find(signingKeyName);
144 if (keyIt == m_trustAnchors.end())
145 return onValidationFailed("Cannot reach any trust anchor");
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800146
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700147 if (!Validator::verifySignature(buf, size, signature, keyIt->second))
148 return onValidationFailed("Cannot verify outer signature");
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800149
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700150 // Temporarily disabled, we should get it back when we create a specific key for the chatroom.
151 // if(!Validator::verifySignature(innerData, m_trustAnchors[signingKeyName]))
152 // return onValidationFailed("Cannot verify inner signature");
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800153
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700154 if (!m_innerKeyRegex.match(innerData.getName()) ||
155 m_innerKeyRegex.expand() != signingKeyName.getPrefix(-1))
156 return onValidationFailed("Inner certificate does not comply with the rule");
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800157
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700158 return onValidated();
Yingdi Yu348f5ea2014-03-01 14:47:25 -0800159}
160
Yingdi Yu0b0a7362014-08-05 16:31:30 -0700161} // namespace chronos