blob: b19f32c989bb34a3e68dd3c6576ec065c0a82774 [file] [log] [blame]
Mickey Sweatt11314b72015-06-10 17:20:19 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Yingdi Yu6ee2d362015-07-16 21:48:05 -07003 * Copyright (c) 2013-2017 Regents of the University of California.
Mickey Sweatt11314b72015-06-10 17:20:19 -07004 *
5 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
6 *
7 * ndn-cxx library is free software: you can redistribute it and/or modify it under the
8 * terms of the GNU Lesser General Public License as published by the Free Software
9 * Foundation, either version 3 of the License, or (at your option) any later version.
10 *
11 * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
12 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
13 * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
14 *
15 * You should have received copies of the GNU General Public License and GNU Lesser
16 * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
17 * <http://www.gnu.org/licenses/>.
18 *
19 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
20 */
21
22#include "pib-sqlite3.hpp"
Mickey Sweatt11314b72015-06-10 17:20:19 -070023#include "pib.hpp"
Yingdi Yu6ee2d362015-07-16 21:48:05 -070024#include "../security-common.hpp"
25#include "../../util/sqlite3-statement.hpp"
Mickey Sweatt11314b72015-06-10 17:20:19 -070026
27#include <sqlite3.h>
28#include <boost/filesystem.hpp>
29#include <boost/algorithm/string.hpp>
30
31namespace ndn {
32namespace security {
Yingdi Yu6ee2d362015-07-16 21:48:05 -070033namespace pib {
Mickey Sweatt11314b72015-06-10 17:20:19 -070034
35using std::string;
36using util::Sqlite3Statement;
37
38static const string INITIALIZATION =
39 "CREATE TABLE IF NOT EXISTS \n"
40 " tpmInfo( \n"
41 " tpm_locator BLOB \n"
42 " ); \n"
43 " \n"
Mickey Sweatt11314b72015-06-10 17:20:19 -070044 "CREATE TABLE IF NOT EXISTS \n"
45 " identities( \n"
46 " id INTEGER PRIMARY KEY,\n"
47 " identity BLOB NOT NULL, \n"
48 " is_default INTEGER DEFAULT 0 \n"
49 " ); \n"
50 " \n"
51 "CREATE UNIQUE INDEX IF NOT EXISTS \n"
52 " identityIndex ON identities(identity); \n"
53 " \n"
54 "CREATE TRIGGER IF NOT EXISTS \n"
55 " identity_default_before_insert_trigger \n"
56 " BEFORE INSERT ON identities \n"
57 " FOR EACH ROW \n"
58 " WHEN NEW.is_default=1 \n"
59 " BEGIN \n"
60 " UPDATE identities SET is_default=0; \n"
61 " END; \n"
62 " \n"
63 "CREATE TRIGGER IF NOT EXISTS \n"
64 " identity_default_after_insert_trigger \n"
65 " AFTER INSERT ON identities \n"
66 " FOR EACH ROW \n"
67 " WHEN NOT EXISTS \n"
68 " (SELECT id \n"
69 " FROM identities \n"
70 " WHERE is_default=1) \n"
71 " BEGIN \n"
72 " UPDATE identities \n"
73 " SET is_default=1 \n"
74 " WHERE identity=NEW.identity; \n"
75 " END; \n"
76 " \n"
77 "CREATE TRIGGER IF NOT EXISTS \n"
78 " identity_default_update_trigger \n"
79 " BEFORE UPDATE ON identities \n"
80 " FOR EACH ROW \n"
81 " WHEN NEW.is_default=1 AND OLD.is_default=0 \n"
82 " BEGIN \n"
83 " UPDATE identities SET is_default=0; \n"
84 " END; \n"
85 " \n"
86 " \n"
87 "CREATE TABLE IF NOT EXISTS \n"
88 " keys( \n"
89 " id INTEGER PRIMARY KEY,\n"
90 " identity_id INTEGER NOT NULL, \n"
91 " key_name BLOB NOT NULL, \n"
Mickey Sweatt11314b72015-06-10 17:20:19 -070092 " key_bits BLOB NOT NULL, \n"
93 " is_default INTEGER DEFAULT 0, \n"
94 " FOREIGN KEY(identity_id) \n"
95 " REFERENCES identities(id) \n"
96 " ON DELETE CASCADE \n"
97 " ON UPDATE CASCADE \n"
98 " ); \n"
99 " \n"
100 "CREATE UNIQUE INDEX IF NOT EXISTS \n"
101 " keyIndex ON keys(key_name); \n"
102 " \n"
103 "CREATE TRIGGER IF NOT EXISTS \n"
104 " key_default_before_insert_trigger \n"
105 " BEFORE INSERT ON keys \n"
106 " FOR EACH ROW \n"
107 " WHEN NEW.is_default=1 \n"
108 " BEGIN \n"
109 " UPDATE keys \n"
110 " SET is_default=0 \n"
111 " WHERE identity_id=NEW.identity_id; \n"
112 " END; \n"
113 " \n"
114 "CREATE TRIGGER IF NOT EXISTS \n"
115 " key_default_after_insert_trigger \n"
116 " AFTER INSERT ON keys \n"
117 " FOR EACH ROW \n"
118 " WHEN NOT EXISTS \n"
119 " (SELECT id \n"
120 " FROM keys \n"
121 " WHERE is_default=1 \n"
122 " AND identity_id=NEW.identity_id) \n"
123 " BEGIN \n"
124 " UPDATE keys \n"
125 " SET is_default=1 \n"
126 " WHERE key_name=NEW.key_name; \n"
127 " END; \n"
128 " \n"
129 "CREATE TRIGGER IF NOT EXISTS \n"
130 " key_default_update_trigger \n"
131 " BEFORE UPDATE ON keys \n"
132 " FOR EACH ROW \n"
133 " WHEN NEW.is_default=1 AND OLD.is_default=0 \n"
134 " BEGIN \n"
135 " UPDATE keys \n"
136 " SET is_default=0 \n"
137 " WHERE identity_id=NEW.identity_id; \n"
138 " END; \n"
139 " \n"
140 " \n"
141 "CREATE TABLE IF NOT EXISTS \n"
142 " certificates( \n"
143 " id INTEGER PRIMARY KEY,\n"
144 " key_id INTEGER NOT NULL, \n"
145 " certificate_name BLOB NOT NULL, \n"
146 " certificate_data BLOB NOT NULL, \n"
147 " is_default INTEGER DEFAULT 0, \n"
148 " FOREIGN KEY(key_id) \n"
149 " REFERENCES keys(id) \n"
150 " ON DELETE CASCADE \n"
151 " ON UPDATE CASCADE \n"
152 " ); \n"
153 " \n"
154 "CREATE UNIQUE INDEX IF NOT EXISTS \n"
155 " certIndex ON certificates(certificate_name);\n"
156 " \n"
157 "CREATE TRIGGER IF NOT EXISTS \n"
158 " cert_default_before_insert_trigger \n"
159 " BEFORE INSERT ON certificates \n"
160 " FOR EACH ROW \n"
161 " WHEN NEW.is_default=1 \n"
162 " BEGIN \n"
163 " UPDATE certificates \n"
164 " SET is_default=0 \n"
165 " WHERE key_id=NEW.key_id; \n"
166 " END; \n"
167 " \n"
168 "CREATE TRIGGER IF NOT EXISTS \n"
169 " cert_default_after_insert_trigger \n"
170 " AFTER INSERT ON certificates \n"
171 " FOR EACH ROW \n"
172 " WHEN NOT EXISTS \n"
173 " (SELECT id \n"
174 " FROM certificates \n"
175 " WHERE is_default=1 \n"
176 " AND key_id=NEW.key_id) \n"
177 " BEGIN \n"
178 " UPDATE certificates \n"
179 " SET is_default=1 \n"
180 " WHERE certificate_name=NEW.certificate_name;\n"
181 " END; \n"
182 " \n"
183 "CREATE TRIGGER IF NOT EXISTS \n"
184 " cert_default_update_trigger \n"
185 " BEFORE UPDATE ON certificates \n"
186 " FOR EACH ROW \n"
187 " WHEN NEW.is_default=1 AND OLD.is_default=0 \n"
188 " BEGIN \n"
189 " UPDATE certificates \n"
190 " SET is_default=0 \n"
191 " WHERE key_id=NEW.key_id; \n"
192 " END; \n";
193
Mickey Sweatt11314b72015-06-10 17:20:19 -0700194PibSqlite3::PibSqlite3(const string& dir)
195{
196 // Determine the path of PIB DB
Yingdi Yu6ee2d362015-07-16 21:48:05 -0700197 boost::filesystem::path dbDir;
198 if (!dir.empty()) {
199 dbDir = boost::filesystem::path(dir);
200 }
Alexander Afanasyev57e00362016-06-23 13:22:54 -0700201#ifdef NDN_CXX_HAVE_TESTS
Yingdi Yu6ee2d362015-07-16 21:48:05 -0700202 else if (getenv("TEST_HOME") != nullptr) {
203 dbDir = boost::filesystem::path(getenv("TEST_HOME")) / ".ndn";
204 }
Alexander Afanasyev57e00362016-06-23 13:22:54 -0700205#endif // NDN_CXX_HAVE_TESTS
Yingdi Yu6ee2d362015-07-16 21:48:05 -0700206 else if (getenv("HOME") != nullptr) {
207 dbDir = boost::filesystem::path(getenv("HOME")) / ".ndn";
Mickey Sweatt11314b72015-06-10 17:20:19 -0700208 }
209 else {
Yingdi Yu6ee2d362015-07-16 21:48:05 -0700210 dbDir = boost::filesystem::current_path() / ".ndn";
Mickey Sweatt11314b72015-06-10 17:20:19 -0700211 }
Yingdi Yu6ee2d362015-07-16 21:48:05 -0700212 boost::filesystem::create_directories(dbDir);
Alexander Afanasyev57e00362016-06-23 13:22:54 -0700213
Mickey Sweatt11314b72015-06-10 17:20:19 -0700214 // Open PIB
Yingdi Yu6ee2d362015-07-16 21:48:05 -0700215 int result = sqlite3_open_v2((dbDir / "pib.db").c_str(), &m_database,
Mickey Sweatt11314b72015-06-10 17:20:19 -0700216 SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE,
217#ifdef NDN_CXX_DISABLE_SQLITE3_FS_LOCKING
218 "unix-dotfile"
219#else
220 nullptr
221#endif
222 );
223
Yingdi Yu6ee2d362015-07-16 21:48:05 -0700224 if (result != SQLITE_OK) {
225 BOOST_THROW_EXCEPTION(PibImpl::Error("PIB database cannot be opened/created in " + dir));
226 }
Mickey Sweatt11314b72015-06-10 17:20:19 -0700227
228 // enable foreign key
229 sqlite3_exec(m_database, "PRAGMA foreign_keys=ON", nullptr, nullptr, nullptr);
230
231 // initialize PIB tables
232 char* errorMessage = nullptr;
233 result = sqlite3_exec(m_database, INITIALIZATION.c_str(), nullptr, nullptr, &errorMessage);
234 if (result != SQLITE_OK && errorMessage != nullptr) {
235 sqlite3_free(errorMessage);
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700236 BOOST_THROW_EXCEPTION(PibImpl::Error("PIB DB cannot be initialized"));
Mickey Sweatt11314b72015-06-10 17:20:19 -0700237 }
238}
239
240PibSqlite3::~PibSqlite3()
241{
242 sqlite3_close(m_database);
243}
244
245void
246PibSqlite3::setTpmLocator(const std::string& tpmLocator)
247{
248 Sqlite3Statement statement(m_database, "UPDATE tpmInfo SET tpm_locator=?");
249 statement.bind(1, tpmLocator, SQLITE_TRANSIENT);
250 statement.step();
251
Yingdi Yu6ee2d362015-07-16 21:48:05 -0700252 if (sqlite3_changes(m_database) == 0) {
253 // no row is updated, tpm_locator does not exist, insert it directly
Mickey Sweatt11314b72015-06-10 17:20:19 -0700254 Sqlite3Statement insertStatement(m_database, "INSERT INTO tpmInfo (tpm_locator) values (?)");
255 insertStatement.bind(1, tpmLocator, SQLITE_TRANSIENT);
256 insertStatement.step();
257 }
258}
259
260std::string
261PibSqlite3::getTpmLocator() const
262{
263 Sqlite3Statement statement(m_database, "SELECT tpm_locator FROM tpmInfo");
264 int res = statement.step();
Mickey Sweatt11314b72015-06-10 17:20:19 -0700265 if (res == SQLITE_ROW)
266 return statement.getString(0);
267 else
Yingdi Yu7b3b5e92015-08-13 19:52:35 -0700268 return "";
Mickey Sweatt11314b72015-06-10 17:20:19 -0700269}
270
271bool
272PibSqlite3::hasIdentity(const Name& identity) const
273{
274 Sqlite3Statement statement(m_database, "SELECT id FROM identities WHERE identity=?");
275 statement.bind(1, identity.wireEncode(), SQLITE_TRANSIENT);
276 return (statement.step() == SQLITE_ROW);
277}
278
279void
280PibSqlite3::addIdentity(const Name& identity)
281{
Yingdi Yu03997682015-11-23 16:41:38 -0800282 if (!hasIdentity(identity)) {
283 Sqlite3Statement statement(m_database, "INSERT INTO identities (identity) values (?)");
284 statement.bind(1, identity.wireEncode(), SQLITE_TRANSIENT);
285 statement.step();
286 }
287
288 if (!hasDefaultIdentity()) {
289 setDefaultIdentity(identity);
290 }
Mickey Sweatt11314b72015-06-10 17:20:19 -0700291}
292
293void
294PibSqlite3::removeIdentity(const Name& identity)
295{
296 Sqlite3Statement statement(m_database, "DELETE FROM identities WHERE identity=?");
297 statement.bind(1, identity.wireEncode(), SQLITE_TRANSIENT);
298 statement.step();
299}
300
Yingdi Yu7b3b5e92015-08-13 19:52:35 -0700301void
302PibSqlite3::clearIdentities()
303{
304 Sqlite3Statement statement(m_database, "DELETE FROM identities");
305 statement.step();
306}
307
Mickey Sweatt11314b72015-06-10 17:20:19 -0700308std::set<Name>
309PibSqlite3::getIdentities() const
310{
311 std::set<Name> identities;
312 Sqlite3Statement statement(m_database, "SELECT identity FROM identities");
313
314 while (statement.step() == SQLITE_ROW)
315 identities.insert(Name(statement.getBlock(0)));
316
317 return identities;
318}
319
320void
321PibSqlite3::setDefaultIdentity(const Name& identityName)
322{
323 Sqlite3Statement statement(m_database, "UPDATE identities SET is_default=1 WHERE identity=?");
324 statement.bind(1, identityName.wireEncode(), SQLITE_TRANSIENT);
325 statement.step();
326}
327
328Name
329PibSqlite3::getDefaultIdentity() const
330{
331 Sqlite3Statement statement(m_database, "SELECT identity FROM identities WHERE is_default=1");
332
333 if (statement.step() == SQLITE_ROW)
334 return Name(statement.getBlock(0));
335 else
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700336 BOOST_THROW_EXCEPTION(Pib::Error("No default identity"));
Mickey Sweatt11314b72015-06-10 17:20:19 -0700337}
338
339bool
Yingdi Yu03997682015-11-23 16:41:38 -0800340PibSqlite3::hasDefaultIdentity() const
341{
342 Sqlite3Statement statement(m_database, "SELECT identity FROM identities WHERE is_default=1");
343 return (statement.step() == SQLITE_ROW);
344}
345
346bool
Yingdi Yu6ee2d362015-07-16 21:48:05 -0700347PibSqlite3::hasKey(const Name& keyName) const
Mickey Sweatt11314b72015-06-10 17:20:19 -0700348{
Mickey Sweatt11314b72015-06-10 17:20:19 -0700349 Sqlite3Statement statement(m_database, "SELECT id FROM keys WHERE key_name=?");
350 statement.bind(1, keyName.wireEncode(), SQLITE_TRANSIENT);
351
352 return (statement.step() == SQLITE_ROW);
353}
354
355void
Yingdi Yu6ee2d362015-07-16 21:48:05 -0700356PibSqlite3::addKey(const Name& identity, const Name& keyName,
357 const uint8_t* key, size_t keyLen)
Mickey Sweatt11314b72015-06-10 17:20:19 -0700358{
Mickey Sweatt11314b72015-06-10 17:20:19 -0700359 // ensure identity exists
360 addIdentity(identity);
361
Yingdi Yu03997682015-11-23 16:41:38 -0800362 if (!hasKey(keyName)) {
363 Sqlite3Statement statement(m_database,
364 "INSERT INTO keys (identity_id, key_name, key_bits) "
365 "VALUES ((SELECT id FROM identities WHERE identity=?), ?, ?)");
366 statement.bind(1, identity.wireEncode(), SQLITE_TRANSIENT);
367 statement.bind(2, keyName.wireEncode(), SQLITE_TRANSIENT);
368 statement.bind(3, key, keyLen, SQLITE_STATIC);
369 statement.step();
370 }
371 else {
372 Sqlite3Statement statement(m_database,
373 "UPDATE keys SET key_bits=? WHERE key_name=?");
374 statement.bind(1, key, keyLen, SQLITE_STATIC);
375 statement.bind(2, keyName.wireEncode(), SQLITE_TRANSIENT);
376 statement.step();
377 }
378
379 if (!hasDefaultKeyOfIdentity(identity)) {
380 setDefaultKeyOfIdentity(identity, keyName);
381 }
Mickey Sweatt11314b72015-06-10 17:20:19 -0700382}
383
384void
Yingdi Yu6ee2d362015-07-16 21:48:05 -0700385PibSqlite3::removeKey(const Name& keyName)
Mickey Sweatt11314b72015-06-10 17:20:19 -0700386{
Mickey Sweatt11314b72015-06-10 17:20:19 -0700387 Sqlite3Statement statement(m_database, "DELETE FROM keys WHERE key_name=?");
388 statement.bind(1, keyName.wireEncode(), SQLITE_TRANSIENT);
389 statement.step();
390}
391
Yingdi Yu6ee2d362015-07-16 21:48:05 -0700392Buffer
393PibSqlite3::getKeyBits(const Name& keyName) const
Mickey Sweatt11314b72015-06-10 17:20:19 -0700394{
Mickey Sweatt11314b72015-06-10 17:20:19 -0700395 Sqlite3Statement statement(m_database, "SELECT key_bits FROM keys WHERE key_name=?");
396 statement.bind(1, keyName.wireEncode(), SQLITE_TRANSIENT);
397
398 if (statement.step() == SQLITE_ROW)
Yingdi Yu6ee2d362015-07-16 21:48:05 -0700399 return Buffer(statement.getBlob(0), statement.getSize(0));
Mickey Sweatt11314b72015-06-10 17:20:19 -0700400 else
Yingdi Yu6ee2d362015-07-16 21:48:05 -0700401 BOOST_THROW_EXCEPTION(Pib::Error("Key `" + keyName.toUri() + "` does not exist"));
Mickey Sweatt11314b72015-06-10 17:20:19 -0700402}
403
Yingdi Yu6ee2d362015-07-16 21:48:05 -0700404std::set<Name>
Mickey Sweatt11314b72015-06-10 17:20:19 -0700405PibSqlite3::getKeysOfIdentity(const Name& identity) const
406{
Yingdi Yu6ee2d362015-07-16 21:48:05 -0700407 std::set<Name> keyNames;
Mickey Sweatt11314b72015-06-10 17:20:19 -0700408
409 Sqlite3Statement statement(m_database,
410 "SELECT key_name "
411 "FROM keys JOIN identities ON keys.identity_id=identities.id "
412 "WHERE identities.identity=?");
413 statement.bind(1, identity.wireEncode(), SQLITE_TRANSIENT);
414
415 while (statement.step() == SQLITE_ROW) {
Yingdi Yu6ee2d362015-07-16 21:48:05 -0700416 keyNames.insert(Name(statement.getBlock(0)));
Mickey Sweatt11314b72015-06-10 17:20:19 -0700417 }
418
419 return keyNames;
420}
421
422void
Yingdi Yu6ee2d362015-07-16 21:48:05 -0700423PibSqlite3::setDefaultKeyOfIdentity(const Name& identity, const Name& keyName)
Mickey Sweatt11314b72015-06-10 17:20:19 -0700424{
Yingdi Yu6ee2d362015-07-16 21:48:05 -0700425 if (!hasKey(keyName)) {
426 BOOST_THROW_EXCEPTION(Pib::Error("Key `" + keyName.toUri() + "` does not exist"));
Mickey Sweatt11314b72015-06-10 17:20:19 -0700427 }
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
Yingdi Yu6ee2d362015-07-16 21:48:05 -0700434Name
Mickey Sweatt11314b72015-06-10 17:20:19 -0700435PibSqlite3::getDefaultKeyOfIdentity(const Name& identity) const
436{
437 if (!hasIdentity(identity)) {
Yingdi Yu6ee2d362015-07-16 21:48:05 -0700438 BOOST_THROW_EXCEPTION(Pib::Error("Identity `" + identity.toUri() + "` does not exist"));
Mickey Sweatt11314b72015-06-10 17:20:19 -0700439 }
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) {
Yingdi Yu6ee2d362015-07-16 21:48:05 -0700448 return Name(statement.getBlock(0));
Mickey Sweatt11314b72015-06-10 17:20:19 -0700449 }
450 else
Yingdi Yu6ee2d362015-07-16 21:48:05 -0700451 BOOST_THROW_EXCEPTION(Pib::Error("No default key for identity `" + identity.toUri() + "`"));
Mickey Sweatt11314b72015-06-10 17:20:19 -0700452}
453
454bool
Yingdi Yu03997682015-11-23 16:41:38 -0800455PibSqlite3::hasDefaultKeyOfIdentity(const Name& identity) const
456{
457 Sqlite3Statement statement(m_database,
458 "SELECT key_name "
459 "FROM keys JOIN identities ON keys.identity_id=identities.id "
460 "WHERE identities.identity=? AND keys.is_default=1");
461 statement.bind(1, identity.wireEncode(), SQLITE_TRANSIENT);
462
463 return (statement.step() == SQLITE_ROW);
464}
465
466bool
Mickey Sweatt11314b72015-06-10 17:20:19 -0700467PibSqlite3::hasCertificate(const Name& certName) const
468{
469 Sqlite3Statement statement(m_database, "SELECT id FROM certificates WHERE certificate_name=?");
470 statement.bind(1, certName.wireEncode(), SQLITE_TRANSIENT);
471 return (statement.step() == SQLITE_ROW);
472}
473
474void
Yingdi Yu6ee2d362015-07-16 21:48:05 -0700475PibSqlite3::addCertificate(const v2::Certificate& certificate)
Mickey Sweatt11314b72015-06-10 17:20:19 -0700476{
Mickey Sweatt11314b72015-06-10 17:20:19 -0700477 // ensure key exists
Yingdi Yu6ee2d362015-07-16 21:48:05 -0700478 const Block& content = certificate.getContent();
479 addKey(certificate.getIdentity(), certificate.getKeyName(), content.value(), content.value_size());
Mickey Sweatt11314b72015-06-10 17:20:19 -0700480
Yingdi Yu03997682015-11-23 16:41:38 -0800481 if (!hasCertificate(certificate.getName())) {
482 Sqlite3Statement statement(m_database,
483 "INSERT INTO certificates "
484 "(key_id, certificate_name, certificate_data) "
485 "VALUES ((SELECT id FROM keys WHERE key_name=?), ?, ?)");
486 statement.bind(1, certificate.getKeyName().wireEncode(), SQLITE_TRANSIENT);
487 statement.bind(2, certificate.getName().wireEncode(), SQLITE_TRANSIENT);
488 statement.bind(3, certificate.wireEncode(), SQLITE_STATIC);
489 statement.step();
490 }
491 else {
492 Sqlite3Statement statement(m_database,
493 "UPDATE certificates SET certificate_data=? WHERE certificate_name=?");
494 statement.bind(1, certificate.wireEncode(), SQLITE_STATIC);
495 statement.bind(2, certificate.getName().wireEncode(), SQLITE_TRANSIENT);
496 statement.step();
497 }
498
499 if (!hasDefaultCertificateOfKey(certificate.getKeyName())) {
500 setDefaultCertificateOfKey(certificate.getKeyName(), certificate.getName());
501 }
Mickey Sweatt11314b72015-06-10 17:20:19 -0700502}
503
504void
505PibSqlite3::removeCertificate(const Name& certName)
506{
507 Sqlite3Statement statement(m_database, "DELETE FROM certificates WHERE certificate_name=?");
508 statement.bind(1, certName.wireEncode(), SQLITE_TRANSIENT);
509 statement.step();
510}
511
Yingdi Yu6ee2d362015-07-16 21:48:05 -0700512v2::Certificate
Mickey Sweatt11314b72015-06-10 17:20:19 -0700513PibSqlite3::getCertificate(const Name& certName) const
514{
515 Sqlite3Statement statement(m_database,
516 "SELECT certificate_data FROM certificates WHERE certificate_name=?");
517 statement.bind(1, certName.wireEncode(), SQLITE_TRANSIENT);
518
519 if (statement.step() == SQLITE_ROW)
Yingdi Yu6ee2d362015-07-16 21:48:05 -0700520 return v2::Certificate(statement.getBlock(0));
Mickey Sweatt11314b72015-06-10 17:20:19 -0700521 else
Yingdi Yu6ee2d362015-07-16 21:48:05 -0700522 BOOST_THROW_EXCEPTION(Pib::Error("Certificate `" + certName.toUri() + "` does not exit"));
Mickey Sweatt11314b72015-06-10 17:20:19 -0700523}
524
525std::set<Name>
Yingdi Yu6ee2d362015-07-16 21:48:05 -0700526PibSqlite3::getCertificatesOfKey(const Name& keyName) const
Mickey Sweatt11314b72015-06-10 17:20:19 -0700527{
528 std::set<Name> certNames;
529
Mickey Sweatt11314b72015-06-10 17:20:19 -0700530 Sqlite3Statement statement(m_database,
531 "SELECT certificate_name "
532 "FROM certificates JOIN keys ON certificates.key_id=keys.id "
533 "WHERE keys.key_name=?");
534 statement.bind(1, keyName.wireEncode(), SQLITE_TRANSIENT);
535
536 while (statement.step() == SQLITE_ROW)
537 certNames.insert(Name(statement.getBlock(0)));
538
539 return certNames;
540}
541
542void
Yingdi Yu6ee2d362015-07-16 21:48:05 -0700543PibSqlite3::setDefaultCertificateOfKey(const Name& keyName, const Name& certName)
Mickey Sweatt11314b72015-06-10 17:20:19 -0700544{
545 if (!hasCertificate(certName)) {
Yingdi Yu6ee2d362015-07-16 21:48:05 -0700546 BOOST_THROW_EXCEPTION(Pib::Error("Certificate `" + certName.toUri() + "` does not exist"));
Mickey Sweatt11314b72015-06-10 17:20:19 -0700547 }
548
549 Sqlite3Statement statement(m_database,
550 "UPDATE certificates SET is_default=1 WHERE certificate_name=?");
551 statement.bind(1, certName.wireEncode(), SQLITE_TRANSIENT);
552 statement.step();
553}
554
Yingdi Yu6ee2d362015-07-16 21:48:05 -0700555v2::Certificate
556PibSqlite3::getDefaultCertificateOfKey(const Name& keyName) const
Mickey Sweatt11314b72015-06-10 17:20:19 -0700557{
Mickey Sweatt11314b72015-06-10 17:20:19 -0700558 Sqlite3Statement statement(m_database,
559 "SELECT certificate_data "
560 "FROM certificates JOIN keys ON certificates.key_id=keys.id "
561 "WHERE certificates.is_default=1 AND keys.key_name=?");
562 statement.bind(1, keyName.wireEncode(), SQLITE_TRANSIENT);
563
564 if (statement.step() == SQLITE_ROW)
Yingdi Yu6ee2d362015-07-16 21:48:05 -0700565 return v2::Certificate(statement.getBlock(0));
Mickey Sweatt11314b72015-06-10 17:20:19 -0700566 else
Yingdi Yu6ee2d362015-07-16 21:48:05 -0700567 BOOST_THROW_EXCEPTION(Pib::Error("No default certificate for key `" + keyName.toUri() + "`"));
Mickey Sweatt11314b72015-06-10 17:20:19 -0700568}
569
Yingdi Yu03997682015-11-23 16:41:38 -0800570bool
571PibSqlite3::hasDefaultCertificateOfKey(const Name& keyName) const
572{
573 Sqlite3Statement statement(m_database,
574 "SELECT certificate_data "
575 "FROM certificates JOIN keys ON certificates.key_id=keys.id "
576 "WHERE certificates.is_default=1 AND keys.key_name=?");
577 statement.bind(1, keyName.wireEncode(), SQLITE_TRANSIENT);
578
579 return (statement.step() == SQLITE_ROW);
580}
581
Yingdi Yu6ee2d362015-07-16 21:48:05 -0700582} // namespace pib
Mickey Sweatt11314b72015-06-10 17:20:19 -0700583} // namespace security
584} // namespace ndn