SSLSocketAcceptor.cpp
Go to the documentation of this file.
1/* ====================================================================
2 * Copyright (c) 1998-2006 Ralf S. Engelschall. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following
13 * disclaimer in the documentation and/or other materials
14 * provided with the distribution.
15 *
16 * 3. All advertising materials mentioning features or use of this
17 * software must display the following acknowledgment:
18 * "This product includes software developed by
19 * Ralf S. Engelschall <rse@engelschall.com> for use in the
20 * mod_ssl project (http://www.modssl.org/)."
21 *
22 * 4. The names "mod_ssl" must not be used to endorse or promote
23 * products derived from this software without prior written
24 * permission. For written permission, please contact
25 * rse@engelschall.com.
26 *
27 * 5. Products derived from this software may not be called "mod_ssl"
28 * nor may "mod_ssl" appear in their names without prior
29 * written permission of Ralf S. Engelschall.
30 *
31 * 6. Redistributions of any form whatsoever must retain the following
32 * acknowledgment:
33 * "This product includes software developed by
34 * Ralf S. Engelschall <rse@engelschall.com> for use in the
35 * mod_ssl project (http://www.modssl.org/)."
36 *
37 * THIS SOFTWARE IS PROVIDED BY RALF S. ENGELSCHALL ``AS IS'' AND ANY
38 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
39 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
40 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RALF S. ENGELSCHALL OR
41 * HIS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
42 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
43 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
44 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
45 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
46 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
47 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
48 * OF THE POSSIBILITY OF SUCH DAMAGE.
49 * ====================================================================
50 */
51
52/* ====================================================================
53 * Copyright (c) 1995-1999 Ben Laurie. All rights reserved.
54 *
55 * Redistribution and use in source and binary forms, with or without
56 * modification, are permitted provided that the following conditions
57 * are met:
58 *
59 * 1. Redistributions of source code must retain the above copyright
60 * notice, this list of conditions and the following disclaimer.
61 *
62 * 2. Redistributions in binary form must reproduce the above copyright
63 * notice, this list of conditions and the following disclaimer in
64 * the documentation and/or other materials provided with the
65 * distribution.
66 *
67 * 3. All advertising materials mentioning features or use of this
68 * software must display the following acknowledgment:
69 * "This product includes software developed by Ben Laurie
70 * for use in the Apache-SSL HTTP server project."
71 *
72 * 4. The name "Apache-SSL Server" must not be used to
73 * endorse or promote products derived from this software without
74 * prior written permission.
75 *
76 * 5. Redistributions of any form whatsoever must retain the following
77 * acknowledgment:
78 * "This product includes software developed by Ben Laurie
79 * for use in the Apache-SSL HTTP server project."
80 *
81 * THIS SOFTWARE IS PROVIDED BY BEN LAURIE ``AS IS'' AND ANY
82 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
83 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
84 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BEN LAURIE OR
85 * HIS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
86 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
87 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
88 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
89 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
90 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
91 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
92 * OF THE POSSIBILITY OF SUCH DAMAGE.
93 * ====================================================================
94 */
95
96/****************************************************************************
97** Copyright (c) 2001-2014
98**
99** This file is part of the QuickFIX FIX Engine
100**
101** This file may be distributed under the terms of the quickfixengine.org
102** license as defined by quickfixengine.org and appearing in the file
103** LICENSE included in the packaging of this file.
104**
105** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
106** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
107**
108** See http://www.quickfixengine.org/LICENSE for licensing information.
109**
110** Contact ask@quickfixengine.org if any conditions of this licensing are
111** not clear to you.
112**
113****************************************************************************/
114
115#ifdef _MSC_VER
116#include "stdafx.h"
117#else
118#include "config.h"
119#endif
120
121#if (HAVE_SSL > 0)
122
123#include "SSLSocketAcceptor.h"
124#include "Session.h"
125#include "Settings.h"
126#include "Utility.h"
127#include "Exceptions.h"
128
129namespace FIX
130{
131
132FIX::SSLSocketAcceptor *acceptObj = 0;
133
134int SSLSocketAcceptor::passPhraseHandleCB(char *buf, int bufsize, int verify, void *job)
135{
136 return acceptObj->passwordHandleCallback(buf, bufsize, verify, job);
137}
138
139SSLSocketAcceptor::SSLSocketAcceptor( Application& application,
140 MessageStoreFactory& factory,
141 const SessionSettings& settings ) throw( ConfigError )
142: Acceptor( application, factory, settings ),
143 m_pServer( 0 ), m_sslInit(false),
144 m_verify(SSL_CLIENT_VERIFY_NOTSET), m_ctx(0), m_revocationStore(0)
145{
146 acceptObj = this;
147}
148
149SSLSocketAcceptor::SSLSocketAcceptor( Application& application,
150 MessageStoreFactory& factory,
151 const SessionSettings& settings,
152 LogFactory& logFactory ) throw( ConfigError )
153: Acceptor( application, factory, settings, logFactory ),
154 m_pServer( 0 ), m_sslInit(false),
155 m_verify(SSL_CLIENT_VERIFY_NOTSET), m_ctx(0), m_revocationStore(0)
156{
157 acceptObj = this;
158}
159
160SSLSocketAcceptor::~SSLSocketAcceptor()
161{
162 SocketConnections::iterator iter;
163 for ( iter = m_connections.begin(); iter != m_connections.end(); ++iter )
164 delete iter->second;
165
166 if (m_sslInit)
167 {
168 SSL_CTX_free(m_ctx);
169 m_ctx = 0;
170 ssl_term();
171 }
172}
173
174void SSLSocketAcceptor::onConfigure( const SessionSettings& s )
175throw ( ConfigError )
176{
177 std::set<SessionID> sessions = s.getSessions();
178 std::set<SessionID>::iterator i;
179 for( i = sessions.begin(); i != sessions.end(); ++i )
180 {
181 const Dictionary& settings = s.get( *i );
182 settings.getInt( SOCKET_ACCEPT_PORT );
183 if( settings.has(SOCKET_REUSE_ADDRESS) )
184 settings.getBool( SOCKET_REUSE_ADDRESS );
185 if( settings.has(SOCKET_NODELAY) )
186 settings.getBool( SOCKET_NODELAY );
187 }
188}
189
190void SSLSocketAcceptor::onInitialize( const SessionSettings& s )
191throw ( RuntimeError )
192{
193 if (!m_sslInit)
194 {
195
196 ssl_init();
197
198 std::string errStr;
199
200 /* set up the application context */
201 if ((m_ctx = createSSLContext(true, m_settings, errStr)) == 0)
202 {
203 ssl_term();
204 throw RuntimeError(errStr);
205 }
206
207 if (!loadSSLCert(m_ctx, true, m_settings, getLog(), SSLSocketAcceptor::passPhraseHandleCB, errStr))
208 {
209 ssl_term();
210 throw RuntimeError(errStr);
211 }
212
213 if (!loadCAInfo(m_ctx, true, m_settings, getLog(), errStr, m_verify))
214 {
215 ssl_term();
216 throw RuntimeError(errStr);
217 }
218
219 m_revocationStore = loadCRLInfo(m_ctx, m_settings, getLog(), errStr);
220 if (!m_revocationStore && !errStr.empty())
221 {
222 ssl_term();
223 throw RuntimeError(errStr);
224 }
225
226 m_sslInit = true;
227 }
228
229 short port = 0;
230
231 try
232 {
233 m_pServer = new SocketServer( 1 );
234
235 std::set<SessionID> sessions = s.getSessions();
236 std::set<SessionID>::iterator i = sessions.begin();
237 for( ; i != sessions.end(); ++i )
238 {
239 const Dictionary& settings = s.get( *i );
240 port = (short)settings.getInt( SOCKET_ACCEPT_PORT );
241
242 const bool reuseAddress = settings.has( SOCKET_REUSE_ADDRESS ) ?
243 settings.getBool( SOCKET_REUSE_ADDRESS ) : true;
244
245 const bool noDelay = settings.has( SOCKET_NODELAY ) ?
246 settings.getBool( SOCKET_NODELAY ) : false;
247
248 const int sendBufSize = settings.has( SOCKET_SEND_BUFFER_SIZE ) ?
249 settings.getInt( SOCKET_SEND_BUFFER_SIZE ) : 0;
250
251 const int rcvBufSize = settings.has( SOCKET_RECEIVE_BUFFER_SIZE ) ?
252 settings.getInt( SOCKET_RECEIVE_BUFFER_SIZE ) : 0;
253
254 m_portToSessions[port].insert( *i );
255 m_pServer->add( port, reuseAddress, noDelay, sendBufSize, rcvBufSize );
256 }
257 }
258 catch( SocketException& e )
259 {
260 throw RuntimeError( "Unable to create, bind, or listen to port "
261 + IntConvertor::convert( (unsigned short)port ) + " (" + e.what() + ")" );
262 }
263}
264
265void SSLSocketAcceptor::onStart()
266{
267 while ( !isStopped() && m_pServer && m_pServer->block( *this ) ) {}
268
269 if( !m_pServer )
270 return;
271
272 time_t start = 0;
273 time_t now = 0;
274
275 ::time( &start );
276 while ( isLoggedOn() )
277 {
278 m_pServer->block( *this );
279 if( ::time(&now) -5 >= start )
280 break;
281 }
282
283 m_pServer->close();
284 delete m_pServer;
285 m_pServer = 0;
286}
287
288bool SSLSocketAcceptor::onPoll( double timeout )
289{
290 if( !m_pServer )
291 return false;
292
293 time_t start = 0;
294 time_t now = 0;
295
296 if( isStopped() )
297 {
298 if( start == 0 )
299 ::time( &start );
300 if( !isLoggedOn() )
301 {
302 start = 0;
303 return false;
304 }
305 if( ::time(&now) - 5 >= start )
306 {
307 start = 0;
308 return false;
309 }
310 }
311
312 m_pServer->block( *this, true, timeout );
313 return true;
314}
315
316void SSLSocketAcceptor::onStop()
317{
318}
319
320void SSLSocketAcceptor::onConnect( SocketServer& server, int a, int s )
321{
322 if ( !socket_isValid( s ) ) return;
323 SocketConnections::iterator i = m_connections.find( s );
324 if ( i != m_connections.end() ) return;
325 int port = server.socketToPort( a );
326 Sessions sessions = m_portToSessions[port];
327
328 SSL *ssl = SSL_new(m_ctx);
329 SSL_clear(ssl);
330 BIO *sBio = BIO_new_socket(s, BIO_CLOSE);
331 SSL_set_bio(ssl, sBio, sBio);
332 // TODO - check this
333 SSL_set_app_data(ssl, m_revocationStore);
334 SSL_set_verify_result(ssl, X509_V_OK);
335
336 SSLSocketConnection * sconn = new SSLSocketConnection( s, ssl, sessions, &server.getMonitor() );
337 // SSL accept
338 if (acceptSSLConnection(sconn->getSocket(), sconn->sslObject(), getLog(), m_verify) != 0)
339 {
340 std::stringstream stream;
341 stream << "Failed to accept SSL connection from " << socket_peername( s ) << " on port " << port;
342 if( getLog() )
343 getLog()->onEvent( stream.str() );
344
345 delete sconn;
346 return;
347 }
348
349 m_connections[ s ] = sconn;
350
351 std::stringstream stream;
352 stream << "Accepted SSL connection from " << socket_peername( s ) << " on port " << port;
353
354 if( getLog() )
355 getLog()->onEvent( stream.str() );
356}
357
358void SSLSocketAcceptor::onWrite( SocketServer& server, int s )
359{
360 SocketConnections::iterator i = m_connections.find( s );
361 if ( i == m_connections.end() ) return ;
362 SSLSocketConnection* pSocketConnection = i->second;
363 if( pSocketConnection->processQueue() )
364 pSocketConnection->unsignal();
365}
366
367bool SSLSocketAcceptor::onData( SocketServer& server, int s )
368{
369 SocketConnections::iterator i = m_connections.find( s );
370 if ( i == m_connections.end() ) return false;
371 SSLSocketConnection* pSocketConnection = i->second;
372 return pSocketConnection->read( *this, server );
373}
374
375void SSLSocketAcceptor::onDisconnect( SocketServer&, int s )
376{
377 SocketConnections::iterator i = m_connections.find( s );
378 if ( i == m_connections.end() ) return ;
379 SSLSocketConnection* pSocketConnection = i->second;
380
381 Session* pSession = pSocketConnection->getSession();
382 if ( pSession ) pSession->disconnect();
383
384 delete pSocketConnection;
385 m_connections.erase( s );
386}
387
388void SSLSocketAcceptor::onError( SocketServer& )
389{
390}
391
392void SSLSocketAcceptor::onTimeout( SocketServer& )
393{
394 SocketConnections::iterator i;
395 for ( i = m_connections.begin(); i != m_connections.end(); ++i )
396 i->second->onTimeout();
397}
398
399int SSLSocketAcceptor::passwordHandleCallback(char *buf, size_t bufsize,
400 int verify, void *job)
401{
402 if (m_password.length() > bufsize)
403 return -1;
404
405 std::strcpy(buf, m_password.c_str());
406 return m_password.length();
407}
408}
409
410#endif
const char SOCKET_SEND_BUFFER_SIZE[]
const char SOCKET_ACCEPT_PORT[]
const char SOCKET_REUSE_ADDRESS[]
const char SOCKET_NODELAY[]
const char SOCKET_RECEIVE_BUFFER_SIZE[]
bool socket_isValid(int socket)
Definition Utility.cpp:277
const char * socket_peername(int socket)
Definition Utility.cpp:353
static std::string convert(signed_int value)

Generated on Thu May 22 2025 08:23:50 for QuickFIX by doxygen 1.9.8 written by Dimitri van Heesch, © 1997-2001