Botan  2.7.0
Crypto and TLS for C++11
Public Member Functions | List of all members
Botan::TLS::Session_Manager_SQL Class Reference

#include <tls_session_manager_sql.h>

Inheritance diagram for Botan::TLS::Session_Manager_SQL:
Botan::TLS::Session_Manager Botan::TLS::Session_Manager_SQLite

Public Member Functions

bool load_from_server_info (const Server_Information &info, Session &session) override
 
bool load_from_session_id (const std::vector< uint8_t > &session_id, Session &session) override
 
Session_Manager_SQLoperator= (const Session_Manager_SQL &)=delete
 
size_t remove_all () override
 
void remove_entry (const std::vector< uint8_t > &session_id) override
 
void save (const Session &session_data) override
 
std::chrono::seconds session_lifetime () const override
 
 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))
 
 Session_Manager_SQL (const Session_Manager_SQL &)=delete
 

Detailed Description

An implementation of Session_Manager that saves values in a SQL database file, with the session data encrypted using a passphrase.

Warning
For clients, the hostnames associated with the saved sessions are stored in the database in plaintext. This may be a serious privacy risk in some situations.

Definition at line 28 of file tls_session_manager_sql.h.

Constructor & Destructor Documentation

◆ Session_Manager_SQL() [1/2]

