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