Botan 2.1.0 Crypto and TLS for C++11

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

tls_session_manager_sql.cpp
Go to the documentation of this file.
1 /*
2 * SQL TLS Session Manager
3 * (C) 2012,2014 Jack Lloyd
4 *
5 * Botan is released under the Simplified BSD License (see license.txt)
6 */
7
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>
13 #include <chrono>
14
15 namespace Botan {
16
17 namespace TLS {
18
19 Session_Manager_SQL::Session_Manager_SQL(std::shared_ptr<SQL_Database> db,
20 const std::string& passphrase,
21 RandomNumberGenerator& rng,
22 size_t max_sessions,
23 std::chrono::seconds session_lifetime) :
24 m_db(db),
25 m_rng(rng),
26 m_max_sessions(max_sessions),
27 m_session_lifetime(session_lifetime)
28 {
29 m_db->create_table(
30 "create table if not exists tls_sessions "
31 "("
32 "session_id TEXT PRIMARY KEY, "
33 "session_start INTEGER, "
34 "hostname TEXT, "
35 "hostport INTEGER, "
36 "session BLOB"
37 ")");
38
39 m_db->create_table(
40 "create table if not exists tls_sessions_metadata "
41 "("
42 "passphrase_salt BLOB, "
43 "passphrase_iterations INTEGER, "
44 "passphrase_check INTEGER "
45 ")");
46
47 const size_t salts = m_db->row_count("tls_sessions_metadata");
48
49 std::unique_ptr<PBKDF> pbkdf(get_pbkdf("PBKDF2(SHA-512)"));
50
51 if(salts == 1)
52 {
53 // existing db
54 auto stmt = m_db->new_statement("select * from tls_sessions_metadata");
55
56 if(stmt->step())
57 {
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);
61
62 secure_vector<uint8_t> x = pbkdf->pbkdf_iterations(32 + 2,
63 passphrase,
64 salt.first, salt.second,
65 iterations);
66
67 const size_t check_val_created = make_uint16(x[0], x[1]);
68 m_session_key.assign(x.begin() + 2, x.end());
69
70 if(check_val_created != check_val_db)
71 throw Exception("Session database password not valid");
72 }
73 }
74 else
75 {
76 // maybe just zap the salts + sessions tables in this case?
77 if(salts != 0)
78 throw Exception("Seemingly corrupted database, multiple salts found");
79
80 // new database case
81
82 std::vector<uint8_t> salt = unlock(rng.random_vec(16));
83 size_t iterations = 0;
84
85 secure_vector<uint8_t> x = pbkdf->pbkdf_timed(32 + 2,
86 passphrase,
87 salt.data(), salt.size(),
88 std::chrono::milliseconds(100),
89 iterations);
90
91 size_t check_val = make_uint16(x[0], x[1]);
92 m_session_key.assign(x.begin() + 2, x.end());
93
94 auto stmt = m_db->new_statement("insert into tls_sessions_metadata values(?1, ?2, ?3)");
95
96 stmt->bind(1, salt);
97 stmt->bind(2, iterations);
98 stmt->bind(3, check_val);
99
100 stmt->spin();
101 }
102 }
103
104 bool Session_Manager_SQL::load_from_session_id(const std::vector<uint8_t>& session_id,
105 Session& session)
106 {
107 auto stmt = m_db->new_statement("select session from tls_sessions where session_id = ?1");
108
109 stmt->bind(1, hex_encode(session_id));
110
111 while(stmt->step())
112 {
113 std::pair<const uint8_t*, size_t> blob = stmt->get_blob(0);
114
115 try
116 {
117 session = Session::decrypt(blob.first, blob.second, m_session_key);
118 return true;
119 }
120 catch(...)
121 {
122 }
123 }
124
125 return false;
126 }
127
128 bool Session_Manager_SQL::load_from_server_info(const Server_Information& server,
129 Session& session)
130 {
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");
134
135 stmt->bind(1, server.hostname());
136 stmt->bind(2, server.port());
137
138 while(stmt->step())
139 {
140 std::pair<const uint8_t*, size_t> blob = stmt->get_blob(0);
141
142 try
143 {
144 session = Session::decrypt(blob.first, blob.second, m_session_key);
145 return true;
146 }
147 catch(...)
148 {
149 }
150 }
151
152 return false;
153 }
154
155 void Session_Manager_SQL::remove_entry(const std::vector<uint8_t>& session_id)
156 {
157 auto stmt = m_db->new_statement("delete from tls_sessions where session_id = ?1");
158
159 stmt->bind(1, hex_encode(session_id));
160
161 stmt->spin();
162 }
163
164 size_t Session_Manager_SQL::remove_all()
165 {
166 auto stmt = m_db->new_statement("delete from tls_sessions");
167 return stmt->spin();
168 }
169
170 void Session_Manager_SQL::save(const Session& session)
171 {
172 auto stmt = m_db->new_statement("insert or replace into tls_sessions"
173 " values(?1, ?2, ?3, ?4, ?5)");
174
175 stmt->bind(1, hex_encode(session.session_id()));
176 stmt->bind(2, session.start_time());
177 stmt->bind(3, session.server_info().hostname());
178 stmt->bind(4, session.server_info().port());
179 stmt->bind(5, session.encrypt(m_session_key, m_rng));
180
181 stmt->spin();
182
183 prune_session_cache();
184 }
185
186 void Session_Manager_SQL::prune_session_cache()
187 {
188 // First expire old sessions
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();
192
193 const size_t sessions = m_db->row_count("tls_sessions");
194
195 // Then if needed expire some more sessions at random
196 if(sessions > m_max_sessions)
197 {
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)");
200
201 remove_some->bind(1, sessions - m_max_sessions);
202 remove_some->spin();
203 }
204 }
205
206 }
207
208 }
Botan::TLS::Session
Definition: tls_session.h:27
Botan::TLS::Session::decrypt
static Session decrypt(const uint8_t ctext[], size_t ctext_size, const SymmetricKey &key)
Definition: tls_session.cpp:193
Botan::TLS::Session::start_time
std::chrono::system_clock::time_point start_time() const
Definition: tls_session.h:175
Botan::Exception
Definition: exceptn.h:21
Botan::RandomNumberGenerator::random_vec
secure_vector< uint8_t > random_vec(size_t bytes)
Definition: rng.h:133
Botan::RandomNumberGenerator
Definition: rng.h:25
Botan::TLS::Session::server_info
const Server_Information & server_info() const
Definition: tls_session.h:190
Botan::TLS::Session::encrypt
std::vector< uint8_t > encrypt(const SymmetricKey &key, RandomNumberGenerator &rng) const
Definition: tls_session.cpp:172
Botan::TLS::Session_Manager_SQL::load_from_server_info
bool load_from_server_info(const Server_Information &info, Session &session) override
Definition: tls_session_manager_sql.cpp:128
Botan::TLS::Server_Information::port
uint16_t port() const
Definition: tls_server_info.h:64
Botan::TLS::Server_Information::hostname
std::string hostname() const
Definition: tls_server_info.h:53
Botan::TLS::Session::session_id
const std::vector< uint8_t > & session_id() const
Definition: tls_session.h:156
Botan::secure_vector
std::vector< T, secure_allocator< T >> secure_vector
Definition: secmem.h:121
Botan::TLS::Session_Manager_SQL::remove_entry
void remove_entry(const std::vector< uint8_t > &session_id) override
Definition: tls_session_manager_sql.cpp:155
Botan::TLS::Session_Manager_SQL::load_from_session_id
bool load_from_session_id(const std::vector< uint8_t > &session_id, Session &session) override
Definition: tls_session_manager_sql.cpp:104
Botan::get_pbkdf
PBKDF * get_pbkdf(const std::string &algo_spec, const std::string &provider="")
Definition: pbkdf.h:216
Botan::TLS::Session_Manager_SQL::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))
Definition: tls_session_manager_sql.cpp:19
Botan::TLS::Server_Information
Definition: tls_server_info.h:21
Botan
Definition: alg_id.cpp:13
m_rng
RandomNumberGenerator & m_rng
Definition: ecdh.cpp:52
Botan::unlock
std::vector< T > unlock(const secure_vector< T > &in)
Definition: secmem.h:125
Botan::TLS::Session_Manager_SQL::save
void save(const Session &session_data) override
Definition: tls_session_manager_sql.cpp:170
Botan::make_uint16
uint16_t make_uint16(uint8_t i0, uint8_t i1)
Definition: loadstor.h:60
Botan::hex_encode
void hex_encode(char output[], const uint8_t input[], size_t input_length, bool uppercase)
Definition: hex.cpp:14
Botan::TLS::Session_Manager_SQL::remove_all
size_t remove_all() override
Definition: tls_session_manager_sql.cpp:164