aboutsummaryrefslogtreecommitdiffstats
path: root/src/tls/tls_session_state.cpp
blob: dd2c91c70da10393119d3fa8830145b7b6f27373 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
/*
* TLS Session Management
* (C) 2011 Jack Lloyd
*
* Released under the terms of the Botan license
*/

#include <botan/tls_session_state.h>
#include <botan/der_enc.h>
#include <botan/ber_dec.h>
#include <botan/asn1_str.h>
#include <botan/time.h>

namespace Botan {

TLS_Session_Params::TLS_Session_Params(const MemoryRegion<byte>& session_identifier,
                                       const MemoryRegion<byte>& master_secret,
                                       Version_Code version,
                                       u16bit ciphersuite,
                                       byte compression_method,
                                       Connection_Side side,
                                       const X509_Certificate* cert,
                                       const std::string& sni_hostname,
                                       const std::string& srp_identifier) :
   session_start_time(system_time()),
   session_identifier(session_identifier),
   session_master_secret(master_secret),
   session_version(version),
   session_ciphersuite(ciphersuite),
   session_compression_method(compression_method),
   session_connection_side(side),
   session_sni_hostname(sni_hostname),
   session_srp_identifier(srp_identifier)
   {
   if(cert)
      session_peer_certificate = cert->BER_encode();
   }

TLS_Session_Params::TLS_Session_Params(const byte ber[], size_t ber_len)
   {
   BER_Decoder decoder(ber, ber_len);

   byte side_code = 0;
   ASN1_String sni_hostname_str;
   ASN1_String srp_identifier_str;

   BER_Decoder(ber, ber_len)
      .decode_and_check(static_cast<size_t>(TLS_SESSION_PARAM_STRUCT_VERSION),
                        "Unknown version in session structure")
      .decode(session_identifier, OCTET_STRING)
      .decode_integer_type(session_start_time)
      .decode_integer_type(session_version)
      .decode_integer_type(session_ciphersuite)
      .decode_integer_type(session_compression_method)
      .decode_integer_type(side_code)
      .decode(session_master_secret, OCTET_STRING)
      .decode(session_peer_certificate, OCTET_STRING)
      .decode(sni_hostname_str)
      .decode(srp_identifier_str);

   session_sni_hostname = sni_hostname_str.value();
   session_srp_identifier = srp_identifier_str.value();
   session_connection_side = static_cast<Connection_Side>(side_code);
   }

SecureVector<byte> TLS_Session_Params::BER_encode() const
   {
   return DER_Encoder()
      .start_cons(SEQUENCE)
         .encode(static_cast<size_t>(TLS_SESSION_PARAM_STRUCT_VERSION))
         .encode(session_identifier, OCTET_STRING)
         .encode(static_cast<size_t>(session_start_time))
         .encode(static_cast<size_t>(session_version))
         .encode(static_cast<size_t>(session_ciphersuite))
         .encode(static_cast<size_t>(session_compression_method))
         .encode(static_cast<size_t>(session_connection_side))
         .encode(session_master_secret, OCTET_STRING)
         .encode(session_peer_certificate, OCTET_STRING)
         .encode(ASN1_String(session_sni_hostname, UTF8_STRING))
         .encode(ASN1_String(session_srp_identifier, UTF8_STRING))
      .end_cons()
   .get_contents();
   }

bool TLS_Session_Manager_In_Memory::find(const MemoryVector<byte>& session_id,
                                         TLS_Session_Params& params)
   {
   std::map<std::string, TLS_Session_Params>::iterator i =
      sessions.find(hex_encode(session_id));

   if(i == sessions.end())
      return false;

   // session has expired, remove it
   const u64bit now = system_time();
   if(i->second.start_time() + session_lifetime >= now)
      {
      sessions.erase(i);
      return false;
      }

   params = i->second;
   return true;
   }

void TLS_Session_Manager_In_Memory::prohibit_resumption(const MemoryVector<byte>& session_id)
   {
   std::map<std::string, TLS_Session_Params>::iterator i =
      sessions.find(hex_encode(session_id));

   if(i != sessions.end())
      sessions.erase(i);
   }

void TLS_Session_Manager_In_Memory::save(const TLS_Session_Params& session_data)
   {
   if(max_sessions != 0)
      {
      /*
      This removes randomly based on ordering of session ids.
      Instead, remove oldest first?
      */
      while(sessions.size() >= max_sessions)
         sessions.erase(sessions.begin());
      }

   sessions[hex_encode(session_data.session_id())] = session_data;
   }

}