]> git.ipfire.org Git - thirdparty/squid.git/blob - src/security/Session.cc
SourceFormat Enforcement
[thirdparty/squid.git] / src / security / Session.cc
1 /*
2 * Copyright (C) 1996-2017 The Squid Software Foundation and contributors
3 *
4 * Squid software is distributed under GPLv2+ license and includes
5 * contributions from numerous individuals and organizations.
6 * Please see the COPYING and CONTRIBUTORS files for details.
7 */
8
9 /* DEBUG: section 83 TLS session management */
10
11 #include "squid.h"
12 #include "anyp/PortCfg.h"
13 #include "base/RunnersRegistry.h"
14 #include "Debug.h"
15 #include "ipc/MemMap.h"
16 #include "security/Session.h"
17 #include "SquidConfig.h"
18
19 #define SSL_SESSION_ID_SIZE 32
20 #define SSL_SESSION_MAX_SIZE 10*1024
21
22 bool
23 Security::SessionIsResumed(const Security::SessionPointer &s)
24 {
25 bool result = false;
26 #if USE_OPENSSL
27 result = SSL_session_reused(s.get()) == 1;
28 #elif USE_GNUTLS
29 result = gnutls_session_is_resumed(s.get()) != 0;
30 #endif
31 debugs(83, 7, "session=" << (void*)s.get() << ", query? answer: " << (result ? 'T' : 'F') );
32 return result;
33 }
34
35 void
36 Security::MaybeGetSessionResumeData(const Security::SessionPointer &s, Security::SessionStatePointer &data)
37 {
38 if (!SessionIsResumed(s)) {
39 #if USE_OPENSSL
40 // nil is valid for SSL_get1_session(), it cannot fail.
41 data.reset(SSL_get1_session(s.get()));
42 #elif USE_GNUTLS
43 gnutls_datum_t *tmp = nullptr;
44 const auto x = gnutls_session_get_data2(s.get(), tmp);
45 if (x != GNUTLS_E_SUCCESS) {
46 debugs(83, 3, "session=" << (void*)s.get() << " error: " << Security::ErrorString(x));
47 }
48 data.reset(tmp);
49 #endif
50 debugs(83, 5, "session=" << (void*)s.get() << " data=" << (void*)data.get());
51 } else {
52 debugs(83, 5, "session=" << (void*)s.get() << " data=" << (void*)data.get() << ", do nothing.");
53 }
54 }
55
56 void
57 Security::SetSessionResumeData(const Security::SessionPointer &s, const Security::SessionStatePointer &data)
58 {
59 if (data) {
60 #if USE_OPENSSL
61 if (!SSL_set_session(s.get(), data.get())) {
62 const auto ssl_error = ERR_get_error();
63 debugs(83, 3, "session=" << (void*)s.get() << " data=" << (void*)data.get() <<
64 " resume error: " << Security::ErrorString(ssl_error));
65 }
66 #elif USE_GNUTLS
67 const auto x = gnutls_session_set_data(s.get(), data->data, data->size);
68 if (x != GNUTLS_E_SUCCESS) {
69 debugs(83, 3, "session=" << (void*)s.get() << " data=" << (void*)data.get() <<
70 " resume error: " << Security::ErrorString(x));
71 }
72 #else
73 // critical because, how did it get here?
74 debugs(83, DBG_CRITICAL, "no TLS library. session=" << (void*)s.get() << " data=" << (void*)data.get());
75 #endif
76 debugs(83, 5, "session=" << (void*)s.get() << " data=" << (void*)data.get());
77 } else {
78 debugs(83, 5, "session=" << (void*)s.get() << " no resume data");
79 }
80 }
81
82 static bool
83 isTlsServer()
84 {
85 for (AnyP::PortCfgPointer s = HttpPortList; s != nullptr; s = s->next) {
86 if (s->secure.encryptTransport)
87 return true;
88 if (s->flags.tunnelSslBumping)
89 return true;
90 }
91
92 return false;
93 }
94
95 void
96 initializeSessionCache()
97 {
98 #if USE_OPENSSL
99 // Check if the MemMap keys and data are enough big to hold
100 // session ids and session data
101 assert(SSL_SESSION_ID_SIZE >= MEMMAP_SLOT_KEY_SIZE);
102 assert(SSL_SESSION_MAX_SIZE >= MEMMAP_SLOT_DATA_SIZE);
103
104 int configuredItems = ::Config.SSL.sessionCacheSize / sizeof(Ipc::MemMap::Slot);
105 if (IamWorkerProcess() && configuredItems)
106 Ssl::SessionCache = new Ipc::MemMap(Ssl::SessionCacheName);
107 else {
108 Ssl::SessionCache = nullptr;
109 return;
110 }
111
112 for (AnyP::PortCfgPointer s = HttpPortList; s != nullptr; s = s->next) {
113 if (s->secure.staticContext)
114 Ssl::SetSessionCallbacks(s->secure.staticContext);
115 }
116 #endif
117 }
118
119 /// initializes shared memory segments used by MemStore
120 class SharedSessionCacheRr: public Ipc::Mem::RegisteredRunner
121 {
122 public:
123 /* RegisteredRunner API */
124 SharedSessionCacheRr(): owner(nullptr) {}
125 virtual void useConfig();
126 virtual ~SharedSessionCacheRr();
127
128 protected:
129 virtual void create();
130
131 private:
132 Ipc::MemMap::Owner *owner;
133 };
134
135 RunnerRegistrationEntry(SharedSessionCacheRr);
136
137 void
138 SharedSessionCacheRr::useConfig()
139 {
140 #if USE_OPENSSL // while Ssl:: bits in use
141 if (Ssl::SessionCache || !isTlsServer()) //no need to configure ssl session cache.
142 return;
143
144 Ipc::Mem::RegisteredRunner::useConfig();
145 initializeSessionCache();
146 #endif
147 }
148
149 void
150 SharedSessionCacheRr::create()
151 {
152 if (!isTlsServer()) //no need to configure ssl session cache.
153 return;
154
155 #if USE_OPENSSL // while Ssl:: bits in use
156 if (int items = Config.SSL.sessionCacheSize / sizeof(Ipc::MemMap::Slot))
157 owner = Ipc::MemMap::Init(Ssl::SessionCacheName, items);
158 #endif
159 }
160
161 SharedSessionCacheRr::~SharedSessionCacheRr()
162 {
163 // XXX: Enable after testing to reduce at-exit memory "leaks".
164 // delete Ssl::SessionCache;
165
166 delete owner;
167 }
168