blob: 7b07824daa70a5c027dfa457dc5c958de6bb9d54 [file] [log] [blame]
Yingdi Yu9236c432013-10-18 11:29:25 -07001/* -*- 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
11#include "contact-manager.h"
12
Yingdi Yu4685b1b2013-10-18 17:05:02 -070013#ifndef Q_MOC_RUN
Yingdi Yu9236c432013-10-18 11:29:25 -070014#include <ndn.cxx/wrapper/wrapper.h>
15#include <ndn.cxx/security/keychain.h>
16#include <ndn.cxx/security/identity/basic-identity-storage.h>
17#include <ndn.cxx/security/identity/osx-privatekey-storage.h>
18#include <ndn.cxx/security/policy/simple-policy-manager.h>
19#include <ndn.cxx/security/policy/identity-policy-rule.h>
20#include <ndn.cxx/security/cache/ttl-certificate-cache.h>
21#include <ndn.cxx/security/encryption/basic-encryption-manager.h>
Yingdi Yu9236c432013-10-18 11:29:25 -070022#include <fstream>
Yingdi Yuec3d9a32013-10-18 18:35:09 -070023#include "logging.h"
Yingdi Yu4685b1b2013-10-18 17:05:02 -070024#endif
Yingdi Yu9236c432013-10-18 11:29:25 -070025
26using namespace ndn;
27using namespace ndn::security;
28
Yingdi Yuec3d9a32013-10-18 18:35:09 -070029INIT_LOGGER("ContactManager");
30
Yingdi Yu4685b1b2013-10-18 17:05:02 -070031ContactManager::ContactManager(Ptr<ContactStorage> contactStorage,
Yingdi Yuec3d9a32013-10-18 18:35:09 -070032 Ptr<DnsStorage> dnsStorage,
33 QObject* parent)
34 : QObject(parent)
35 , m_contactStorage(contactStorage)
Yingdi Yu4685b1b2013-10-18 17:05:02 -070036 , m_dnsStorage(dnsStorage)
Yingdi Yu9236c432013-10-18 11:29:25 -070037{
Yingdi Yu4685b1b2013-10-18 17:05:02 -070038 setKeychain();
39
40 m_wrapper = Ptr<Wrapper>(new Wrapper(m_keychain));
Yingdi Yu9236c432013-10-18 11:29:25 -070041}
42
43ContactManager::~ContactManager()
44{
45}
46
Yingdi Yu4685b1b2013-10-18 17:05:02 -070047void
Yingdi Yu9236c432013-10-18 11:29:25 -070048ContactManager::setKeychain()
49{
50 Ptr<OSXPrivatekeyStorage> privateStorage = Ptr<OSXPrivatekeyStorage>::Create();
51 Ptr<IdentityManager> identityManager = Ptr<IdentityManager>(new IdentityManager(Ptr<BasicIdentityStorage>::Create(), privateStorage));
52 Ptr<TTLCertificateCache> certificateCache = Ptr<TTLCertificateCache>(new TTLCertificateCache());
53 Ptr<SimplePolicyManager> policyManager = Ptr<SimplePolicyManager>(new SimplePolicyManager(10, certificateCache));
54 Ptr<EncryptionManager> encryptionManager = Ptr<EncryptionManager>(new BasicEncryptionManager(privateStorage, "/tmp/encryption.db"));
55 Ptr<Keychain> keychain = Ptr<Keychain>(new Keychain(identityManager, policyManager, encryptionManager));
56
Yingdi Yu4685b1b2013-10-18 17:05:02 -070057 policyManager->addVerificationPolicyRule(Ptr<IdentityPolicyRule>(new IdentityPolicyRule("^([^<DNS>]*)<DNS><PROFILE>",
58 "^([^<KEY>]*)<KEY>(<>*)<><ID-CERT>",
59 "==", "\\1", "\\1\\2", true)));
Yingdi Yu9236c432013-10-18 11:29:25 -070060 policyManager->addVerificationPolicyRule(Ptr<IdentityPolicyRule>(new IdentityPolicyRule("^([^<PROFILE-CERT>]*)<PROFILE-CERT>",
61 "^([^<KEY>]*)<KEY>(<>*<KSK-.*>)<ID-CERT>",
Yingdi Yu4685b1b2013-10-18 17:05:02 -070062 "==", "\\1", "\\1\\2", true)));
Yingdi Yu9236c432013-10-18 11:29:25 -070063 policyManager->addVerificationPolicyRule(Ptr<IdentityPolicyRule>(new IdentityPolicyRule("^([^<KEY>]*)<KEY>(<>*)<KSK-.*><ID-CERT>",
64 "^([^<KEY>]*)<KEY><DSK-.*><ID-CERT>",
Yingdi Yu4685b1b2013-10-18 17:05:02 -070065 ">", "\\1\\2", "\\1", true)));
Yingdi Yu9236c432013-10-18 11:29:25 -070066 policyManager->addVerificationPolicyRule(Ptr<IdentityPolicyRule>(new IdentityPolicyRule("^([^<KEY>]*)<KEY><DSK-.*><ID-CERT>",
67 "^([^<KEY>]*)<KEY>(<>*)<KSK-.*><ID-CERT>",
Yingdi Yu4685b1b2013-10-18 17:05:02 -070068 "==", "\\1", "\\1\\2", true)));
69
70 policyManager->addSigningPolicyRule(Ptr<IdentityPolicyRule>(new IdentityPolicyRule("^([^<DNS>]*)<DNS><PROFILE>",
71 "^([^<KEY>]*)<KEY>(<>*)<><ID-CERT>",
72 "==", "\\1", "\\1\\2", true)));
Yingdi Yu9236c432013-10-18 11:29:25 -070073
74 ifstream is ("trust-anchor.data", ios::binary);
75 is.seekg (0, ios::end);
76 ifstream::pos_type size = is.tellg();
77 char * memblock = new char [size];
78 is.seekg (0, ios::beg);
79 is.read (memblock, size);
80 is.close();
81
82 Ptr<Blob> readBlob = Ptr<Blob>(new Blob(memblock, size));
83 Ptr<Data> readData = Data::decodeFromWire (readBlob);
84 Ptr<IdentityCertificate> anchor = Ptr<IdentityCertificate>(new IdentityCertificate(*readData));
85 policyManager->addTrustAnchor(anchor);
86
87 delete memblock;
88
Yingdi Yu4685b1b2013-10-18 17:05:02 -070089 m_keychain = keychain;
Yingdi Yu9236c432013-10-18 11:29:25 -070090}
Yingdi Yu4685b1b2013-10-18 17:05:02 -070091
92
93void
94ContactManager::fetchSelfEndorseCertificate(const ndn::Name& identity)
95{
96 Name interestName = identity;
97 interestName.append("DNS").append("PROFILE");
98
99 Ptr<Interest> interestPtr = Ptr<Interest>(new Interest(interestName));
100 Ptr<Closure> closure = Ptr<Closure> (new Closure(boost::bind(&ContactManager::onDnsSelfEndorseCertificateVerified,
101 this,
102 _1,
103 identity),
104 boost::bind(&ContactManager::onDnsSelfEndorseCertificateTimeout,
105 this,
106 _1,
107 _2,
108 identity,
109 0),
110 boost::bind(&ContactManager::onDnsSelfEndorseCertificateUnverified,
111 this,
112 _1,
113 identity)));
114 m_wrapper->sendInterest(interestPtr, closure);
115}
116
117void
118ContactManager::updateProfileData(const Name& identity)
119{
120 // Get current profile;
121 Ptr<Profile> newProfile = m_contactStorage->getSelfProfile(identity);
122 if(NULL == newProfile)
123 return;
124 Ptr<Blob> newProfileBlob = newProfile->toDerBlob();
125
126 // Check if profile exists
127 Ptr<Blob> profileDataBlob = m_contactStorage->getSelfEndorseCertificate(identity);
128 if(NULL != profileDataBlob)
129 {
130 Ptr<Data> plainData = Data::decodeFromWire(profileDataBlob);
131 EndorseCertificate oldEndorseCertificate(*plainData);
132 // _LOG_DEBUG("Certificate converted!");
133 const Blob& oldProfileBlob = oldEndorseCertificate.getProfileData()->content();
134
135 if(oldProfileBlob == *newProfileBlob)
136 return;
137
138 Ptr<EndorseCertificate> newEndorseCertificate = getSignedSelfEndorseCertificate(identity, *newProfile);
139 // _LOG_DEBUG("Signing DONE!");
140 if(NULL == newEndorseCertificate)
141 return;
Yingdi Yuec3d9a32013-10-18 18:35:09 -0700142 _LOG_DEBUG("About to update");
Yingdi Yu4685b1b2013-10-18 17:05:02 -0700143 m_contactStorage->updateSelfEndorseCertificate(newEndorseCertificate, identity);
144
145 publishSelfEndorseCertificateInDNS(newEndorseCertificate);
146 }
147 else
148 {
149 Ptr<EndorseCertificate> newEndorseCertificate = getSignedSelfEndorseCertificate(identity, *newProfile);
150 // _LOG_DEBUG("Signing DONE!");
151 if(NULL == newEndorseCertificate)
152 return;
Yingdi Yuec3d9a32013-10-18 18:35:09 -0700153 _LOG_DEBUG("About to Insert");
Yingdi Yu4685b1b2013-10-18 17:05:02 -0700154 m_contactStorage->addSelfEndorseCertificate(newEndorseCertificate, identity);
155
156 publishSelfEndorseCertificateInDNS(newEndorseCertificate);
157 }
158}
159
160Ptr<EndorseCertificate>
161ContactManager::getSignedSelfEndorseCertificate(const Name& identity,
162 const Profile& profile)
163{
164 Ptr<IdentityManager> identityManager = m_keychain->getIdentityManager();
165 Name certificateName = identityManager->getDefaultCertificateNameByIdentity(identity);
166 if(0 == certificateName.size())
167 return NULL;
168
169 Ptr<ProfileData> profileData = Ptr<ProfileData>(new ProfileData(identity, profile));
170 identityManager->signByCertificate(*profileData, certificateName);
171
172 Ptr<security::IdentityCertificate> dskCert = identityManager->getCertificate(certificateName);
173 Ptr<const signature::Sha256WithRsa> dskCertSig = DynamicCast<const signature::Sha256WithRsa>(dskCert->getSignature());
174 // HACK! KSK certificate should be retrieved from network.
175 Ptr<security::IdentityCertificate> kskCert = identityManager->getCertificate(dskCertSig->getKeyLocator().getKeyName());
176
177 vector<string> endorseList;
178 Profile::const_iterator it = profile.begin();
179 for(; it != profile.end(); it++)
180 endorseList.push_back(it->first);
181
182 Ptr<EndorseCertificate> selfEndorseCertificate = Ptr<EndorseCertificate>(new EndorseCertificate(*kskCert,
183 kskCert->getNotBefore(),
184 kskCert->getNotAfter(),
185 profileData,
186 endorseList));
187 identityManager->signByCertificate(*selfEndorseCertificate, kskCert->getName());
188
189 return selfEndorseCertificate;
190}
191
192
193void
194ContactManager::onDnsSelfEndorseCertificateVerified(Ptr<Data> data, const Name& identity)
195{
196 const Blob& dataContentBlob = data->content();
197
198 boost::iostreams::stream
199 <boost::iostreams::array_source> is (dataContentBlob.buf(), dataContentBlob.size());
200
201 Ptr<Data> plainData = Data::decodeFromWire(is);
202 Ptr<EndorseCertificate> selfEndorseCertificate = Ptr<EndorseCertificate>(new EndorseCertificate(*plainData));
203
204 const security::Publickey& ksk = selfEndorseCertificate->getPublicKeyInfo();
205 if(security::PolicyManager::verifySignature(*plainData, ksk))
206 emit contactFetched (selfEndorseCertificate);
207 else
208 emit contactFetchFailed (identity);
209}
210
211void
212ContactManager::onDnsSelfEndorseCertificateUnverified(Ptr<Data> data, const Name& identity)
213{ emit contactFetchFailed (identity); }
214
215void
216ContactManager::onDnsSelfEndorseCertificateTimeout(Ptr<Closure> closure, Ptr<Interest> interest, const Name& identity, int retry)
217{
218 if(retry > 0)
219 {
220 Ptr<Closure> newClosure = Ptr<Closure>(new Closure(closure->m_dataCallback,
221 boost::bind(&ContactManager::onDnsSelfEndorseCertificateTimeout,
222 this,
223 _1,
224 _2,
225 identity,
226 retry - 1),
227 closure->m_unverifiedCallback,
228 closure->m_stepCount)
229 );
230 m_wrapper->sendInterest(interest, newClosure);
231 }
232 else
233 emit contactFetchFailed(identity);
234}
235
236void
237ContactManager::publishSelfEndorseCertificateInDNS(Ptr<EndorseCertificate> selfEndorseCertificate)
238{
239 Ptr<Data> data = Ptr<Data>::Create();
240
241 Name keyName = selfEndorseCertificate->getPublicKeyName();
242 Name identity = keyName.getSubName(0, keyName.size()-1);
243
244 TimeInterval ti = time::NowUnixTimestamp();
245 ostringstream oss;
246 oss << ti.total_seconds();
247
248 Name dnsName = identity;
249 dnsName.append("DNS").append("PROFILE").append(oss.str());
250
251 data->setName(dnsName);
252 Ptr<Blob> blob = selfEndorseCertificate->encodeToWire();
253 Content content(blob->buf(), blob->size());
254 data->setContent(content);
255
256 m_keychain->signByIdentity(*data, identity);
Yingdi Yuec3d9a32013-10-18 18:35:09 -0700257
258 m_dnsStorage->updateDnsSelfProfileData(*data, identity);
Yingdi Yu4685b1b2013-10-18 17:05:02 -0700259
260 Ptr<Blob> dnsBlob = data->encodeToWire();
261
262 m_wrapper->putToCcnd(*dnsBlob);
263}
264
265
266#if WAF
267#include "contact-manager.moc"
268#include "contact-manager.cpp.moc"
269#endif