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 
129 namespace FIX
130 {
131 
132 FIX::SSLSocketAcceptor *acceptObj = 0;
133 
134 int SSLSocketAcceptor::passPhraseHandleCB(char *buf, int bufsize, int verify, void *job)
135 {
136  return acceptObj->passwordHandleCallback(buf, bufsize, verify, job);
137 }
138 
139 SSLSocketAcceptor::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 
149 SSLSocketAcceptor::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 
160 SSLSocketAcceptor::~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 
174 void SSLSocketAcceptor::onConfigure( const SessionSettings& s )
175 throw ( 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 
190 void SSLSocketAcceptor::onInitialize( const SessionSettings& s )
191 throw ( 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 
265 void 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 
288 bool 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 
316 void SSLSocketAcceptor::onStop()
317 {
318 }
319 
320 void 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 
358 void 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 
367 bool 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 
375 void 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 
388 void SSLSocketAcceptor::onError( SocketServer& )
389 {
390 }
391 
392 void 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 
399 int 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
FIX::SOCKET_RECEIVE_BUFFER_SIZE
const char SOCKET_RECEIVE_BUFFER_SIZE[]
Definition: SessionSettings.h:87
FIX::SOCKET_NODELAY
const char SOCKET_NODELAY[]
Definition: SessionSettings.h:85
FIX::SOCKET_SEND_BUFFER_SIZE
const char SOCKET_SEND_BUFFER_SIZE[]
Definition: SessionSettings.h:86
FIX::socket_isValid
bool socket_isValid(int socket)
Definition: Utility.cpp:294
FIX::SOCKET_ACCEPT_PORT
const char SOCKET_ACCEPT_PORT[]
Definition: SessionSettings.h:79
FIX::IntConvertor::convert
static std::string convert(signed_int value)
Definition: FieldConvertors.h:170
SSLSocketAcceptor.h
Settings.h
FIX
Definition: Acceptor.cpp:34
Session.h
Exceptions.h
Utility.h
FIX::SOCKET_REUSE_ADDRESS
const char SOCKET_REUSE_ADDRESS[]
Definition: SessionSettings.h:80
FIX::socket_peername
const char * socket_peername(int socket)
Definition: Utility.cpp:370

Generated on Wed Apr 29 2020 19:41:30 for QuickFIX by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2001