diff options
author | lloyd <[email protected]> | 2012-06-08 22:33:01 +0000 |
---|---|---|
committer | lloyd <[email protected]> | 2012-06-08 22:33:01 +0000 |
commit | a4b2dba2bfea267e1a1535fbe33103f4c2153724 (patch) | |
tree | 4d37fe1951c13fc577c63f512e35dde20511ffad | |
parent | 23d037076cc8ecd9cdce0b6c53b2f0174c5f536c (diff) |
Make a proper wrapper in util for SQLite3, update the TLS session
manager to use it. Add --with-sqlite to configure.py
-rwxr-xr-x | configure.py | 6 | ||||
-rw-r--r-- | src/tls/sessions_sqlite/info.txt | 7 | ||||
-rw-r--r-- | src/tls/sessions_sqlite/tls_sqlite_sess_mgr.cpp | 187 | ||||
-rw-r--r-- | src/tls/sessions_sqlite/tls_sqlite_sess_mgr.h | 6 | ||||
-rw-r--r-- | src/utils/sqlite/info.txt | 14 | ||||
-rw-r--r-- | src/utils/sqlite/sqlite.cpp | 138 | ||||
-rw-r--r-- | src/utils/sqlite/sqlite.h | 68 |
7 files changed, 255 insertions, 171 deletions
diff --git a/configure.py b/configure.py index 32c8bfab5..baad4fd84 100755 --- a/configure.py +++ b/configure.py @@ -341,12 +341,10 @@ def process_command_line(args): mods_group.add_option('--no-autoload', action='store_true', default=False, help='disable automatic loading') - for lib in ['OpenSSL', 'GNU MP', 'Bzip2', 'Zlib']: - - mod = lib.lower().replace(' ', '') + for mod in ['sqlite', 'openssl', 'gnump', 'bzip2', 'zlib']: mods_group.add_option('--with-%s' % (mod), - help='add support for using %s' % (lib), + help='add support for using %s' % (mod), action='append_const', const=mod, dest='enabled_modules') diff --git a/src/tls/sessions_sqlite/info.txt b/src/tls/sessions_sqlite/info.txt index c5fc35952..5761d53ea 100644 --- a/src/tls/sessions_sqlite/info.txt +++ b/src/tls/sessions_sqlite/info.txt @@ -1,11 +1,6 @@ define TLS_SQLITE_SESSION_MANAGER -load_on request - -<libs> -all -> sqlite3 -</libs> - <requires> pbkdf2 +sqlite </requires> diff --git a/src/tls/sessions_sqlite/tls_sqlite_sess_mgr.cpp b/src/tls/sessions_sqlite/tls_sqlite_sess_mgr.cpp index 24efa74f3..dcfc79ed2 100644 --- a/src/tls/sessions_sqlite/tls_sqlite_sess_mgr.cpp +++ b/src/tls/sessions_sqlite/tls_sqlite_sess_mgr.cpp @@ -4,8 +4,9 @@ * * Released under the terms of the Botan license */ - + #include <botan/tls_sqlite_sess_mgr.h> +#include <botan/internal/sqlite.h> #include <botan/internal/assert.h> #include <botan/lookup.h> #include <botan/hex.h> @@ -13,122 +14,10 @@ #include <memory> #include <chrono> -#include <sqlite3.h> - namespace Botan { namespace TLS { -namespace { - -class sqlite3_statement - { - public: - sqlite3_statement(sqlite3* db, const std::string& base_sql) - { - int rc = sqlite3_prepare_v2(db, base_sql.c_str(), -1, &m_stmt, 0); - - if(rc != SQLITE_OK) - throw std::runtime_error("sqlite3_prepare failed " + base_sql + - ", code " + std::to_string(rc)); - } - - void bind(int column, const std::string& val) - { - int rc = sqlite3_bind_text(m_stmt, column, val.c_str(), -1, SQLITE_TRANSIENT); - if(rc != SQLITE_OK) - throw std::runtime_error("sqlite3_bind_text failed, code " + std::to_string(rc)); - } - - void bind(int column, int val) - { - int rc = sqlite3_bind_int(m_stmt, column, val); - if(rc != SQLITE_OK) - throw std::runtime_error("sqlite3_bind_int failed, code " + std::to_string(rc)); - } - - void bind(int column, std::chrono::system_clock::time_point time) - { - const int timeval = std::chrono::duration_cast<std::chrono::seconds>(time.time_since_epoch()).count(); - bind(column, timeval); - } - - void bind(int column, const std::vector<byte>& val) - { - int rc = sqlite3_bind_blob(m_stmt, column, &val[0], val.size(), SQLITE_TRANSIENT); - if(rc != SQLITE_OK) - throw std::runtime_error("sqlite3_bind_text failed, code " + std::to_string(rc)); - } - - std::pair<const byte*, size_t> get_blob(int column) - { - BOTAN_ASSERT(sqlite3_column_type(m_stmt, 0) == SQLITE_BLOB, - "Return value is a blob"); - - const void* session_blob = sqlite3_column_blob(m_stmt, column); - const int session_blob_size = sqlite3_column_bytes(m_stmt, column); - - BOTAN_ASSERT(session_blob_size >= 0, "Blob size is non-negative"); - - return std::make_pair(static_cast<const byte*>(session_blob), - static_cast<size_t>(session_blob_size)); - } - - size_t get_size_t(int column) - { - BOTAN_ASSERT(sqlite3_column_type(m_stmt, column) == SQLITE_INTEGER, - "Return count is an integer"); - - const int sessions_int = sqlite3_column_int(m_stmt, column); - - BOTAN_ASSERT(sessions_int >= 0, "Expected size_t is non-negative"); - - return static_cast<size_t>(sessions_int); - } - - void spin() - { - while(sqlite3_step(m_stmt) == SQLITE_ROW) - {} - } - - int step() - { - return sqlite3_step(m_stmt); - } - - sqlite3_stmt* stmt() { return m_stmt; } - - ~sqlite3_statement() { sqlite3_finalize(m_stmt); } - private: - sqlite3_stmt* m_stmt; - }; - -size_t row_count(sqlite3* db, const std::string& table_name) - { - sqlite3_statement stmt(db, "select count(*) from " + table_name); - - if(stmt.step() == SQLITE_ROW) - return stmt.get_size_t(0); - else - throw std::runtime_error("Querying size of table " + table_name + " failed"); - } - -void create_table(sqlite3* db, const char* table_schema) - { - char* errmsg = 0; - int rc = sqlite3_exec(db, table_schema, 0, 0, &errmsg); - - if(rc != SQLITE_OK) - { - const std::string err_msg = errmsg; - sqlite3_free(errmsg); - sqlite3_close(db); - throw std::runtime_error("sqlite3_exec for table failed - " + err_msg); - } - } - - SymmetricKey derive_key(const std::string& passphrase, const byte salt[], size_t salt_len, @@ -146,8 +35,6 @@ SymmetricKey derive_key(const std::string& passphrase, return SymmetricKey(&x[3], x.size() - 3); } -} - Session_Manager_SQLite::Session_Manager_SQLite(const std::string& passphrase, RandomNumberGenerator& rng, const std::string& db_filename, @@ -157,42 +44,34 @@ Session_Manager_SQLite::Session_Manager_SQLite(const std::string& passphrase, m_max_sessions(max_sessions), m_session_lifetime(session_lifetime) { - int rc = sqlite3_open(db_filename.c_str(), &m_db); - - if(rc) - { - const std::string err_msg = sqlite3_errmsg(m_db); - sqlite3_close(m_db); - throw std::runtime_error("sqlite3_open failed - " + err_msg); - } - - create_table(m_db, - "create table if not exists tls_sessions " - "(" - "session_id TEXT PRIMARY KEY, " - "session_start INTEGER, " - "hostname TEXT, " - "hostport INTEGER, " - "session BLOB" - ")"); - - create_table(m_db, - "create table if not exists tls_sessions_metadata " - "(" - "passphrase_salt BLOB, " - "passphrase_iterations INTEGER, " - "passphrase_check INTEGER " - ")"); - - const size_t salts = row_count(m_db, "tls_sessions_metadata"); + m_db = new sqlite3_database(db_filename); + + m_db->create_table( + "create table if not exists tls_sessions " + "(" + "session_id TEXT PRIMARY KEY, " + "session_start INTEGER, " + "hostname TEXT, " + "hostport INTEGER, " + "session BLOB" + ")"); + + m_db->create_table( + "create table if not exists tls_sessions_metadata " + "(" + "passphrase_salt BLOB, " + "passphrase_iterations INTEGER, " + "passphrase_check INTEGER " + ")"); + + const size_t salts = m_db->row_count("tls_sessions_metadata"); if(salts == 1) { // existing db sqlite3_statement stmt(m_db, "select * from tls_sessions_metadata"); - int rc = stmt.step(); - if(rc == SQLITE_ROW) + if(stmt.step()) { std::pair<const byte*, size_t> salt = stmt.get_blob(0); const size_t iterations = stmt.get_size_t(1); @@ -218,7 +97,7 @@ Session_Manager_SQLite::Session_Manager_SQLite(const std::string& passphrase, // new database case std::vector<byte> salt = unlock(rng.random_vec(16)); - const size_t iterations = 64 * 1024; + const size_t iterations = 256 * 1024; size_t check_val = 0; m_session_key = derive_key(passphrase, &salt[0], salt.size(), @@ -237,7 +116,7 @@ Session_Manager_SQLite::Session_Manager_SQLite(const std::string& passphrase, Session_Manager_SQLite::~Session_Manager_SQLite() { - sqlite3_close(m_db); + delete m_db; } bool Session_Manager_SQLite::load_from_session_id(const std::vector<byte>& session_id, @@ -247,9 +126,7 @@ bool Session_Manager_SQLite::load_from_session_id(const std::vector<byte>& sessi stmt.bind(1, hex_encode(session_id)); - int rc = stmt.step(); - - while(rc == SQLITE_ROW) + while(stmt.step()) { std::pair<const byte*, size_t> blob = stmt.get_blob(0); @@ -261,8 +138,6 @@ bool Session_Manager_SQLite::load_from_session_id(const std::vector<byte>& sessi catch(...) { } - - rc = stmt.step(); } return false; @@ -279,9 +154,7 @@ bool Session_Manager_SQLite::load_from_host_info(const std::string& hostname, stmt.bind(1, hostname); stmt.bind(2, port); - int rc = stmt.step(); - - while(rc == SQLITE_ROW) + while(stmt.step()) { std::pair<const byte*, size_t> blob = stmt.get_blob(0); @@ -293,8 +166,6 @@ bool Session_Manager_SQLite::load_from_host_info(const std::string& hostname, catch(...) { } - - rc = stmt.step(); } return false; @@ -333,7 +204,7 @@ void Session_Manager_SQLite::prune_session_cache() remove_expired.spin(); - const size_t sessions = row_count(m_db, "tls_sessions"); + const size_t sessions = m_db->row_count("tls_sessions"); if(sessions > m_max_sessions) { diff --git a/src/tls/sessions_sqlite/tls_sqlite_sess_mgr.h b/src/tls/sessions_sqlite/tls_sqlite_sess_mgr.h index 923915496..1bcf88892 100644 --- a/src/tls/sessions_sqlite/tls_sqlite_sess_mgr.h +++ b/src/tls/sessions_sqlite/tls_sqlite_sess_mgr.h @@ -11,10 +11,10 @@ #include <botan/tls_session_manager.h> #include <botan/rng.h> -class sqlite3; - namespace Botan { +class sqlite3_database; + namespace TLS { /** @@ -61,7 +61,7 @@ class BOTAN_DLL Session_Manager_SQLite : public Session_Manager RandomNumberGenerator& m_rng; size_t m_max_sessions; std::chrono::seconds m_session_lifetime; - class sqlite3* m_db; + sqlite3_database* m_db; }; } diff --git a/src/utils/sqlite/info.txt b/src/utils/sqlite/info.txt new file mode 100644 index 000000000..9b2fe575d --- /dev/null +++ b/src/utils/sqlite/info.txt @@ -0,0 +1,14 @@ + +load_on request + +<libs> +all -> sqlite3 +</libs> + +<header:internal> +sqlite.h +</header:internal> + +<source> +sqlite.cpp +</source> diff --git a/src/utils/sqlite/sqlite.cpp b/src/utils/sqlite/sqlite.cpp new file mode 100644 index 000000000..b78112e28 --- /dev/null +++ b/src/utils/sqlite/sqlite.cpp @@ -0,0 +1,138 @@ +/* +* SQLite wrapper +* (C) 2012 Jack Lloyd +* +* Released under the terms of the Botan license +*/ + +#include <botan/internal/sqlite.h> +#include <botan/internal/assert.h> +#include <stdexcept> +#include <sqlite3.h> + +namespace Botan { + +sqlite3_database::sqlite3_database(const std::string& db_filename) + { + int rc = ::sqlite3_open(db_filename.c_str(), &m_db); + + if(rc) + { + const std::string err_msg = ::sqlite3_errmsg(m_db); + ::sqlite3_close(m_db); + m_db = nullptr; + throw std::runtime_error("sqlite3_open failed - " + err_msg); + } + } + +sqlite3_database::~sqlite3_database() + { + if(m_db) + ::sqlite3_close(m_db); + m_db = nullptr; + } + +size_t sqlite3_database::row_count(const std::string& table_name) + { + sqlite3_statement stmt(this, "select count(*) from " + table_name); + + if(stmt.step()) + return stmt.get_size_t(0); + else + throw std::runtime_error("Querying size of table " + table_name + " failed"); + } + +void sqlite3_database::create_table(const std::string& table_schema) + { + char* errmsg = 0; + int rc = ::sqlite3_exec(m_db, table_schema.c_str(), 0, 0, &errmsg); + + if(rc != SQLITE_OK) + { + const std::string err_msg = errmsg; + ::sqlite3_free(errmsg); + ::sqlite3_close(m_db); + m_db = nullptr; + throw std::runtime_error("sqlite3_exec for table failed - " + err_msg); + } + } + + +sqlite3_statement::sqlite3_statement(sqlite3_database* db, const std::string& base_sql) + { + int rc = ::sqlite3_prepare_v2(db->m_db, base_sql.c_str(), -1, &m_stmt, 0); + + if(rc != SQLITE_OK) + throw std::runtime_error("sqlite3_prepare failed " + base_sql + + ", code " + std::to_string(rc)); + } + +void sqlite3_statement::bind(int column, const std::string& val) + { + int rc = ::sqlite3_bind_text(m_stmt, column, val.c_str(), -1, SQLITE_TRANSIENT); + if(rc != SQLITE_OK) + throw std::runtime_error("sqlite3_bind_text failed, code " + std::to_string(rc)); + } + +void sqlite3_statement::bind(int column, int val) + { + int rc = ::sqlite3_bind_int(m_stmt, column, val); + if(rc != SQLITE_OK) + throw std::runtime_error("sqlite3_bind_int failed, code " + std::to_string(rc)); + } + +void sqlite3_statement::bind(int column, std::chrono::system_clock::time_point time) + { + const int timeval = std::chrono::duration_cast<std::chrono::seconds>(time.time_since_epoch()).count(); + bind(column, timeval); + } + +void sqlite3_statement::bind(int column, const std::vector<byte>& val) + { + int rc = ::sqlite3_bind_blob(m_stmt, column, &val[0], val.size(), SQLITE_TRANSIENT); + if(rc != SQLITE_OK) + throw std::runtime_error("sqlite3_bind_text failed, code " + std::to_string(rc)); + } + +std::pair<const byte*, size_t> sqlite3_statement::get_blob(int column) + { + BOTAN_ASSERT(::sqlite3_column_type(m_stmt, 0) == SQLITE_BLOB, + "Return value is a blob"); + + const void* session_blob = ::sqlite3_column_blob(m_stmt, column); + const int session_blob_size = ::sqlite3_column_bytes(m_stmt, column); + + BOTAN_ASSERT(session_blob_size >= 0, "Blob size is non-negative"); + + return std::make_pair(static_cast<const byte*>(session_blob), + static_cast<size_t>(session_blob_size)); + } + +size_t sqlite3_statement::get_size_t(int column) + { + BOTAN_ASSERT(::sqlite3_column_type(m_stmt, column) == SQLITE_INTEGER, + "Return count is an integer"); + + const int sessions_int = ::sqlite3_column_int(m_stmt, column); + + BOTAN_ASSERT(sessions_int >= 0, "Expected size_t is non-negative"); + + return static_cast<size_t>(sessions_int); + } + +void sqlite3_statement::spin() + { + while(step()) {} + } + +bool sqlite3_statement::step() + { + return (::sqlite3_step(m_stmt) == SQLITE_ROW); + } + +sqlite3_statement::~sqlite3_statement() + { + ::sqlite3_finalize(m_stmt); + } + +} diff --git a/src/utils/sqlite/sqlite.h b/src/utils/sqlite/sqlite.h new file mode 100644 index 000000000..aef04ab4d --- /dev/null +++ b/src/utils/sqlite/sqlite.h @@ -0,0 +1,68 @@ +/* +* SQLite wrapper +* (C) 2012 Jack Lloyd +* +* Released under the terms of the Botan license +*/ + +#ifndef BOTAN_UTILS_SQLITE_WRAPPER_H__ +#define BOTAN_UTILS_SQLITE_WRAPPER_H__ + +#include <botan/types.h> +#include <string> +#include <chrono> +#include <vector> + +class sqlite3; +class sqlite3_stmt; + +namespace Botan { + +class sqlite3_database + { + public: + sqlite3_database(const std::string& file); + + ~sqlite3_database(); + + size_t row_count(const std::string& table_name); + + void create_table(const std::string& table_schema); + private: + friend class sqlite3_statement; + + sqlite3* m_db; + }; + +class sqlite3_statement + { + public: + sqlite3_statement(sqlite3_database* db, + const std::string& base_sql); + + void bind(int column, const std::string& val); + + void bind(int column, int val); + + void bind(int column, std::chrono::system_clock::time_point time); + + void bind(int column, const std::vector<byte>& val); + + std::pair<const byte*, size_t> get_blob(int column); + + size_t get_size_t(int column); + + void spin(); + + bool step(); + + sqlite3_stmt* stmt() { return m_stmt; } + + ~sqlite3_statement(); + private: + sqlite3_stmt* m_stmt; + }; + +} + +#endif |