NS-3 based Named Data Networking (NDN) simulator
ndnSIM 2.0: 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  if (getenv("HOME") == nullptr)
220  BOOST_THROW_EXCEPTION(PibImpl::Error("Environment variable HOME is not set"));
221 
222  actualDir = boost::filesystem::path(getenv("HOME")) / ".ndn";
223  boost::filesystem::create_directories(actualDir);
224  }
225  else {
226  actualDir = boost::filesystem::path(dir);
227  boost::filesystem::create_directories(actualDir);
228  }
229  // Open PIB
230  int result = sqlite3_open_v2((actualDir / "pib.db").c_str(), &m_database,
231  SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE,
232 #ifdef NDN_CXX_DISABLE_SQLITE3_FS_LOCKING
233  "unix-dotfile"
234 #else
235  nullptr
236 #endif
237  );
238 
239  if (result != SQLITE_OK)
240  BOOST_THROW_EXCEPTION(PibImpl::Error("PIB DB cannot be opened/created: " + dir));
241 
242 
243  // enable foreign key
244  sqlite3_exec(m_database, "PRAGMA foreign_keys=ON", nullptr, nullptr, nullptr);
245 
246  // initialize PIB tables
247  char* errorMessage = nullptr;
248  result = sqlite3_exec(m_database, INITIALIZATION.c_str(), nullptr, nullptr, &errorMessage);
249  if (result != SQLITE_OK && errorMessage != nullptr) {
250  sqlite3_free(errorMessage);
251  BOOST_THROW_EXCEPTION(PibImpl::Error("PIB DB cannot be initialized"));
252  }
253 }
254 
256 {
257  sqlite3_close(m_database);
258 }
259 
260 void
261 PibSqlite3::setTpmLocator(const std::string& tpmLocator)
262 {
263  Sqlite3Statement statement(m_database, "UPDATE tpmInfo SET tpm_locator=?");
264  statement.bind(1, tpmLocator, SQLITE_TRANSIENT);
265  statement.step();
266 
267  // no row is updated, tpm_locator does not exist, insert it directly
268  if (0 == sqlite3_changes(m_database)) {
269  Sqlite3Statement insertStatement(m_database, "INSERT INTO tpmInfo (tpm_locator) values (?)");
270  insertStatement.bind(1, tpmLocator, SQLITE_TRANSIENT);
271  insertStatement.step();
272  }
273 }
274 
275 std::string
277 {
278  Sqlite3Statement statement(m_database, "SELECT tpm_locator FROM tpmInfo");
279  int res = statement.step();
280 
281  string tpmLocator;
282  if (res == SQLITE_ROW)
283  return statement.getString(0);
284  else
285  BOOST_THROW_EXCEPTION(Pib::Error("TPM info does not exist"));
286 }
287 
288 bool
289 PibSqlite3::hasIdentity(const Name& identity) const
290 {
291  Sqlite3Statement statement(m_database, "SELECT id FROM identities WHERE identity=?");
292  statement.bind(1, identity.wireEncode(), SQLITE_TRANSIENT);
293  return (statement.step() == SQLITE_ROW);
294 }
295 
296 void
298 {
299  Sqlite3Statement statement(m_database, "INSERT INTO identities (identity) values (?)");
300  statement.bind(1, identity.wireEncode(), SQLITE_TRANSIENT);
301  statement.step();
302 }
303 
304 void
306 {
307  Sqlite3Statement statement(m_database, "DELETE FROM identities WHERE identity=?");
308  statement.bind(1, identity.wireEncode(), SQLITE_TRANSIENT);
309  statement.step();
310 }
311 
312 std::set<Name>
314 {
315  std::set<Name> identities;
316  Sqlite3Statement statement(m_database, "SELECT identity FROM identities");
317 
318  while (statement.step() == SQLITE_ROW)
319  identities.insert(Name(statement.getBlock(0)));
320 
321  return identities;
322 }
323 
324 void
326 {
327  Sqlite3Statement statement(m_database, "UPDATE identities SET is_default=1 WHERE identity=?");
328  statement.bind(1, identityName.wireEncode(), SQLITE_TRANSIENT);
329  statement.step();
330 }
331 
332 Name
334 {
335  Sqlite3Statement statement(m_database, "SELECT identity FROM identities WHERE is_default=1");
336 
337  if (statement.step() == SQLITE_ROW)
338  return Name(statement.getBlock(0));
339  else
340  BOOST_THROW_EXCEPTION(Pib::Error("No default identity"));
341 }
342 
343 bool
344 PibSqlite3::hasKey(const Name& identity, const name::Component& keyId) const
345 {
346  Name keyName = getKeyName(identity, keyId);
347 
348  Sqlite3Statement statement(m_database, "SELECT id FROM keys WHERE key_name=?");
349  statement.bind(1, keyName.wireEncode(), SQLITE_TRANSIENT);
350 
351  return (statement.step() == SQLITE_ROW);
352 }
353 
354 void
355 PibSqlite3::addKey(const Name& identity, const name::Component& keyId, const PublicKey& publicKey)
356 {
357  if (hasKey(identity, keyId)) {
358  return;
359  }
360 
361  // ensure identity exists
362  addIdentity(identity);
363 
364  // add key
365  Name keyName = getKeyName(identity, keyId);
366 
367  Sqlite3Statement statement(m_database,
368  "INSERT INTO keys (identity_id, key_name, key_type, key_bits) "
369  "VALUES ((SELECT id FROM identities WHERE identity=?), ?, ?, ?)");
370  statement.bind(1, identity.wireEncode(), SQLITE_TRANSIENT);
371  statement.bind(2, keyName.wireEncode(), SQLITE_TRANSIENT);
372  statement.bind(3, publicKey.getKeyType());
373  statement.bind(4, publicKey.get().buf(), publicKey.get().size(), SQLITE_STATIC);
374  statement.step();
375 }
376 
377 void
378 PibSqlite3::removeKey(const Name& identity, const name::Component& keyId)
379 {
380  Name keyName = getKeyName(identity, keyId);
381 
382  Sqlite3Statement statement(m_database, "DELETE FROM keys WHERE key_name=?");
383  statement.bind(1, keyName.wireEncode(), SQLITE_TRANSIENT);
384  statement.step();
385 }
386 
387 PublicKey
388 PibSqlite3::getKeyBits(const Name& identity, const name::Component& keyId) const
389 {
390  Name keyName = getKeyName(identity, keyId);
391 
392  Sqlite3Statement statement(m_database, "SELECT key_bits FROM keys WHERE key_name=?");
393  statement.bind(1, keyName.wireEncode(), SQLITE_TRANSIENT);
394 
395  if (statement.step() == SQLITE_ROW)
396  return PublicKey(statement.getBlob(0), statement.getSize(0));
397  else
398  BOOST_THROW_EXCEPTION(Pib::Error("Key does not exist"));
399 }
400 
401 std::set<name::Component>
402 PibSqlite3::getKeysOfIdentity(const Name& identity) const
403 {
404  std::set<name::Component> keyNames;
405 
406  Sqlite3Statement statement(m_database,
407  "SELECT key_name "
408  "FROM keys JOIN identities ON keys.identity_id=identities.id "
409  "WHERE identities.identity=?");
410  statement.bind(1, identity.wireEncode(), SQLITE_TRANSIENT);
411 
412  while (statement.step() == SQLITE_ROW) {
413  Name keyName(statement.getBlock(0));
414  keyNames.insert(keyName.get(-1));
415  }
416 
417  return keyNames;
418 }
419 
420 void
422 {
423  Name keyName = getKeyName(identity, keyId);
424 
425  if (!hasKey(identity, keyId)) {
426  BOOST_THROW_EXCEPTION(Pib::Error("No such key"));
427  }
428 
429  Sqlite3Statement statement(m_database, "UPDATE keys SET is_default=1 WHERE key_name=?");
430  statement.bind(1, keyName.wireEncode(), SQLITE_TRANSIENT);
431  statement.step();
432 }
433 
436 {
437  if (!hasIdentity(identity)) {
438  BOOST_THROW_EXCEPTION(Pib::Error("Identity does not exist"));
439  }
440 
441  Sqlite3Statement statement(m_database,
442  "SELECT key_name "
443  "FROM keys JOIN identities ON keys.identity_id=identities.id "
444  "WHERE identities.identity=? AND keys.is_default=1");
445  statement.bind(1, identity.wireEncode(), SQLITE_TRANSIENT);
446 
447  if (statement.step() == SQLITE_ROW) {
448  Name keyName(statement.getBlock(0));
449  return keyName.get(-1);
450  }
451  else
452  BOOST_THROW_EXCEPTION(Pib::Error("No default key"));
453 }
454 
455 bool
456 PibSqlite3::hasCertificate(const Name& certName) const
457 {
458  Sqlite3Statement statement(m_database, "SELECT id FROM certificates WHERE certificate_name=?");
459  statement.bind(1, certName.wireEncode(), SQLITE_TRANSIENT);
460  return (statement.step() == SQLITE_ROW);
461 }
462 
463 void
465 {
466  const Name& certName = certificate.getName();
467  const Name& keyName = certificate.getPublicKeyName();
468 
469  name::Component keyId = keyName.get(-1);
470  Name identityName = keyName.getPrefix(-1);
471 
472  // ensure key exists
473  addKey(identityName, keyId, certificate.getPublicKeyInfo());
474 
475  Sqlite3Statement statement(m_database,
476  "INSERT INTO certificates "
477  "(key_id, certificate_name, certificate_data) "
478  "VALUES ((SELECT id FROM keys WHERE key_name=?), ?, ?)");
479  statement.bind(1, keyName.wireEncode(), SQLITE_TRANSIENT);
480  statement.bind(2, certName.wireEncode(), SQLITE_TRANSIENT);
481  statement.bind(3, certificate.wireEncode(), SQLITE_STATIC);
482  statement.step();
483 }
484 
485 void
487 {
488  Sqlite3Statement statement(m_database, "DELETE FROM certificates WHERE certificate_name=?");
489  statement.bind(1, certName.wireEncode(), SQLITE_TRANSIENT);
490  statement.step();
491 }
492 
494 PibSqlite3::getCertificate(const Name& certName) const
495 {
496  Sqlite3Statement statement(m_database,
497  "SELECT certificate_data FROM certificates WHERE certificate_name=?");
498  statement.bind(1, certName.wireEncode(), SQLITE_TRANSIENT);
499 
500  if (statement.step() == SQLITE_ROW)
501  return IdentityCertificate(statement.getBlock(0));
502  else
503  BOOST_THROW_EXCEPTION(Pib::Error("Certificate does not exit"));
504 }
505 
506 std::set<Name>
507 PibSqlite3::getCertificatesOfKey(const Name& identity, const name::Component& keyId) const
508 {
509  std::set<Name> certNames;
510 
511  Name keyName = getKeyName(identity, keyId);
512 
513  Sqlite3Statement statement(m_database,
514  "SELECT certificate_name "
515  "FROM certificates JOIN keys ON certificates.key_id=keys.id "
516  "WHERE keys.key_name=?");
517  statement.bind(1, keyName.wireEncode(), SQLITE_TRANSIENT);
518 
519  while (statement.step() == SQLITE_ROW)
520  certNames.insert(Name(statement.getBlock(0)));
521 
522  return certNames;
523 }
524 
525 void
527  const Name& certName)
528 {
529  if (!hasCertificate(certName)) {
530  BOOST_THROW_EXCEPTION(Pib::Error("Certificate does not exist"));
531  }
532 
533  Sqlite3Statement statement(m_database,
534  "UPDATE certificates SET is_default=1 WHERE certificate_name=?");
535  statement.bind(1, certName.wireEncode(), SQLITE_TRANSIENT);
536  statement.step();
537 }
538 
540 PibSqlite3::getDefaultCertificateOfKey(const Name& identity, const name::Component& keyId) const
541 {
542  Name keyName = getKeyName(identity, keyId);
543 
544  Sqlite3Statement statement(m_database,
545  "SELECT certificate_data "
546  "FROM certificates JOIN keys ON certificates.key_id=keys.id "
547  "WHERE certificates.is_default=1 AND keys.key_name=?");
548  statement.bind(1, keyName.wireEncode(), SQLITE_TRANSIENT);
549 
550  if (statement.step() == SQLITE_ROW)
551  return IdentityCertificate(statement.getBlock(0));
552  else
553  BOOST_THROW_EXCEPTION(Pib::Error("Certificate does not exit"));
554 }
555 
556 } // namespace security
557 } // namespace ndn
virtual bool hasCertificate(const Name &certName) const final
Check the existence of a certificate with name certName.
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 of .
represents a non-semantic error
Definition: pib-impl.hpp:46
Copyright (c) 2011-2015 Regents of the University of California.
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.
virtual void addIdentity(const Name &identity) final
Add an identity.
virtual PublicKey getKeyBits(const Name &identity, const name::Component &keyId) const final
Get the key bits of a key.
virtual name::Component getDefaultKeyOfIdentity(const Name &identity) const final
Get the id of the default key of an identity with name identity.
virtual void removeIdentity(const Name &identity) final
Remove an identity.
virtual bool hasKey(const Name &identity, const name::Component &keyId) const final
Check the existence of a key.
size_t wireEncode(EncodingImpl< TAG > &encoder) const
Fast encoding or block size estimation.
Definition: name.cpp:69
static Name getKeyName(const Name &identity, const name::Component &keyId)
PublicKey & getPublicKeyInfo()
represents a semantic error
Definition: pib.hpp:55
const Name & getName() const
Get name of the Data packet.
Definition: data.hpp:343
size_t wireEncode(EncodingImpl< TAG > &encoder, bool wantUnsignedPortionOnly=false) const
Fast encoding or block size estimation.
Definition: data.cpp:52
uint8_t * buf()
Definition: buffer.hpp:87
virtual IdentityCertificate getDefaultCertificateOfKey(const Name &identity, const name::Component &keyId) const final
Get the default certificate of a key with id of .
virtual std::string getTpmLocator() const final
Get TPM Locator.
virtual std::set< name::Component > getKeysOfIdentity(const Name &identity) const final
Get all the key ids of an identity with name identity.
KeyType getKeyType() const
Definition: public-key.hpp:83
Name abstraction to represent an absolute name.
Definition: name.hpp:46
virtual void setTpmLocator(const std::string &tpmLocator) final
Set the corresponding TPM information to tpmLocator.
virtual bool hasIdentity(const Name &identity) const final
Check the existence of an identity.
const Name & getPublicKeyName() const
virtual void removeCertificate(const Name &certName) final
Remove a certificate with name certName.
virtual Name getDefaultIdentity() const final
Get the default identity.
virtual std::set< Name > getIdentities() const final
Get the name of all the identities.
virtual void addKey(const Name &identity, const name::Component &keyId, const PublicKey &publicKey) final
Add a key.
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.
Component holds a read-only name component value.
const Buffer & get() const
Definition: public-key.hpp:70
virtual IdentityCertificate getCertificate(const Name &certName) const final
Get a certificate with name certName.
Name & append(const uint8_t *value, size_t valueLength)
Append a new component, copying from value of length valueLength.
Definition: name.hpp:148
static const string INITIALIZATION
Definition: pib-sqlite3.cpp:38
PartialName getPrefix(ssize_t nComponents) const
Extract a prefix (PartialName) of the name, containing first nComponents components.
Definition: name.hpp:249
virtual void removeKey(const Name &identity, const name::Component &keyId) final
Remove a key.
~PibSqlite3()
Destruct and cleanup internal state.
const Component & get(ssize_t i) const
Get the component at the given index.
Definition: name.hpp:419
virtual void addCertificate(const IdentityCertificate &certificate) final
Add a certificate.