aboutsummaryrefslogtreecommitdiffstats
path: root/src/tls/sessions_sqlite
diff options
context:
space:
mode:
authorlloyd <[email protected]>2012-03-22 12:00:58 +0000
committerlloyd <[email protected]>2012-03-22 12:00:58 +0000
commit931a64ed4af06ef912dc43ff122a09cb96e24ea4 (patch)
tree3ee5bbb5d74b4d0ed6918fe58d6373a6990c9caa /src/tls/sessions_sqlite
parent1abb402dcc4037e283546852dbc2e587f564d611 (diff)
Expire old sessions and limit the cache size in the sqlite session manager.
Also when pulling a session via host info, try the most recent session first (rather than the oldest!).
Diffstat (limited to 'src/tls/sessions_sqlite')
-rw-r--r--src/tls/sessions_sqlite/tls_sqlite_sess_mgr.cpp69
-rw-r--r--src/tls/sessions_sqlite/tls_sqlite_sess_mgr.h9
2 files changed, 62 insertions, 16 deletions
diff --git a/src/tls/sessions_sqlite/tls_sqlite_sess_mgr.cpp b/src/tls/sessions_sqlite/tls_sqlite_sess_mgr.cpp
index 5150fb3c3..3b68939fa 100644
--- a/src/tls/sessions_sqlite/tls_sqlite_sess_mgr.cpp
+++ b/src/tls/sessions_sqlite/tls_sqlite_sess_mgr.cpp
@@ -8,6 +8,7 @@
#include <botan/tls_sqlite_sess_mgr.h>
#include <botan/internal/assert.h>
#include <botan/hex.h>
+#include <botan/time.h>
#include <sqlite3.h>
namespace Botan {
@@ -16,10 +17,10 @@ namespace TLS {
namespace {
-class sqlite3_statment
+class sqlite3_statement
{
public:
- sqlite3_statment(sqlite3* db, const std::string& base_sql)
+ sqlite3_statement(sqlite3* db, const std::string& base_sql)
{
int rc = sqlite3_prepare_v2(db, base_sql.c_str(), -1, &m_stmt, 0);
@@ -48,6 +49,12 @@ class sqlite3_statment
throw std::runtime_error("sqlite3_bind_text failed, code " + to_string(rc));
}
+ void spin()
+ {
+ while(sqlite3_step(m_stmt) == SQLITE_ROW)
+ {}
+ }
+
int step()
{
return sqlite3_step(m_stmt);
@@ -55,7 +62,7 @@ class sqlite3_statment
sqlite3_stmt* stmt() { return m_stmt; }
- ~sqlite3_statment() { sqlite3_finalize(m_stmt); }
+ ~sqlite3_statement() { sqlite3_finalize(m_stmt); }
private:
sqlite3_stmt* m_stmt;
};
@@ -66,7 +73,9 @@ Session_Manager_SQLite::Session_Manager_SQLite(const std::string& db_filename,
const std::string& table_name,
size_t max_sessions,
size_t session_lifetime) :
- m_table_name(table_name)
+ m_table_name(table_name),
+ m_max_sessions(max_sessions),
+ m_session_lifetime(session_lifetime)
{
int rc = sqlite3_open(db_filename.c_str(), &m_db);
if(rc)
@@ -106,7 +115,7 @@ Session_Manager_SQLite::~Session_Manager_SQLite()
bool Session_Manager_SQLite::load_from_session_id(const MemoryRegion<byte>& session_id,
Session& session)
{
- sqlite3_statment stmt(m_db, "select session from " + m_table_name + " where session_id = ?1");
+ sqlite3_statement stmt(m_db, "select session from " + m_table_name + " where session_id = ?1");
stmt.bind(1, hex_encode(session_id));
@@ -139,9 +148,9 @@ bool Session_Manager_SQLite::load_from_host_info(const std::string& hostname,
u16bit port,
Session& session)
{
- sqlite3_statment stmt(m_db, "select session from " + m_table_name +
- " where hostname = ?1 and hostport = ?2"
- " order by session_start limit 1");
+ sqlite3_statement stmt(m_db, "select session from " + m_table_name +
+ " where hostname = ?1 and hostport = ?2"
+ " order by session_start desc");
stmt.bind(1, hostname);
stmt.bind(2, port);
@@ -173,17 +182,16 @@ bool Session_Manager_SQLite::load_from_host_info(const std::string& hostname,
void Session_Manager_SQLite::remove_entry(const MemoryRegion<byte>& session_id)
{
- sqlite3_statment stmt(m_db, "delete from " + m_table_name + " where session_id = ?1");
+ sqlite3_statement stmt(m_db, "delete from " + m_table_name + " where session_id = ?1");
stmt.bind(1, hex_encode(session_id));
- while(stmt.step() == SQLITE_ROW)
- ;
+ stmt.spin();
}
void Session_Manager_SQLite::save(const Session& session)
{
- sqlite3_statment stmt(m_db, "insert into " + m_table_name + " values(?1, ?2, ?3, ?4, ?5)");
+ sqlite3_statement stmt(m_db, "insert into " + m_table_name + " values(?1, ?2, ?3, ?4, ?5)");
stmt.bind(1, session.sni_hostname());
stmt.bind(2, 0);
@@ -191,8 +199,41 @@ void Session_Manager_SQLite::save(const Session& session)
stmt.bind(4, hex_encode(session.session_id()));
stmt.bind(5, session.DER_encode());
- while(stmt.step() == SQLITE_ROW)
- ;
+ stmt.spin();
+
+ prune_session_cache();
+ }
+
+void Session_Manager_SQLite::prune_session_cache()
+ {
+ sqlite3_statement remove_expired(m_db, "delete from " + m_table_name + " where session_start <= ?1");
+
+ remove_expired.bind(1, system_time() - m_session_lifetime);
+
+ remove_expired.spin();
+
+ sqlite3_statement row_count(m_db, "select count(*) from " + m_table_name);
+
+ if(row_count.step() == SQLITE_ROW)
+ {
+ BOTAN_ASSERT(sqlite3_column_type(row_count.stmt(), 0) == SQLITE_INTEGER,
+ "Return count is a blob");
+
+ const int sessions_int = sqlite3_column_int(row_count.stmt(), 0);
+
+ BOTAN_ASSERT(sessions_int >= 0, "SQLite returned positive row count");
+
+ const size_t sessions = static_cast<size_t>(sessions_int);
+
+ if(sessions > m_max_sessions)
+ {
+ sqlite3_statement remove_some(m_db, "delete from " + m_table_name + " where session_id in "
+ "(select session_id from " + m_table_name + " limit ?1)");
+
+ remove_some.bind(1, sessions - m_max_sessions);
+ remove_some.spin();
+ }
+ }
}
}
diff --git a/src/tls/sessions_sqlite/tls_sqlite_sess_mgr.h b/src/tls/sessions_sqlite/tls_sqlite_sess_mgr.h
index 2bc435da3..35a37d206 100644
--- a/src/tls/sessions_sqlite/tls_sqlite_sess_mgr.h
+++ b/src/tls/sessions_sqlite/tls_sqlite_sess_mgr.h
@@ -22,13 +22,15 @@ class BOTAN_DLL Session_Manager_SQLite : public Session_Manager
{
public:
/**
+ * @param db_filename filename of the SQLite database file
+ * @param table_name names the table to store sessions in
* @param max_sessions a hint on the maximum number of sessions
* to keep in memory at any one time. (If zero, don't cap)
* @param session_lifetime sessions are expired after this many
* seconds have elapsed from initial handshake.
*/
Session_Manager_SQLite(const std::string& db_filename,
- const std::string& table_name,
+ const std::string& table_name = "tls_sessions",
size_t max_sessions = 1000,
size_t session_lifetime = 7200);
@@ -47,7 +49,10 @@ class BOTAN_DLL Session_Manager_SQLite : public Session_Manager
Session_Manager_SQLite(const Session_Manager_SQLite&) {}
Session_Manager_SQLite& operator=(const Session_Manager_SQLite&) { return (*this); }
- const std::string m_table_name;
+ void prune_session_cache();
+
+ std::string m_table_name;
+ size_t m_max_sessions, m_session_lifetime;
class sqlite3* m_db;
};