]> git.ipfire.org Git - thirdparty/squid.git/blame - src/security/Session.cc
Merged from v5 r14956
[thirdparty/squid.git] / src / security / Session.cc
CommitLineData
824d4656
AJ
1/*
2 * Copyright (C) 1996-2016 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
5d9a65df
AJ
9/* DEBUG: section 83 TLS session management */
10
824d4656
AJ
11#include "squid.h"
12#include "anyp/PortCfg.h"
13#include "base/RunnersRegistry.h"
5d9a65df 14#include "Debug.h"
86f77270 15#include "fde.h"
824d4656
AJ
16#include "ipc/MemMap.h"
17#include "security/Session.h"
18#include "SquidConfig.h"
86f77270 19#include "ssl/bio.h"
824d4656
AJ
20
21#define SSL_SESSION_ID_SIZE 32
22#define SSL_SESSION_MAX_SIZE 10*1024
23
86f77270
AJ
24static bool
25CreateSession(const Security::ContextPointer &ctx, const Comm::ConnectionPointer &conn, Security::Io::Type type, const char *squidCtx)
26{
27 if (!Comm::IsConnOpen(conn)) {
28 debugs(83, DBG_IMPORTANT, "Gone connection");
29 return false;
30 }
31
32 const char *errAction = "with no TLS/SSL library";
86f77270 33 int errCode = 0;
e0cf4700 34#if USE_OPENSSL
d0aafe66
AJ
35 Security::SessionPointer ssl(SSL_new(ctx.get()));
36 if (ssl) {
86f77270 37 const int fd = conn->fd;
d0aafe66 38 // without BIO, we would call SSL_set_fd(ssl.get(), fd) instead
86f77270 39 if (BIO *bio = Ssl::Bio::Create(fd, type)) {
d0aafe66 40 Ssl::Bio::Link(ssl.get(), bio); // cannot fail
86f77270 41
d0aafe66 42 fd_table[fd].ssl = ssl;
86f77270
AJ
43 fd_table[fd].read_method = &ssl_read_method;
44 fd_table[fd].write_method = &ssl_write_method;
45 fd_note(fd, squidCtx);
46 return true;
47 }
48 errCode = ERR_get_error();
49 errAction = "failed to initialize I/O";
86f77270
AJ
50 } else {
51 errCode = ERR_get_error();
52 errAction = "failed to allocate handle";
53 }
86f77270 54#endif
e0cf4700
AJ
55 debugs(83, DBG_IMPORTANT, "ERROR: " << squidCtx << ' ' << errAction <<
56 ": " << (errCode != 0 ? Security::ErrorString(errCode) : ""));
86f77270
AJ
57 return false;
58}
59
60bool
61Security::CreateClientSession(const Security::ContextPointer &ctx, const Comm::ConnectionPointer &c, const char *squidCtx)
62{
63 return CreateSession(ctx, c, Security::Io::BIO_TO_SERVER, squidCtx);
64}
65
66bool
67Security::CreateServerSession(const Security::ContextPointer &ctx, const Comm::ConnectionPointer &c, const char *squidCtx)
68{
69 return CreateSession(ctx, c, Security::Io::BIO_TO_CLIENT, squidCtx);
70}
71
5d9a65df
AJ
72bool
73Security::SessionIsResumed(const Security::SessionPointer &s)
74{
75 bool result = false;
76#if USE_OPENSSL
77 result = SSL_session_reused(s.get()) == 1;
78#elif USE_GNUTLS
79 result = gnutls_session_is_resumed(s.get()) != 0;
80#endif
81 debugs(83, 7, "session=" << (void*)s.get() << ", query? answer: " << (result ? 'T' : 'F') );
82 return result;
83}
84
85void
86Security::MaybeGetSessionResumeData(const Security::SessionPointer &s, Security::SessionStatePointer &data)
87{
88 if (!SessionIsResumed(s)) {
89#if USE_OPENSSL
90 // nil is valid for SSL_get1_session(), it cannot fail.
91 data.reset(SSL_get1_session(s.get()));
92#elif USE_GNUTLS
93 gnutls_datum_t *tmp = nullptr;
94 const auto x = gnutls_session_get_data2(s.get(), tmp);
95 if (x != GNUTLS_E_SUCCESS) {
ea574635 96 debugs(83, 3, "session=" << (void*)s.get() << " error: " << Security::ErrorString(x));
5d9a65df
AJ
97 }
98 data.reset(tmp);
99#endif
100 debugs(83, 5, "session=" << (void*)s.get() << " data=" << (void*)data.get());
101 } else {
102 debugs(83, 5, "session=" << (void*)s.get() << " data=" << (void*)data.get() << ", do nothing.");
103 }
104}
105
106void
107Security::SetSessionResumeData(const Security::SessionPointer &s, const Security::SessionStatePointer &data)
108{
109 if (data) {
110#if USE_OPENSSL
111 if (!SSL_set_session(s.get(), data.get())) {
112 const auto ssl_error = ERR_get_error();
113 debugs(83, 3, "session=" << (void*)s.get() << " data=" << (void*)data.get() <<
ea574635 114 " resume error: " << Security::ErrorString(ssl_error));
5d9a65df
AJ
115 }
116#elif USE_GNUTLS
117 const auto x = gnutls_session_set_data(s.get(), data->data, data->size);
118 if (x != GNUTLS_E_SUCCESS) {
119 debugs(83, 3, "session=" << (void*)s.get() << " data=" << (void*)data.get() <<
ea574635 120 " resume error: " << Security::ErrorString(x));
5d9a65df
AJ
121 }
122#else
123 // critical because, how did it get here?
124 debugs(83, DBG_CRITICAL, "no TLS library. session=" << (void*)s.get() << " data=" << (void*)data.get());
125#endif
126 debugs(83, 5, "session=" << (void*)s.get() << " data=" << (void*)data.get());
127 } else {
128 debugs(83, 5, "session=" << (void*)s.get() << " no resume data");
129 }
130}
131
824d4656
AJ
132static bool
133isTlsServer()
134{
135 for (AnyP::PortCfgPointer s = HttpPortList; s != nullptr; s = s->next) {
136 if (s->secure.encryptTransport)
137 return true;
138 if (s->flags.tunnelSslBumping)
139 return true;
140 }
141
142 return false;
143}
144
145void
146initializeSessionCache()
147{
148#if USE_OPENSSL
149 // Check if the MemMap keys and data are enough big to hold
150 // session ids and session data
151 assert(SSL_SESSION_ID_SIZE >= MEMMAP_SLOT_KEY_SIZE);
152 assert(SSL_SESSION_MAX_SIZE >= MEMMAP_SLOT_DATA_SIZE);
153
154 int configuredItems = ::Config.SSL.sessionCacheSize / sizeof(Ipc::MemMap::Slot);
155 if (IamWorkerProcess() && configuredItems)
156 Ssl::SessionCache = new Ipc::MemMap(Ssl::SessionCacheName);
157 else {
158 Ssl::SessionCache = nullptr;
159 return;
160 }
161
162 for (AnyP::PortCfgPointer s = HttpPortList; s != nullptr; s = s->next) {
b23f5f9c
AJ
163 if (s->secure.staticContext)
164 Ssl::SetSessionCallbacks(s->secure.staticContext);
824d4656
AJ
165 }
166#endif
167}
168
169/// initializes shared memory segments used by MemStore
170class SharedSessionCacheRr: public Ipc::Mem::RegisteredRunner
171{
172public:
173 /* RegisteredRunner API */
174 SharedSessionCacheRr(): owner(nullptr) {}
175 virtual void useConfig();
176 virtual ~SharedSessionCacheRr();
177
178protected:
179 virtual void create();
180
181private:
182 Ipc::MemMap::Owner *owner;
183};
184
185RunnerRegistrationEntry(SharedSessionCacheRr);
186
187void
188SharedSessionCacheRr::useConfig()
189{
190#if USE_OPENSSL // while Ssl:: bits in use
191 if (Ssl::SessionCache || !isTlsServer()) //no need to configure ssl session cache.
192 return;
193
194 Ipc::Mem::RegisteredRunner::useConfig();
195 initializeSessionCache();
196#endif
197}
198
199void
200SharedSessionCacheRr::create()
201{
202 if (!isTlsServer()) //no need to configure ssl session cache.
203 return;
204
205#if USE_OPENSSL // while Ssl:: bits in use
206 if (int items = Config.SSL.sessionCacheSize / sizeof(Ipc::MemMap::Slot))
207 owner = Ipc::MemMap::Init(Ssl::SessionCacheName, items);
208#endif
209}
210
211SharedSessionCacheRr::~SharedSessionCacheRr()
212{
213 // XXX: Enable after testing to reduce at-exit memory "leaks".
214 // delete Ssl::SessionCache;
215
216 delete owner;
217}
218