blob: 989702a846f43f555674be7a36c371ff0413dc3b [file] [log] [blame]
Yingdi Yuede8eaf2013-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
Yingdi Yuede8eaf2013-10-14 14:07:03 -070014#include <boost/filesystem.hpp>
Yingdi Yu68aced92013-10-17 21:13:03 -070015#include <ndn.cxx/fields/signature-sha256-with-rsa.h>
Yingdi Yu0a6b6c52013-10-15 17:54:00 -070016#include "logging.h"
Yingdi Yuede8eaf2013-10-14 14:07:03 -070017
18using namespace std;
19using namespace ndn;
20namespace fs = boost::filesystem;
21
Yingdi Yu0a6b6c52013-10-15 17:54:00 -070022INIT_LOGGER ("ContactStorage");
23
24const string INIT_SP_TABLE = "\
25CREATE TABLE IF NOT EXISTS \n \
26 SelfProfile( \n \
Yingdi Yu49eea9f2013-10-17 15:07:17 -070027 profile_identity BLOB NOT NULL, \n \
Yingdi Yu0a6b6c52013-10-15 17:54:00 -070028 profile_type BLOB NOT NULL, \n \
Yingdi Yu49eea9f2013-10-17 15:07:17 -070029 profile_value BLOB NOT NULL, \n \
30 \
31 PRIMARY KEY (profile_identity, profile_type) \n \
Yingdi Yu0a6b6c52013-10-15 17:54:00 -070032 ); \n \
33 \
Yingdi Yu49eea9f2013-10-17 15:07:17 -070034CREATE INDEX sp_index ON SelfProfile(profile_identity,profile_type); \n \
Yingdi Yu0a6b6c52013-10-15 17:54:00 -070035";
36
37const string INIT_PD_TABLE = "\
38CREATE TABLE IF NOT EXISTS \n \
39 ProfileData( \n \
40 identity BLOB NOT NULL UNIQUE, \n \
41 profile_data BLOB NOT NULL, \n \
42 \
43 PRIMARY KEY (identity) \n \
44 ); \n \
45CREATE INDEX pd_index ON ProfileData(identity); \n \
46";
Yingdi Yuede8eaf2013-10-14 14:07:03 -070047
48const string INIT_TC_TABLE = "\
49CREATE TABLE IF NOT EXISTS \n \
50 TrustedContact( \n \
51 contact_namespace BLOB NOT NULL, \n \
52 contact_alias BLOB NOT NULL, \n \
53 self_certificate BLOB NOT NULL, \n \
54 trust_scope BLOB NOT NULL, \n \
55 \
56 PRIMARY KEY (contact_namespace) \n \
57 ); \n \
58 \
59CREATE INDEX tc_index ON TrustedContact(contact_namespace); \n \
60";
61
62const string INIT_NC_TABLE = "\
63CREATE TABLE IF NOT EXISTS \n \
64 NormalContact( \n \
65 contact_namespace BLOB NOT NULL, \n \
66 contact_alias BLOB NOT NULL, \n \
67 self_certificate BLOB NOT NULL, \n \
68 \
69 PRIMARY KEY (contact_namespace) \n \
70 ); \n \
71 \
72CREATE INDEX nc_index ON NormalContact(contact_namespace); \n \
73";
74
Yingdi Yuaa8d7692013-10-18 17:05:02 -070075ContactStorage::ContactStorage()
Yingdi Yuede8eaf2013-10-14 14:07:03 -070076{
77 fs::path chronosDir = fs::path(getenv("HOME")) / ".chronos";
78 fs::create_directories (chronosDir);
79
80 int res = sqlite3_open((chronosDir / "chronos.db").c_str (), &m_db);
81 if (res != SQLITE_OK)
82 throw LnException("Chronos DB cannot be open/created");
83
Yingdi Yu0a6b6c52013-10-15 17:54:00 -070084 // Check if SelfProfile table exists
Yingdi Yuede8eaf2013-10-14 14:07:03 -070085 sqlite3_stmt *stmt;
Yingdi Yu0a6b6c52013-10-15 17:54:00 -070086 sqlite3_prepare_v2 (m_db, "SELECT name FROM sqlite_master WHERE type='table' And name='SelfProfile'", -1, &stmt, 0);
87 res = sqlite3_step (stmt);
88
89 bool spTableExist = false;
90 if (res == SQLITE_ROW)
91 spTableExist = true;
92 sqlite3_finalize (stmt);
93
94 if(!spTableExist)
95 {
96 char *errmsg = 0;
97 res = sqlite3_exec (m_db, INIT_SP_TABLE.c_str (), NULL, NULL, &errmsg);
98 if (res != SQLITE_OK && errmsg != 0)
99 throw LnException("Init \"error\" in SelfProfile");
100 }
101
102 // Check if ProfileData table exists
103 sqlite3_prepare_v2 (m_db, "SELECT name FROM sqlite_master WHERE type='table' And name='ProfileData'", -1, &stmt, 0);
104 res = sqlite3_step (stmt);
105
106 bool pdTableExist = false;
107 if (res == SQLITE_ROW)
108 pdTableExist = true;
109 sqlite3_finalize (stmt);
110
111 if(!pdTableExist)
112 {
113 char *errmsg = 0;
114 res = sqlite3_exec (m_db, INIT_PD_TABLE.c_str (), NULL, NULL, &errmsg);
115 if (res != SQLITE_OK && errmsg != 0)
116 throw LnException("Init \"error\" in ProfileData");
117 }
118
119
120 // Check if TrustedContact table exists
Yingdi Yuede8eaf2013-10-14 14:07:03 -0700121 sqlite3_prepare_v2 (m_db, "SELECT name FROM sqlite_master WHERE type='table' And name='TrustedContact'", -1, &stmt, 0);
122 res = sqlite3_step (stmt);
123
124 bool tcTableExist = false;
125 if (res == SQLITE_ROW)
126 tcTableExist = true;
127 sqlite3_finalize (stmt);
128
129 if(!tcTableExist)
130 {
131 char *errmsg = 0;
132 res = sqlite3_exec (m_db, INIT_TC_TABLE.c_str (), NULL, NULL, &errmsg);
133 if (res != SQLITE_OK && errmsg != 0)
134 throw LnException("Init \"error\" in TrustedContact");
Yingdi Yuede8eaf2013-10-14 14:07:03 -0700135 }
136
137 // Check if NormalContact table exists
138 sqlite3_prepare_v2 (m_db, "SELECT name FROM sqlite_master WHERE type='table' And name='NormalContact'", -1, &stmt, 0);
139 res = sqlite3_step (stmt);
140
141 bool ncTableExist = false;
142 if (res == SQLITE_ROW)
143 ncTableExist = true;
144 sqlite3_finalize (stmt);
145
146 if(!ncTableExist)
147 {
148 char *errmsg = 0;
149 res = sqlite3_exec (m_db, INIT_NC_TABLE.c_str (), NULL, NULL, &errmsg);
150
151 if (res != SQLITE_OK && errmsg != 0)
152 throw LnException("Init \"error\" in NormalContact");
153 }
154}
155
Yingdi Yu0a6b6c52013-10-15 17:54:00 -0700156bool
Yingdi Yu49eea9f2013-10-17 15:07:17 -0700157ContactStorage::doesSelfEntryExist(const Name& identity, const string& profileType)
Yingdi Yu0a6b6c52013-10-15 17:54:00 -0700158{
159 bool result = false;
160
161 sqlite3_stmt *stmt;
Yingdi Yu49eea9f2013-10-17 15:07:17 -0700162 sqlite3_prepare_v2 (m_db, "SELECT count(*) FROM SelfProfile WHERE profile_type=? and profile_identity=?", -1, &stmt, 0);
Yingdi Yu0a6b6c52013-10-15 17:54:00 -0700163 sqlite3_bind_text(stmt, 1, profileType.c_str(), profileType.size(), SQLITE_TRANSIENT);
Yingdi Yu49eea9f2013-10-17 15:07:17 -0700164 sqlite3_bind_text(stmt, 2, identity.toUri().c_str(), identity.toUri().size(), SQLITE_TRANSIENT);
Yingdi Yu0a6b6c52013-10-15 17:54:00 -0700165
166 int res = sqlite3_step (stmt);
167
168 if (res == SQLITE_ROW)
169 {
170 int countAll = sqlite3_column_int (stmt, 0);
171 if (countAll > 0)
172 result = true;
173 }
174 sqlite3_finalize (stmt);
175 return result;
176}
177
Yingdi Yu0a6b6c52013-10-15 17:54:00 -0700178void
Yingdi Yu49eea9f2013-10-17 15:07:17 -0700179ContactStorage::setSelfProfileEntry(const Name& identity, const string& profileType, const Blob& profileValue)
Yingdi Yu0a6b6c52013-10-15 17:54:00 -0700180{
Yingdi Yu0a6b6c52013-10-15 17:54:00 -0700181 sqlite3_stmt *stmt;
Yingdi Yu49eea9f2013-10-17 15:07:17 -0700182 if(doesSelfEntryExist(identity, profileType))
Yingdi Yu0a6b6c52013-10-15 17:54:00 -0700183 {
Yingdi Yu49eea9f2013-10-17 15:07:17 -0700184 sqlite3_prepare_v2 (m_db, "UPDATE SelfProfile SET profile_value=? WHERE profile_type=? and profile_identity=?", -1, &stmt, 0);
Yingdi Yu0a6b6c52013-10-15 17:54:00 -0700185 sqlite3_bind_text(stmt, 1, profileValue.buf(), profileValue.size(), SQLITE_TRANSIENT);
186 sqlite3_bind_text(stmt, 2, profileType.c_str(), profileType.size(), SQLITE_TRANSIENT);
Yingdi Yu49eea9f2013-10-17 15:07:17 -0700187 sqlite3_bind_text(stmt, 3, identity.toUri().c_str(), identity.toUri().size(), SQLITE_TRANSIENT);
Yingdi Yu0a6b6c52013-10-15 17:54:00 -0700188 }
189 else
190 {
Yingdi Yu49eea9f2013-10-17 15:07:17 -0700191 sqlite3_prepare_v2 (m_db, "INSERT INTO SelfProfile (profile_identity, profile_type, profile_value) values (?, ?, ?)", -1, &stmt, 0);
192 sqlite3_bind_text(stmt, 1, identity.toUri().c_str(), identity.toUri().size(), SQLITE_TRANSIENT);
193 sqlite3_bind_text(stmt, 2, profileType.c_str(), profileType.size(), SQLITE_TRANSIENT);
194 sqlite3_bind_text(stmt, 3, profileValue.buf(), profileValue.size(), SQLITE_TRANSIENT);
Yingdi Yu0a6b6c52013-10-15 17:54:00 -0700195 }
196 sqlite3_step (stmt);
197 sqlite3_finalize (stmt);
198}
199
200Ptr<Profile>
Yingdi Yu49eea9f2013-10-17 15:07:17 -0700201ContactStorage::getSelfProfile(const Name& identity)
Yingdi Yu0a6b6c52013-10-15 17:54:00 -0700202{
Yingdi Yu0a6b6c52013-10-15 17:54:00 -0700203 sqlite3_stmt *stmt;
Yingdi Yu49eea9f2013-10-17 15:07:17 -0700204 Ptr<Profile> profile = Ptr<Profile>(new Profile(identity));
Yingdi Yu0a6b6c52013-10-15 17:54:00 -0700205
Yingdi Yu49eea9f2013-10-17 15:07:17 -0700206 sqlite3_prepare_v2(m_db, "SELECT profile_type, profile_value FROM SelfProfile WHERE profile_identity=", -1, &stmt, 0);
207 sqlite3_bind_text(stmt, 1, identity.toUri().c_str(), identity.toUri().size(), SQLITE_TRANSIENT);
Yingdi Yu0a6b6c52013-10-15 17:54:00 -0700208
209 while( sqlite3_step (stmt) == SQLITE_ROW)
210 {
211 string profileType(reinterpret_cast<const char *>(sqlite3_column_text(stmt, 0)), sqlite3_column_bytes (stmt, 0));
212 Blob profileValue(reinterpret_cast<const char *>(sqlite3_column_text(stmt, 1)), sqlite3_column_bytes (stmt, 1));
213
214 profile->setProfileEntry(profileType, profileValue );
215 }
216
217 return profile;
218}
219
Yingdi Yuede8eaf2013-10-14 14:07:03 -0700220void
221ContactStorage::addTrustedContact(const TrustedContact& trustedContact)
222{
223 if(doesTrustedContactExist(trustedContact.getNameSpace()))
224 throw LnException("Trusted Contact has already existed");
225
226 sqlite3_stmt *stmt;
227 sqlite3_prepare_v2 (m_db,
228 "INSERT INTO TrustedContact (contact_namespace, contact_alias, self_certificate, trust_scope) values (?, ?, ?, ?)",
229 -1,
230 &stmt,
231 0);
232
233 sqlite3_bind_text(stmt, 1, trustedContact.getNameSpace().toUri().c_str(), trustedContact.getNameSpace().toUri().size (), SQLITE_TRANSIENT);
234 sqlite3_bind_text(stmt, 2, trustedContact.getAlias().c_str(), trustedContact.getAlias().size(), SQLITE_TRANSIENT);
235 Ptr<Blob> selfCertificateBlob = trustedContact.getSelfEndorseCertificate().encodeToWire();
236 sqlite3_bind_text(stmt, 3, selfCertificateBlob->buf(), selfCertificateBlob->size(), SQLITE_TRANSIENT);
237 Ptr<Blob> trustScopeBlob = trustedContact.getTrustScopeBlob();
238 sqlite3_bind_text(stmt, 4, trustScopeBlob->buf(), trustScopeBlob->size(),SQLITE_TRANSIENT);
239
240 int res = sqlite3_step (stmt);
241 sqlite3_finalize (stmt);
242}
243
244void
245ContactStorage::addNormalContact(const ContactItem& normalContact)
246{
247 if(doesNormalContactExist(normalContact.getNameSpace()))
248 throw LnException("Normal Contact has already existed");
249
250 sqlite3_stmt *stmt;
251 sqlite3_prepare_v2 (m_db,
252 "INSERT INTO NormalContact (contact_namespace, contact_alias, self_certificate) values (?, ?, ?)",
253 -1,
254 &stmt,
255 0);
256
257 sqlite3_bind_text(stmt, 1, normalContact.getNameSpace().toUri().c_str(), normalContact.getNameSpace().toUri().size (), SQLITE_TRANSIENT);
258 sqlite3_bind_text(stmt, 2, normalContact.getAlias().c_str(), normalContact.getAlias().size(), SQLITE_TRANSIENT);
259 Ptr<Blob> selfCertificateBlob = normalContact.getSelfEndorseCertificate().encodeToWire();
260 sqlite3_bind_text(stmt, 3, selfCertificateBlob->buf(), selfCertificateBlob->size(), SQLITE_TRANSIENT);
261
262 int res = sqlite3_step (stmt);
263 sqlite3_finalize (stmt);
264}
265
266bool
267ContactStorage::doesContactExist(const Name& name, bool normal)
268{
269 bool result = false;
270
271 sqlite3_stmt *stmt;
272 if(normal)
273 sqlite3_prepare_v2 (m_db, "SELECT count(*) FROM NormalContact WHERE contact_namespace=?", -1, &stmt, 0);
274 else
275 sqlite3_prepare_v2 (m_db, "SELECT count(*) FROM TrustedContact WHERE contact_namespace=?", -1, &stmt, 0);
276 sqlite3_bind_text(stmt, 1, name.toUri().c_str(), name.toUri().size(), SQLITE_TRANSIENT);
277
278 int res = sqlite3_step (stmt);
279
280 if (res == SQLITE_ROW)
281 {
282 int countAll = sqlite3_column_int (stmt, 0);
283 if (countAll > 0)
284 result = true;
285 }
286 sqlite3_finalize (stmt);
287 return result;
288}
289
290vector<Ptr<TrustedContact> >
291ContactStorage::getAllTrustedContacts() const
292{
293 vector<Ptr<TrustedContact> > trustedContacts;
294
295 sqlite3_stmt *stmt;
296 sqlite3_prepare_v2 (m_db,
297 "SELECT contact_alias, self_certificate, trust_scope FROM TrustedContact",
298 -1,
299 &stmt,
300 0);
301
302 while( sqlite3_step (stmt) == SQLITE_ROW)
303 {
304 string alias(reinterpret_cast<const char *>(sqlite3_column_text(stmt, 0)), sqlite3_column_bytes (stmt, 0));
305 Ptr<Blob> certBlob = Ptr<Blob>(new Blob(reinterpret_cast<const char *>(sqlite3_column_text(stmt, 1)), sqlite3_column_bytes (stmt, 1)));
306 Ptr<Data> certData = Data::decodeFromWire(certBlob);
307 EndorseCertificate endorseCertificate(*certData);
308 string trustScope(reinterpret_cast<const char *>(sqlite3_column_text(stmt, 2)), sqlite3_column_bytes (stmt, 2));
309
310 trustedContacts.push_back(Ptr<TrustedContact>(new TrustedContact(endorseCertificate, trustScope, alias)));
311 }
312
313 return trustedContacts;
314}
315
316vector<Ptr<ContactItem> >
317ContactStorage::getAllNormalContacts() const
318{
319 vector<Ptr<ContactItem> > normalContacts;
320
321 sqlite3_stmt *stmt;
322 sqlite3_prepare_v2 (m_db,
323 "SELECT contact_alias, self_certificate FROM NormalContact",
324 -1,
325 &stmt,
326 0);
327
328 while( sqlite3_step (stmt) == SQLITE_ROW)
329 {
330 string alias(reinterpret_cast<const char *>(sqlite3_column_text(stmt, 0)), sqlite3_column_bytes (stmt, 0));
331 Ptr<Blob> certBlob = Ptr<Blob>(new Blob(reinterpret_cast<const char *>(sqlite3_column_text(stmt, 1)), sqlite3_column_bytes (stmt, 1)));
332 Ptr<Data> certData = Data::decodeFromWire(certBlob);
333 EndorseCertificate endorseCertificate(*certData);
334
335 normalContacts.push_back(Ptr<ContactItem>(new ContactItem(endorseCertificate, alias)));
336 }
337
338 return normalContacts;
339}
Yingdi Yu0a6b6c52013-10-15 17:54:00 -0700340
Yingdi Yu0a6b6c52013-10-15 17:54:00 -0700341Ptr<Profile>
Yingdi Yu49eea9f2013-10-17 15:07:17 -0700342ContactStorage::getSelfProfile(const Name& identity) const
343{
Yingdi Yu0a6b6c52013-10-15 17:54:00 -0700344 Ptr<Profile> profile = Ptr<Profile>(new Profile(identity));
Yingdi Yu49eea9f2013-10-17 15:07:17 -0700345 sqlite3_stmt *stmt;
346 sqlite3_prepare_v2 (m_db, "SELECT profile_type, profile_value FROM SelfProfile WHERE profile_identity=?", -1, &stmt, 0);
347 sqlite3_bind_text (stmt, 1, identity.toUri().c_str(), identity.toUri().size(), SQLITE_TRANSIENT);
Yingdi Yu0a6b6c52013-10-15 17:54:00 -0700348
349 while( sqlite3_step (stmt) == SQLITE_ROW)
350 {
351 string profileType(reinterpret_cast<const char *>(sqlite3_column_text(stmt, 0)), sqlite3_column_bytes (stmt, 0));
352 Blob profileValue(reinterpret_cast<const char *>(sqlite3_column_text(stmt, 1)), sqlite3_column_bytes (stmt, 1));
353 profile->setProfileEntry(profileType, profileValue);
354 }
355
356 return profile;
357}
358
Yingdi Yuaa8d7692013-10-18 17:05:02 -0700359Ptr<Blob>
360ContactStorage::getSelfEndorseCertificate(const Name& identity)
Yingdi Yu0a6b6c52013-10-15 17:54:00 -0700361{
Yingdi Yuaa8d7692013-10-18 17:05:02 -0700362 sqlite3_stmt *stmt;
363 sqlite3_prepare_v2 (m_db, "SELECT profile_data FROM ProfileData where identity=?", -1, &stmt, 0);
364 sqlite3_bind_text(stmt, 1, identity.toUri().c_str(), identity.toUri().size(), SQLITE_TRANSIENT);
Yingdi Yu49eea9f2013-10-17 15:07:17 -0700365
Yingdi Yuaa8d7692013-10-18 17:05:02 -0700366 Ptr<Blob> result = NULL;
367 if(sqlite3_step (stmt) == SQLITE_ROW)
368 result = Ptr<Blob>(new Blob(reinterpret_cast<const char *>(sqlite3_column_text(stmt, 0)), sqlite3_column_bytes (stmt, 0)));
Yingdi Yu0a6b6c52013-10-15 17:54:00 -0700369
Yingdi Yuaa8d7692013-10-18 17:05:02 -0700370 sqlite3_finalize (stmt);
Yingdi Yu68aced92013-10-17 21:13:03 -0700371
Yingdi Yuaa8d7692013-10-18 17:05:02 -0700372 return result;
Yingdi Yu0a6b6c52013-10-15 17:54:00 -0700373}
374
Yingdi Yuaa8d7692013-10-18 17:05:02 -0700375void
376ContactStorage::updateSelfEndorseCertificate(Ptr<EndorseCertificate> newEndorseCertificate, const Name& identity)
377{
378 Ptr<Blob> newEndorseCertificateBlob = newEndorseCertificate->encodeToWire();
379
380 sqlite3_stmt *stmt;
381 sqlite3_prepare_v2 (m_db, "UPDATE ProfileData SET profile_data=? WHERE identity=?", -1, &stmt, 0);
382 sqlite3_bind_text(stmt, 1, newEndorseCertificateBlob->buf(), newEndorseCertificateBlob->size(), SQLITE_TRANSIENT);
383 sqlite3_bind_text(stmt, 2, identity.toUri().c_str(), identity.toUri().size(), SQLITE_TRANSIENT);
384 sqlite3_step(stmt);
385}
386
387void
388ContactStorage::addSelfEndorseCertificate(Ptr<EndorseCertificate> newEndorseCertificate, const Name& identity)
389{
390 Ptr<Blob> newEndorseCertificateBlob = newEndorseCertificate->encodeToWire();
391
392 sqlite3_stmt *stmt;
393 sqlite3_prepare_v2 (m_db, "INSERT INTO ProfileData (identity, profile_data) values (?, ?)", -1, &stmt, 0);
394 sqlite3_bind_text(stmt, 1, identity.toUri().c_str(), identity.toUri().size(), SQLITE_TRANSIENT);
395 sqlite3_bind_text(stmt, 2, newEndorseCertificateBlob->buf(), newEndorseCertificateBlob->size(), SQLITE_TRANSIENT);
396 sqlite3_step(stmt);
397}