blob: 829a5093d2468a18b5b9aca5fd5ff7ae00fcd652 [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"
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"
Mickey Sweatt11314b72015-06-10 17:20:19 -0700103 " key_bits BLOB NOT NULL, \n"
104 " is_default INTEGER DEFAULT 0, \n"
105 " FOREIGN KEY(identity_id) \n"
106 " REFERENCES identities(id) \n"
107 " ON DELETE CASCADE \n"
108 " ON UPDATE CASCADE \n"
109 " ); \n"
110 " \n"
111 "CREATE UNIQUE INDEX IF NOT EXISTS \n"
112 " keyIndex ON keys(key_name); \n"
113 " \n"
114 "CREATE TRIGGER IF NOT EXISTS \n"
115 " key_default_before_insert_trigger \n"
116 " BEFORE INSERT ON keys \n"
117 " FOR EACH ROW \n"
118 " WHEN NEW.is_default=1 \n"
119 " BEGIN \n"
120 " UPDATE keys \n"
121 " SET is_default=0 \n"
122 " WHERE identity_id=NEW.identity_id; \n"
123 " END; \n"
124 " \n"
125 "CREATE TRIGGER IF NOT EXISTS \n"
126 " key_default_after_insert_trigger \n"
127 " AFTER INSERT ON keys \n"
128 " FOR EACH ROW \n"
129 " WHEN NOT EXISTS \n"
130 " (SELECT id \n"
131 " FROM keys \n"
132 " WHERE is_default=1 \n"
133 " AND identity_id=NEW.identity_id) \n"
134 " BEGIN \n"
135 " UPDATE keys \n"
136 " SET is_default=1 \n"
137 " WHERE key_name=NEW.key_name; \n"
138 " END; \n"
139 " \n"
140 "CREATE TRIGGER IF NOT EXISTS \n"
141 " key_default_update_trigger \n"
142 " BEFORE UPDATE ON keys \n"
143 " FOR EACH ROW \n"
144 " WHEN NEW.is_default=1 AND OLD.is_default=0 \n"
145 " BEGIN \n"
146 " UPDATE keys \n"
147 " SET is_default=0 \n"
148 " WHERE identity_id=NEW.identity_id; \n"
149 " END; \n"
150 " \n"
151 " \n"
152 "CREATE TABLE IF NOT EXISTS \n"
153 " certificates( \n"
154 " id INTEGER PRIMARY KEY,\n"
155 " key_id INTEGER NOT NULL, \n"
156 " certificate_name BLOB NOT NULL, \n"
157 " certificate_data BLOB NOT NULL, \n"
158 " is_default INTEGER DEFAULT 0, \n"
159 " FOREIGN KEY(key_id) \n"
160 " REFERENCES keys(id) \n"
161 " ON DELETE CASCADE \n"
162 " ON UPDATE CASCADE \n"
163 " ); \n"
164 " \n"
165 "CREATE UNIQUE INDEX IF NOT EXISTS \n"
166 " certIndex ON certificates(certificate_name);\n"
167 " \n"
168 "CREATE TRIGGER IF NOT EXISTS \n"
169 " cert_default_before_insert_trigger \n"
170 " BEFORE INSERT ON certificates \n"
171 " FOR EACH ROW \n"
172 " WHEN NEW.is_default=1 \n"
173 " BEGIN \n"
174 " UPDATE certificates \n"
175 " SET is_default=0 \n"
176 " WHERE key_id=NEW.key_id; \n"
177 " END; \n"
178 " \n"
179 "CREATE TRIGGER IF NOT EXISTS \n"
180 " cert_default_after_insert_trigger \n"
181 " AFTER INSERT ON certificates \n"
182 " FOR EACH ROW \n"
183 " WHEN NOT EXISTS \n"
184 " (SELECT id \n"
185 " FROM certificates \n"
186 " WHERE is_default=1 \n"
187 " AND key_id=NEW.key_id) \n"
188 " BEGIN \n"
189 " UPDATE certificates \n"
190 " SET is_default=1 \n"
191 " WHERE certificate_name=NEW.certificate_name;\n"
192 " END; \n"
193 " \n"
194 "CREATE TRIGGER IF NOT EXISTS \n"
195 " cert_default_update_trigger \n"
196 " BEFORE UPDATE ON certificates \n"
197 " FOR EACH ROW \n"
198 " WHEN NEW.is_default=1 AND OLD.is_default=0 \n"
199 " BEGIN \n"
200 " UPDATE certificates \n"
201 " SET is_default=0 \n"
202 " WHERE key_id=NEW.key_id; \n"
203 " END; \n";
204
Mickey Sweatt11314b72015-06-10 17:20:19 -0700205PibSqlite3::PibSqlite3(const string& dir)
206{
207 // Determine the path of PIB DB
Yingdi Yu6ee2d362015-07-16 21:48:05 -0700208 boost::filesystem::path dbDir;
209 if (!dir.empty()) {
210 dbDir = boost::filesystem::path(dir);
211 }
Alexander Afanasyev57e00362016-06-23 13:22:54 -0700212#ifdef NDN_CXX_HAVE_TESTS
Yingdi Yu6ee2d362015-07-16 21:48:05 -0700213 else if (getenv("TEST_HOME") != nullptr) {
214 dbDir = boost::filesystem::path(getenv("TEST_HOME")) / ".ndn";
215 }
Alexander Afanasyev57e00362016-06-23 13:22:54 -0700216#endif // NDN_CXX_HAVE_TESTS
Yingdi Yu6ee2d362015-07-16 21:48:05 -0700217 else if (getenv("HOME") != nullptr) {
218 dbDir = boost::filesystem::path(getenv("HOME")) / ".ndn";
Mickey Sweatt11314b72015-06-10 17:20:19 -0700219 }
220 else {
Yingdi Yu6ee2d362015-07-16 21:48:05 -0700221 dbDir = boost::filesystem::current_path() / ".ndn";
Mickey Sweatt11314b72015-06-10 17:20:19 -0700222 }
Yingdi Yu6ee2d362015-07-16 21:48:05 -0700223 boost::filesystem::create_directories(dbDir);
Alexander Afanasyev57e00362016-06-23 13:22:54 -0700224
Mickey Sweatt11314b72015-06-10 17:20:19 -0700225 // Open PIB
Yingdi Yu6ee2d362015-07-16 21:48:05 -0700226 int result = sqlite3_open_v2((dbDir / "pib.db").c_str(), &m_database,
Mickey Sweatt11314b72015-06-10 17:20:19 -0700227 SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE,
228#ifdef NDN_CXX_DISABLE_SQLITE3_FS_LOCKING
229 "unix-dotfile"
230#else
231 nullptr
232#endif
233 );
234
Yingdi Yu6ee2d362015-07-16 21:48:05 -0700235 if (result != SQLITE_OK) {
236 BOOST_THROW_EXCEPTION(PibImpl::Error("PIB database cannot be opened/created in " + dir));
237 }
Mickey Sweatt11314b72015-06-10 17:20:19 -0700238
239 // enable foreign key
240 sqlite3_exec(m_database, "PRAGMA foreign_keys=ON", nullptr, nullptr, nullptr);
241
242 // initialize PIB tables
243 char* errorMessage = nullptr;
244 result = sqlite3_exec(m_database, INITIALIZATION.c_str(), nullptr, nullptr, &errorMessage);
245 if (result != SQLITE_OK && errorMessage != nullptr) {
246 sqlite3_free(errorMessage);
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700247 BOOST_THROW_EXCEPTION(PibImpl::Error("PIB DB cannot be initialized"));
Mickey Sweatt11314b72015-06-10 17:20:19 -0700248 }
249}
250
251PibSqlite3::~PibSqlite3()
252{
253 sqlite3_close(m_database);
254}
255
256void
257PibSqlite3::setTpmLocator(const std::string& tpmLocator)
258{
259 Sqlite3Statement statement(m_database, "UPDATE tpmInfo SET tpm_locator=?");
260 statement.bind(1, tpmLocator, SQLITE_TRANSIENT);
261 statement.step();
262
Yingdi Yu6ee2d362015-07-16 21:48:05 -0700263 if (sqlite3_changes(m_database) == 0) {
264 // no row is updated, tpm_locator does not exist, insert it directly
Mickey Sweatt11314b72015-06-10 17:20:19 -0700265 Sqlite3Statement insertStatement(m_database, "INSERT INTO tpmInfo (tpm_locator) values (?)");
266 insertStatement.bind(1, tpmLocator, SQLITE_TRANSIENT);
267 insertStatement.step();
268 }
269}
270
271std::string
272PibSqlite3::getTpmLocator() const
273{
274 Sqlite3Statement statement(m_database, "SELECT tpm_locator FROM tpmInfo");
275 int res = statement.step();
276
277 string tpmLocator;
278 if (res == SQLITE_ROW)
279 return statement.getString(0);
280 else
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700281 BOOST_THROW_EXCEPTION(Pib::Error("TPM info does not exist"));
Mickey Sweatt11314b72015-06-10 17:20:19 -0700282}
283
284bool
285PibSqlite3::hasIdentity(const Name& identity) const
286{
287 Sqlite3Statement statement(m_database, "SELECT id FROM identities WHERE identity=?");
288 statement.bind(1, identity.wireEncode(), SQLITE_TRANSIENT);
289 return (statement.step() == SQLITE_ROW);
290}
291
292void
293PibSqlite3::addIdentity(const Name& identity)
294{
295 Sqlite3Statement statement(m_database, "INSERT INTO identities (identity) values (?)");
296 statement.bind(1, identity.wireEncode(), SQLITE_TRANSIENT);
297 statement.step();
298}
299
300void
301PibSqlite3::removeIdentity(const Name& identity)
302{
303 Sqlite3Statement statement(m_database, "DELETE FROM identities WHERE identity=?");
304 statement.bind(1, identity.wireEncode(), SQLITE_TRANSIENT);
305 statement.step();
306}
307
308std::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 Yu6ee2d362015-07-16 21:48:05 -0700340PibSqlite3::hasKey(const Name& keyName) const
Mickey Sweatt11314b72015-06-10 17:20:19 -0700341{
Mickey Sweatt11314b72015-06-10 17:20:19 -0700342 Sqlite3Statement statement(m_database, "SELECT id FROM keys WHERE key_name=?");
343 statement.bind(1, keyName.wireEncode(), SQLITE_TRANSIENT);
344
345 return (statement.step() == SQLITE_ROW);
346}
347
348void
Yingdi Yu6ee2d362015-07-16 21:48:05 -0700349PibSqlite3::addKey(const Name& identity, const Name& keyName,
350 const uint8_t* key, size_t keyLen)
Mickey Sweatt11314b72015-06-10 17:20:19 -0700351{
Yingdi Yu6ee2d362015-07-16 21:48:05 -0700352 if (hasKey(keyName)) {
Mickey Sweatt11314b72015-06-10 17:20:19 -0700353 return;
354 }
355
356 // ensure identity exists
357 addIdentity(identity);
358
Mickey Sweatt11314b72015-06-10 17:20:19 -0700359 Sqlite3Statement statement(m_database,
Yingdi Yu6ee2d362015-07-16 21:48:05 -0700360 "INSERT INTO keys (identity_id, key_name, key_bits) "
361 "VALUES ((SELECT id FROM identities WHERE identity=?), ?, ?)");
Mickey Sweatt11314b72015-06-10 17:20:19 -0700362 statement.bind(1, identity.wireEncode(), SQLITE_TRANSIENT);
363 statement.bind(2, keyName.wireEncode(), SQLITE_TRANSIENT);
Yingdi Yu6ee2d362015-07-16 21:48:05 -0700364 statement.bind(3, key, keyLen, SQLITE_STATIC);
Mickey Sweatt11314b72015-06-10 17:20:19 -0700365 statement.step();
366}
367
368void
Yingdi Yu6ee2d362015-07-16 21:48:05 -0700369PibSqlite3::removeKey(const Name& keyName)
Mickey Sweatt11314b72015-06-10 17:20:19 -0700370{
Mickey Sweatt11314b72015-06-10 17:20:19 -0700371 Sqlite3Statement statement(m_database, "DELETE FROM keys WHERE key_name=?");
372 statement.bind(1, keyName.wireEncode(), SQLITE_TRANSIENT);
373 statement.step();
374}
375
Yingdi Yu6ee2d362015-07-16 21:48:05 -0700376Buffer
377PibSqlite3::getKeyBits(const Name& keyName) const
Mickey Sweatt11314b72015-06-10 17:20:19 -0700378{
Mickey Sweatt11314b72015-06-10 17:20:19 -0700379 Sqlite3Statement statement(m_database, "SELECT key_bits FROM keys WHERE key_name=?");
380 statement.bind(1, keyName.wireEncode(), SQLITE_TRANSIENT);
381
382 if (statement.step() == SQLITE_ROW)
Yingdi Yu6ee2d362015-07-16 21:48:05 -0700383 return Buffer(statement.getBlob(0), statement.getSize(0));
Mickey Sweatt11314b72015-06-10 17:20:19 -0700384 else
Yingdi Yu6ee2d362015-07-16 21:48:05 -0700385 BOOST_THROW_EXCEPTION(Pib::Error("Key `" + keyName.toUri() + "` does not exist"));
Mickey Sweatt11314b72015-06-10 17:20:19 -0700386}
387
Yingdi Yu6ee2d362015-07-16 21:48:05 -0700388std::set<Name>
Mickey Sweatt11314b72015-06-10 17:20:19 -0700389PibSqlite3::getKeysOfIdentity(const Name& identity) const
390{
Yingdi Yu6ee2d362015-07-16 21:48:05 -0700391 std::set<Name> keyNames;
Mickey Sweatt11314b72015-06-10 17:20:19 -0700392
393 Sqlite3Statement statement(m_database,
394 "SELECT key_name "
395 "FROM keys JOIN identities ON keys.identity_id=identities.id "
396 "WHERE identities.identity=?");
397 statement.bind(1, identity.wireEncode(), SQLITE_TRANSIENT);
398
399 while (statement.step() == SQLITE_ROW) {
Yingdi Yu6ee2d362015-07-16 21:48:05 -0700400 keyNames.insert(Name(statement.getBlock(0)));
Mickey Sweatt11314b72015-06-10 17:20:19 -0700401 }
402
403 return keyNames;
404}
405
406void
Yingdi Yu6ee2d362015-07-16 21:48:05 -0700407PibSqlite3::setDefaultKeyOfIdentity(const Name& identity, const Name& keyName)
Mickey Sweatt11314b72015-06-10 17:20:19 -0700408{
Yingdi Yu6ee2d362015-07-16 21:48:05 -0700409 if (!hasKey(keyName)) {
410 BOOST_THROW_EXCEPTION(Pib::Error("Key `" + keyName.toUri() + "` does not exist"));
Mickey Sweatt11314b72015-06-10 17:20:19 -0700411 }
412
413 Sqlite3Statement statement(m_database, "UPDATE keys SET is_default=1 WHERE key_name=?");
414 statement.bind(1, keyName.wireEncode(), SQLITE_TRANSIENT);
415 statement.step();
416}
417
Yingdi Yu6ee2d362015-07-16 21:48:05 -0700418Name
Mickey Sweatt11314b72015-06-10 17:20:19 -0700419PibSqlite3::getDefaultKeyOfIdentity(const Name& identity) const
420{
421 if (!hasIdentity(identity)) {
Yingdi Yu6ee2d362015-07-16 21:48:05 -0700422 BOOST_THROW_EXCEPTION(Pib::Error("Identity `" + identity.toUri() + "` does not exist"));
Mickey Sweatt11314b72015-06-10 17:20:19 -0700423 }
424
425 Sqlite3Statement statement(m_database,
426 "SELECT key_name "
427 "FROM keys JOIN identities ON keys.identity_id=identities.id "
428 "WHERE identities.identity=? AND keys.is_default=1");
429 statement.bind(1, identity.wireEncode(), SQLITE_TRANSIENT);
430
431 if (statement.step() == SQLITE_ROW) {
Yingdi Yu6ee2d362015-07-16 21:48:05 -0700432 return Name(statement.getBlock(0));
Mickey Sweatt11314b72015-06-10 17:20:19 -0700433 }
434 else
Yingdi Yu6ee2d362015-07-16 21:48:05 -0700435 BOOST_THROW_EXCEPTION(Pib::Error("No default key for identity `" + identity.toUri() + "`"));
Mickey Sweatt11314b72015-06-10 17:20:19 -0700436}
437
438bool
439PibSqlite3::hasCertificate(const Name& certName) const
440{
441 Sqlite3Statement statement(m_database, "SELECT id FROM certificates WHERE certificate_name=?");
442 statement.bind(1, certName.wireEncode(), SQLITE_TRANSIENT);
443 return (statement.step() == SQLITE_ROW);
444}
445
446void
Yingdi Yu6ee2d362015-07-16 21:48:05 -0700447PibSqlite3::addCertificate(const v2::Certificate& certificate)
Mickey Sweatt11314b72015-06-10 17:20:19 -0700448{
Mickey Sweatt11314b72015-06-10 17:20:19 -0700449 // ensure key exists
Yingdi Yu6ee2d362015-07-16 21:48:05 -0700450 const Block& content = certificate.getContent();
451 addKey(certificate.getIdentity(), certificate.getKeyName(), content.value(), content.value_size());
Mickey Sweatt11314b72015-06-10 17:20:19 -0700452
453 Sqlite3Statement statement(m_database,
454 "INSERT INTO certificates "
455 "(key_id, certificate_name, certificate_data) "
456 "VALUES ((SELECT id FROM keys WHERE key_name=?), ?, ?)");
Yingdi Yu6ee2d362015-07-16 21:48:05 -0700457 statement.bind(1, certificate.getKeyName().wireEncode(), SQLITE_TRANSIENT);
458 statement.bind(2, certificate.getName().wireEncode(), SQLITE_TRANSIENT);
Mickey Sweatt11314b72015-06-10 17:20:19 -0700459 statement.bind(3, certificate.wireEncode(), SQLITE_STATIC);
460 statement.step();
461}
462
463void
464PibSqlite3::removeCertificate(const Name& certName)
465{
466 Sqlite3Statement statement(m_database, "DELETE FROM certificates WHERE certificate_name=?");
467 statement.bind(1, certName.wireEncode(), SQLITE_TRANSIENT);
468 statement.step();
469}
470
Yingdi Yu6ee2d362015-07-16 21:48:05 -0700471v2::Certificate
Mickey Sweatt11314b72015-06-10 17:20:19 -0700472PibSqlite3::getCertificate(const Name& certName) const
473{
474 Sqlite3Statement statement(m_database,
475 "SELECT certificate_data FROM certificates WHERE certificate_name=?");
476 statement.bind(1, certName.wireEncode(), SQLITE_TRANSIENT);
477
478 if (statement.step() == SQLITE_ROW)
Yingdi Yu6ee2d362015-07-16 21:48:05 -0700479 return v2::Certificate(statement.getBlock(0));
Mickey Sweatt11314b72015-06-10 17:20:19 -0700480 else
Yingdi Yu6ee2d362015-07-16 21:48:05 -0700481 BOOST_THROW_EXCEPTION(Pib::Error("Certificate `" + certName.toUri() + "` does not exit"));
Mickey Sweatt11314b72015-06-10 17:20:19 -0700482}
483
484std::set<Name>
Yingdi Yu6ee2d362015-07-16 21:48:05 -0700485PibSqlite3::getCertificatesOfKey(const Name& keyName) const
Mickey Sweatt11314b72015-06-10 17:20:19 -0700486{
487 std::set<Name> certNames;
488
Mickey Sweatt11314b72015-06-10 17:20:19 -0700489 Sqlite3Statement statement(m_database,
490 "SELECT certificate_name "
491 "FROM certificates JOIN keys ON certificates.key_id=keys.id "
492 "WHERE keys.key_name=?");
493 statement.bind(1, keyName.wireEncode(), SQLITE_TRANSIENT);
494
495 while (statement.step() == SQLITE_ROW)
496 certNames.insert(Name(statement.getBlock(0)));
497
498 return certNames;
499}
500
501void
Yingdi Yu6ee2d362015-07-16 21:48:05 -0700502PibSqlite3::setDefaultCertificateOfKey(const Name& keyName, const Name& certName)
Mickey Sweatt11314b72015-06-10 17:20:19 -0700503{
504 if (!hasCertificate(certName)) {
Yingdi Yu6ee2d362015-07-16 21:48:05 -0700505 BOOST_THROW_EXCEPTION(Pib::Error("Certificate `" + certName.toUri() + "` does not exist"));
Mickey Sweatt11314b72015-06-10 17:20:19 -0700506 }
507
508 Sqlite3Statement statement(m_database,
509 "UPDATE certificates SET is_default=1 WHERE certificate_name=?");
510 statement.bind(1, certName.wireEncode(), SQLITE_TRANSIENT);
511 statement.step();
512}
513
Yingdi Yu6ee2d362015-07-16 21:48:05 -0700514v2::Certificate
515PibSqlite3::getDefaultCertificateOfKey(const Name& keyName) const
Mickey Sweatt11314b72015-06-10 17:20:19 -0700516{
Mickey Sweatt11314b72015-06-10 17:20:19 -0700517 Sqlite3Statement statement(m_database,
518 "SELECT certificate_data "
519 "FROM certificates JOIN keys ON certificates.key_id=keys.id "
520 "WHERE certificates.is_default=1 AND keys.key_name=?");
521 statement.bind(1, keyName.wireEncode(), SQLITE_TRANSIENT);
522
523 if (statement.step() == SQLITE_ROW)
Yingdi Yu6ee2d362015-07-16 21:48:05 -0700524 return v2::Certificate(statement.getBlock(0));
Mickey Sweatt11314b72015-06-10 17:20:19 -0700525 else
Yingdi Yu6ee2d362015-07-16 21:48:05 -0700526 BOOST_THROW_EXCEPTION(Pib::Error("No default certificate for key `" + keyName.toUri() + "`"));
Mickey Sweatt11314b72015-06-10 17:20:19 -0700527}
528
Yingdi Yu6ee2d362015-07-16 21:48:05 -0700529} // namespace pib
Mickey Sweatt11314b72015-06-10 17:20:19 -0700530} // namespace security
531} // namespace ndn