aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorlloyd <[email protected]>2012-06-08 22:33:01 +0000
committerlloyd <[email protected]>2012-06-08 22:33:01 +0000
commita4b2dba2bfea267e1a1535fbe33103f4c2153724 (patch)
tree4d37fe1951c13fc577c63f512e35dde20511ffad
parent23d037076cc8ecd9cdce0b6c53b2f0174c5f536c (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-xconfigure.py6
-rw-r--r--src/tls/sessions_sqlite/info.txt7
-rw-r--r--src/tls/sessions_sqlite/tls_sqlite_sess_mgr.cpp187
-rw-r--r--src/tls/sessions_sqlite/tls_sqlite_sess_mgr.h6
-rw-r--r--src/utils/sqlite/info.txt14
-rw-r--r--src/utils/sqlite/sqlite.cpp138
-rw-r--r--src/utils/sqlite/sqlite.h68
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