Botan::TLS::Session_Manager_SQL::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) 
)
Parameters
dbA connection to the database to use The table names botan_tls_sessions and botan_tls_sessions_metadata will be used
passphraseused to encrypt the session data
rnga random number generator
max_sessionsa hint on the maximum number of sessions to keep in memory at any one time. (If zero, don't cap)
session_lifetimesessions are expired after this many seconds have elapsed from initial handshake.

Definition at line 20 of file tls_session_manager_sql.cpp.

24  :
25  m_db(db),
26  m_rng(rng),
27  m_max_sessions(max_sessions),
28  m_session_lifetime(session_lifetime)
29  {
30  m_db->create_table(
31  "create table if not exists tls_sessions "
32  "("
33  "session_id TEXT PRIMARY KEY, "
34  "session_start INTEGER, "
35  "hostname TEXT, "
36  "hostport INTEGER, "
37  "session BLOB"
38  ")");
39 
40  m_db->create_table(
41  "create table if not exists tls_sessions_metadata "
42  "("
43  "passphrase_salt BLOB, "
44  "passphrase_iterations INTEGER, "
45  "passphrase_check INTEGER "
46  ")");
47 
48  const size_t salts = m_db->row_count("tls_sessions_metadata");
49 
50  std::unique_ptr<PBKDF> pbkdf(get_pbkdf("PBKDF2(SHA-512)"));
51 
52  if(salts == 1)
53  {
54  // existing db
55  auto stmt = m_db->new_statement("select * from tls_sessions_metadata");
56 
57  if(stmt->step())
58  {
59  std::pair<const uint8_t*, size_t> salt = stmt->get_blob(0);
60  const size_t iterations = stmt->get_size_t(1);
61  const size_t check_val_db = stmt->get_size_t(2);
62 
63  secure_vector<uint8_t> x = pbkdf->pbkdf_iterations(32 + 2,
64  passphrase,
65  salt.first, salt.second,
66  iterations);
67 
68  const size_t check_val_created = make_uint16(x[0], x[1]);
69  m_session_key.assign(x.begin() + 2, x.end());
70 
71  if(check_val_created != check_val_db)
72  throw Exception("Session database password not valid");
73  }
74  }
75  else
76  {
77  // maybe just zap the salts + sessions tables in this case?
78  if(salts != 0)
79  throw Exception("Seemingly corrupted database, multiple salts found");
80 
81  // new database case
82 
83  std::vector<uint8_t> salt = unlock(rng.random_vec(16));
84  size_t iterations = 0;
85 
86  secure_vector<uint8_t> x = pbkdf->pbkdf_timed(32 + 2,
87  passphrase,
88  salt.data(), salt.size(),
89  std::chrono::milliseconds(100),
90  iterations);
91 
92  size_t check_val = make_uint16(x[0], x[1]);
93  m_session_key.assign(x.begin() + 2, x.end());
94 
95  auto stmt = m_db->new_statement("insert into tls_sessions_metadata values(?1, ?2, ?3)");
96 
97  stmt->bind(1, salt);
98  stmt->bind(2, iterations);
99  stmt->bind(3, check_val);
100 
101  stmt->spin();
102  }
103  }
std::chrono::seconds session_lifetime() const override
PBKDF * get_pbkdf(const std::string &algo_spec, const std::string &provider="")
Definition: pbkdf.h:229
std::vector< T > unlock(const secure_vector< T > &in)
Definition: secmem.h:95
uint16_t make_uint16(uint8_t i0, uint8_t i1)
Definition: loadstor.h:52

◆ Session_Manager_SQL() [2/2]

Botan::TLS::Session_Manager_SQL::Session_Manager_SQL ( const Session_Manager_SQL )
delete

Member Function Documentation

◆ load_from_server_info()

bool Botan::TLS::Session_Manager_SQL::load_from_server_info ( const Server_Information info,
Session session 
)
overridevirtual

Try to load a saved session (using info about server)

Parameters
infothe information about the server
sessionwill be set to the saved session data (if found), or not modified if not found
Returns
true if session was modified

Implements Botan::TLS::Session_Manager.

Definition at line 129 of file tls_session_manager_sql.cpp.

References Botan::TLS::Session::decrypt(), Botan::TLS::Server_Information::hostname(), and Botan::TLS::Server_Information::port().

131  {
132  auto stmt = m_db->new_statement("select session from tls_sessions"
133  " where hostname = ?1 and hostport = ?2"
134  " order by session_start desc");
135 
136  stmt->bind(1, server.hostname());
137  stmt->bind(2, server.port());
138 
139  while(stmt->step())
140  {
141  std::pair<const uint8_t*, size_t> blob = stmt->get_blob(0);
142 
143  try
144  {
145  session = Session::decrypt(blob.first, blob.second, m_session_key);
146  return true;
147  }
148  catch(...)
149  {
150  }
151  }
152 
153  return false;
154  }
static Session decrypt(const uint8_t ctext[], size_t ctext_size, const SymmetricKey &key)

◆ load_from_session_id()

bool Botan::TLS::Session_Manager_SQL::load_from_session_id ( const std::vector< uint8_t > &  session_id,
Session session 
)
overridevirtual

Try to load a saved session (using session ID)

Parameters
session_idthe session identifier we are trying to resume
sessionwill be set to the saved session data (if found), or not modified if not found
Returns
true if session was modified

Implements Botan::TLS::Session_Manager.

Definition at line 105 of file tls_session_manager_sql.cpp.

References Botan::TLS::Session::decrypt(), and Botan::hex_encode().

107  {
108  auto stmt = m_db->new_statement("select session from tls_sessions where session_id = ?1");
109 
110  stmt->bind(1, hex_encode(session_id));
111 
112  while(stmt->step())
113  {
114  std::pair<const uint8_t*, size_t> blob = stmt->get_blob(0);
115 
116  try
117  {
118  session = Session::decrypt(blob.first, blob.second, m_session_key);
119  return true;
120  }
121  catch(...)
122  {
123  }
124  }
125 
126  return false;
127  }
void hex_encode(char output[], const uint8_t input[], size_t input_length, bool uppercase)
Definition: hex.cpp:14
static Session decrypt(const uint8_t ctext[], size_t ctext_size, const SymmetricKey &key)

◆ operator=()

Session_Manager_SQL& Botan::TLS::Session_Manager_SQL::operator= ( const Session_Manager_SQL )
delete

◆ remove_all()

size_t Botan::TLS::Session_Manager_SQL::remove_all ( )
overridevirtual

Remove all sessions from the cache, return number of sessions deleted

Implements Botan::TLS::Session_Manager.

Definition at line 165 of file tls_session_manager_sql.cpp.

166  {
167  auto stmt = m_db->new_statement("delete from tls_sessions");
168  return stmt->spin();
169  }

◆ remove_entry()

void Botan::TLS::Session_Manager_SQL::remove_entry ( const std::vector< uint8_t > &  session_id)
overridevirtual

Remove this session id from the cache, if it exists

Implements Botan::TLS::Session_Manager.

Definition at line 156 of file tls_session_manager_sql.cpp.

References Botan::hex_encode().

157  {
158  auto stmt = m_db->new_statement("delete from tls_sessions where session_id = ?1");
159 
160  stmt->bind(1, hex_encode(session_id));
161 
162  stmt->spin();
163  }
void hex_encode(char output[], const uint8_t input[], size_t input_length, bool uppercase)
Definition: hex.cpp:14

◆ save()

void Botan::TLS::Session_Manager_SQL::save ( const Session session)
overridevirtual

Save a session on a best effort basis; the manager may not in fact be able to save the session for whatever reason; this is not an error. Caller cannot assume that calling save followed immediately by load_from_* will result in a successful lookup.

Parameters
sessionto save

Implements Botan::TLS::Session_Manager.

Definition at line 171 of file tls_session_manager_sql.cpp.

References Botan::TLS::Session::encrypt(), Botan::hex_encode(), Botan::TLS::Server_Information::hostname(), Botan::TLS::Server_Information::port(), Botan::TLS::Session::server_info(), Botan::TLS::Session::session_id(), and Botan::TLS::Session::start_time().

172  {
173  if(session.server_info().hostname().empty())
174  return;
175 
176  auto stmt = m_db->new_statement("insert or replace into tls_sessions"
177  " values(?1, ?2, ?3, ?4, ?5)");
178 
179  stmt->bind(1, hex_encode(session.session_id()));
180  stmt->bind(2, session.start_time());
181  stmt->bind(3, session.server_info().hostname());
182  stmt->bind(4, session.server_info().port());
183  stmt->bind(5, session.encrypt(m_session_key, m_rng));
184 
185  stmt->spin();
186 
187  prune_session_cache();
188  }
void hex_encode(char output[], const uint8_t input[], size_t input_length, bool uppercase)
Definition: hex.cpp:14

◆ session_lifetime()

std::chrono::seconds Botan::TLS::Session_Manager_SQL::session_lifetime ( ) const
inlineoverridevirtual

Return the allowed lifetime of a session; beyond this time, sessions are not resumed. Returns 0 if unknown/no explicit expiration policy.

Implements Botan::TLS::Session_Manager.

Definition at line 64 of file tls_session_manager_sql.h.

65  { return m_session_lifetime; }

The documentation for this class was generated from the following files: