NS-3 based Named Data Networking (NDN) simulator
ndnSIM 2.3: NDN, CCN, CCNx, content centric networks
API Documentation
pib-sqlite3.cpp
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
22 #include "pib-sqlite3.hpp"
23 
24 #include "common.hpp"
25 #include "pib.hpp"
27 
28 #include <sqlite3.h>
29 #include <boost/filesystem.hpp>
30 #include <boost/algorithm/string.hpp>
31 
32 namespace ndn {
33 namespace security {
34 
35 using std::string;
36 using util::Sqlite3Statement;
37 
38 static const string INITIALIZATION =
39  "CREATE TABLE IF NOT EXISTS \n"
40  " tpmInfo( \n"
41  " tpm_locator BLOB \n"
42  " ); \n"
43  " \n"
44  "CREATE TRIGGER IF NOT EXISTS \n"
45  " tpm_update_trigger \n"
46  " BEFORE UPDATE ON tpmInfo \n"
47  " WHEN NEW.tpm_locator!=OLD.tpm_locator \n"
48  " BEGIN \n"
49  " DELETE FROM certificates; \n"
50  " DELETE FROM keys; \n"
51  " DELETE FROM identities; \n"
52  " END; \n"
53  " \n"
54  " \n"
55  "CREATE TABLE IF NOT EXISTS \n"
56  " identities( \n"
57  " id INTEGER PRIMARY KEY,\n"
58  " identity BLOB NOT NULL, \n"
59  " is_default INTEGER DEFAULT 0 \n"
60  " ); \n"
61  " \n"
62  "CREATE UNIQUE INDEX IF NOT EXISTS \n"
63  " identityIndex ON identities(identity); \n"
64  " \n"
65  "CREATE TRIGGER IF NOT EXISTS \n"
66  " identity_default_before_insert_trigger \n"
67  " BEFORE INSERT ON identities \n"
68  " FOR EACH ROW \n"
69  " WHEN NEW.is_default=1 \n"
70  " BEGIN \n"
71  " UPDATE identities SET is_default=0; \n"
72  " END; \n"
73  " \n"
74  "CREATE TRIGGER IF NOT EXISTS \n"
75  " identity_default_after_insert_trigger \n"
76  " AFTER INSERT ON identities \n"
77  " FOR EACH ROW \n"
78  " WHEN NOT EXISTS \n"
79  " (SELECT id \n"
80  " FROM identities \n"
81  " WHERE is_default=1) \n"
82  " BEGIN \n"
83  " UPDATE identities \n"
84  " SET is_default=1 \n"
85  " WHERE identity=NEW.identity; \n"
86  " END; \n"
87  " \n"
88  "CREATE TRIGGER IF NOT EXISTS \n"
89  " identity_default_update_trigger \n"
90  " BEFORE UPDATE ON identities \n"
91  " FOR EACH ROW \n"
92  " WHEN NEW.is_default=1 AND OLD.is_default=0 \n"
93  " BEGIN \n"
94  " UPDATE identities SET is_default=0; \n"
95  " END; \n"
96  " \n"
97  " \n"
98  "CREATE TABLE IF NOT EXISTS \n"
99  " keys( \n"
100  " id INTEGER PRIMARY KEY,\n"
101  " identity_id INTEGER NOT NULL, \n"
102  " key_name BLOB NOT NULL, \n"
103  " key_type INTEGER NOT NULL, \n"
104  " key_bits BLOB NOT NULL, \n"
105  " is_default INTEGER DEFAULT 0, \n"
106  " FOREIGN KEY(identity_id) \n"
107  " REFERENCES identities(id) \n"
108  " ON DELETE CASCADE \n"
109  " ON UPDATE CASCADE \n"
110  " ); \n"
111  " \n"
112  "CREATE UNIQUE INDEX IF NOT EXISTS \n"
113  " keyIndex ON keys(key_name); \n"
114  " \n"
115  "CREATE TRIGGER IF NOT EXISTS \n"
116  " key_default_before_insert_trigger \n"
117  " BEFORE INSERT ON keys \n"
118  " FOR EACH ROW \n"
119  " WHEN NEW.is_default=1 \n"
120  " BEGIN \n"
121  " UPDATE keys \n"
122  " SET is_default=0 \n"
123  " WHERE identity_id=NEW.identity_id; \n"
124  " END; \n"
125  " \n"
126  "CREATE TRIGGER IF NOT EXISTS \n"
127  " key_default_after_insert_trigger \n"
128  " AFTER INSERT ON keys \n"
129  " FOR EACH ROW \n"
130  " WHEN NOT EXISTS \n"
131  " (SELECT id \n"
132  " FROM keys \n"
133  " WHERE is_default=1 \n"
134  " AND identity_id=NEW.identity_id) \n"
135  " BEGIN \n"
136  " UPDATE keys \n"
137  " SET is_default=1 \n"
138  " WHERE key_name=NEW.key_name; \n"
139  " END; \n"
140  " \n"
141  "CREATE TRIGGER IF NOT EXISTS \n"
142  " key_default_update_trigger \n"
143  " BEFORE UPDATE ON keys \n"
144  " FOR EACH ROW \n"
145  " WHEN NEW.is_default=1 AND OLD.is_default=0 \n"
146  " BEGIN \n"
147  " UPDATE keys \n"
148  " SET is_default=0 \n"
149  " WHERE identity_id=NEW.identity_id; \n"
150  " END; \n"
151  " \n"
152  " \n"
153  "CREATE TABLE IF NOT EXISTS \n"
154  " certificates( \n"
155  " id INTEGER PRIMARY KEY,\n"
156  " key_id INTEGER NOT NULL, \n"
157  " certificate_name BLOB NOT NULL, \n"
158  " certificate_data BLOB NOT NULL, \n"
159  " is_default INTEGER DEFAULT 0, \n"
160  " FOREIGN KEY(key_id) \n"
161  " REFERENCES keys(id) \n"
162  " ON DELETE CASCADE \n"
163  " ON UPDATE CASCADE \n"
164  " ); \n"
165  " \n"
166  "CREATE UNIQUE INDEX IF NOT EXISTS \n"
167  " certIndex ON certificates(certificate_name);\n"
168  " \n"
169  "CREATE TRIGGER IF NOT EXISTS \n"
170  " cert_default_before_insert_trigger \n"
171  " BEFORE INSERT ON certificates \n"
172  " FOR EACH ROW \n"
173  " WHEN NEW.is_default=1 \n"
174  " BEGIN \n"
175  " UPDATE certificates \n"
176  " SET is_default=0 \n"
177  " WHERE key_id=NEW.key_id; \n"
178  " END; \n"
179  " \n"
180  "CREATE TRIGGER IF NOT EXISTS \n"
181  " cert_default_after_insert_trigger \n"
182  " AFTER INSERT ON certificates \n"
183  " FOR EACH ROW \n"
184  " WHEN NOT EXISTS \n"
185  " (SELECT id \n"
186  " FROM certificates \n"
187  " WHERE is_default=1 \n"
188  " AND key_id=NEW.key_id) \n"
189  " BEGIN \n"
190  " UPDATE certificates \n"
191  " SET is_default=1 \n"
192  " WHERE certificate_name=NEW.certificate_name;\n"
193  " END; \n"
194  " \n"
195  "CREATE TRIGGER IF NOT EXISTS \n"
196  " cert_default_update_trigger \n"
197  " BEFORE UPDATE ON certificates \n"
198  " FOR EACH ROW \n"
199  " WHEN NEW.is_default=1 AND OLD.is_default=0 \n"
200  " BEGIN \n"
201  " UPDATE certificates \n"
202  " SET is_default=0 \n"
203  " WHERE key_id=NEW.key_id; \n"
204  " END; \n";
205 
206 static Name
207 getKeyName(const Name& identity, const name::Component& keyId)
208 {
209  Name keyName = identity;
210  keyName.append(keyId);
211  return keyName;
212 }
213 
214 PibSqlite3::PibSqlite3(const string& dir)
215 {
216  // Determine the path of PIB DB
217  boost::filesystem::path actualDir;
218  if (dir == "") {
219 #ifdef NDN_CXX_HAVE_TESTS
220  if (getenv("TEST_HOME") != nullptr) {
221  actualDir = boost::filesystem::path(getenv("TEST_HOME")) / ".ndn";
222  }
223  else
224 #endif // NDN_CXX_HAVE_TESTS
225  if (getenv("HOME") != nullptr) {
226  actualDir = boost::filesystem::path(getenv("HOME")) / ".ndn";
227  }
228  else {
229  actualDir = boost::filesystem::path(".") / ".ndn";
230  }
231  }
232  else {
233  actualDir = boost::filesystem::path(dir);
234  }
235  boost::filesystem::create_directories(actualDir);
236 
237  // Open PIB
238  int result = sqlite3_open_v2((actualDir / "pib.db").c_str(), &m_database,
239  SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE,
240 #ifdef NDN_CXX_DISABLE_SQLITE3_FS_LOCKING
241  "unix-dotfile"
242 #else
243  nullptr
244 #endif
245  );
246 
247  if (result != SQLITE_OK)
248  BOOST_THROW_EXCEPTION(PibImpl::Error("PIB DB cannot be opened/created: " + dir));
249 
250 
251  // enable foreign key
252  sqlite3_exec(m_database, "PRAGMA foreign_keys=ON", nullptr, nullptr, nullptr);
253 
254  // initialize PIB tables
255  char* errorMessage = nullptr;
256  result = sqlite3_exec(m_database, INITIALIZATION.c_str(), nullptr, nullptr, &errorMessage);
257  if (result != SQLITE_OK && errorMessage != nullptr) {
258  sqlite3_free(errorMessage);
259  BOOST_THROW_EXCEPTION(PibImpl::Error("PIB DB cannot be initialized"));
260  }
261 }
262 
264 {
265  sqlite3_close(m_database);
266 }
267 
268 void
269 PibSqlite3::setTpmLocator(const std::string& tpmLocator)
270 {
271  Sqlite3Statement statement(m_database, "UPDATE tpmInfo SET tpm_locator=?");
272  statement.bind(1, tpmLocator, SQLITE_TRANSIENT);
273  statement.step();
274 
275  // no row is updated, tpm_locator does not exist, insert it directly
276  if (0 == sqlite3_changes(m_database)) {
277  Sqlite3Statement insertStatement(m_database, "INSERT INTO tpmInfo (tpm_locator) values (?)");
278  insertStatement.bind(1, tpmLocator, SQLITE_TRANSIENT);
279  insertStatement.step();
280  }
281 }
282 
283 std::string
285 {
286  Sqlite3Statement statement(m_database, "SELECT tpm_locator FROM tpmInfo");
287  int res = statement.step();
288 
289  string tpmLocator;
290  if (res == SQLITE_ROW)
291  return statement.getString(0);
292  else
293  BOOST_THROW_EXCEPTION(Pib::Error("TPM info does not exist"));
294 }
295 
296 bool
297 PibSqlite3::hasIdentity(const Name& identity) const
298 {
299  Sqlite3Statement statement(m_database, "SELECT id FROM identities WHERE identity=?");
300  statement.bind(1, identity.wireEncode(), SQLITE_TRANSIENT);
301  return (statement.step() == SQLITE_ROW);
302 }
303 
304 void
306 {
307  Sqlite3Statement statement(m_database, "INSERT INTO identities (identity) values (?)");
308  statement.bind(1, identity.wireEncode(), SQLITE_TRANSIENT);
309  statement.step();
310 }
311 
312 void
314 {
315  Sqlite3Statement statement(m_database, "DELETE FROM identities WHERE identity=?");
316  statement.bind(1, identity.wireEncode(), SQLITE_TRANSIENT);
317  statement.step();
318 }
319 
320 std::set<Name>
322 {
323  std::set<Name> identities;
324  Sqlite3Statement statement(m_database, "SELECT identity FROM identities");
325 
326  while (statement.step() == SQLITE_ROW)
327  identities.insert(Name(statement.getBlock(0)));
328 
329  return identities;
330 }
331 
332 void
334 {
335  Sqlite3Statement statement(m_database, "UPDATE identities SET is_default=1 WHERE identity=?");
336  statement.bind(1, identityName.wireEncode(), SQLITE_TRANSIENT);
337  statement.step();
338 }
339 
340 Name
342 {
343  Sqlite3Statement statement(m_database, "SELECT identity FROM identities WHERE is_default=1");
344 
345  if (statement.step() == SQLITE_ROW)
346  return Name(statement.getBlock(0));
347  else
348  BOOST_THROW_EXCEPTION(Pib::Error("No default identity"));
349 }
350 
351 bool
352 PibSqlite3::hasKey(const Name& identity, const name::Component& keyId) const
353 {
354  Name keyName = getKeyName(identity, keyId);
355 
356  Sqlite3Statement statement(m_database, "SELECT id FROM keys WHERE key_name=?");
357  statement.bind(1, keyName.wireEncode(), SQLITE_TRANSIENT);
358 
359  return (statement.step() == SQLITE_ROW);
360 }
361 
362 void
363 PibSqlite3::addKey(const Name& identity, const name::Component& keyId, const v1::PublicKey& publicKey)
364 {
365  if (hasKey(identity, keyId)) {
366  return;
367  }
368 
369  // ensure identity exists
370  addIdentity(identity);
371 
372  // add key
373  Name keyName = getKeyName(identity, keyId);
374 
375  Sqlite3Statement statement(m_database,
376  "INSERT INTO keys (identity_id, key_name, key_type, key_bits) "
377  "VALUES ((SELECT id FROM identities WHERE identity=?), ?, ?, ?)");
378  statement.bind(1, identity.wireEncode(), SQLITE_TRANSIENT);
379  statement.bind(2, keyName.wireEncode(), SQLITE_TRANSIENT);
380  statement.bind(3, static_cast<int>(publicKey.getKeyType()));
381  statement.bind(4, publicKey.get().buf(), publicKey.get().size(), SQLITE_STATIC);
382  statement.step();
383 }
384 
385 void
386 PibSqlite3::removeKey(const Name& identity, const name::Component& keyId)
387 {
388  Name keyName = getKeyName(identity, keyId);
389 
390  Sqlite3Statement statement(m_database, "DELETE FROM keys WHERE key_name=?");
391  statement.bind(1, keyName.wireEncode(), SQLITE_TRANSIENT);
392  statement.step();
393 }
394 
396 PibSqlite3::getKeyBits(const Name& identity, const name::Component& keyId) const
397 {
398  Name keyName = getKeyName(identity, keyId);
399 
400  Sqlite3Statement statement(m_database, "SELECT key_bits FROM keys WHERE key_name=?");
401  statement.bind(1, keyName.wireEncode(), SQLITE_TRANSIENT);
402 
403  if (statement.step() == SQLITE_ROW)
404  return v1::PublicKey(statement.getBlob(0), statement.getSize(0));
405  else
406  BOOST_THROW_EXCEPTION(Pib::Error("Key does not exist"));
407 }
408 
409 std::set<name::Component>
410 PibSqlite3::getKeysOfIdentity(const Name& identity) const
411 {
412  std::set<name::Component> keyNames;
413 
414  Sqlite3Statement statement(m_database,
415  "SELECT key_name "
416  "FROM keys JOIN identities ON keys.identity_id=identities.id "
417  "WHERE identities.identity=?");
418  statement.bind(1, identity.wireEncode(), SQLITE_TRANSIENT);
419 
420  while (statement.step() == SQLITE_ROW) {
421  Name keyName(statement.getBlock(0));
422  keyNames.insert(keyName.get(-1));
423  }
424 
425  return keyNames;
426 }
427 
428 void
430 {
431  Name keyName = getKeyName(identity, keyId);
432 
433  if (!hasKey(identity, keyId)) {
434  BOOST_THROW_EXCEPTION(Pib::Error("No such key"));
435  }
436 
437  Sqlite3Statement statement(m_database, "UPDATE keys SET is_default=1 WHERE key_name=?");
438  statement.bind(1, keyName.wireEncode(), SQLITE_TRANSIENT);
439  statement.step();
440 }
441 
444 {
445  if (!hasIdentity(identity)) {
446  BOOST_THROW_EXCEPTION(Pib::Error("Identity does not exist"));
447  }
448 
449  Sqlite3Statement statement(m_database,
450  "SELECT key_name "
451  "FROM keys JOIN identities ON keys.identity_id=identities.id "
452  "WHERE identities.identity=? AND keys.is_default=1");
453  statement.bind(1, identity.wireEncode(), SQLITE_TRANSIENT);
454 
455  if (statement.step() == SQLITE_ROW) {
456  Name keyName(statement.getBlock(0));
457  return keyName.get(-1);
458  }
459  else
460  BOOST_THROW_EXCEPTION(Pib::Error("No default key"));
461 }
462 
463 bool
464 PibSqlite3::hasCertificate(const Name& certName) const
465 {
466  Sqlite3Statement statement(m_database, "SELECT id FROM certificates WHERE certificate_name=?");
467  statement.bind(1, certName.wireEncode(), SQLITE_TRANSIENT);
468  return (statement.step() == SQLITE_ROW);
469 }
470 
471 void
473 {
474  const Name& certName = certificate.getName();
475  const Name& keyName = certificate.getPublicKeyName();
476 
477  name::Component keyId = keyName.get(-1);
478  Name identityName = keyName.getPrefix(-1);
479 
480  // ensure key exists
481  addKey(identityName, keyId, certificate.getPublicKeyInfo());
482 
483  Sqlite3Statement statement(m_database,
484  "INSERT INTO certificates "
485  "(key_id, certificate_name, certificate_data) "
486  "VALUES ((SELECT id FROM keys WHERE key_name=?), ?, ?)");
487  statement.bind(1, keyName.wireEncode(), SQLITE_TRANSIENT);
488  statement.bind(2, certName.wireEncode(), SQLITE_TRANSIENT);
489  statement.bind(3, certificate.wireEncode(), SQLITE_STATIC);
490  statement.step();
491 }
492 
493 void
495 {
496  Sqlite3Statement statement(m_database, "DELETE FROM certificates WHERE certificate_name=?");
497  statement.bind(1, certName.wireEncode(), SQLITE_TRANSIENT);
498  statement.step();
499 }
500 
502 PibSqlite3::getCertificate(const Name& certName) const
503 {
504  Sqlite3Statement statement(m_database,
505  "SELECT certificate_data FROM certificates WHERE certificate_name=?");
506  statement.bind(1, certName.wireEncode(), SQLITE_TRANSIENT);
507 
508  if (statement.step() == SQLITE_ROW)
509  return v1::IdentityCertificate(statement.getBlock(0));
510  else
511  BOOST_THROW_EXCEPTION(Pib::Error("Certificate does not exit"));
512 }
513 
514 std::set<Name>
515 PibSqlite3::getCertificatesOfKey(const Name& identity, const name::Component& keyId) const
516 {
517  std::set<Name> certNames;
518 
519  Name keyName = getKeyName(identity, keyId);
520 
521  Sqlite3Statement statement(m_database,
522  "SELECT certificate_name "
523  "FROM certificates JOIN keys ON certificates.key_id=keys.id "
524  "WHERE keys.key_name=?");
525  statement.bind(1, keyName.wireEncode(), SQLITE_TRANSIENT);
526 
527  while (statement.step() == SQLITE_ROW)
528  certNames.insert(Name(statement.getBlock(0)));
529 
530  return certNames;
531 }
532 
533 void
535  const Name& certName)
536 {
537  if (!hasCertificate(certName)) {
538  BOOST_THROW_EXCEPTION(Pib::Error("Certificate does not exist"));
539  }
540 
541  Sqlite3Statement statement(m_database,
542  "UPDATE certificates SET is_default=1 WHERE certificate_name=?");
543  statement.bind(1, certName.wireEncode(), SQLITE_TRANSIENT);
544  statement.step();
545 }
546 
548 PibSqlite3::getDefaultCertificateOfKey(const Name& identity, const name::Component& keyId) const
549 {
550  Name keyName = getKeyName(identity, keyId);
551 
552  Sqlite3Statement statement(m_database,
553  "SELECT certificate_data "
554  "FROM certificates JOIN keys ON certificates.key_id=keys.id "
555  "WHERE certificates.is_default=1 AND keys.key_name=?");
556  statement.bind(1, keyName.wireEncode(), SQLITE_TRANSIENT);
557 
558  if (statement.step() == SQLITE_ROW)
559  return v1::IdentityCertificate(statement.getBlock(0));
560  else
561  BOOST_THROW_EXCEPTION(Pib::Error("Certificate does not exit"));
562 }
563 
564 } // namespace security
565 } // namespace ndn
PibSqlite3(const std::string &dir="")
Constructor of PibSqlite3.
virtual void setDefaultIdentity(const Name &identityName) final
Set an identity with name identityName as the default identity.
virtual void setDefaultCertificateOfKey(const Name &identity, const name::Component &keyId, const Name &certName) final
Set a cert with name certName as the default of a key with id keyId of identity.
PartialName getPrefix(ssize_t nComponents) const
Extract a prefix (PartialName) of the name, containing first nComponents components.
Definition: name.hpp:241
represents a non-semantic error
Definition: pib-impl.hpp:46
Copyright (c) 2011-2015 Regents of the University of California.
virtual bool hasKey(const Name &identity, const name::Component &keyId) const final
Check the existence of a key.
int getSize(int column)
get the size of column.
const Buffer & get() const
Definition: public-key.hpp:72
virtual std::set< name::Component > getKeysOfIdentity(const Name &identity) const final
Get all the key ids of an identity with name identity.
const Component & get(ssize_t i) const
Get the component at the given index.
Definition: name.hpp:411
virtual v1::IdentityCertificate getDefaultCertificateOfKey(const Name &identity, const name::Component &keyId) const final
Get the default certificate of a key with id keyId of identity.
const Name & getName() const
Get name of the Data packet.
Definition: data.hpp:318
virtual void addIdentity(const Name &identity) final
Add an identity.
virtual void removeIdentity(const Name &identity) final
Remove an identity.
virtual std::set< Name > getIdentities() const final
Get the name of all the identities.
virtual bool hasCertificate(const Name &certName) const final
Check the existence of a certificate with name certName.
static Name getKeyName(const Name &identity, const name::Component &keyId)
virtual std::set< Name > getCertificatesOfKey(const Name &identity, const name::Component &keyId) const final
Get a list of certificate names of a key with id keyId of identity.
represents a semantic error
Definition: pib.hpp:55
Block getBlock(int column)
get a block from column.
uint8_t * buf()
Definition: buffer.hpp:87
virtual void addKey(const Name &identity, const name::Component &keyId, const v1::PublicKey &publicKey) final
Add a key.
const uint8_t * getBlob(int column)
get a pointer of byte blob from column.
int bind(int index, const char *value, size_t size, void(*destructor)(void *))
bind a string to the statement
virtual void addCertificate(const v1::IdentityCertificate &certificate) final
Add a certificate.
Name abstraction to represent an absolute name.
Definition: name.hpp:46
virtual std::string getTpmLocator() const final
Get TPM Locator.
virtual void setTpmLocator(const std::string &tpmLocator) final
Set the corresponding TPM information to tpmLocator.
virtual void removeCertificate(const Name &certName) final
Remove a certificate with name certName.
virtual v1::IdentityCertificate getCertificate(const Name &certName) const final
Get a certificate with name certName.
std::string getString(int column)
get a string from column.
virtual Name getDefaultIdentity() const final
Get the default identity.
virtual void setDefaultKeyOfIdentity(const Name &identity, const name::Component &keyId) final
Set an key with id keyId as the default key of an identity with name identity.
int step()
wrapper of sqlite3_step
Component holds a read-only name component value.
wrap an SQLite3 prepared statement
Name & append(const uint8_t *value, size_t valueLength)
Append a new component, copying from value of length valueLength.
Definition: name.hpp:140
size_t wireEncode(EncodingImpl< TAG > &encoder, bool wantUnsignedPortionOnly=false) const
Fast encoding or block size estimation.
Definition: data.cpp:52
static const string INITIALIZATION
Definition: pib-sqlite3.cpp:38
size_t wireEncode(EncodingImpl< TAG > &encoder) const
Fast encoding or block size estimation.
Definition: name.cpp:122
virtual v1::PublicKey getKeyBits(const Name &identity, const name::Component &keyId) const final
Get the key bits of a key.
virtual void removeKey(const Name &identity, const name::Component &keyId) final
Remove a key.
~PibSqlite3()
Destruct and cleanup internal state.
KeyType getKeyType() const
Definition: public-key.hpp:85
virtual bool hasIdentity(const Name &identity) const final
Check the existence of an identity.
virtual name::Component getDefaultKeyOfIdentity(const Name &identity) const final
Get the id of the default key of an identity with name identity.