blob: 3eb8ac151eebd23e501347338fb3c46b6ad25ed8 [file] [log] [blame]
Yingdi Yud04ed1a2013-10-14 14:07:03 -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-storage.h"
12#include "exception.h"
13
14#include <string>
15#include <boost/filesystem.hpp>
Yingdi Yu3b318c12013-10-15 17:54:00 -070016#include "logging.h"
Yingdi Yud04ed1a2013-10-14 14:07:03 -070017
18using namespace std;
19using namespace ndn;
20namespace fs = boost::filesystem;
21
Yingdi Yu3b318c12013-10-15 17:54:00 -070022INIT_LOGGER ("ContactStorage");
23
24const string INIT_SP_TABLE = "\
25CREATE TABLE IF NOT EXISTS \n \
26 SelfProfile( \n \
27 profile_id INTEGER PRIMARY KEY AUTOINCREMENT, \n \
28 profile_type BLOB NOT NULL, \n \
29 profile_value BLOB NOT NULL \n \
30 ); \n \
31 \
32CREATE INDEX sp_index ON SelfProfile(profile_type); \n \
33";
34
35const string INIT_PD_TABLE = "\
36CREATE TABLE IF NOT EXISTS \n \
37 ProfileData( \n \
38 identity BLOB NOT NULL UNIQUE, \n \
39 profile_data BLOB NOT NULL, \n \
40 \
41 PRIMARY KEY (identity) \n \
42 ); \n \
43CREATE INDEX pd_index ON ProfileData(identity); \n \
44";
Yingdi Yud04ed1a2013-10-14 14:07:03 -070045
46const string INIT_TC_TABLE = "\
47CREATE TABLE IF NOT EXISTS \n \
48 TrustedContact( \n \
49 contact_namespace BLOB NOT NULL, \n \
50 contact_alias BLOB NOT NULL, \n \
51 self_certificate BLOB NOT NULL, \n \
52 trust_scope BLOB NOT NULL, \n \
53 \
54 PRIMARY KEY (contact_namespace) \n \
55 ); \n \
56 \
57CREATE INDEX tc_index ON TrustedContact(contact_namespace); \n \
58";
59
60const string INIT_NC_TABLE = "\
61CREATE TABLE IF NOT EXISTS \n \
62 NormalContact( \n \
63 contact_namespace BLOB NOT NULL, \n \
64 contact_alias BLOB NOT NULL, \n \
65 self_certificate BLOB NOT NULL, \n \
66 \
67 PRIMARY KEY (contact_namespace) \n \
68 ); \n \
69 \
70CREATE INDEX nc_index ON NormalContact(contact_namespace); \n \
71";
72
Yingdi Yu3b318c12013-10-15 17:54:00 -070073ContactStorage::ContactStorage(Ptr<security::IdentityManager> identityManager)
74 : m_identityManager(identityManager)
Yingdi Yud04ed1a2013-10-14 14:07:03 -070075{
76 fs::path chronosDir = fs::path(getenv("HOME")) / ".chronos";
77 fs::create_directories (chronosDir);
78
79 int res = sqlite3_open((chronosDir / "chronos.db").c_str (), &m_db);
80 if (res != SQLITE_OK)
81 throw LnException("Chronos DB cannot be open/created");
82
Yingdi Yu3b318c12013-10-15 17:54:00 -070083 // Check if SelfProfile table exists
Yingdi Yud04ed1a2013-10-14 14:07:03 -070084 sqlite3_stmt *stmt;
Yingdi Yu3b318c12013-10-15 17:54:00 -070085 sqlite3_prepare_v2 (m_db, "SELECT name FROM sqlite_master WHERE type='table' And name='SelfProfile'", -1, &stmt, 0);
86 res = sqlite3_step (stmt);
87
88 bool spTableExist = false;
89 if (res == SQLITE_ROW)
90 spTableExist = true;
91 sqlite3_finalize (stmt);
92
93 if(!spTableExist)
94 {
95 char *errmsg = 0;
96 res = sqlite3_exec (m_db, INIT_SP_TABLE.c_str (), NULL, NULL, &errmsg);
97 if (res != SQLITE_OK && errmsg != 0)
98 throw LnException("Init \"error\" in SelfProfile");
99 }
100
101 // Check if ProfileData table exists
102 sqlite3_prepare_v2 (m_db, "SELECT name FROM sqlite_master WHERE type='table' And name='ProfileData'", -1, &stmt, 0);
103 res = sqlite3_step (stmt);
104
105 bool pdTableExist = false;
106 if (res == SQLITE_ROW)
107 pdTableExist = true;
108 sqlite3_finalize (stmt);
109
110 if(!pdTableExist)
111 {
112 char *errmsg = 0;
113 res = sqlite3_exec (m_db, INIT_PD_TABLE.c_str (), NULL, NULL, &errmsg);
114 if (res != SQLITE_OK && errmsg != 0)
115 throw LnException("Init \"error\" in ProfileData");
116 }
117
118
119 // Check if TrustedContact table exists
Yingdi Yud04ed1a2013-10-14 14:07:03 -0700120 sqlite3_prepare_v2 (m_db, "SELECT name FROM sqlite_master WHERE type='table' And name='TrustedContact'", -1, &stmt, 0);
121 res = sqlite3_step (stmt);
122
123 bool tcTableExist = false;
124 if (res == SQLITE_ROW)
125 tcTableExist = true;
126 sqlite3_finalize (stmt);
127
128 if(!tcTableExist)
129 {
130 char *errmsg = 0;
131 res = sqlite3_exec (m_db, INIT_TC_TABLE.c_str (), NULL, NULL, &errmsg);
132 if (res != SQLITE_OK && errmsg != 0)
133 throw LnException("Init \"error\" in TrustedContact");
Yingdi Yud04ed1a2013-10-14 14:07:03 -0700134 }
135
136 // Check if NormalContact table exists
137 sqlite3_prepare_v2 (m_db, "SELECT name FROM sqlite_master WHERE type='table' And name='NormalContact'", -1, &stmt, 0);
138 res = sqlite3_step (stmt);
139
140 bool ncTableExist = false;
141 if (res == SQLITE_ROW)
142 ncTableExist = true;
143 sqlite3_finalize (stmt);
144
145 if(!ncTableExist)
146 {
147 char *errmsg = 0;
148 res = sqlite3_exec (m_db, INIT_NC_TABLE.c_str (), NULL, NULL, &errmsg);
149
150 if (res != SQLITE_OK && errmsg != 0)
151 throw LnException("Init \"error\" in NormalContact");
152 }
153}
154
Yingdi Yu3b318c12013-10-15 17:54:00 -0700155bool
156ContactStorage::doesSelfEntryExist(const string& profileType)
157{
158 bool result = false;
159
160 sqlite3_stmt *stmt;
161 sqlite3_prepare_v2 (m_db, "SELECT count(*) FROM SelfProfile WHERE profile_type=?", -1, &stmt, 0);
162 sqlite3_bind_text(stmt, 1, profileType.c_str(), profileType.size(), SQLITE_TRANSIENT);
163
164 int res = sqlite3_step (stmt);
165
166 if (res == SQLITE_ROW)
167 {
168 int countAll = sqlite3_column_int (stmt, 0);
169 if (countAll > 0)
170 result = true;
171 }
172 sqlite3_finalize (stmt);
173 return result;
174}
175
176void
177ContactStorage::setSelfProfileIdentity(const Name& identity)
178{
179 string profileType("IDENTITY");
180 Blob identityBlob(identity.toUri().c_str(), identity.toUri().size());
181
182 sqlite3_stmt *stmt;
183 if(doesSelfEntryExist(profileType))
184 {
185 sqlite3_prepare_v2 (m_db, "UPDATE SelfProfile SET profile_value=? WHERE profile_type=?", -1, &stmt, 0);
186 sqlite3_bind_text(stmt, 1, identityBlob.buf(), identityBlob.size(), SQLITE_TRANSIENT);
187 sqlite3_bind_text(stmt, 2, profileType.c_str(), profileType.size(), SQLITE_TRANSIENT);
188 }
189 else
190 {
191 sqlite3_prepare_v2 (m_db, "INSERT INTO SelfProfile (profile_type, profile_value) values (?, ?)", -1, &stmt, 0);
192 sqlite3_bind_text(stmt, 1, profileType.c_str(), profileType.size(), SQLITE_TRANSIENT);
193 sqlite3_bind_text(stmt, 2, identityBlob.buf(), identityBlob.size(), SQLITE_TRANSIENT);
194 }
195 sqlite3_step (stmt);
196 sqlite3_finalize (stmt);
197}
198
199void
200ContactStorage::setSelfProfileEntry(const string& profileType, const Blob& profileValue)
201{
202 if(profileType == string("IDENTITY"))
203 return;
204
205 sqlite3_stmt *stmt;
206 if(doesSelfEntryExist(profileType))
207 {
208 sqlite3_prepare_v2 (m_db, "UPDATE SelfProfile SET profile_value=? WHERE profile_type=?", -1, &stmt, 0);
209 sqlite3_bind_text(stmt, 1, profileValue.buf(), profileValue.size(), SQLITE_TRANSIENT);
210 sqlite3_bind_text(stmt, 2, profileType.c_str(), profileType.size(), SQLITE_TRANSIENT);
211 }
212 else
213 {
214 sqlite3_prepare_v2 (m_db, "INSERT INTO SelfProfile (profile_type, profile_value) values (?, ?)", -1, &stmt, 0);
215 sqlite3_bind_text(stmt, 1, profileType.c_str(), profileType.size(), SQLITE_TRANSIENT);
216 sqlite3_bind_text(stmt, 2, profileValue.buf(), profileValue.size(), SQLITE_TRANSIENT);
217 }
218 sqlite3_step (stmt);
219 sqlite3_finalize (stmt);
220}
221
222Ptr<Profile>
223ContactStorage::getSelfProfile()
224{
225 string idString("IDENTITY");
226 sqlite3_stmt *stmt;
227 sqlite3_prepare_v2(m_db, "SELECT profile_value FROM SelfProfile WHERE profile_type=?", -1, &stmt, 0);
228 sqlite3_bind_text(stmt, 1, idString.c_str(), idString.size(), SQLITE_TRANSIENT);
229
230 Name nameSpace;
231 int res = sqlite3_step (stmt);
232 if (res == SQLITE_ROW)
233 nameSpace.append(string(reinterpret_cast<const char *>(sqlite3_column_text(stmt, 0)), sqlite3_column_bytes (stmt, 0)));
234
235 Ptr<Profile> profile = Ptr<Profile>(new Profile(nameSpace));
236
237 sqlite3_prepare_v2(m_db, "SELECT profile_type, profile_value FROM SelfProfile WHERE profile_type!=?", -1, &stmt, 0);
238 sqlite3_bind_text(stmt, 1, idString.c_str(), idString.size(), SQLITE_TRANSIENT);
239
240 while( sqlite3_step (stmt) == SQLITE_ROW)
241 {
242 string profileType(reinterpret_cast<const char *>(sqlite3_column_text(stmt, 0)), sqlite3_column_bytes (stmt, 0));
243 Blob profileValue(reinterpret_cast<const char *>(sqlite3_column_text(stmt, 1)), sqlite3_column_bytes (stmt, 1));
244
245 profile->setProfileEntry(profileType, profileValue );
246 }
247
248 return profile;
249}
250
Yingdi Yud04ed1a2013-10-14 14:07:03 -0700251void
252ContactStorage::addTrustedContact(const TrustedContact& trustedContact)
253{
254 if(doesTrustedContactExist(trustedContact.getNameSpace()))
255 throw LnException("Trusted Contact has already existed");
256
257 sqlite3_stmt *stmt;
258 sqlite3_prepare_v2 (m_db,
259 "INSERT INTO TrustedContact (contact_namespace, contact_alias, self_certificate, trust_scope) values (?, ?, ?, ?)",
260 -1,
261 &stmt,
262 0);
263
264 sqlite3_bind_text(stmt, 1, trustedContact.getNameSpace().toUri().c_str(), trustedContact.getNameSpace().toUri().size (), SQLITE_TRANSIENT);
265 sqlite3_bind_text(stmt, 2, trustedContact.getAlias().c_str(), trustedContact.getAlias().size(), SQLITE_TRANSIENT);
266 Ptr<Blob> selfCertificateBlob = trustedContact.getSelfEndorseCertificate().encodeToWire();
267 sqlite3_bind_text(stmt, 3, selfCertificateBlob->buf(), selfCertificateBlob->size(), SQLITE_TRANSIENT);
268 Ptr<Blob> trustScopeBlob = trustedContact.getTrustScopeBlob();
269 sqlite3_bind_text(stmt, 4, trustScopeBlob->buf(), trustScopeBlob->size(),SQLITE_TRANSIENT);
270
271 int res = sqlite3_step (stmt);
272 sqlite3_finalize (stmt);
273}
274
275void
276ContactStorage::addNormalContact(const ContactItem& normalContact)
277{
278 if(doesNormalContactExist(normalContact.getNameSpace()))
279 throw LnException("Normal Contact has already existed");
280
281 sqlite3_stmt *stmt;
282 sqlite3_prepare_v2 (m_db,
283 "INSERT INTO NormalContact (contact_namespace, contact_alias, self_certificate) values (?, ?, ?)",
284 -1,
285 &stmt,
286 0);
287
288 sqlite3_bind_text(stmt, 1, normalContact.getNameSpace().toUri().c_str(), normalContact.getNameSpace().toUri().size (), SQLITE_TRANSIENT);
289 sqlite3_bind_text(stmt, 2, normalContact.getAlias().c_str(), normalContact.getAlias().size(), SQLITE_TRANSIENT);
290 Ptr<Blob> selfCertificateBlob = normalContact.getSelfEndorseCertificate().encodeToWire();
291 sqlite3_bind_text(stmt, 3, selfCertificateBlob->buf(), selfCertificateBlob->size(), SQLITE_TRANSIENT);
292
293 int res = sqlite3_step (stmt);
294 sqlite3_finalize (stmt);
295}
296
297bool
298ContactStorage::doesContactExist(const Name& name, bool normal)
299{
300 bool result = false;
301
302 sqlite3_stmt *stmt;
303 if(normal)
304 sqlite3_prepare_v2 (m_db, "SELECT count(*) FROM NormalContact WHERE contact_namespace=?", -1, &stmt, 0);
305 else
306 sqlite3_prepare_v2 (m_db, "SELECT count(*) FROM TrustedContact WHERE contact_namespace=?", -1, &stmt, 0);
307 sqlite3_bind_text(stmt, 1, name.toUri().c_str(), name.toUri().size(), SQLITE_TRANSIENT);
308
309 int res = sqlite3_step (stmt);
310
311 if (res == SQLITE_ROW)
312 {
313 int countAll = sqlite3_column_int (stmt, 0);
314 if (countAll > 0)
315 result = true;
316 }
317 sqlite3_finalize (stmt);
318 return result;
319}
320
321vector<Ptr<TrustedContact> >
322ContactStorage::getAllTrustedContacts() const
323{
324 vector<Ptr<TrustedContact> > trustedContacts;
325
326 sqlite3_stmt *stmt;
327 sqlite3_prepare_v2 (m_db,
328 "SELECT contact_alias, self_certificate, trust_scope FROM TrustedContact",
329 -1,
330 &stmt,
331 0);
332
333 while( sqlite3_step (stmt) == SQLITE_ROW)
334 {
335 string alias(reinterpret_cast<const char *>(sqlite3_column_text(stmt, 0)), sqlite3_column_bytes (stmt, 0));
336 Ptr<Blob> certBlob = Ptr<Blob>(new Blob(reinterpret_cast<const char *>(sqlite3_column_text(stmt, 1)), sqlite3_column_bytes (stmt, 1)));
337 Ptr<Data> certData = Data::decodeFromWire(certBlob);
338 EndorseCertificate endorseCertificate(*certData);
339 string trustScope(reinterpret_cast<const char *>(sqlite3_column_text(stmt, 2)), sqlite3_column_bytes (stmt, 2));
340
341 trustedContacts.push_back(Ptr<TrustedContact>(new TrustedContact(endorseCertificate, trustScope, alias)));
342 }
343
344 return trustedContacts;
345}
346
347vector<Ptr<ContactItem> >
348ContactStorage::getAllNormalContacts() const
349{
350 vector<Ptr<ContactItem> > normalContacts;
351
352 sqlite3_stmt *stmt;
353 sqlite3_prepare_v2 (m_db,
354 "SELECT contact_alias, self_certificate FROM NormalContact",
355 -1,
356 &stmt,
357 0);
358
359 while( sqlite3_step (stmt) == SQLITE_ROW)
360 {
361 string alias(reinterpret_cast<const char *>(sqlite3_column_text(stmt, 0)), sqlite3_column_bytes (stmt, 0));
362 Ptr<Blob> certBlob = Ptr<Blob>(new Blob(reinterpret_cast<const char *>(sqlite3_column_text(stmt, 1)), sqlite3_column_bytes (stmt, 1)));
363 Ptr<Data> certData = Data::decodeFromWire(certBlob);
364 EndorseCertificate endorseCertificate(*certData);
365
366 normalContacts.push_back(Ptr<ContactItem>(new ContactItem(endorseCertificate, alias)));
367 }
368
369 return normalContacts;
370}
Yingdi Yu3b318c12013-10-15 17:54:00 -0700371
372void
373ContactStorage::updateProfileData() const
374{
375 sqlite3_stmt *stmt;
376 sqlite3_prepare_v2 (m_db, "SELECT identity, profile_data FROM ProfileData", -1, &stmt, 0);
377
378 if(sqlite3_step (stmt) != SQLITE_ROW)
379 {
380 sqlite3_finalize (stmt);
381 return;
382 }
383
384 Name identity(string(reinterpret_cast<const char *>(sqlite3_column_text(stmt, 0)), sqlite3_column_bytes (stmt, 0)));
385
386 Ptr<Blob> profileDataBlob = Ptr<Blob>(new Blob(reinterpret_cast<const char *>(sqlite3_column_text(stmt, 1)), sqlite3_column_bytes (stmt, 1)));
387 Ptr<Data> plainData = Data::decodeFromWire(profileDataBlob);
388 const Blob& oldProfileBlob = plainData->content();
389 sqlite3_finalize (stmt);
390
391 Ptr<Profile> newProfile = getSelfProfile();
392 if(NULL == newProfile)
393 return;
394 Ptr<Blob> newProfileBlob = newProfile->toDerBlob();
395
396 if(oldProfileBlob == *newProfileBlob)
397 return;
398
399 string idString("IDENTITY");
400 Ptr<const Blob> identityBlob = newProfile->getProfileEntry(idString);
401 Name newIdentity(string(identityBlob->buf(), identityBlob->size()));
402
403 Ptr<ProfileData> newProfileData = getSignedSelfProfileData(newIdentity, *newProfile);
404 Ptr<Blob> newProfileDataBlob = newProfileData->encodeToWire();
405
406 if(identity == newIdentity)
407 {
408 sqlite3_prepare_v2 (m_db, "UPDATE ProfileData SET profile_data=? WHERE identity=?", -1, &stmt, 0);
409 sqlite3_bind_text(stmt, 1, newProfileDataBlob->buf(), newProfileDataBlob->size(), SQLITE_TRANSIENT);
410 sqlite3_bind_text(stmt, 2, newIdentity.toUri().c_str(), newIdentity.toUri().size(), SQLITE_TRANSIENT);
411 }
412 else
413 {
414 sqlite3_prepare_v2 (m_db, "INSERT INTO ProfileData (identity, profile_data) values (?, ?)", -1, &stmt, 0);
415 sqlite3_bind_text(stmt, 2, newIdentity.toUri().c_str(), newIdentity.toUri().size(), SQLITE_TRANSIENT);
416 sqlite3_bind_text(stmt, 1, newProfileDataBlob->buf(), newProfileDataBlob->size(), SQLITE_TRANSIENT);
417 }
418}
419
420Ptr<Profile>
421ContactStorage::getSelfProfile() const
422{
423 string idString("IDENTITY");
424
425 sqlite3_stmt *stmt;
426 sqlite3_prepare_v2 (m_db, "SELECT profile_value FROM SelfProfile WHERE profile_type=?", -1, &stmt, 0);
427 sqlite3_bind_text(stmt, 1, idString.c_str(), idString.size(), SQLITE_TRANSIENT);
428
429 if(sqlite3_step (stmt) != SQLITE_ROW)
430 {
431 sqlite3_finalize (stmt);
432 return NULL;
433 }
434
435 Name identity(string(reinterpret_cast<const char *>(sqlite3_column_text(stmt, 0)), sqlite3_column_bytes (stmt, 0)));
436
437 Ptr<Profile> profile = Ptr<Profile>(new Profile(identity));
438 sqlite3_finalize (stmt);
439
440 sqlite3_prepare_v2 (m_db, "SELECT profile_type, profile_value FROM SelfProfile WHERE profile_type!=? and profile_type!=?", -1, &stmt, 0);
441 sqlite3_bind_text(stmt, 1, idString.c_str(), idString.size(), SQLITE_TRANSIENT);
442
443 while( sqlite3_step (stmt) == SQLITE_ROW)
444 {
445 string profileType(reinterpret_cast<const char *>(sqlite3_column_text(stmt, 0)), sqlite3_column_bytes (stmt, 0));
446 Blob profileValue(reinterpret_cast<const char *>(sqlite3_column_text(stmt, 1)), sqlite3_column_bytes (stmt, 1));
447 profile->setProfileEntry(profileType, profileValue);
448 }
449
450 return profile;
451}
452
453Ptr<ProfileData>
454ContactStorage::getSignedSelfProfileData(const Name& identity,
455 const Profile& profile) const
456{
457 Name certificateName = m_identityManager->getDefaultCertificateNameByIdentity(identity);
458 Ptr<ProfileData> profileData = Ptr<ProfileData>(new ProfileData(identity, profile));
459 m_identityManager->signByCertificate(*profileData, certificateName);
460
461 return profileData;
462}
463