1 /*
2 * TLS Session Management
3 * (C) 2011,2012 Jack Lloyd
4 *
5 * Botan is released under the Simplified BSD License (see license.txt)
6 */
7 
8 #include <botan/tls_session_manager.h>
9 #include <botan/hex.h>
10 #include <botan/rng.h>
11 #include <chrono>
12 
13 namespace Botan {
14 
15 namespace TLS {
16 
Session_Manager_In_Memory(RandomNumberGenerator & rng,size_t max_sessions,std::chrono::seconds session_lifetime)17 Session_Manager_In_Memory::Session_Manager_In_Memory(
18    RandomNumberGenerator& rng,
19    size_t max_sessions,
20    std::chrono::seconds session_lifetime) :
21    m_max_sessions(max_sessions),
22    m_session_lifetime(session_lifetime),
23    m_rng(rng),
24    m_session_key(m_rng.random_vec(32))
25    {}
26 
load_from_session_str(const std::string & session_str,Session & session)27 bool Session_Manager_In_Memory::load_from_session_str(
28    const std::string& session_str, Session& session)
29    {
30    // assert(lock is held)
31 
32    auto i = m_sessions.find(session_str);
33 
34    if(i == m_sessions.end())
35       return false;
36 
37    try
38       {
39       session = Session::decrypt(i->second, m_session_key);
40       }
41    catch(...)
42       {
43       return false;
44       }
45 
46    // if session has expired, remove it
47    const auto now = std::chrono::system_clock::now();
48 
49    if(session.start_time() + session_lifetime() < now)
50       {
51       m_sessions.erase(i);
52       return false;
53       }
54 
55    return true;
56    }
57 
load_from_session_id(const std::vector<uint8_t> & session_id,Session & session)58 bool Session_Manager_In_Memory::load_from_session_id(
59    const std::vector<uint8_t>& session_id, Session& session)
60    {
61    lock_guard_type<mutex_type> lock(m_mutex);
62 
63    return load_from_session_str(hex_encode(session_id), session);
64    }
65 
load_from_server_info(const Server_Information & info,Session & session)66 bool Session_Manager_In_Memory::load_from_server_info(
67    const Server_Information& info, Session& session)
68    {
69    lock_guard_type<mutex_type> lock(m_mutex);
70 
71    auto i = m_info_sessions.find(info);
72 
73    if(i == m_info_sessions.end())
74       return false;
75 
76    if(load_from_session_str(i->second, session))
77       return true;
78 
79    /*
80    * It existed at one point but was removed from the sessions map,
81    * remove m_info_sessions entry as well
82    */
83    m_info_sessions.erase(i);
84 
85    return false;
86    }
87 
remove_entry(const std::vector<uint8_t> & session_id)88 void Session_Manager_In_Memory::remove_entry(
89    const std::vector<uint8_t>& session_id)
90    {
91    lock_guard_type<mutex_type> lock(m_mutex);
92 
93    auto i = m_sessions.find(hex_encode(session_id));
94 
95    if(i != m_sessions.end())
96       m_sessions.erase(i);
97    }
98 
remove_all()99 size_t Session_Manager_In_Memory::remove_all()
100    {
101    const size_t removed = m_sessions.size();
102    m_info_sessions.clear();
103    m_sessions.clear();
104    m_rng.random_vec(m_session_key, 32);
105    return removed;
106    }
107 
save(const Session & session)108 void Session_Manager_In_Memory::save(const Session& session)
109    {
110    lock_guard_type<mutex_type> lock(m_mutex);
111 
112    if(m_max_sessions != 0)
113       {
114       /*
115       We generate new session IDs with the first 4 bytes being a
116       timestamp, so this actually removes the oldest sessions first.
117       */
118       while(m_sessions.size() >= m_max_sessions)
119          m_sessions.erase(m_sessions.begin());
120       }
121 
122    const std::string session_id_str = hex_encode(session.session_id());
123 
124    m_sessions[session_id_str] = session.encrypt(m_session_key, m_rng);
125 
126    if(session.side() == CLIENT && !session.server_info().empty())
127       m_info_sessions[session.server_info()] = session_id_str;
128    }
129 
130 }
131 
132 }
133