8 #include <botan/tls_session_manager_sql.h>
9 #include <botan/database.h>
10 #include <botan/pbkdf.h>
11 #include <botan/hex.h>
12 #include <botan/loadstor.h>
20 const std::string& passphrase,
23 std::chrono::seconds session_lifetime) :
26 m_max_sessions(max_sessions),
27 m_session_lifetime(session_lifetime)
30 "create table if not exists tls_sessions "
32 "session_id TEXT PRIMARY KEY, "
33 "session_start INTEGER, "
40 "create table if not exists tls_sessions_metadata "
42 "passphrase_salt BLOB, "
43 "passphrase_iterations INTEGER, "
44 "passphrase_check INTEGER "
47 const size_t salts = m_db->row_count(
"tls_sessions_metadata");
49 std::unique_ptr<PBKDF> pbkdf(
get_pbkdf(
"PBKDF2(SHA-512)"));
54 auto stmt = m_db->new_statement(
"select * from tls_sessions_metadata");
58 std::pair<const uint8_t*, size_t> salt = stmt->get_blob(0);
59 const size_t iterations = stmt->get_size_t(1);
60 const size_t check_val_db = stmt->get_size_t(2);
64 salt.first, salt.second,
67 const size_t check_val_created =
make_uint16(x[0], x[1]);
68 m_session_key.assign(x.begin() + 2, x.end());
70 if(check_val_created != check_val_db)
71 throw Exception(
"Session database password not valid");
78 throw Exception(
"Seemingly corrupted database, multiple salts found");
83 size_t iterations = 0;
87 salt.data(), salt.size(),
88 std::chrono::milliseconds(100),
92 m_session_key.assign(x.begin() + 2, x.end());
94 auto stmt = m_db->new_statement(
"insert into tls_sessions_metadata values(?1, ?2, ?3)");
97 stmt->bind(2, iterations);
98 stmt->bind(3, check_val);
107 auto stmt = m_db->new_statement(
"select session from tls_sessions where session_id = ?1");
113 std::pair<const uint8_t*, size_t> blob = stmt->get_blob(0);
131 auto stmt = m_db->new_statement(
"select session from tls_sessions"
132 " where hostname = ?1 and hostport = ?2"
133 " order by session_start desc");
136 stmt->bind(2, server.
port());
140 std::pair<const uint8_t*, size_t> blob = stmt->get_blob(0);
157 auto stmt = m_db->new_statement(
"delete from tls_sessions where session_id = ?1");
166 auto stmt = m_db->new_statement(
"delete from tls_sessions");
172 auto stmt = m_db->new_statement(
"insert or replace into tls_sessions"
173 " values(?1, ?2, ?3, ?4, ?5)");
179 stmt->bind(5, session.
encrypt(m_session_key, m_rng));
183 prune_session_cache();
186 void Session_Manager_SQL::prune_session_cache()
189 auto remove_expired = m_db->new_statement(
"delete from tls_sessions where session_start <= ?1");
190 remove_expired->bind(1, std::chrono::system_clock::now() - m_session_lifetime);
191 remove_expired->spin();
193 const size_t sessions = m_db->row_count(
"tls_sessions");
196 if(sessions > m_max_sessions)
198 auto remove_some = m_db->new_statement(
"delete from tls_sessions where session_id in "
199 "(select session_id from tls_sessions limit ?1)");
201 remove_some->bind(1, sessions - m_max_sessions);
static Session decrypt(const uint8_t ctext[], size_t ctext_size, const SymmetricKey &key)
std::chrono::system_clock::time_point start_time() const
secure_vector< uint8_t > random_vec(size_t bytes)
const Server_Information & server_info() const
std::vector< uint8_t > encrypt(const SymmetricKey &key, RandomNumberGenerator &rng) const
bool load_from_server_info(const Server_Information &info, Session &session) override
const std::vector< uint8_t > & session_id() const
std::vector< T, secure_allocator< T >> secure_vector
void remove_entry(const std::vector< uint8_t > &session_id) override
bool load_from_session_id(const std::vector< uint8_t > &session_id, Session &session) override
PBKDF * get_pbkdf(const std::string &algo_spec, const std::string &provider="")
Session_Manager_SQL(std::shared_ptr< SQL_Database > db, const std::string &passphrase, RandomNumberGenerator &rng, size_t max_sessions=1000, std::chrono::seconds session_lifetime=std::chrono::seconds(7200))
RandomNumberGenerator & m_rng
std::vector< T > unlock(const secure_vector< T > &in)
void save(const Session &session_data) override
uint16_t make_uint16(uint8_t i0, uint8_t i1)
void hex_encode(char output[], const uint8_t input[], size_t input_length, bool uppercase)
size_t remove_all() override