Add OpenSSL integration with ACE (5.6.6) for Windows. Will be used in the future.

*nix users will already have these files.
Credits to the original authors over at ACE.

--HG--
branch : trunk
This commit is contained in:
Machiavelli
2010-05-23 17:54:36 +02:00
parent e658298053
commit 37e6aa3634
22 changed files with 5946 additions and 8 deletions

View File

@@ -0,0 +1,253 @@
// -*- C++ -*-
#include "SSL_Asynch_BIO.h"
#if OPENSSL_VERSION_NUMBER > 0x0090581fL && ((defined (ACE_WIN32) && !defined (ACE_HAS_WINCE)) || (defined (ACE_HAS_AIO_CALLS)))
#include "SSL_Asynch_Stream.h"
#include "ace/OS_NS_string.h"
#include "ace/Truncate.h"
ACE_RCSID (ACE_SSL,
SSL_Asynch_BIO,
"$Id: SSL_Asynch_BIO.cpp 82574 2008-08-08 19:35:06Z parsons $")
#if (defined (ACE_HAS_VERSIONED_NAMESPACE) && ACE_HAS_VERSIONED_NAMESPACE == 1)
# define ACE_ASYNCH_BIO_WRITE_NAME ACE_PREPROC_CONCATENATE(ACE_VERSIONED_NAMESPACE_NAME, _ACE_Asynch_BIO_write)
# define ACE_ASYNCH_BIO_READ_NAME ACE_PREPROC_CONCATENATE(ACE_VERSIONED_NAMESPACE_NAME, _ACE_Asynch_BIO_read)
# define ACE_ASYNCH_BIO_PUTS_NAME ACE_PREPROC_CONCATENATE(ACE_VERSIONED_NAMESPACE_NAME, _ACE_Asynch_BIO_puts)
# define ACE_ASYNCH_BIO_CTRL_NAME ACE_PREPROC_CONCATENATE(ACE_VERSIONED_NAMESPACE_NAME, _ACE_Asynch_BIO_ctrl)
# define ACE_ASYNCH_BIO_NEW_NAME ACE_PREPROC_CONCATENATE(ACE_VERSIONED_NAMESPACE_NAME, _ACE_Asynch_BIO_new)
# define ACE_ASYNCH_BIO_FREE_NAME ACE_PREPROC_CONCATENATE(ACE_VERSIONED_NAMESPACE_NAME, _ACE_Asynch_BIO_free)
#else
# define ACE_ASYNCH_BIO_WRITE_NAME ACE_Asynch_BIO_write
# define ACE_ASYNCH_BIO_READ_NAME ACE_Asynch_BIO_read
# define ACE_ASYNCH_BIO_PUTS_NAME ACE_Asynch_BIO_puts
# define ACE_ASYNCH_BIO_CTRL_NAME ACE_Asynch_BIO_ctrl
# define ACE_ASYNCH_BIO_NEW_NAME ACE_Asynch_BIO_new
# define ACE_ASYNCH_BIO_FREE_NAME ACE_Asynch_BIO_free
#endif /* ACE_HAS_VERSIONED_NAMESPACE == 1 */
/**
* @name OpenSSL BIO Helper Methods for use with ACE's Asynchronous
* SSL I/O support.
*/
//@{
extern "C"
{
int ACE_ASYNCH_BIO_WRITE_NAME (BIO *pBIO, const char *buf, int len);
int ACE_ASYNCH_BIO_READ_NAME (BIO *pBIO, char *buf, int len);
int ACE_ASYNCH_BIO_PUTS_NAME (BIO *pBIO, const char *str);
long ACE_ASYNCH_BIO_CTRL_NAME (BIO *pBIO, int cmd, long arg1, void *arg2);
int ACE_ASYNCH_BIO_NEW_NAME (BIO *pBIO);
int ACE_ASYNCH_BIO_FREE_NAME (BIO *pBIO);
}
//@}
#define BIO_TYPE_ACE ( 21 | BIO_TYPE_SOURCE_SINK )
static BIO_METHOD methods_ACE =
{
BIO_TYPE_ACE, // BIO_TYPE_PROXY_SERVER,
"ACE_Asynch_BIO",
ACE_ASYNCH_BIO_WRITE_NAME,
ACE_ASYNCH_BIO_READ_NAME,
ACE_ASYNCH_BIO_PUTS_NAME,
0, /* ACE_ASYNCH_BIO_GETS_NAME, */
ACE_ASYNCH_BIO_CTRL_NAME,
ACE_ASYNCH_BIO_NEW_NAME,
ACE_ASYNCH_BIO_FREE_NAME,
0
};
ACE_BEGIN_VERSIONED_NAMESPACE_DECL
BIO *
ACE_SSL_make_BIO (void * ssl_asynch_stream)
{
BIO * const pBIO = BIO_new (&methods_ACE);
if (pBIO)
BIO_ctrl (pBIO,
BIO_C_SET_FILE_PTR,
0,
ssl_asynch_stream);
return pBIO;
}
/**
* @struct @c ACE_SSL_Asynch_Stream_Accessor
*
* @brief Privileged @c ACE_SSL_Asynch_Stream accessor.
*
* This structure is a @c friend to the @c ACE_SSL_Asynch_Stream
* class so that it can gain access to the protected
* ssl_bio_{read,write}() methods in that class. It is full declared
* in this implementation file to hide its interface from users to
* prevent potential abuse of the friend relationship between it and
* the @c ACE_SSL_Asynch_Stream class.
*/
struct ACE_SSL_Asynch_Stream_Accessor
{
static int read (ACE_SSL_Asynch_Stream * stream,
char * buf,
size_t len,
int & errval)
{
return stream->ssl_bio_read (buf, len, errval);
}
static int write (ACE_SSL_Asynch_Stream * stream,
const char * buf,
size_t len,
int & errval)
{
return stream->ssl_bio_write (buf, len, errval);
}
};
ACE_END_VERSIONED_NAMESPACE_DECL
int
ACE_ASYNCH_BIO_NEW_NAME (BIO * pBIO)
{
pBIO->init = 0; // not initialized
pBIO->num = 0; // still zero ( we can use it )
pBIO->ptr = 0; // will be pointer to ACE_SSL_Asynch_Stream
pBIO->flags = 0; //
return 1;
}
int
ACE_ASYNCH_BIO_FREE_NAME (BIO * pBIO)
{
if (pBIO && pBIO->shutdown)
{
pBIO->ptr = 0;
pBIO->init = 0;
pBIO->num = 0;
pBIO->flags = 0;
return 1;
}
return 0;
}
int
ACE_ASYNCH_BIO_READ_NAME (BIO * pBIO, char * buf, int len)
{
BIO_clear_retry_flags (pBIO);
ACE_SSL_Asynch_Stream * const p_stream =
static_cast<ACE_SSL_Asynch_Stream *> (pBIO->ptr);
if (pBIO->init == 0 || p_stream == 0 || buf == 0 || len <= 0)
return -1;
BIO_clear_retry_flags (pBIO);
int errval = 0;
int retval =
ACE_SSL_Asynch_Stream_Accessor::read (p_stream,
buf,
len,
errval);
if (retval >= 0)
return retval;
if (errval == EINPROGRESS)
BIO_set_retry_read (pBIO);
return -1;
}
int
ACE_ASYNCH_BIO_WRITE_NAME (BIO * pBIO, const char * buf, int len)
{
BIO_clear_retry_flags (pBIO);
ACE_SSL_Asynch_Stream * p_stream =
static_cast<ACE_SSL_Asynch_Stream *> (pBIO->ptr);
if (pBIO->init == 0 || p_stream == 0 || buf == 0 || len <= 0)
return -1;
BIO_clear_retry_flags (pBIO);
int errval = 0;
int retval =
ACE_SSL_Asynch_Stream_Accessor::write (p_stream,
buf,
len,
errval);
if (retval >= 0)
return retval;
if (errval == EINPROGRESS)
BIO_set_retry_write (pBIO);
return -1;
}
long
ACE_ASYNCH_BIO_CTRL_NAME (BIO * pBIO, int cmd, long num, void *ptr)
{
long ret = 1;
switch (cmd)
{
case BIO_C_SET_FILE_PTR:
pBIO->shutdown = static_cast<int> (num);
pBIO->ptr = ptr;
pBIO->init = 1;
break;
case BIO_CTRL_INFO:
ret = 0;
break;
case BIO_CTRL_GET_CLOSE:
ret = pBIO->shutdown;
break;
case BIO_CTRL_SET_CLOSE:
pBIO->shutdown = static_cast<int> (num);
break;
case BIO_CTRL_PENDING:
case BIO_CTRL_WPENDING:
ret = 0;
break;
case BIO_CTRL_DUP:
case BIO_CTRL_FLUSH:
ret = 1;
break;
default:
ret = 0;
break;
}
return ret;
}
int
ACE_ASYNCH_BIO_PUTS_NAME (BIO *pBIO, const char *str)
{
size_t const n = ACE_OS::strlen (str);
return ACE_ASYNCH_BIO_WRITE_NAME (pBIO,
str,
ACE_Utils::truncate_cast<int> (n));
}
#endif /* OPENSSL_VERSION_NUMBER > 0x0090581fL && (ACE_WIN32 ||
ACE_HAS_AIO_CALLS) */

View File

@@ -0,0 +1,42 @@
// -*- C++ -*-
//=============================================================================
/**
* @file SSL_Asynch_BIO.h
*
* $Id: SSL_Asynch_BIO.h 80826 2008-03-04 14:51:23Z wotte $
*
* @author Alexander Libman <alibman@baltimore.com>
* @author Ossama Othman <ossama@uci.edu>
*
*/
//=============================================================================
#ifndef ACE_SSL_ASYNCH_BIO_H
#define ACE_SSL_ASYNCH_BIO_H
#include /**/ "ace/pre.h"
#include "SSL_Export.h"
#if !defined (ACE_LACKS_PRAGMA_ONCE)
#pragma once
#endif /* ACE_LACKS_PRAGMA_ONCE */
// This must be included before any <openssl> include on LynxOS
#include "ace/os_include/os_stdio.h"
#include <openssl/bio.h>
#if OPENSSL_VERSION_NUMBER > 0x0090581fL && ((defined (ACE_WIN32) && !defined (ACE_HAS_WINCE)) || (defined (ACE_HAS_AIO_CALLS)))
ACE_BEGIN_VERSIONED_NAMESPACE_DECL
extern BIO * ACE_SSL_make_BIO (void * ssl_asynch_stream);
ACE_END_VERSIONED_NAMESPACE_DECL
#endif /* OPENSSL_VERSION_NUMBER > 0x0090581fL (ACE_WIN32 ||
ACE_HAS_AIO_CALLS) */
#include /**/ "ace/post.h"
#endif /* ACE_SSL_ASYNCH_BIO_H */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,425 @@
// -*- C++ -*-
//=============================================================================
/**
* @file SSL_Asynch_Stream.h
*
* $Id: SSL_Asynch_Stream.h 80826 2008-03-04 14:51:23Z wotte $
*
* @author Alexander Libman <alibman@baltimore.com>
*/
//=============================================================================
#ifndef ACE_SSL_ASYNCH_STREAM_H
#define ACE_SSL_ASYNCH_STREAM_H
#include /**/ "ace/pre.h"
#include "SSL_Context.h"
#if !defined (ACE_LACKS_PRAGMA_ONCE)
#pragma once
#endif /* ACE_LACKS_PRAGMA_ONCE */
#if OPENSSL_VERSION_NUMBER > 0x0090581fL && ((defined (ACE_WIN32) && !defined (ACE_HAS_WINCE)) || (defined (ACE_HAS_AIO_CALLS)))
#include "SSL_Asynch_BIO.h"
#include "ace/Asynch_IO_Impl.h"
#include "ace/Message_Block.h"
#include "ace/Synch_Traits.h"
#include "ace/Thread_Mutex.h"
/*
* This facility doesn't follow the normal ACE asynch I/O support classes'
* interface/implementation arrangement. It's not needed because rather than
* branching off to platform-specific APIs, all platforms use the OpenSSL
* API. Thus, you can think of this class as the implementation class (for
* OpenSSL) and there's no separate interface class.
* Also, since both read and write operations are defined in one I/O
* factory, there's no single Result class defined as there is for
* ACE_Asynch_Read_Stream, et al. There are separate result classes defined
* for read and write operations.
*/
#if defined (ACE_WIN32)
# include "ace/WIN32_Asynch_IO.h"
typedef ACE_WIN32_Asynch_Result A_RESULT;
typedef ACE_WIN32_Asynch_Read_Stream_Result ARS_RESULT;
typedef ACE_WIN32_Asynch_Write_Stream_Result AWS_RESULT;
# define ERR_CANCELED ERROR_OPERATION_ABORTED
#else
# include "ace/POSIX_Asynch_IO.h"
typedef ACE_POSIX_Asynch_Result A_RESULT;
typedef ACE_POSIX_Asynch_Read_Stream_Result ARS_RESULT;
typedef ACE_POSIX_Asynch_Write_Stream_Result AWS_RESULT;
# define ERR_CANCELED ECANCELED
#endif /* ACE_WIN32 */
ACE_BEGIN_VERSIONED_NAMESPACE_DECL
class ACE_SSL_Asynch_Stream; // Forward decl for use in result class def.
/**
* @class ACE_SSL_Asynch_Read_Stream_Result
*
* Result class that communicates result of read operations initiated on
* an ACE_SSL_Asynch_Stream object.
*/
class ACE_SSL_Asynch_Read_Stream_Result : public ARS_RESULT
{
/// Factory class will have special permissions.
friend class ACE_SSL_Asynch_Stream;
protected:
ACE_SSL_Asynch_Read_Stream_Result (ACE_Handler &handler,
ACE_HANDLE handle,
ACE_Message_Block &message_block,
size_t bytes_to_read,
const void* act,
ACE_HANDLE event,
int priority,
int signal_number);
};
/**
* @class ACE_SSL_Asynch_Write_Stream_Result
*
* Result class that communicates result of write operations initiated on
* an ACE_SSL_Asynch_Stream object.
*/
class ACE_SSL_Asynch_Write_Stream_Result : public AWS_RESULT
{
/// Factory class will have special permissions.
friend class ACE_SSL_Asynch_Stream;
protected:
ACE_SSL_Asynch_Write_Stream_Result (ACE_Handler &handler,
ACE_HANDLE handle,
ACE_Message_Block &message_block,
size_t bytes_to_read,
const void* act,
ACE_HANDLE event,
int priority,
int signal_number);
};
/**
* @class ACE_SSL_Asynch_Result
*
* Result class that is used internally for socket close notifications.
*/
class ACE_SSL_Asynch_Result : public A_RESULT
{
public:
ACE_SSL_Asynch_Result (ACE_Handler &handler);
void complete (size_t bytes_transferred,
int success,
const void * completion_key,
u_long error);
};
// Only provide forward declarations to prevent possible abuse of the
// friend declarations in ACE_SSL_Asynch_Stream.
struct ACE_SSL_Asynch_Stream_Accessor;
/**
* @class ACE_SSL_Asynch_Stream
*
* @brief This class is a factory for initiating asynchronous reads
* and writes on an SSL stream.
*
* Once open() is called, multiple asynchronous read and write operations
* can be started using this class. The handler object (derived from
* ACE_Handler) specified in open() will receive completion events for the
* operations initiated via this class.
*/
class ACE_SSL_Export ACE_SSL_Asynch_Stream
: public ACE_Asynch_Operation,
public ACE_Handler
{
public:
// Use a class/struct to work around scoping
// problems for extern "C" free functions with some compilers. For
// example, some can't handle
//
// friend ::some_extern_c_free_function (...)
//
// Note that we could use a straight C++ (i.e. not extern "C") free
// function, but using a class or struct allows us to hide the
// interface from the user, which prevents abuse of this friend
// relationship.
friend struct ACE_SSL_Asynch_Stream_Accessor;
enum Stream_Type
{
ST_CLIENT = 0x0001,
ST_SERVER = 0x0002
};
/// Constructor.
/**
* @arg context Pointer to an ACE_SSL_Context instance containing
* the OpenSSL information to be associated with this
* ACE_SSL_Asynch_Stream. The needed SSL data will be
* copied before return. Therefore, this object can be
* reused, modified, or deleted upon return. If a 0 pointer
* is passed, the ACE_SSL_Context::instance() method will
* be called to get access to a singleton.
*/
ACE_SSL_Asynch_Stream (Stream_Type s_type = ST_SERVER,
ACE_SSL_Context * context = 0);
/// Destructor
virtual ~ACE_SSL_Asynch_Stream (void);
int cancel (void);
int close (void);
/**
* Initializes the factory with information which will be used with
* each asynchronous call.
*
* @arg handler The ACE_Handler that will be called to handle completions
* for operations initiated using this factory.
* @arg handle The handle that future read/write operations will use.
*
* @retval 0 for success.
* @retval -1 for failure; consult @c errno for further information.
*/
int open (ACE_Handler &handler,
ACE_HANDLE handle = ACE_INVALID_HANDLE,
const void *completion_key = 0,
ACE_Proactor *proactor = 0);
/**
* Initiates an asynchronous read. If the operation is successfully
* initiated, the handle_read_stream() method will be called on the
* ACE_Handler object passed to open() when the operation completes.
* Data is read into the specified ACE_Message_Block beginning at its
* write pointer; the block's write pointer is updated to reflect any
* added data when the operation completes.
*
* @arg message_block The specified ACE_Message_Block will receive any
* data that is read. Data will be read into the
* block beginning at the block's write pointer.
* @arg num_bytes_to_read The maximum number of bytes to read. The actual
* amount read may be less.
* @arg act ACT which is passed to the completion handler in
* the result object.
* @arg priority Specifies the operation priority. This has an
* affect on POSIX only. Works like @i nice in Unix.
* Negative values are not allowed. 0 means priority
* of the operation same as the process priority.
* 1 means priority of the operation is one less than
* process, and so forth. This parameter has no
* affect on Win32.
* @arg signal_number The POSIX4 real-time signal number to be used
* for the operation. signal_number ranges from
* ACE_SIGRTMIN to ACE_SIGRTMAX. This argument is
* unused on non-POSIX4 systems.
*
* @retval 0 for success.
* @retval -1 for failure; consult @c errno for further information.
*/
int read (ACE_Message_Block &message_block,
size_t num_bytes_to_read,
const void *act = 0,
int priority = 0,
int signal_number = ACE_SIGRTMIN);
/**
* Initiates an asynchronous write. If the operation is successfully
* initiated, the handle_write_stream() method will be called on the
* ACE_Handler object passed to open() when the operation completes.
* Data is taken from the specified ACE_Message_Block beginning at its
* read pointer; the block's read pointer is updated to reflect any
* data successfully sent when the operation completes.
*
* @arg message_block The specified ACE_Message_Block is the source of
* data that is written. Data will be taken from the
* block beginning at the block's read pointer.
* @arg bytes_to_write The maximum number of bytes to write. The actual
* amount written may be less.
* @arg act ACT which is passed to the completion handler in
* the result object.
* @arg priority Specifies the operation priority. This has an
* affect on POSIX only. Works like @i nice in Unix.
* Negative values are not allowed. 0 means priority
* of the operation same as the process priority.
* 1 means priority of the operation is one less than
* process, and so forth. This parameter has no
* affect on Win32.
* @arg signal_number The POSIX4 real-time signal number to be used
* for the operation. signal_number ranges from
* ACE_SIGRTMIN to ACE_SIGRTMAX. This argument is
* unused on non-POSIX4 systems.
*
* @retval 0 for success.
* @retval -1 for failure; consult @c errno for further information.
*/
int write (ACE_Message_Block &message_block,
size_t bytes_to_write,
const void *act = 0,
int priority = 0,
int signal_number = ACE_SIGRTMIN);
protected:
/// Virtual from ACE_Asynch_Operation. Since this class is essentially an
/// implementation class, simply return 0.
virtual ACE_Asynch_Operation_Impl *implementation (void) const { return 0; }
/// virtual from ACE_Handler
/// This method is called when BIO write request is completed. It
/// processes the IO completion and calls do_SSL_state_machine().
virtual void handle_write_stream
(const ACE_Asynch_Write_Stream::Result &result);
/// This method is called when BIO read request is completed. It
/// processes the IO completion and calls do_SSL_state_machine().
virtual void handle_read_stream
(const ACE_Asynch_Read_Stream::Result &result);
/// This method is called when all SSL sessions are closed and no
/// more pending AIOs exist. It also calls users handle_wakeup().
virtual void handle_wakeup (void);
/**
* @name SSL State Machine
*/
//@{
int do_SSL_state_machine (void);
int do_SSL_handshake (void);
int do_SSL_read (void);
int do_SSL_write(void);
int do_SSL_shutdown(void);
//@}
void print_error (int err_ssl,
const ACE_TCHAR *pText);
int pending_BIO_count (void);
/// This method is called to notify user handler when user's read in
/// done.
int notify_read (int bytes_transferred, int error);
/// This method is called to notify user handler when user's write
/// in done.
int notify_write (int bytes_transferred, int error);
/// This method is called to notify ourself that SSL session is
/// shutdown and that there is no more I/O activity now and in the
/// future.
int notify_close(void);
/**
* @name BIO Helpers
*/
//@{
int ssl_bio_read (char * buf, size_t len, int & errval);
int ssl_bio_write (const char * buf, size_t len, int & errval);
//@}
private:
// Preventing copying through construction or assignment.
ACE_SSL_Asynch_Stream (ACE_SSL_Asynch_Stream const &);
ACE_SSL_Asynch_Stream & operator= (ACE_SSL_Asynch_Stream const &);
protected:
/// Stream Type ST_CLIENT/ST_SERVER
Stream_Type type_;
/// The real file/socket handle
ACE_HANDLE handle_;
/// The proactor
ACE_Proactor * proactor_;
/// External,i.e user handler
ACE_Handler * ext_handler_;
/// External, i.e. read result faked for user
ACE_SSL_Asynch_Read_Stream_Result * ext_read_result_ ;
/// External, i.e. write result faked for user
ACE_SSL_Asynch_Write_Stream_Result * ext_write_result_ ;
/// Stream state/flags
enum Stream_Flag
{
/// istream_ open OK
SF_STREAM_OPEN = 0x0001,
/// request to SSL shutdown
SF_REQ_SHUTDOWN = 0x0002,
/// SSL shutdown finished
SF_SHUTDOWN_DONE = 0x0004,
/// Close notification sent
SF_CLOSE_NTF_SENT = 0x0008,
/// Stream can be safely destroyed
SF_DELETE_ENABLE = 0x0010
};
int flags_;
/// The SSL session.
SSL * ssl_;
/// The BIO implementation
BIO * bio_;
/// The real streams which work under the ssl connection.
/// BIO performs I/O via this streams
enum BIO_Flag // internal IO flags
{
/// End of stream
BF_EOS = 0x01,
/// Real AIO in progress
BF_AIO = 0x02
};
/**
* @name Internal stream, buffer and info for BIO read
*/
//@{
ACE_Asynch_Read_Stream bio_istream_;
ACE_Message_Block bio_inp_msg_;
int bio_inp_errno_;
int bio_inp_flag_;
//@}
/**
* @name Internal stream, buffer and info for BIO write
*/
//@{
ACE_Asynch_Write_Stream bio_ostream_;
ACE_Message_Block bio_out_msg_;
int bio_out_errno_;
int bio_out_flag_;
//@}
/// Mutex to protect work
ACE_SYNCH_MUTEX mutex_;
};
ACE_END_VERSIONED_NAMESPACE_DECL
#endif /* OPENSSL_VERSION_NUMBER > 0x0090581fL && (ACE_WIN32 ||
ACE_HAS_AIO_CALLS) */
#include /**/ "ace/post.h"
#endif /* ACE_SSL_ASYNCH_STREAM_H */

View File

@@ -0,0 +1,640 @@
#include "SSL_Context.h"
#include "sslconf.h"
#if !defined(__ACE_INLINE__)
#include "SSL_Context.inl"
#endif /* __ACE_INLINE__ */
#include "ace/Guard_T.h"
#include "ace/Object_Manager.h"
#include "ace/Log_Msg.h"
#include "ace/Singleton.h"
#include "ace/Synch_Traits.h"
#include "ace/Truncate.h"
#include "ace/ACE.h"
#include "ace/OS_NS_errno.h"
#include "ace/OS_NS_string.h"
#ifdef ACE_HAS_THREADS
# include "ace/Thread_Mutex.h"
# include "ace/OS_NS_Thread.h"
#endif /* ACE_HAS_THREADS */
#include <openssl/x509.h>
#include <openssl/err.h>
#include <openssl/rand.h>
#include <openssl/safestack.h>
ACE_RCSID (ACE_SSL,
SSL_Context,
"$Id: SSL_Context.cpp 82574 2008-08-08 19:35:06Z parsons $")
namespace
{
/// Reference count of the number of times the ACE_SSL_Context was
/// initialized.
int ssl_library_init_count = 0;
// @@ This should also be done with a singleton, otherwise it is not
// thread safe and/or portable to some weird platforms...
#ifdef ACE_HAS_THREADS
/// Array of mutexes used internally by OpenSSL when the SSL
/// application is multithreaded.
ACE_SSL_Context::lock_type * ssl_locks = 0;
// @@ This should also be managed by a singleton.
#endif
}
#ifdef ACE_HAS_THREADS
# if (defined (ACE_HAS_VERSIONED_NAMESPACE) && ACE_HAS_VERSIONED_NAMESPACE == 1)
# define ACE_SSL_LOCKING_CALLBACK_NAME ACE_PREPROC_CONCATENATE(ACE_VERSIONED_NAMESPACE_NAME, _ACE_SSL_locking_callback)
# define ACE_SSL_THREAD_ID_NAME ACE_PREPROC_CONCATENATE(ACE_VERSIONED_NAMESPACE_NAME, _ACE_SSL_thread_id)
# else
# define ACE_SSL_LOCKING_CALLBACK_NAME ACE_SSL_locking_callback
# define ACE_SSL_THREAD_ID_NAME ACE_SSL_thread_id
# endif /* ACE_HAS_VERSIONED_NAMESPACE == 1 */
extern "C"
{
void
ACE_SSL_LOCKING_CALLBACK_NAME (int mode,
int type,
const char * /* file */,
int /* line */)
{
// #ifdef undef
// fprintf(stderr,"thread=%4d mode=%s lock=%s %s:%d\n",
// CRYPTO_thread_id(),
// (mode&CRYPTO_LOCK)?"l":"u",
// (type&CRYPTO_READ)?"r":"w",file,line);
// #endif
// /*
// if (CRYPTO_LOCK_SSL_CERT == type)
// fprintf(stderr,"(t,m,f,l) %ld %d %s %d\n",
// CRYPTO_thread_id(),
// mode,file,line);
// */
if (mode & CRYPTO_LOCK)
(void) ssl_locks[type].acquire ();
else
(void) ssl_locks[type].release ();
}
// -------------------------------
// Return the current thread ID. OpenSSL uses this on platforms
// that need it.
unsigned long
ACE_SSL_THREAD_ID_NAME (void)
{
return (unsigned long) ACE_VERSIONED_NAMESPACE_NAME::ACE_OS::thr_self ();
}
}
#endif /* ACE_HAS_THREADS */
// ****************************************************************
ACE_BEGIN_VERSIONED_NAMESPACE_DECL
#ifdef ACE_HAS_THREADS
ACE_SSL_Context::lock_type * ACE_SSL_Context::locks_ = 0;
#endif /* ACE_HAS_THREADS */
ACE_SSL_Context::ACE_SSL_Context (void)
: context_ (0),
mode_ (-1),
default_verify_mode_ (SSL_VERIFY_NONE),
have_ca_ (0)
{
ACE_SSL_Context::ssl_library_init ();
}
ACE_SSL_Context::~ACE_SSL_Context (void)
{
if (this->context_)
{
::SSL_CTX_free (this->context_);
this->context_ = 0;
}
ACE_SSL_Context::ssl_library_fini ();
}
ACE_SSL_Context *
ACE_SSL_Context::instance (void)
{
return ACE_Singleton<ACE_SSL_Context, ACE_SYNCH_MUTEX>::instance ();
}
void
ACE_SSL_Context::ssl_library_init (void)
{
ACE_MT (ACE_GUARD (ACE_Recursive_Thread_Mutex,
ace_ssl_mon,
*ACE_Static_Object_Lock::instance ()));
if (ssl_library_init_count == 0)
{
// Initialize the locking callbacks before initializing anything
// else.
#ifdef ACE_HAS_THREADS
int const num_locks = ::CRYPTO_num_locks ();
this->locks_ = new lock_type[num_locks];
ssl_locks = this->locks_;
# if !defined (WIN32)
// This call isn't necessary on some platforms. See the CRYPTO
// library's threads(3) man page for details.
::CRYPTO_set_id_callback (ACE_SSL_THREAD_ID_NAME);
# endif /* !WIN32 */
::CRYPTO_set_locking_callback (ACE_SSL_LOCKING_CALLBACK_NAME);
#endif /* ACE_HAS_THREADS */
::SSLeay_add_ssl_algorithms ();
::SSL_load_error_strings ();
// Seed the random number generator. Note that the random
// number generator can be seeded more than once to "stir" its
// state.
#ifdef WIN32
// Seed the random number generator by sampling the screen.
::RAND_screen ();
#endif /* WIN32 */
#if OPENSSL_VERSION_NUMBER >= 0x00905100L
// OpenSSL < 0.9.5 doesn't have EGD support.
const char *egd_socket_file =
ACE_OS::getenv (ACE_SSL_EGD_FILE_ENV);
if (egd_socket_file != 0)
(void) this->egd_file (egd_socket_file);
#endif /* OPENSSL_VERSION_NUMBER */
const char *rand_file =
ACE_OS::getenv (ACE_SSL_RAND_FILE_ENV);
if (rand_file != 0)
(void) this->seed_file (rand_file);
// Initialize the mutexes that will be used by the SSL and
// crypto library.
}
++ssl_library_init_count;
}
void
ACE_SSL_Context::ssl_library_fini (void)
{
ACE_MT (ACE_GUARD (ACE_Recursive_Thread_Mutex,
ace_ssl_mon,
*ACE_Static_Object_Lock::instance ()));
--ssl_library_init_count;
if (ssl_library_init_count == 0)
{
::ERR_free_strings ();
::EVP_cleanup ();
// Clean up the locking callbacks after everything else has been
// cleaned up.
#ifdef ACE_HAS_THREADS
::CRYPTO_set_locking_callback (0);
ssl_locks = 0;
delete [] this->locks_;
this->locks_ = 0;
#endif /* ACE_HAS_THREADS */
}
}
int
ACE_SSL_Context::set_mode (int mode)
{
ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex,
ace_ssl_mon,
*ACE_Static_Object_Lock::instance (),
-1));
if (this->context_ != 0)
return -1;
SSL_METHOD *method = 0;
switch (mode)
{
case ACE_SSL_Context::SSLv2_client:
method = ::SSLv2_client_method ();
break;
case ACE_SSL_Context::SSLv2_server:
method = ::SSLv2_server_method ();
break;
case ACE_SSL_Context::SSLv2:
method = ::SSLv2_method ();
break;
case ACE_SSL_Context::SSLv3_client:
method = ::SSLv3_client_method ();
break;
case ACE_SSL_Context::SSLv3_server:
method = ::SSLv3_server_method ();
break;
case ACE_SSL_Context::SSLv3:
method = ::SSLv3_method ();
break;
case ACE_SSL_Context::SSLv23_client:
method = ::SSLv23_client_method ();
break;
case ACE_SSL_Context::SSLv23_server:
method = ::SSLv23_server_method ();
break;
case ACE_SSL_Context::SSLv23:
method = ::SSLv23_method ();
break;
case ACE_SSL_Context::TLSv1_client:
method = ::TLSv1_client_method ();
break;
case ACE_SSL_Context::TLSv1_server:
method = ::TLSv1_server_method ();
break;
case ACE_SSL_Context::TLSv1:
method = ::TLSv1_method ();
break;
default:
method = ::SSLv3_method ();
break;
}
this->context_ = ::SSL_CTX_new (method);
if (this->context_ == 0)
return -1;
this->mode_ = mode;
// Load the trusted certificate authority (default) certificate
// locations. But do not return -1 on error, doing so confuses CTX
// allocation (severe error) with the less important loading of CA
// certificate location error. If it is important for your
// application then call ACE_SSL_Context::have_trusted_ca(),
// immediately following this call to set_mode().
(void) this->load_trusted_ca ();
return 0;
}
int
ACE_SSL_Context::load_trusted_ca (const char* ca_file,
const char* ca_dir,
bool use_env_defaults)
{
this->check_context ();
if (ca_file == 0 && use_env_defaults)
{
// Use the default environment settings.
ca_file = ACE_OS::getenv (ACE_SSL_CERT_FILE_ENV);
if (ca_file == 0)
ca_file = ACE_DEFAULT_SSL_CERT_FILE;
}
if (ca_dir == 0 && use_env_defaults)
{
// Use the default environment settings.
ca_dir = ACE_OS::getenv (ACE_SSL_CERT_DIR_ENV);
if (ca_dir == 0)
ca_dir = ACE_DEFAULT_SSL_CERT_DIR;
}
// NOTE: SSL_CTX_load_verify_locations() returns 0 on error.
if (::SSL_CTX_load_verify_locations (this->context_,
ca_file,
ca_dir) <= 0)
{
if (ACE::debug ())
ACE_SSL_Context::report_error ();
return -1;
}
++this->have_ca_;
// For TLS/SSL servers scan all certificates in ca_file and ca_dir and
// list them as acceptable CAs when requesting a client certificate.
if (mode_ == SSLv23
|| mode_ == SSLv23_server
|| mode_ == TLSv1
|| mode_ == TLSv1_server
|| mode_ == SSLv3
|| mode_ == SSLv3_server
|| mode_ == SSLv2
|| mode_ == SSLv2_server)
{
// Note: The STACK_OF(X509_NAME) pointer is a copy of the pointer in
// the CTX; any changes to it by way of these function calls will
// change the CTX directly.
STACK_OF (X509_NAME) * cert_names = 0;
cert_names = ::SSL_CTX_get_client_CA_list (this->context_);
bool error = false;
// Add CAs from both the file and dir, if specified. There should
// already be a STACK_OF(X509_NAME) in the CTX, but if not, we create
// one.
if (ca_file)
{
if (cert_names == 0)
{
if ((cert_names = ::SSL_load_client_CA_file (ca_file)) != 0)
::SSL_CTX_set_client_CA_list (this->context_, cert_names);
else
error = true;
}
else
{
// Add new certificate names to the list.
error = (0 == ::SSL_add_file_cert_subjects_to_stack (cert_names,
ca_file));
}
if (error)
{
if (ACE::debug ())
ACE_SSL_Context::report_error ();
return -1;
}
}
// SSL_add_dir_cert_subjects_to_stack is defined at 0.9.8a (but not
// on OpenVMS or Mac Classic); it may be available earlier. Change
// this comparison if so.
#if defined (OPENSSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER >= 0x0090801fL)
# if !defined (OPENSSL_SYS_VMS) && !defined (OPENSSL_SYS_MACINTOSH_CLASSIC)
# if !defined (OPENSSL_SYS_WIN32) || (OPENSSL_VERSION_NUMBER > 0x0090807fL)
if (ca_dir != 0)
{
if (cert_names == 0)
{
if ((cert_names = sk_X509_NAME_new_null ()) == 0)
{
if (ACE::debug ())
ACE_SSL_Context::report_error ();
return -1;
}
::SSL_CTX_set_client_CA_list (this->context_, cert_names);
}
if (0 == ::SSL_add_dir_cert_subjects_to_stack (cert_names, ca_dir))
{
if (ACE::debug ())
ACE_SSL_Context::report_error ();
return -1;
}
}
# endif /* !OPENSSL_SYS_WIN32 || OPENSSL_VERSION_NUMBER >= 0x0090807fL */
# endif /* !OPENSSL_SYS_VMS && !OPENSSL_SYS_MACINTOSH_CLASSIC */
#endif /* OPENSSL_VERSION_NUMBER >= 0.9.8a release */
}
return 0;
}
int
ACE_SSL_Context::private_key (const char *file_name,
int type)
{
if (this->private_key_.type () != -1)
return 0;
this->check_context ();
this->private_key_ = ACE_SSL_Data_File (file_name, type);
if (::SSL_CTX_use_PrivateKey_file (this->context_,
this->private_key_.file_name (),
this->private_key_.type ()) <= 0)
{
this->private_key_ = ACE_SSL_Data_File ();
return -1;
}
else
return this->verify_private_key ();
}
int
ACE_SSL_Context::verify_private_key (void)
{
this->check_context ();
return (::SSL_CTX_check_private_key (this->context_) <= 0 ? -1 : 0);
}
int
ACE_SSL_Context::certificate (const char *file_name,
int type)
{
if (this->certificate_.type () != -1)
return 0;
this->certificate_ = ACE_SSL_Data_File (file_name, type);
this->check_context ();
if (::SSL_CTX_use_certificate_file (this->context_,
this->certificate_.file_name (),
this->certificate_.type ()) <= 0)
{
this->certificate_ = ACE_SSL_Data_File ();
return -1;
}
else
return 0;
}
int
ACE_SSL_Context::certificate (X509* cert)
{
// Is it really a good idea to return 0 if we're not setting the
// certificate?
if (this->certificate_.type () != -1)
return 0;
this->check_context();
if (::SSL_CTX_use_certificate (this->context_, cert) <= 0)
{
return -1;
}
else
{
// No file is associated with the certificate, set this to a fictional
// value so we don't reset it later.
this->certificate_ = ACE_SSL_Data_File ("MEMORY CERTIFICATE");
return 0;
}
}
void
ACE_SSL_Context::set_verify_peer (int strict, int once, int depth)
{
this->check_context ();
// Setup the peer verififcation mode.
int verify_mode = SSL_VERIFY_PEER;
if (once)
verify_mode |= SSL_VERIFY_CLIENT_ONCE;
if (strict)
verify_mode |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
// set the default verify mode
this->default_verify_mode (verify_mode);
// Set the max certificate depth but later let the verify_callback
// catch the depth error by adding one to the required depth.
if (depth > 0)
::SSL_CTX_set_verify_depth (this->context_, depth + 1);
}
int
ACE_SSL_Context::random_seed (const char * seed)
{
int len = ACE_Utils::truncate_cast<int> (ACE_OS::strlen (seed));
::RAND_seed (seed, len);
#if OPENSSL_VERSION_NUMBER >= 0x00905100L
// RAND_status() returns 1 if the PRNG has enough entropy.
return (::RAND_status () == 1 ? 0 : -1);
#else
return 0; // Ugly, but OpenSSL <= 0.9.4 doesn't have RAND_status().
#endif /* OPENSSL_VERSION_NUMBER >= 0x00905100L */
}
int
ACE_SSL_Context::egd_file (const char * socket_file)
{
#if OPENSSL_VERSION_NUMBER < 0x00905100L
// OpenSSL < 0.9.5 doesn't have EGD support.
ACE_UNUSED_ARG (socket_file);
ACE_NOTSUP_RETURN (-1);
#else
// RAND_egd() returns the amount of entropy used to seed the random
// number generator. The actual value should be greater than 16,
// i.e. 128 bits.
if (::RAND_egd (socket_file) > 0)
return 0;
else
return -1;
#endif /* OPENSSL_VERSION_NUMBER >= 0x00905100L */
}
int
ACE_SSL_Context::seed_file (const char * seed_file, long bytes)
{
// RAND_load_file() returns the number of bytes used to seed the
// random number generator. If the file reads ok, check RAND_status to
// see if it got enough entropy.
if (::RAND_load_file (seed_file, bytes) > 0)
#if OPENSSL_VERSION_NUMBER >= 0x00905100L
// RAND_status() returns 1 if the PRNG has enough entropy.
return (::RAND_status () == 1 ? 0 : -1);
#else
return 0; // Ugly, but OpenSSL <= 0.9.4 doesn't have RAND_status().
#endif /* OPENSSL_VERSION_NUMBER >= 0x00905100L */
else
return -1;
}
void
ACE_SSL_Context::report_error (unsigned long error_code)
{
if (error_code == 0)
return;
char error_string[256];
(void) ::ERR_error_string (error_code, error_string);
ACE_ERROR ((LM_ERROR,
ACE_TEXT ("ACE_SSL (%P|%t) error code: %u - %C\n"),
error_code,
error_string));
}
void
ACE_SSL_Context::report_error (void)
{
unsigned long err = ::ERR_get_error ();
ACE_SSL_Context::report_error (err);
ACE_OS::last_error (err);
}
int
ACE_SSL_Context::dh_params (const char *file_name,
int type)
{
if (this->dh_params_.type () != -1)
return 0;
// For now we only support PEM encodings
if (type != SSL_FILETYPE_PEM)
return -1;
this->dh_params_ = ACE_SSL_Data_File (file_name, type);
this->check_context ();
{
// Swiped from Rescorla's examples and the OpenSSL s_server.c app
DH * ret=0;
BIO * bio = 0;
if ((bio = ::BIO_new_file (this->dh_params_.file_name (), "r")) == 0)
{
this->dh_params_ = ACE_SSL_Data_File ();
return -1;
}
ret = PEM_read_bio_DHparams (bio, 0, 0, 0);
BIO_free (bio);
if (ret == 0)
{
this->dh_params_ = ACE_SSL_Data_File ();
return -1;
}
if (::SSL_CTX_set_tmp_dh (this->context_, ret) < 0)
{
this->dh_params_ = ACE_SSL_Data_File ();
return -1;
}
DH_free (ret);
}
return 0;
}
// ****************************************************************
#if defined (ACE_HAS_EXPLICIT_STATIC_TEMPLATE_MEMBER_INSTANTIATION)
template ACE_Singleton<ACE_SSL_Context, ACE_SYNCH_MUTEX> *
ACE_Singleton<ACE_SSL_Context, ACE_SYNCH_MUTEX>::singleton_;
#endif /* ACE_HAS_EXPLICIT_STATIC_TEMPLATE_MEMBER_INSTANTIATION */
ACE_END_VERSIONED_NAMESPACE_DECL

View File

@@ -0,0 +1,384 @@
// -*- C++ -*-
//=============================================================================
/**
* @file SSL_Context.h
*
* $Id: SSL_Context.h 80826 2008-03-04 14:51:23Z wotte $
*
* @author Carlos O'Ryan <coryan@ece.uci.edu>
* @author Ossama Othman <ossama@dre.vanderbilt.edu>
*/
//=============================================================================
#ifndef ACE_SSL_CONTEXT_H
#define ACE_SSL_CONTEXT_H
#include /**/ "ace/pre.h"
#include "SSL_Export.h"
#if !defined (ACE_LACKS_PRAGMA_ONCE)
# pragma once
#endif /* ACE_LACKS_PRAGMA_ONCE */
#include "ace/SString.h"
#ifdef ACE_HAS_THREADS
# include "ace/Synch_Traits.h"
#endif /* ACE_HAS_THREADS */
#include <openssl/ssl.h>
ACE_BEGIN_VERSIONED_NAMESPACE_DECL
class ACE_SSL_Export ACE_SSL_Data_File
{
public:
/// Default constructor
ACE_SSL_Data_File (void);
/// Contructor from a file name and the file type.
ACE_SSL_Data_File (const char *file_name,
int type = SSL_FILETYPE_PEM);
/// The file name
const char *file_name (void) const;
/// The type
int type (void) const;
private:
/// The file name
ACE_CString file_name_;
/// The type, used by the SSL library to parse the file contents.
int type_;
};
// ****************************************************************
/**
* @class ACE_SSL_Context
*
* @brief A wrapper for the OpenSSL SSL_CTX related functions.
*
* This class provides a wrapper for the SSL_CTX data structure.
* Since most applications have a single SSL_CTX structure, this class
* can be used as a singleton.
*/
class ACE_SSL_Export ACE_SSL_Context
{
public:
#ifdef ACE_HAS_THREADS
typedef ACE_SYNCH_MUTEX lock_type;
#endif /* ACE_HAS_THREADS */
enum {
INVALID_METHOD = -1,
SSLv2_client = 1,
SSLv2_server,
SSLv2,
SSLv3_client,
SSLv3_server,
SSLv3,
SSLv23_client,
SSLv23_server,
SSLv23,
TLSv1_client,
TLSv1_server,
TLSv1
};
/// Constructor
ACE_SSL_Context (void);
/// Destructor
~ACE_SSL_Context (void);
/// The Singleton context, the SSL components use the singleton if
/// nothing else is available.
static ACE_SSL_Context *instance (void);
/**
* Set the CTX mode. The mode can be set only once, afterwards the
* function has no effect and returns -1.
* Once the mode is set the underlying SSL_CTX is initialized and
* the class can be used.
* If the mode is not set, then the class automatically initializes
* itself to the default mode.
*/
int set_mode (int mode = ACE_SSL_Context::SSLv23);
int get_mode (void) const;
/// Get the SSL context
SSL_CTX *context (void);
/// Get the file name and file format used for the private key
int private_key_type (void) const;
const char *private_key_file_name (void) const;
/// Set the private key file.
/**
* @note This method should only be called after a certificate has
* been set since key verification is performed against the
* certificate, among other things.
*/
int private_key (const char *file_name, int type = SSL_FILETYPE_PEM);
/// Verify that the private key is valid.
/**
* @note This method should only be called after a certificate has
* been set since key verification is performed against the
* certificate, among other things.
*/
int verify_private_key (void);
/// Get the file name and file format used for the certificate file
int certificate_type (void) const;
const char *certificate_file_name (void) const;
/// Set the certificate file.
int certificate (const char *file_name,
int type = SSL_FILETYPE_PEM);
/// Load certificate from memory rather than a file.
int certificate (X509* cert);
/**
* Load the location of the trusted certification authority
* certificates. Note that CA certificates are stored in PEM format
* as a sequence of certificates in @a ca_file or as a set of
* individual certificates in @a ca_dir (or both).
*
* Note this method is called by set_mode() to load the default
* environment settings for @a ca_file and @a ca_dir, if any. This
* allows for automatic service configuration (and backward
* compatibility with previous versions).
*
* Note that the underlying SSL function will add valid file and
* directory names to the load location lists maintained as part of
* the SSL_CTX table. It therefore doesn't make sense to keep a
* copy of the file and path name of the most recently added
* @a ca_file or @a ca_path.
*
* @param[in] ca_file CA file pathname. Passed to
* @c SSL_CTX_load_verify_locations() if not
* 0. If 0, behavior depends on the value of
* @a use_env_defaults.
* @param[in] ca_dir CA directory pathname. Passed to
* @c SSL_CTX_load_verify_locations() if not
* 0. If 0, behavior depends on the value of
* @a use_env_defaults.
* @param[in] use_env_defaults If false, the specified @a ca_file argument
* is passed to
* @c SSL_CTX_load_verify_locations(),
* regardless of its value.
* If true (the default), additional defaults
* can be applied to either @a ca_file,
* @a ca_dir, or both. The following
* additional defaults are applied when the
* @a ca_file argument is 0:
* - The @c SSL_CERT_FILE environment variable
* will be queried for a file name to use as
* the @a ca_file argument. The environment
* variable name to query can be changed by
* supplying a @c ACE_SSL_CERT_FILE_ENV
* configuration item when building ACE.
* - If there is no @c SSL_CERT_FILE in the
* current environment, the file specified
* by the @c ACE_DEFAULT_SSL_CERT_FILE ACE
* configuration item will be used. The
* default value is "cert.pem" on Windows
* and "/etc/ssl/cert.pem" on all other
* platforms.
* The following additional defaults are
* applied when the @a ca_dir argument is 0:
* - The @c SSL_CERT_DIR environment variable
* will be queried for a file name to use as
* the @a ca_dir argument. The environment
* variable name to query can be changed by
* supplying a @c ACE_SSL_CERT_DIR_ENV
* configuration item when building ACE.
* - If there is no @c SSL_CERT_DIR in the
* current environment, the directory
* specified by the @c
* ACE_DEFAULT_SSL_CERT_DIR ACE
* configuration item will be used. The
* default value is "certs" on Windows
* and "/etc/ssl/certs" on all other
* platforms.
*
* @return 0 for success or -1 on error.
*
* @see OpenSSL manual SSL_CTX_load_verify_locations(3) for a
* detailed description of the CA file and directory requirements
* and processing.
*/
int load_trusted_ca (const char* ca_file = 0,
const char* ca_dir = 0,
bool use_env_defaults = true);
/**
* Test whether any CA locations have been successfully loaded and
* return the number of successful attempts.
*
* @retval >0 The number of successful CA load attempts.
* @retval 0 If all CA load attempts have failed.
*/
int have_trusted_ca (void) const;
/**
* @todo Complete this documentation where elipses(...) are used
*
* @doc Use this method when certificate chain verification is
* required. The default server behaviour is SSL_VERIFY_NONE
* i.e. client certicates are requested for verified. This method
* can be used to configure server to request client certificates
* and perform the certificate verification. If <strict> is set
* true the client connection is rejected when certificate
* verification fails. Otherwise the session is accepted with a
* warning, which is the default behaviour. If <once> is set true
* (default), certificates are requested only once per session.
* The last parameter <depth> can be used to set the verification
* depth.
*
* Note for verification to work correctly there should be a valid
* CA name list set using load_trusted_ca().
*
* @see OpenSSL documentation of SSL_CTX_set_verify(3) for details of
* the verification process.
*
* @see OpenSSL documentation ... set_verify_depth(3) ...
*
* Note that this method overrides the use of the
* default_verify_mode() method.
*/
void set_verify_peer (int strict = 0, int once = 1, int depth = 0);
/// TODO: a implementation that will lookup the CTX table for the list
/// of files and paths etc.
/// Query the location of trusted certification authority
/// certificates.
// const char* ca_file_name(void) const;
// const char* ca_dir_name(void) const;
/**
* Set and query the default verify mode for this context, it is
* inherited by all the ACE_SSL objects created using the context.
* It can be overriden on a per-ACE_SSL object.
*/
void default_verify_mode (int mode);
int default_verify_mode (void) const;
/**
* @name OpenSSL Random Number Generator Seed Related Methods
*
* These are methods that can be used to seed OpenSSL's
* pseudo-random number generator. These methods can be called more
* than once.
*/
//@{
/// Seed the underlying random number generator. This value should
/// have at least 128 bits of entropy.
static int random_seed (const char * seed);
/// Set the Entropy Gathering Daemon (EGD) UNIX domain socket file to
/// read random seed values from.
static int egd_file (const char * socket_file);
/**
* Set the file that contains the random seed value state, and the
* amount of bytes to read. "-1" bytes causes the entire file to be
* read.
*/
static int seed_file (const char * seed_file, long bytes = -1);
//@}
/// Print SSL error corresponding to the given error code.
static void report_error (unsigned long error_code);
/// Print the last SSL error for the current thread.
static void report_error (void);
/**
* @name Diffie-Hellman (DH) Parameters
*
* When using DSS-based certificates, Diffie-Hellman keys need to be
* exchanged. These must be provided in the form of DH key
* generation parameters loaded in, or as fixed keys hardcoded into
* the code itself. ACE_SSL supports loaded parameters.
*
*/
//@{
/**
* Load Diffie-Hellman parameters from file_name. The specified file can be
* a standalone file containing only DH parameters (e.g., as created
* by <code>openssl dhparam</code>), or it can be a certificate which has
* a PEM-encoded set of DH params concatenated on to i.
*/
int dh_params (const char *file_name, int type = SSL_FILETYPE_PEM);
const char *dh_params_file_name () const;
int dh_params_file_type () const;
//@}
private:
/// Verify if the context has been initialized or not.
void check_context (void);
/// @@ More to document
void ssl_library_init ();
void ssl_library_fini ();
// = Prevent assignment and copy initialization.
//@{
ACE_SSL_Context (const ACE_SSL_Context &);
ACE_SSL_Context & operator= (const ACE_SSL_Context &);
//@}
private:
/// The SSL_CTX structure
SSL_CTX *context_;
/// Cache the mode so we can answer fast
int mode_;
/// The private key, certificate, and Diffie-Hellman paramters files
ACE_SSL_Data_File private_key_;
ACE_SSL_Data_File certificate_;
ACE_SSL_Data_File dh_params_;
/// The default verify mode.
int default_verify_mode_;
/// count of successful CA load attempts
int have_ca_;
#ifdef ACE_HAS_THREADS
/// Array of mutexes used internally by OpenSSL when the SSL
/// application is multithreaded.
static lock_type * locks_;
#endif /* ACE_HAS_THREADS */
};
ACE_END_VERSIONED_NAMESPACE_DECL
#if defined(__ACE_INLINE__)
#include "SSL_Context.inl"
#endif /* __ACE_INLINE__ */
#include /**/ "ace/post.h"
#endif /* ACE_SSL_CONTEXT_H */

View File

@@ -0,0 +1,113 @@
// -*- C++ -*-
//
// $Id: SSL_Context.inl 80826 2008-03-04 14:51:23Z wotte $
ACE_BEGIN_VERSIONED_NAMESPACE_DECL
ACE_INLINE
ACE_SSL_Data_File::ACE_SSL_Data_File (void)
: type_ (-1)
{
}
ACE_INLINE
ACE_SSL_Data_File::ACE_SSL_Data_File (const char *file_name,
int type)
: file_name_ (file_name),
type_ (type)
{
}
ACE_INLINE const char *
ACE_SSL_Data_File::file_name (void) const
{
return this->file_name_.c_str ();
}
ACE_INLINE int
ACE_SSL_Data_File::type (void) const
{
return this->type_;
}
// ****************************************************************
ACE_INLINE void
ACE_SSL_Context::check_context (void)
{
if (this->context_ == 0)
{
this->set_mode ();
}
::SSL_CTX_set_verify (this->context_, this->default_verify_mode (), 0);
}
ACE_INLINE SSL_CTX *
ACE_SSL_Context::context (void)
{
this->check_context ();
return this->context_;
}
ACE_INLINE int
ACE_SSL_Context::private_key_type (void) const
{
return this->private_key_.type ();
}
ACE_INLINE const char*
ACE_SSL_Context::private_key_file_name (void) const
{
return this->private_key_.file_name ();
}
ACE_INLINE int
ACE_SSL_Context::certificate_type (void) const
{
return this->certificate_.type ();
}
ACE_INLINE const char*
ACE_SSL_Context::certificate_file_name (void) const
{
return this->certificate_.file_name ();
}
ACE_INLINE int
ACE_SSL_Context::dh_params_file_type (void) const
{
return this->dh_params_.type ();
}
ACE_INLINE const char*
ACE_SSL_Context::dh_params_file_name (void) const
{
return this->dh_params_.file_name ();
}
ACE_INLINE void
ACE_SSL_Context::default_verify_mode (int mode)
{
this->default_verify_mode_ = mode;
}
ACE_INLINE int
ACE_SSL_Context::default_verify_mode (void) const
{
return this->default_verify_mode_;
}
ACE_INLINE int
ACE_SSL_Context::get_mode (void) const
{
return this->mode_;
}
ACE_INLINE int
ACE_SSL_Context::have_trusted_ca (void) const
{
return this->have_ca_;
}
ACE_END_VERSIONED_NAMESPACE_DECL

View File

@@ -0,0 +1,45 @@
// -*- C++ -*-
// $Id: SSL_Export.h 80826 2008-03-04 14:51:23Z wotte $
// Definition for Win32 Export directives.
// This file is generated automatically by
// generate_export_file.pl
// ------------------------------
#if !defined (ACE_SSL_EXPORT_H)
#define ACE_SSL_EXPORT_H
#define ACE_SSL_BUILD_DLL
#include /**/ "ace/config-all.h"
#if defined (ACE_AS_STATIC_LIBS) && !defined (ACE_SSL_HAS_DLL)
# define ACE_SSL_HAS_DLL 0
#endif /* ACE_AS_STATIC_LIBS && ACE_SSL_HAS_DLL */
#if !defined (ACE_SSL_HAS_DLL)
#define ACE_SSL_HAS_DLL 1
#endif /* ! ACE_SSL_HAS_DLL */
#if defined (ACE_SSL_HAS_DLL)
# if (ACE_SSL_HAS_DLL == 1)
# if defined (ACE_SSL_BUILD_DLL)
# define ACE_SSL_Export ACE_Proper_Export_Flag
# define ACE_SSL_SINGLETON_DECLARATION(T) ACE_EXPORT_SINGLETON_DECLARATION (T)
# define ACE_SSL_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) ACE_EXPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK)
# else
# define ACE_SSL_Export ACE_Proper_Import_Flag
# define ACE_SSL_SINGLETON_DECLARATION(T) ACE_IMPORT_SINGLETON_DECLARATION (T)
# define ACE_SSL_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) ACE_IMPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK)
# endif /* ACE_SSL_BUILD_DLL */
# else
# define ACE_SSL_Export
# define ACE_SSL_SINGLETON_DECLARATION(T)
# define ACE_SSL_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK)
# endif /* ! ACE_SSL_HAS_DLL == 1 */
#else
# define ACE_SSL_Export
# define ACE_SSL_SINGLETON_DECLARATION(T)
# define ACE_SSL_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK)
#endif /* ACE_SSL_HAS_DLL */
#endif /* ACE_SSL_EXPORT_H */
// End of auto generated file.

View File

@@ -0,0 +1,72 @@
// $Id: SSL_SOCK.cpp 80826 2008-03-04 14:51:23Z wotte $
#include "SSL_SOCK.h"
#if !defined (__ACE_INLINE__)
#include "SSL_SOCK.inl"
#endif /* __ACE_INLINE__ */
#include "ace/OS_NS_errno.h"
#include "ace/os_include/os_signal.h"
ACE_RCSID (ACE_SSL,
SSL_SOCK,
"$Id: SSL_SOCK.cpp 80826 2008-03-04 14:51:23Z wotte $")
ACE_BEGIN_VERSIONED_NAMESPACE_DECL
ACE_SSL_SOCK::ACE_SSL_SOCK (void)
{
ACE_TRACE ("ACE_SSL_SOCK::ACE_SSL_SOCK");
}
ACE_SSL_SOCK::~ACE_SSL_SOCK (void)
{
ACE_TRACE ("ACE_SSL_SOCK::~ACE_SSL_SOCK");
}
int
ACE_SSL_SOCK::enable (int value) const
{
ACE_TRACE ("ACE_SSL_SOCK::enable");
switch (value)
{
#ifdef SIGURG
case SIGURG:
case ACE_SIGURG:
#endif /* SIGURG */
case SIGIO:
case ACE_SIGIO:
case ACE_CLOEXEC:
ACE_NOTSUP_RETURN (-1);
case ACE_NONBLOCK:
return ACE_IPC_SAP::enable (value);
default:
return -1;
}
}
int
ACE_SSL_SOCK::disable (int value) const
{
ACE_TRACE("ACE_SSL_SOCK::disable");
switch (value)
{
#ifdef SIGURG
case SIGURG:
case ACE_SIGURG:
#endif /* SIGURG */
case SIGIO:
case ACE_SIGIO:
case ACE_CLOEXEC:
ACE_NOTSUP_RETURN (-1);
case ACE_NONBLOCK:
return ACE_IPC_SAP::disable (value);
default:
return -1;
}
}
ACE_END_VERSIONED_NAMESPACE_DECL

View File

@@ -0,0 +1,103 @@
// -*- C++ -*-
//=============================================================================
/**
* @file SSL_SOCK.h
*
* $Id: SSL_SOCK.h 80826 2008-03-04 14:51:23Z wotte $
*
* @author Ossama Othman <ossama@ece.uci.edu>
*/
//=============================================================================
#ifndef ACE_SSL_SOCK_H
#define ACE_SSL_SOCK_H
#include /**/ "ace/pre.h"
#include "SSL_Export.h"
#if !defined (ACE_LACKS_PRAGMA_ONCE)
# pragma once
#endif /* ACE_LACKS_PRAGMA_ONCE */
#include "ace/SOCK.h"
#if defined (ACE_HAS_TEMPLATE_TYPEDEFS)
# define ACE_SSL_SOCK_ACCEPTOR ACE_SSL_SOCK_Acceptor
# define ACE_SSL_SOCK_CONNECTOR ACE_SSL_SOCK_Connector
# define ACE_SSL_SOCK_STREAM ACE_SSL_SOCK_Stream
#else
# define ACE_SSL_SOCK_ACCEPTOR ACE_SSL_SOCK_Acceptor, ACE_INET_Addr
# define ACE_SSL_SOCK_CONNECTOR ACE_SSL_SOCK_Connector, ACE_INET_Addr
# define ACE_SSL_SOCK_STREAM ACE_SSL_SOCK_Stream, ACE_INET_Addr
#endif /* ACE_HAS_TEMPLATE_TYPEDEFS */
ACE_BEGIN_VERSIONED_NAMESPACE_DECL
/**
* @class ACE_SSL_SOCK
*
* @brief An abstract class that forms the basis for more specific
* classes, such as "ACE_SSL_SOCK_Acceptor" and
* "ACE_SSL_SOCK_Stream". Do not instantiate this class.
*
* This class provides functions that are common to all of the
* ACE_SSL_SOCK_* classes. ACE_SSL_SOCK provides the ability
* to get and set socket options, get the local and remote
* addresses, and close the socket.
*/
class ACE_SSL_Export ACE_SSL_SOCK : public ACE_SOCK
{
public:
/**
* Override ACE_SOCK base class implementations with these SSL
* specific ones.
*/
//@{
int set_option (int level,
int option,
void *optval,
int optlen) const;
int get_option (int level,
int option,
void *optval,
int *optlen) const;
int enable (int value) const;
int disable (int value) const;
void set_handle (ACE_HANDLE);
ACE_HANDLE get_handle (void) const;
int control (int cmd, void *arg) const;
//@}
protected:
/// Default constructor is private to prevent instances of this class
/// from being defined.
ACE_SSL_SOCK (void);
/// Destructor
/**
* Not a virtual destructor. Protected destructor to prevent
* operator delete() from being called through a base class
* ACE_SSL_SOCK pointer/reference.
*/
~ACE_SSL_SOCK (void);
};
ACE_END_VERSIONED_NAMESPACE_DECL
#if defined (__ACE_INLINE__)
#include "SSL_SOCK.inl"
#endif /* __ACE_INLINE__ */
#include /**/ "ace/post.h"
#endif /* ACE_SSL_SOCK_H */

View File

@@ -0,0 +1,71 @@
// -*- C++ -*-
//
// $Id: SSL_SOCK.inl 80826 2008-03-04 14:51:23Z wotte $
#include "ace/OS_NS_sys_socket.h"
ACE_BEGIN_VERSIONED_NAMESPACE_DECL
ACE_INLINE void
ACE_SSL_SOCK::set_handle (ACE_HANDLE fd)
{
this->ACE_SOCK::set_handle (fd);
}
ACE_INLINE ACE_HANDLE
ACE_SSL_SOCK::get_handle (void) const
{
// return this->ssl_ ? (ACE_HANDLE) ::SSL_get_fd (this->ssl_) : ACE_INVALID_HANDLE;
return this->ACE_SOCK::get_handle ();
}
ACE_INLINE int
ACE_SSL_SOCK::control (int cmd, void *arg) const
{
return ACE_OS::ioctl (this->get_handle (), cmd, arg);
}
ACE_INLINE int
ACE_SSL_SOCK::set_option (int level,
int option,
void *optval,
int optlen) const
{
// switch (option)
// {
// case SO_SNDBUF:
// return ::BIO_set_write_buffer_size (this->io_bio_, *((int *) optval));
// case SO_RCVCBUF:
// return ::BIO_set_read_buffer_size (this->io_bio_, *((int *) optval));
// default:
return ACE_OS::setsockopt (this->get_handle (),
level,
option, (char *) optval,
optlen);
// }
}
// Provides access to the ACE_OS::getsockopt system call.
ACE_INLINE int
ACE_SSL_SOCK::get_option (int level,
int option,
void *optval,
int *optlen) const
{
// switch (option)
// {
// case SO_SNDBUF:
// return ::BIO_get_write_buffer_size (this->io_bio_, *((int *) optval));
// case SO_RCVCBUF:
// return ::BIO_get_read_buffer_size (this->io_bio_, *((int *) optval));
// default:
return ACE_OS::getsockopt (this->get_handle (),
level,
option, (char *) optval,
optlen);
// }
}
ACE_END_VERSIONED_NAMESPACE_DECL

View File

@@ -0,0 +1,250 @@
// -*- C++ -*-
//
// $Id: SSL_SOCK_Acceptor.cpp 82577 2008-08-09 17:43:11Z mitza $
#include "SSL_SOCK_Acceptor.h"
#include "ace/Handle_Set.h"
#include "ace/OS_Errno.h"
#include "ace/OS_NS_errno.h"
#include "ace/Log_Msg.h"
#include "ace/Time_Value.h"
#include "ace/Countdown_Time.h"
#include "ace/Truncate.h"
#if !defined (__ACE_INLINE__)
#include "SSL_SOCK_Acceptor.inl"
#endif /* __ACE_INLINE__ */
ACE_RCSID (ACE_SSL,
SSL_SOCK_Acceptor,
"$Id: SSL_SOCK_Acceptor.cpp 82577 2008-08-09 17:43:11Z mitza $")
ACE_BEGIN_VERSIONED_NAMESPACE_DECL
ACE_ALLOC_HOOK_DEFINE(ACE_SSL_SOCK_Acceptor)
ACE_SSL_SOCK_Acceptor::~ACE_SSL_SOCK_Acceptor (void)
{
ACE_TRACE ("ACE_SSL_SOCK_Acceptor::~ACE_SSL_SOCK_Acceptor");
}
int
ACE_SSL_SOCK_Acceptor::ssl_accept (ACE_SSL_SOCK_Stream &new_stream,
ACE_Time_Value *timeout) const
{
SSL *ssl = new_stream.ssl ();
if (SSL_is_init_finished (ssl))
return 0;
if (!SSL_in_accept_init (ssl))
::SSL_set_accept_state (ssl);
ACE_HANDLE handle = new_stream.get_handle ();
// We're going to call SSL_accept, optionally doing ACE::select and
// retrying the SSL_accept, until the SSL handshake is done or
// it fails.
// To get the timeout affect, set the socket to nonblocking mode
// before beginning if there is a timeout specified. If the timeout
// is 0 (wait as long as it takes) then don't worry about the blocking
// status; we'll block in SSL_accept if the socket is blocking, and
// block in ACE::select if not.
int reset_blocking_mode = 0;
if (timeout != 0)
{
reset_blocking_mode = ACE_BIT_DISABLED (ACE::get_flags (handle),
ACE_NONBLOCK);
// Set the handle into non-blocking mode if it's not already
// in it.
if (reset_blocking_mode
&& ACE::set_flags (handle,
ACE_NONBLOCK) == -1)
return -1;
}
// Take into account the time between each select() call below.
ACE_Countdown_Time countdown (timeout);
int status;
do
{
// These handle sets are used to set up for whatever SSL_accept
// says it wants next. They're reset on each pass around the loop.
ACE_Handle_Set rd_handle;
ACE_Handle_Set wr_handle;
status = ::SSL_accept (ssl);
switch (::SSL_get_error (ssl, status))
{
case SSL_ERROR_NONE:
status = 0; // To tell caller about success
break; // Done
case SSL_ERROR_WANT_WRITE:
wr_handle.set_bit (handle);
status = 1; // Wait for more activity
break;
case SSL_ERROR_WANT_READ:
rd_handle.set_bit (handle);
status = 1; // Wait for more activity
break;
case SSL_ERROR_ZERO_RETURN:
// The peer has notified us that it is shutting down via
// the SSL "close_notify" message so we need to
// shutdown, too.
status = -1;
break;
case SSL_ERROR_SYSCALL:
// On some platforms (e.g. MS Windows) OpenSSL does not
// store the last error in errno so explicitly do so.
//
// Explicitly check for EWOULDBLOCK since it doesn't get
// converted to an SSL_ERROR_WANT_{READ,WRITE} on some
// platforms. If SSL_accept failed outright, though, don't
// bother checking more. This can happen if the socket gets
// closed during the handshake.
if (ACE_OS::set_errno_to_last_error () == EWOULDBLOCK &&
status == -1)
{
// Although the SSL_ERROR_WANT_READ/WRITE isn't getting
// set correctly, the read/write state should be valid.
// Use that to decide what to do.
status = 1; // Wait for more activity
if (SSL_want_write (ssl))
wr_handle.set_bit (handle);
else if (SSL_want_read (ssl))
rd_handle.set_bit (handle);
else
status = -1; // Doesn't want anything - bail out
}
else
status = -1;
break;
default:
ACE_SSL_Context::report_error ();
status = -1;
break;
}
if (status == 1)
{
// Must have at least one handle to wait for at this point.
ACE_ASSERT (rd_handle.num_set() == 1 || wr_handle.num_set () == 1);
status = ACE::select (int (handle) + 1,
&rd_handle,
&wr_handle,
0,
timeout);
(void) countdown.update ();
// 0 is timeout, so we're done.
// -1 is error, so we're done.
// Could be both handles set (same handle in both masks) so
// set to 1.
if (status >= 1)
status = 1;
else // Timeout or failure
status = -1;
}
} while (status == 1 && !SSL_is_init_finished (ssl));
if (reset_blocking_mode)
{
ACE_Errno_Guard eguard (errno);
ACE::clr_flags (handle, ACE_NONBLOCK);
}
return (status == -1 ? -1 : 0);
}
// General purpose routine for accepting new connections.
// Since our underlying acceptor is of the plain old ACE_SOCK_Acceptor
// variety, get the basic socket setup done with it, then take care of
// the SSL handshake if the socket is accepted.
int
ACE_SSL_SOCK_Acceptor::accept (ACE_SSL_SOCK_Stream &new_stream,
ACE_Addr *remote_addr,
ACE_Time_Value *timeout,
int restart,
int reset_new_handle) const
{
ACE_TRACE ("ACE_SSL_SOCK_Acceptor::accept");
// Take into account the time to complete the basic TCP handshake
// and the SSL handshake.
ACE_Countdown_Time countdown (timeout);
ACE_SOCK_Stream temp_stream;
if (-1 == this->acceptor_.accept (temp_stream,
remote_addr,
timeout,
restart,
reset_new_handle))
return -1;
(void) countdown.update ();
new_stream.set_handle (temp_stream.get_handle ());
temp_stream.set_handle (ACE_INVALID_HANDLE);
if (this->ssl_accept (new_stream, timeout) == -1)
{
new_stream.close ();
new_stream.set_handle (ACE_INVALID_HANDLE);
return -1;
}
return 0;
}
int
ACE_SSL_SOCK_Acceptor::accept (ACE_SSL_SOCK_Stream &new_stream,
ACE_Accept_QoS_Params qos_params,
ACE_Addr *remote_addr,
ACE_Time_Value *timeout,
int restart,
int reset_new_handle) const
{
ACE_TRACE ("ACE_SSL_SOCK_Acceptor::accept");
// Take into account the time to complete the basic TCP handshake
// and the SSL handshake.
ACE_Countdown_Time countdown (timeout);
ACE_SOCK_Stream temp_stream;
if (-1 == this->acceptor_.accept (temp_stream,
qos_params,
remote_addr,
timeout,
restart,
reset_new_handle))
return -1;
(void) countdown.update ();
new_stream.set_handle (temp_stream.get_handle ());
temp_stream.set_handle (ACE_INVALID_HANDLE);
if (this->ssl_accept (new_stream, timeout) == -1)
{
new_stream.close ();
new_stream.set_handle (ACE_INVALID_HANDLE);
return -1;
}
return 0;
}
ACE_END_VERSIONED_NAMESPACE_DECL

View File

@@ -0,0 +1,197 @@
// -*- C++ -*-
//=============================================================================
/**
* @file SSL_SOCK_Acceptor.h
*
* $Id: SSL_SOCK_Acceptor.h 81826 2008-06-02 15:29:53Z schmidt $
*
* @author John Heitmann
* @author Chris Zimman
* @author Ossama Othman <ossama@uci.edu>
*/
//=============================================================================
#ifndef ACE_SSL_SOCK_ACCEPTOR_H
#define ACE_SSL_SOCK_ACCEPTOR_H
#include /**/ "ace/pre.h"
#include "SSL_Export.h"
#if !defined (ACE_LACKS_PRAGMA_ONCE)
# pragma once
#endif /* ACE_LACKS_PRAGMA_ONCE */
#include "SSL_SOCK_Stream.h"
#include "ace/SOCK_Acceptor.h"
#include "ace/OS_QoS.h"
ACE_BEGIN_VERSIONED_NAMESPACE_DECL
/**
* @class ACE_SSL_SOCK_Acceptor
*
* @brief Defines a factory that creates new @c ACE_SSL_SOCK_Stream
* objects passively.
*
* The ACE_SSL_SOCK_Acceptor has its own @c ACE_SOCK_Acceptor
* which handles the basic socket acceptance. This class is a
* wrapper which adds the SSL acceptance handshake handling.
* Since SSL is record oriented, some additional steps must be taken
* after the basic socket acceptance to complete the SSL handshake that
* takes place at session establishment.
*
* @note The user must currently ensure that only one thread services
* a given SSL session at any given time since some underlying
* SSL implementations, such as OpenSSL, are not entirely
* thread-safe or reentrant.
*/
class ACE_SSL_Export ACE_SSL_SOCK_Acceptor : public ACE_SSL_SOCK
{
public:
/// Default constructor.
ACE_SSL_SOCK_Acceptor (void);
/// Default destructor.
~ACE_SSL_SOCK_Acceptor (void);
/**
* Initiate a passive mode SSL/BSD-style acceptor socket.
* @param local_sap The address that we're going to listen for
* connections on. If this is @c ACE_Addr::sap_any,
* this socket listens on an the "any" IP address
* and selects an unused port. To find out what port
* was selected, call this object's
* @c ACE_SOCK::get_local_addr(ACE_Addr&) method
* upon return.
*/
ACE_SSL_SOCK_Acceptor (const ACE_Addr &local_sap,
int reuse_addr = 0,
int protocol_family = PF_UNSPEC,
int backlog = ACE_DEFAULT_BACKLOG,
int protocol = 0);
/**
* Initiate a passive-mode QoS-enabled acceptor socket.
* @param local_sap The address that we're going to listen for
* connections on. If this is @c ACE_Addr::sap_any,
* this socket listens on an the "any" IP address
* and selects an unused port. To find out what port
* was selected, call this object's
* @c ACE_SOCK::get_local_addr(ACE_Addr&) method
* upon return.
*/
ACE_SSL_SOCK_Acceptor (const ACE_Addr &local_sap,
ACE_Protocol_Info *protocolinfo,
ACE_SOCK_GROUP g,
u_long flags,
int reuse_addr,
int protocol_family = PF_UNSPEC,
int backlog = ACE_DEFAULT_BACKLOG,
int protocol = 0);
/**
* Initiate a passive mode SSL/BSD-style acceptor socket.
* @param local_sap The address that we're going to listen for
* connections on. If this is @c ACE_Addr::sap_any,
* this socket listens on an the "any" IP address
* and selects an unused port. To find out what port
* was selected, call this object's
* @c ACE_SOCK::get_local_addr(ACE_Addr&) method
* upon return.
*
* @return 0 if success; -1 for failure (errno contains error code).
*/
int open (const ACE_Addr &local_sap,
int reuse_addr = 0,
int protocol_family = PF_UNSPEC,
int backlog = ACE_DEFAULT_BACKLOG,
int protocol = 0);
/// Close the listening socket.
int close (void);
/**
* @name Passive Connection "accept" Methods
*
* These are the canonical methods exposed by the Acceptor pattern.
*/
//@{
/**
* Accept a new ACE_SSL_SOCK_Stream connection. On successful return,
* the socket has been accepted and the SSL handshake has been completed.
* @param new_stream The @c ACE_SSL_SOCK_Stream object that will receive
* the new SSL socket.
* @param remote_addr Pointer to an @c ACE_INET_Addr object that will
* receive the address of the peer that connected.
* @param timeout The maximum time to wait for the combined socket
* acceptance and handshake completion. 0 means
* block forever, a timeout of {0, 0} means poll.
* @param restart 1 means "restart if interrupted," that is,
* if errno == EINTR.
*
* @return 0 if success; -1 for failure (errno contains error code).
*/
int accept (ACE_SSL_SOCK_Stream &new_stream,
ACE_Addr *remote_addr = 0,
ACE_Time_Value *timeout = 0,
int restart = 1,
int reset_new_handle = 0) const;
/**
* Accept a new ACE_SSL_SOCK_Stream connection using the RVSP QoS
* information in qos_params.
* @param new_stream The @c ACE_SSL_SOCK_Stream object that will receive
* the new SSL socket.
* @param remote_addr Pointer to an @c ACE_INET_Addr object that will
* receive the address of the peer that connected.
* @param timeout The maximum time to wait for the combined socket
* acceptance and handshake completion. 0 means
* block forever, a timeout of {0, 0} means poll.
* @param restart 1 means "restart if interrupted," that is,
* if errno == EINTR.
*
* @return 0 if success; -1 for failure (errno contains error code).
*/
int accept (ACE_SSL_SOCK_Stream &new_stream,
ACE_Accept_QoS_Params qos_params,
ACE_Addr *remote_addr = 0,
ACE_Time_Value *timeout = 0,
int restart = 1,
int reset_new_handle = 0) const;
//@}
/// Meta-type info
//@{
typedef ACE_INET_Addr PEER_ADDR;
typedef ACE_SSL_SOCK_Stream PEER_STREAM;
//@}
/// Declare the dynamic allocation hooks.
ACE_ALLOC_HOOK_DECLARE;
protected:
/// Complete SSL passive connection establishment.
int ssl_accept (ACE_SSL_SOCK_Stream &new_stream,
ACE_Time_Value *timeout) const;
private:
/// The BSD-socket workhorse
ACE_SOCK_Acceptor acceptor_;
};
ACE_END_VERSIONED_NAMESPACE_DECL
#if defined (__ACE_INLINE__)
#include "SSL_SOCK_Acceptor.inl"
#endif /* __ACE_INLINE__ */
#include /**/ "ace/post.h"
#endif /* ACE_SSL_SOCK_ACCEPTOR_H */

View File

@@ -0,0 +1,85 @@
// -*- C++ -*-
//
// $Id: SSL_SOCK_Acceptor.inl 80826 2008-03-04 14:51:23Z wotte $
ACE_BEGIN_VERSIONED_NAMESPACE_DECL
ACE_INLINE
ACE_SSL_SOCK_Acceptor::ACE_SSL_SOCK_Acceptor (void)
: acceptor_ ()
{
ACE_TRACE ("ACE_SSL_SOCK_Acceptor::ACE_SSL_SOCK_Acceptor");
}
ACE_INLINE
ACE_SSL_SOCK_Acceptor::ACE_SSL_SOCK_Acceptor (const ACE_Addr &local_sap,
int reuse_addr,
int protocol_family,
int backlog,
int protocol)
: acceptor_ (local_sap,
reuse_addr,
protocol_family,
backlog,
protocol)
{
ACE_TRACE ("ACE_SSL_SOCK_Acceptor::ACE_SSL_SOCK_Acceptor");
this->set_handle (this->acceptor_.get_handle ());
}
ACE_INLINE
ACE_SSL_SOCK_Acceptor::ACE_SSL_SOCK_Acceptor (const ACE_Addr &local_sap,
ACE_Protocol_Info *protocolinfo,
ACE_SOCK_GROUP g,
u_long flags,
int reuse_addr,
int protocol_family,
int backlog,
int protocol)
: acceptor_ (local_sap,
protocolinfo,
g,
flags,
reuse_addr,
protocol_family,
backlog,
protocol)
{
ACE_TRACE ("ACE_SSL_SOCK_Acceptor::ACE_SSL_SOCK_Acceptor");
this->set_handle (this->acceptor_.get_handle ());
}
ACE_INLINE int
ACE_SSL_SOCK_Acceptor::open (const ACE_Addr &local_sap,
int reuse_addr,
int protocol_family,
int backlog,
int protocol)
{
ACE_TRACE ("ACE_SSL_SOCK_Acceptor::open");
if (this->acceptor_.open (local_sap,
reuse_addr,
protocol_family,
backlog,
protocol) != 0)
return -1;
else
this->set_handle (this->acceptor_.get_handle ());
return 0;
}
ACE_INLINE int
ACE_SSL_SOCK_Acceptor::close (void)
{
ACE_TRACE ("ACE_SSL_SOCK_Acceptor::close ()");
int result = this->acceptor_.close ();
this->set_handle (ACE_INVALID_HANDLE);
return result;
}
ACE_END_VERSIONED_NAMESPACE_DECL

View File

@@ -0,0 +1,425 @@
// -*- C++ -*-
//
// $Id: SSL_SOCK_Connector.cpp 82577 2008-08-09 17:43:11Z mitza $
#include "SSL_SOCK_Connector.h"
#include "ace/OS_NS_errno.h"
#include "ace/Handle_Set.h"
#include "ace/INET_Addr.h"
#include "ace/Log_Msg.h"
#include "ace/Countdown_Time.h"
#include "ace/Truncate.h"
#include <openssl/err.h>
#if !defined (__ACE_INLINE__)
#include "SSL_SOCK_Connector.inl"
#endif /* __ACE_INLINE__ */
ACE_RCSID (ACE_SSL,
SSL_SOCK_Connector,
"$Id: SSL_SOCK_Connector.cpp 82577 2008-08-09 17:43:11Z mitza $")
ACE_BEGIN_VERSIONED_NAMESPACE_DECL
ACE_ALLOC_HOOK_DEFINE(ACE_SSL_SOCK_Connector)
ACE_SSL_SOCK_Connector::~ACE_SSL_SOCK_Connector (void)
{
ACE_TRACE ("ACE_SSL_SOCK_Connector::~ACE_SSL_SOCK_Connector");
}
int
ACE_SSL_SOCK_Connector::ssl_connect (ACE_SSL_SOCK_Stream &new_stream,
const ACE_Time_Value *timeout)
{
SSL *ssl = new_stream.ssl ();
if (SSL_is_init_finished (ssl))
return 0;
// Check if a connection is already pending for the given SSL
// structure.
if (!SSL_in_connect_init (ssl))
::SSL_set_connect_state (ssl);
ACE_HANDLE handle = new_stream.get_handle ();
// We're going to call SSL_connect, optionally doing ACE::select and
// retrying the SSL_connect, until the SSL handshake is done or
// it fails.
// To get the timeout affect, set the socket to nonblocking mode
// before beginning if there is a timeout specified. If the timeout
// is 0 (wait as long as it takes) then don't worry about the blocking
// status; we'll block in SSL_connect if the socket is blocking, and
// block in ACE::select if not.
int reset_blocking_mode = 0;
if (timeout != 0)
{
reset_blocking_mode = ACE_BIT_DISABLED (ACE::get_flags (handle),
ACE_NONBLOCK);
// Set the handle into non-blocking mode if it's not already
// in it.
if (reset_blocking_mode
&& ACE::set_flags (handle,
ACE_NONBLOCK) == -1)
return -1;
}
ACE_Time_Value t;
if (timeout != 0)
t = *timeout; // Need a non-const copy.
// Take into account the time between each select() call below.
ACE_Countdown_Time countdown ((timeout == 0 ? 0 : &t));
int status;
do
{
// These handle sets are used to set up for whatever SSL_connect
// says it wants next. They're reset on each pass around the loop.
ACE_Handle_Set rd_handle;
ACE_Handle_Set wr_handle;
status = ::SSL_connect (ssl);
switch (::SSL_get_error (ssl, status))
{
case SSL_ERROR_NONE:
// Start out with non-blocking disabled on the SSL stream.
new_stream.disable (ACE_NONBLOCK);
status = 0; // To tell caller about success
break; // Done
case SSL_ERROR_WANT_WRITE:
wr_handle.set_bit (handle);
status = 1; // Wait for more activity
break;
case SSL_ERROR_WANT_READ:
rd_handle.set_bit (handle);
status = 1; // Wait for more activity
break;
case SSL_ERROR_ZERO_RETURN:
// The peer has notified us that it is shutting down via
// the SSL "close_notify" message so we need to
// shutdown, too.
status = -1;
break;
case SSL_ERROR_SYSCALL:
// On some platforms (e.g. MS Windows) OpenSSL does not
// store the last error in errno so explicitly do so.
//
// Explicitly check for EWOULDBLOCK since it doesn't get
// converted to an SSL_ERROR_WANT_{READ,WRITE} on some
// platforms. If SSL_connect failed outright, though, don't
// bother checking more. This can happen if the socket gets
// closed during the handshake.
if (ACE_OS::set_errno_to_last_error () == EWOULDBLOCK &&
status == -1)
{
// Although the SSL_ERROR_WANT_READ/WRITE isn't getting
// set correctly, the read/write state should be valid.
// Use that to decide what to do.
status = 1; // Wait for more activity
if (SSL_want_write (ssl))
{
wr_handle.set_bit (handle);
}
else if (SSL_want_read (ssl))
{
rd_handle.set_bit (handle);
}
else
{
status = -1; // Doesn't want anything - bail out
}
}
else
{
status = -1;
}
break;
default:
ACE_SSL_Context::report_error ();
status = -1;
break;
}
if (status == 1)
{
// Must have at least one handle to wait for at this point.
ACE_ASSERT (rd_handle.num_set () == 1 || wr_handle.num_set () == 1);
// Block indefinitely if timeout pointer is zero.
status = ACE::select (int (handle) + 1,
&rd_handle,
&wr_handle,
0,
(timeout == 0 ? 0 : &t));
(void) countdown.update ();
// 0 is timeout, so we're done.
// -1 is error, so we're done.
// Could be both handles set (same handle in both masks) so set to 1.
if (status >= 1)
{
status = 1;
}
else // Timeout or socket failure
{
status = -1;
}
}
} while (status == 1 && !SSL_is_init_finished (ssl));
if (reset_blocking_mode)
{
ACE_Errno_Guard eguard (errno);
ACE::clr_flags (handle, ACE_NONBLOCK);
}
return (status == -1 ? -1 : 0);
}
int
ACE_SSL_SOCK_Connector::connect (ACE_SSL_SOCK_Stream &new_stream,
const ACE_Addr &remote_sap,
const ACE_Time_Value *timeout,
const ACE_Addr &local_sap,
int reuse_addr,
int flags,
int perms)
{
ACE_TRACE ("ACE_SSL_SOCK_Connector::connect");
// Take into account the time to complete the basic TCP handshake
// and the SSL handshake.
ACE_Time_Value time_copy;
ACE_Countdown_Time countdown (&time_copy);
if (timeout != 0)
{
time_copy += *timeout;
countdown.start ();
}
int result =
this->connector_.connect (new_stream.peer (),
remote_sap,
timeout,
local_sap,
reuse_addr,
flags,
perms);
int error = 0;
if (result == -1)
error = errno; // Save us some TSS accesses.
// Obtain the handle from the underlying SOCK_Stream and set it in
// the SSL_SOCK_Stream. Note that the case where a connection is in
// progress is also handled. In that case, the handle must also be
// set in the SSL_SOCK_Stream so that the correct handle is returned
// when performing non-blocking connect()s.
if (new_stream.get_handle () == ACE_INVALID_HANDLE
&& (result == 0
|| (result == -1 && (error == EWOULDBLOCK
|| error == EINPROGRESS))))
new_stream.set_handle (new_stream.peer ().get_handle ());
if (result == -1)
return result;
// If using a timeout, update the countdown timer to reflect the time
// spent on the connect itself, then pass the remaining time to
// ssl_connect to bound the time on the handshake.
if (timeout != 0)
{
countdown.update ();
timeout = &time_copy;
}
result = this->ssl_connect (new_stream, timeout);
if (result == -1)
new_stream.close ();
return result;
}
int
ACE_SSL_SOCK_Connector::connect (ACE_SSL_SOCK_Stream &new_stream,
const ACE_Addr &remote_sap,
ACE_QoS_Params qos_params,
const ACE_Time_Value *timeout,
const ACE_Addr &local_sap,
ACE_Protocol_Info *protocolinfo,
ACE_SOCK_GROUP g,
u_long flags,
int reuse_addr,
int perms)
{
ACE_TRACE ("ACE_SSL_SOCK_Connector::connect");
// Take into account the time to complete the basic TCP handshake
// and the SSL handshake.
ACE_Time_Value time_copy;
ACE_Countdown_Time countdown (&time_copy);
if (timeout != 0)
{
time_copy += *timeout;
countdown.start ();
}
int result = this->connector_.connect (new_stream.peer (),
remote_sap,
qos_params,
timeout,
local_sap,
protocolinfo,
g,
flags,
reuse_addr,
perms);
int error = 0;
if (result == -1)
error = errno; // Save us some TSS accesses.
// Obtain the handle from the underlying SOCK_Stream and set it in
// the SSL_SOCK_Stream. Note that the case where a connection is in
// progress is also handled. In that case, the handle must also be
// set in the SSL_SOCK_Stream so that the correct handle is returned
// when performing non-blocking connect()s.
if (new_stream.get_handle () == ACE_INVALID_HANDLE
&& (result == 0
|| (result == -1 && (error == EWOULDBLOCK
|| error == EINPROGRESS))))
new_stream.set_handle (new_stream.peer ().get_handle ());
if (result == -1)
return result;
// If using a timeout, update the countdown timer to reflect the time
// spent on the connect itself, then pass the remaining time to
// ssl_connect to bound the time on the handshake.
if (timeout != 0)
{
countdown.update ();
timeout = &time_copy;
}
result = this->ssl_connect (new_stream, timeout);
if (result == -1)
new_stream.close ();
return result;
}
// Try to complete a non-blocking connection.
int
ACE_SSL_SOCK_Connector::complete (ACE_SSL_SOCK_Stream &new_stream,
ACE_Addr *remote_sap,
const ACE_Time_Value *tv)
{
ACE_TRACE ("ACE_SSL_SOCK_Connector::complete");
// Take into account the time to complete the basic TCP handshake
// and the SSL handshake.
ACE_Time_Value time_copy;
ACE_Countdown_Time countdown (&time_copy);
if (tv != 0)
{
time_copy += *tv;
countdown.start ();
}
// Only attempt to complete the TCP connection if it that hasn't
// already been done.
ACE_INET_Addr raddr;
if (new_stream.peer ().get_remote_addr (raddr) != 0
&& this->connector_.complete (new_stream.peer (),
remote_sap,
tv) == -1)
return -1;
// The handle in the SSL_SOCK_Stream should have already been set in
// the connect() method.
// If using a timeout, update the countdown timer to reflect the time
// spent on the connect itself, then pass the remaining time to
// ssl_connect to bound the time on the handshake.
if (tv != 0)
{
countdown.update ();
tv = &time_copy;
}
if (this->ssl_connect (new_stream, tv) == -1)
{
new_stream.close ();
return -1;
}
return 0;
}
ACE_SSL_SOCK_Connector::ACE_SSL_SOCK_Connector (
ACE_SSL_SOCK_Stream &new_stream,
const ACE_Addr &remote_sap,
const ACE_Time_Value *timeout,
const ACE_Addr &local_sap,
int reuse_addr,
int flags,
int perms)
: connector_ ()
{
ACE_TRACE ("ACE_SSL_SOCK_Connector::ACE_SSL_SOCK_Connector");
this->connect (new_stream,
remote_sap,
timeout,
local_sap,
reuse_addr,
flags,
perms);
}
ACE_SSL_SOCK_Connector::ACE_SSL_SOCK_Connector (
ACE_SSL_SOCK_Stream &new_stream,
const ACE_Addr &remote_sap,
ACE_QoS_Params qos_params,
const ACE_Time_Value *timeout,
const ACE_Addr &local_sap,
ACE_Protocol_Info *protocolinfo,
ACE_SOCK_GROUP g,
u_long flags,
int reuse_addr,
int perms)
: connector_ ()
{
ACE_TRACE ("ACE_SSL_SOCK_Connector::ACE_SSL_SOCK_Connector");
this->connect (new_stream,
remote_sap,
qos_params,
timeout,
local_sap,
protocolinfo,
g,
flags,
reuse_addr,
perms);
}
ACE_END_VERSIONED_NAMESPACE_DECL

View File

@@ -0,0 +1,318 @@
// -*- C++ -*-
//=============================================================================
/**
* @file SSL_SOCK_Connector.h
*
* $Id: SSL_SOCK_Connector.h 80826 2008-03-04 14:51:23Z wotte $
*
* @author Ossama Othman <ossama@uci.edu>
* @author Carlos O'Ryan <coryan@uci.edu>
* @author John Heitmann
* @author Chris Zimman
*/
//=============================================================================
#ifndef ACE_SSL_SOCK_CONNECTOR_H
#define ACE_SSL_SOCK_CONNECTOR_H
#include /**/ "ace/pre.h"
#include "SSL_Export.h"
#if !defined (ACE_LACKS_PRAGMA_ONCE)
# pragma once
#endif /* ACE_LACKS_PRAGMA_ONCE */
#include "SSL_SOCK_Stream.h"
#include "ace/SOCK_Connector.h"
#include "ace/OS_QoS.h"
ACE_BEGIN_VERSIONED_NAMESPACE_DECL
/**
* @class ACE_SSL_SOCK_Connector
*
* @brief Defines a factory that creates new <ACE_SSL_SOCK_Stream>s
* actively.
*
* The ACE_SSL_SOCK_Connector doesn't have a socket of its own,
* i.e., it simply "borrows" the one from the ACE_SSL_SOCK_Stream
* that's being connected. The reason for this is that the
* underlying socket API doesn't use a "factory" socket to connect
* "data-mode" sockets. Therefore, there's no need to inherit
* ACE_SSL_SOCK_Connector from ACE_SSL_SOCK.
*
* Since SSL is record-oriented, some additional work is done after
* the plain socket is connected.
*
* @note The user must currently ensure that only one thread services
* a given SSL session at any given time since some underlying
* SSL implementations, such as OpenSSL, are not entirely
* thread-safe or reentrant.
*/
class ACE_SSL_Export ACE_SSL_SOCK_Connector
{
public:
/// Default constructor.
ACE_SSL_SOCK_Connector (void);
/**
* Actively connect to a peer, producing a connected @c ACE_SSL_SOCK_Stream
* object if the connection succeeds. This method performs both the
* initial socket connect and the SSL handshake.
*
* @param new_stream The @c ACE_SSL_SOCK_Stream object that will be
* connected to the peer.
* @param remote_sap The address that we are trying to connect to.
* The protocol family of @c remote_sap is used for
* the connected socket. That is, if @c remote_sap
* contains an IPv6 address, a socket with family
* PF_INET6 will be used, else it will be PF_INET.
* @param timeout Pointer to an @c ACE_Time_Value object with amount
* of time to wait to connect. If the pointer is 0
* then the call blocks until the connection attempt
* is complete, whether it succeeds or fails. If
* *timeout == {0, 0} then the connection is done
* using nonblocking mode. In this case, if the
* connection can't be made immediately, this method
* returns -1 and errno == EWOULDBLOCK.
* If *timeout > {0, 0} then this is the maximum amount
* of time to wait before timing out; if the specified
* amount of time passes before the connection is made,
* this method returns -1 and errno == ETIME. Note
* the difference between this case and when a blocking
* connect is attmpted that TCP times out - in the latter
* case, errno will be ETIMEDOUT.
* @param local_sap (optional) The local address to bind to. If it's
* the default value of @c ACE_Addr::sap_any then the
* OS will choose an unused port.
* @param reuse_addr (optional) If the value is 1, the local address
* (@c local_sap) is reused, even if it hasn't been
* cleaned up yet.
* @param flags Ignored.
* @param perms Ignored.
*
* @return Returns 0 if the connection succeeds. If it fails,
* -1 is returned and errno contains a specific error
* code.
*/
ACE_SSL_SOCK_Connector (ACE_SSL_SOCK_Stream &new_stream,
const ACE_Addr &remote_sap,
const ACE_Time_Value *timeout = 0,
const ACE_Addr &local_sap = ACE_Addr::sap_any,
int reuse_addr = 0,
int flags = 0,
int perms = 0);
/**
* Actively connect to a peer, producing a connected @c ACE_SSL_SOCK_Stream
* object if the connection succeeds. This method performs both the
* initial socket connect and the SSL handshake.
*
* @param new_stream The @c ACE_SSL_SOCK_Stream object that will be
* connected to the peer.
* @param remote_sap The address that we are trying to connect to.
* The protocol family of @c remote_sap is used for
* the connected socket. That is, if @c remote_sap
* contains an IPv6 address, a socket with family
* PF_INET6 will be used, else it will be PF_INET.
* @param qos_params Contains QoS parameters that are passed to the
* IntServ (RSVP) and DiffServ protocols.
* @see ACE_QoS_Params.
* @param timeout Pointer to an @c ACE_Time_Value object with amount
* of time to wait to connect. If the pointer is 0
* then the call blocks until the connection attempt
* is complete, whether it succeeds or fails. If
* *timeout == {0, 0} then the connection is done
* using nonblocking mode. In this case, if the
* connection can't be made immediately, this method
* returns -1 and errno == EWOULDBLOCK.
* If *timeout > {0, 0} then this is the maximum amount
* of time to wait before timing out; if the specified
* amount of time passes before the connection is made,
* this method returns -1 and errno == ETIME. Note
* the difference between this case and when a blocking
* connect is attmpted that TCP times out - in the latter
* case, errno will be ETIMEDOUT.
* @param local_sap (optional) The local address to bind to. If it's
* the default value of @c ACE_Addr::sap_any then the
* OS will choose an unused port.
* @param reuse_addr (optional) If the value is 1, the local address
* (@c local_sap) is reused, even if it hasn't been
* cleaned up yet.
* @param flags Ignored.
* @param perms Ignored.
*
* @return Returns 0 if the connection succeeds. If it fails,
* -1 is returned and errno contains a specific error
* code.
*/
ACE_SSL_SOCK_Connector (ACE_SSL_SOCK_Stream &new_stream,
const ACE_Addr &remote_sap,
ACE_QoS_Params qos_params,
const ACE_Time_Value *timeout = 0,
const ACE_Addr &local_sap = ACE_Addr::sap_any,
ACE_Protocol_Info *protocolinfo = 0,
ACE_SOCK_GROUP g = 0,
u_long flags = 0,
int reuse_addr = 0,
int perms = 0);
/// Default dtor.
~ACE_SSL_SOCK_Connector (void);
/**
* Actively connect to a peer, producing a connected @c ACE_SSL_SOCK_Stream
* object if the connection succeeds. This method performs both the
* initial socket connect and the SSL handshake.
*
* @param new_stream The @c ACE_SSL_SOCK_Stream object that will be
* connected to the peer.
* @param remote_sap The address that we are trying to connect to.
* The protocol family of @c remote_sap is used for
* the connected socket. That is, if @c remote_sap
* contains an IPv6 address, a socket with family
* PF_INET6 will be used, else it will be PF_INET.
* @param timeout Pointer to an @c ACE_Time_Value object with amount
* of time to wait to connect. If the pointer is 0
* then the call blocks until the connection attempt
* is complete, whether it succeeds or fails. If
* *timeout == {0, 0} then the connection is done
* using nonblocking mode. In this case, if the
* connection can't be made immediately, this method
* returns -1 and errno == EWOULDBLOCK.
* If *timeout > {0, 0} then this is the maximum amount
* of time to wait before timing out; if the specified
* amount of time passes before the connection is made,
* this method returns -1 and errno == ETIME. Note
* the difference between this case and when a blocking
* connect is attmpted that TCP times out - in the latter
* case, errno will be ETIMEDOUT.
* @param local_sap (optional) The local address to bind to. If it's
* the default value of @c ACE_Addr::sap_any then the
* OS will choose an unused port.
* @param reuse_addr (optional) If the value is 1, the local address
* (@c local_sap) is reused, even if it hasn't been
* cleaned up yet.
* @param flags Ignored.
* @param perms Ignored.
*
* @return Returns 0 if the connection succeeds. If it fails,
* -1 is returned and errno contains a specific error
* code.
*/
int connect (ACE_SSL_SOCK_Stream &new_stream,
const ACE_Addr &remote_sap,
const ACE_Time_Value *timeout = 0,
const ACE_Addr &local_sap = ACE_Addr::sap_any,
int reuse_addr = 0,
int flags = 0,
int perms = 0);
/**
* Actively connect to a peer, producing a connected @c ACE_SSL_SOCK_Stream
* object if the connection succeeds. This method performs both the
* initial socket connect and the SSL handshake.
*
* @param new_stream The @c ACE_SSL_SOCK_Stream object that will be
* connected to the peer.
* @param remote_sap The address that we are trying to connect to.
* The protocol family of @c remote_sap is used for
* the connected socket. That is, if @c remote_sap
* contains an IPv6 address, a socket with family
* PF_INET6 will be used, else it will be PF_INET.
* @param qos_params Contains QoS parameters that are passed to the
* IntServ (RSVP) and DiffServ protocols.
* @see ACE_QoS_Params.
* @param timeout Pointer to an @c ACE_Time_Value object with amount
* of time to wait to connect. If the pointer is 0
* then the call blocks until the connection attempt
* is complete, whether it succeeds or fails. If
* *timeout == {0, 0} then the connection is done
* using nonblocking mode. In this case, if the
* connection can't be made immediately, this method
* returns -1 and errno == EWOULDBLOCK.
* If *timeout > {0, 0} then this is the maximum amount
* of time to wait before timing out; if the specified
* amount of time passes before the connection is made,
* this method returns -1 and errno == ETIME. Note
* the difference between this case and when a blocking
* connect is attmpted that TCP times out - in the latter
* case, errno will be ETIMEDOUT.
* @param local_sap (optional) The local address to bind to. If it's
* the default value of @c ACE_Addr::sap_any then the
* OS will choose an unused port.
* @param reuse_addr (optional) If the value is 1, the local address
* (@c local_sap) is reused, even if it hasn't been
* cleaned up yet.
* @param flags Ignored.
* @param perms Ignored.
*
* @return Returns 0 if the connection succeeds. If it fails,
* -1 is returned and errno contains a specific error
* code.
*/
int connect (ACE_SSL_SOCK_Stream &new_stream,
const ACE_Addr &remote_sap,
ACE_QoS_Params qos_params,
const ACE_Time_Value *timeout = 0,
const ACE_Addr &local_sap = ACE_Addr::sap_any,
ACE_Protocol_Info *protocolinfo = 0,
ACE_SOCK_GROUP g = 0,
u_long flags = 0,
int reuse_addr = 0,
int perms = 0);
/**
* Try to complete a non-blocking connection.
* If connection completion is successful then <new_stream> contains
* the connected ACE_SSL_SOCK_Stream. If <remote_sap> is non-NULL
* then it will contain the address of the connected peer.
*/
int complete (ACE_SSL_SOCK_Stream &new_stream,
ACE_Addr *remote_sap = 0,
const ACE_Time_Value *timeout = 0);
/// Resets any event associations on this handle
int reset_new_handle (ACE_HANDLE handle);
/// Meta-type info
//@{
typedef ACE_INET_Addr PEER_ADDR;
typedef ACE_SSL_SOCK_Stream PEER_STREAM;
//@}
/// Dump the state of an object.
void dump (void) const;
/// Declare the dynamic allocation hooks.
ACE_ALLOC_HOOK_DECLARE;
protected:
/// Complete non-blocking SSL active connection.
int ssl_connect (ACE_SSL_SOCK_Stream &new_stream,
const ACE_Time_Value *timeout);
private:
/// The class that does all of the non-secure socket connection.
/// It is default contructed, and subsequently used by connect().
ACE_SOCK_Connector connector_;
};
ACE_END_VERSIONED_NAMESPACE_DECL
#if defined (__ACE_INLINE__)
#include "SSL_SOCK_Connector.inl"
#endif /* __ACE_INLINE__ */
#include /**/ "ace/post.h"
#endif /* ACE_SSL_SOCK_CONNECTOR_H */

View File

@@ -0,0 +1,28 @@
// -*- C++ -*-
//
// $Id: SSL_SOCK_Connector.inl 80826 2008-03-04 14:51:23Z wotte $
ACE_BEGIN_VERSIONED_NAMESPACE_DECL
ACE_INLINE
ACE_SSL_SOCK_Connector::ACE_SSL_SOCK_Connector (void)
: connector_ ()
{
ACE_TRACE ("ACE_SSL_SOCK_Connector::ACE_SSL_SOCK_Connector");
}
ACE_INLINE int
ACE_SSL_SOCK_Connector::reset_new_handle (ACE_HANDLE handle)
{
ACE_TRACE ("ACE_SSL_SOCK_Connector::reset_new_handle");
return this->connector_.reset_new_handle (handle);
}
ACE_INLINE void
ACE_SSL_SOCK_Connector::dump (void) const
{
ACE_TRACE ("ACE_SSL_SOCK_Connector::dump");
this->connector_.dump ();
}
ACE_END_VERSIONED_NAMESPACE_DECL

View File

@@ -0,0 +1,630 @@
// $Id: SSL_SOCK_Stream.cpp 82577 2008-08-09 17:43:11Z mitza $
#include "ace/Handle_Set.h"
#include "ace/Log_Msg.h"
#include "ace/Countdown_Time.h"
#include "ace/OS_NS_string.h"
#include "ace/OS_NS_sys_select.h"
#include "ace/OS_Memory.h"
#include <openssl/err.h>
#include "SSL_SOCK_Stream.h"
#if !defined (__ACE_INLINE__)
#include "SSL_SOCK_Stream.inl"
#endif /* __ACE_INLINE__ */
ACE_RCSID (ACE_SSL,
SSL_SOCK_Stream,
"$Id: SSL_SOCK_Stream.cpp 82577 2008-08-09 17:43:11Z mitza $")
ACE_BEGIN_VERSIONED_NAMESPACE_DECL
ACE_ALLOC_HOOK_DEFINE(ACE_SSL_SOCK_Stream)
ACE_SSL_SOCK_Stream::ACE_SSL_SOCK_Stream (ACE_SSL_Context *context)
: ssl_ (0),
stream_ ()
{
ACE_TRACE ("ACE_SSL_SOCK_Stream::ACE_SSL_SOCK_Stream");
ACE_SSL_Context * ctx =
(context == 0 ? ACE_SSL_Context::instance () : context);
this->ssl_ = ::SSL_new (ctx->context ());
if (this->ssl_ == 0)
{
ACE_ERROR ((LM_ERROR,
"(%P|%t) ACE_SSL_SOCK_Stream "
"- cannot allocate new SSL structure %p\n",
ACE_TEXT ("")));
}
}
ACE_SSL_SOCK_Stream::~ACE_SSL_SOCK_Stream (void)
{
ACE_TRACE ("ACE_SSL_SOCK_Stream::~ACE_SSL_SOCK_Stream");
::SSL_free (this->ssl_);
// @@ Question: should we reference count the Context object or
// leave that to the application developer? We do not reference
// count reactors (for example) and following some simple rules
// seems to work fine!
}
ssize_t
ACE_SSL_SOCK_Stream::sendv (const iovec iov[],
size_t n,
const ACE_Time_Value *max_wait_time) const
{
ACE_TRACE ("ACE_SSL_SOCK_Stream::sendv");
// There is subtle problem in this method that occurs when using
// non-blocking IO. The semantics of a non-blocking scatter write
// (sendv()) are not possible to retain with the emulation in this
// method.
ssize_t bytes_sent = 0;
ACE_Time_Value t;
ACE_Time_Value *timeout = const_cast<ACE_Time_Value *> (max_wait_time);
if (max_wait_time != 0)
{
// Make a copy since ACE_Countdown_Time modifies the
// ACE_Time_Value.
t = *max_wait_time;
timeout = &t;
}
// Take into account the time between each send.
ACE_Countdown_Time countdown (timeout);
for (size_t i = 0; i < n; ++i)
{
ssize_t const result = this->send (iov[i].iov_base,
iov[i].iov_len,
timeout);
if (result == -1)
{
// There is a subtle difference in behaviour depending on
// whether or not any data was sent. If no data was sent,
// then always return -1. Otherwise return bytes_sent.
// This gives the caller an opportunity to keep track of
if (bytes_sent > 0)
break;
else
return -1;
}
else
{
bytes_sent += result;
// Do not continue on to the next loop iteration if the
// amount of data sent was less than the amount data given.
// This avoids a subtle problem where "holes" in the data
// stream would occur if partial sends of a given buffer in
// the iovec array occured.
if (static_cast<size_t> (result) < static_cast<size_t> (iov[i].iov_len))
break;
}
(void) countdown.update ();
}
return bytes_sent;
}
ssize_t
ACE_SSL_SOCK_Stream::recvv (iovec *io_vec,
const ACE_Time_Value *timeout) const
{
ACE_TRACE ("ACE_SSL_SOCK_Stream::recvv");
// From ACE_SOCK_IO::recvv().
#if defined (FIONREAD)
ACE_Handle_Set handle_set;
handle_set.reset ();
handle_set.set_bit (this->get_handle ());
io_vec->iov_base = 0;
// Check the status of the current socket.
switch (
ACE_OS::select (int (this->get_handle ()) + 1,
handle_set,
0,
0,
timeout))
{
case -1:
return -1;
/* NOTREACHED */
case 0:
errno = ETIME;
return -1;
/* NOTREACHED */
default:
// Goes fine, fallthrough to get data
break;
}
int inlen;
if (ACE_OS::ioctl (this->get_handle (),
FIONREAD,
&inlen) == -1)
return -1;
else if (inlen > 0)
{
ACE_NEW_RETURN (io_vec->iov_base,
char[inlen],
-1);
io_vec->iov_len = this->recv (io_vec->iov_base,
inlen);
return io_vec->iov_len;
}
else
return 0;
#else
ACE_UNUSED_ARG (io_vec);
ACE_UNUSED_ARG (timeout);
ACE_NOTSUP_RETURN (-1);
#endif /* FIONREAD */
}
ssize_t
ACE_SSL_SOCK_Stream::send (const void *buf,
size_t len,
int flags,
const ACE_Time_Value *timeout) const
{
ACE_TRACE ("ACE_SSL_SOCK_Stream::send");
// If SSL has data in the buffer, i.e. SSL_pending() returns a
// non-zero value, then don't block on select().
if (timeout == 0 || ::SSL_pending (this->ssl_))
return this->send (buf, len, flags);
int val = 0;
if (ACE::enter_send_timedwait (this->get_handle (),
timeout,
val) == -1)
return -1;
ssize_t const bytes_transferred = this->send (buf, len, flags);
ACE::restore_non_blocking_mode (this->get_handle (), val);
return bytes_transferred;
}
ssize_t
ACE_SSL_SOCK_Stream::recv (void *buf,
size_t n,
int flags,
const ACE_Time_Value *timeout) const
{
ACE_TRACE ("ACE_SSL_SOCK_Stream::recv");
return this->recv_i (buf, n, flags, timeout);
}
ssize_t
ACE_SSL_SOCK_Stream::send (size_t n, ...) const
{
ACE_TRACE ("ACE_SSL_SOCK_Stream::send");
size_t const total_tuples = n / 2;
va_list argp;
va_start (argp, n);
ssize_t bytes_sent = 0;
// NOTE: This method used to fill an IO vector (e.g. iovec) and then
// send it using a scatter write (sendv()). However, it is
// not possible to emulate a non-blocking scatter write over
// SSL. As such, there is no point in attempting to use
// scatter writes over SSL.
for (size_t i = 0; i < total_tuples; ++i)
{
ssize_t const data_len = va_arg (argp, ssize_t);
ssize_t const result = this->send (va_arg (argp, char *), data_len);
if (result == -1)
{
// There is a subtle difference in behaviour depending on
// whether or not any data was sent. If no data was sent,
// then always return -1. Otherwise return bytes_sent.
// This gives the caller an opportunity to keep track of
// which data was actually sent.
if (bytes_sent > 0)
break;
else
{
va_end (argp);
return -1;
}
}
else
{
bytes_sent += result;
// Do not continue on to the next loop iteration if the
// amount of data sent was less than the amount of data
// given. This avoids a subtle problem where "holes" in the
// data stream would occur if partial sends of a given
// buffer in the varargs occured.
if (result < data_len)
break;
}
}
va_end (argp);
return bytes_sent;
}
ssize_t
ACE_SSL_SOCK_Stream::recv (size_t n, ...) const
{
ACE_TRACE ("ACE_SSL_SOCK_Stream::recv");
size_t const total_tuples = n / 2;
va_list argp;
va_start (argp, n);
ssize_t bytes_recv = 0;
for (size_t i = 0; i < total_tuples; ++i)
{
ssize_t const data_len = va_arg (argp, ssize_t);
ssize_t const result = this->recv (va_arg (argp, char *), data_len);
if (result == -1)
{
// There is a subtle difference in behaviour depending on
// whether or not any data was received. If no data was
// received, then always return -1. Otherwise return
// bytes_received. This gives the caller an opportunity to
// keep track of which data was actually received.
if (bytes_recv > 0)
{
break;
}
else
{
va_end (argp);
return -1;
}
}
else
{
bytes_recv += result;
// Do not continue on to the next loop iteration if the
// amount of data received was less than the amount of data
// desired. This avoids a subtle problem where "holes" in
// the data stream would occur if partial receives of a
// given buffer in the varargs occured.
if (result < data_len)
{
break;
}
}
}
va_end (argp);
return bytes_recv;
}
ssize_t
ACE_SSL_SOCK_Stream::send_n (const void *buf,
size_t len,
int flags,
const ACE_Time_Value *timeout,
size_t *bt) const
{
ACE_TRACE ("ACE_SSL_SOCK_Stream::send_n");
// No support for send flags in SSL.
if (flags != 0)
{
ACE_NOTSUP_RETURN (-1);
}
/* This code mimics ACE::send_n */
// Total number of bytes written.
size_t temp = 0;
size_t &bytes_transferred = ((bt == 0) ? temp : *bt);
// Actual number of bytes written in each <send> attempt
ssize_t n = 0;
for (bytes_transferred = 0;
bytes_transferred < len;
bytes_transferred += n)
{
n = this->send ((const char*) buf + bytes_transferred,
len - bytes_transferred,
flags,
timeout);
if (n < 0)
{
if (errno == EWOULDBLOCK)
{
// If blocked, try again.
n = 0;
continue;
}
else
{
return -1;
}
}
else if (n == 0)
{
break;
}
}
return ACE_Utils::truncate_cast<ssize_t> (bytes_transferred);
}
ssize_t
ACE_SSL_SOCK_Stream::recv_n (void *buf,
size_t len,
int flags,
const ACE_Time_Value *timeout,
size_t *bt) const
{
ACE_TRACE ("ACE_SSL_SOCK_Stream::recv_n");
if (flags != 0)
{
if ((flags | MSG_PEEK) != MSG_PEEK)
{
ACE_NOTSUP_RETURN (-1);
}
}
size_t temp = 0;
size_t &bytes_transferred = ((bt == 0) ? temp : *bt);
ssize_t n = 0;
for (bytes_transferred = 0;
bytes_transferred < len;
bytes_transferred += n)
{
n = this->recv ((char*) buf + bytes_transferred,
len - bytes_transferred,
flags,
timeout);
if (n < 0)
{
if (errno == EWOULDBLOCK)
{
// If blocked, try again.
n = 0;
continue;
}
else
{
return -1;
}
}
else if (n == 0)
{
break;
}
}
return ACE_Utils::truncate_cast<ssize_t> (bytes_transferred);
}
ssize_t
ACE_SSL_SOCK_Stream::recv_n (void *buf, int len, int flags) const
{
ACE_TRACE ("ACE_SSL_SOCK_Stream::recv_n");
if (flags != 0)
{
if ((flags | MSG_PEEK) != MSG_PEEK)
{
ACE_NOTSUP_RETURN (-1);
}
}
ssize_t bytes_transferred = 0;
ssize_t n = 0;
for (bytes_transferred = 0;
bytes_transferred < len;
bytes_transferred += n)
{
n = this->recv ((char*) buf + bytes_transferred,
len - bytes_transferred,
flags);
if (n < 0)
{
if (errno == EWOULDBLOCK)
{
// If blocked, try again.
n = 0;
continue;
}
else
{
return -1;
}
}
else if (n == 0)
{
break;
}
}
return ACE_Utils::truncate_cast<ssize_t> (bytes_transferred);
}
ssize_t
ACE_SSL_SOCK_Stream::send_n (const void *buf, int len, int flags) const
{
ACE_TRACE ("ACE_SSL_SOCK_Stream::send_n");
// Send flags are unsupported in SSL
if (flags != 0)
{
ACE_NOTSUP_RETURN (-1);
}
/* The following code mimics <ACE::send_n> */
size_t bytes_transferred = 0;
ssize_t n = 0;
for (bytes_transferred = 0;
bytes_transferred < (size_t) len;
bytes_transferred += n)
{
n = this->send ((const char*) buf + bytes_transferred,
len - bytes_transferred,
flags);
if (n < 0)
{
if (errno == EWOULDBLOCK)
{
// If blocked, try again.
n = 0;
continue;
}
else
{
return -1;
}
}
else if (n == 0)
{
break;
}
}
return ACE_Utils::truncate_cast<ssize_t> (bytes_transferred);
}
ssize_t
ACE_SSL_SOCK_Stream::sendv_n (const iovec iov[], size_t iovcnt) const
{
ACE_TRACE ("ACE_SSL_SOCK_Stream::sendv_n");
ssize_t bytes_sent = 0;
for (size_t i = 0; i < iovcnt; ++i)
{
ssize_t result = this->send_n (iov[i].iov_base,
iov[i].iov_len);
if (result == -1)
{
// There is a subtle difference in behaviour depending on
// whether or not any data was sent. If no data was sent,
// then always return -1. Otherwise return bytes_sent.
// This gives the caller an opportunity to keep track of
// which data was actually sent.
if (bytes_sent > 0)
{
break;
}
else
{
return -1;
}
}
else
{
bytes_sent += result;
}
}
return bytes_sent;
}
ssize_t
ACE_SSL_SOCK_Stream::recvv_n (iovec iov[], size_t iovcnt) const
{
ACE_TRACE ("ACE_SSL_SOCK_Stream::recvv_n");
ssize_t bytes_read = 0;
for (size_t i = 0; i < iovcnt; ++i)
{
ssize_t const result = this->recv_n (iov[i].iov_base,
iov[i].iov_len);
if (result == -1)
{
// There is a subtle difference in behaviour depending on
// whether or not any data was read. If no data was read,
// then always return -1. Otherwise return bytes_read.
// This gives the caller an opportunity to keep track of
// which data was actually read.
if (bytes_read > 0)
{
break;
}
else
{
return -1;
}
}
else
{
bytes_read += result;
}
}
return bytes_read;
}
int
ACE_SSL_SOCK_Stream::get_remote_addr (ACE_Addr &addr) const
{
// Some applications use get_remote_addr() as a way of determining
// whether or not a connection has been established. In SSL's case,
// the remote addr will be available once the TCP handshake has been
// complete. Despite that fact, the SSL connection may not have
// been completed. In such a case, a successful return from
// get_remote_addr() would be misleading.
if (SSL_is_init_finished (this->ssl_))
{
return this->ACE_SSL_SOCK::get_remote_addr (addr);
}
if (this->get_handle () == ACE_INVALID_HANDLE)
{
errno = EBADF;
}
else
{
errno = ENOTCONN;
}
return -1;
}
ACE_END_VERSIONED_NAMESPACE_DECL

View File

@@ -0,0 +1,321 @@
// -*- C++ -*-
//=============================================================================
/**
* @file SSL_SOCK_Stream.h
*
* $Id: SSL_SOCK_Stream.h 80826 2008-03-04 14:51:23Z wotte $
*
* @author Ossama Othman <ossama@uci.edu>
* @author Carlos O'Ryan <coryan@uci.edu>
* @author John Heitmann
*/
//=============================================================================
#ifndef ACE_SSL_SOCK_STREAM_H
#define ACE_SSL_SOCK_STREAM_H
#include /**/ "ace/pre.h"
#include "SSL_Export.h"
#if !defined (ACE_LACKS_PRAGMA_ONCE)
# pragma once
#endif /* ACE_LACKS_PRAGMA_ONCE */
// This must be included before any <openssl> include on LynxOS
#include "ace/os_include/os_stdio.h"
#include <openssl/err.h>
#include "SSL_SOCK.h"
#include "SSL_Context.h"
#include "ace/SOCK_Stream.h"
ACE_BEGIN_VERSIONED_NAMESPACE_DECL
/**
* @class ACE_SSL_SOCK_Stream
*
* @brief Defines methods in the ACE_SSL_SOCK_Stream abstraction.
*
* This class encapsulates the methods and functionality necessary to
* send and receive data over TLS/SSL.
* @par
* Since SSL is record-oriented, some additional steps must be taken
* to make the ACE_SSL_SOCK_Stream interact properly with the
* Reactor (if one is used) when performing non-blocking IO. In
* particular, if ::SSL_pending (ssl), where "ssl" is a pointer to the
* SSL data structure returned from ACE_SSL_SOCK_Stream::ssl(),
* returns a non-zero value then the event handler that calls the IO
* methods in this class should return a value greater than zero to
* force the Reactor to invoke the event handler before polling for
* additional events (e.g. blocking on select()).
*
* @note The user must currently ensure that only one thread services
* a given SSL session at any given time since underlying SSL
* implementations, such as OpenSSL, are not entirely
* thread-safe or reentrant.
*/
class ACE_SSL_Export ACE_SSL_SOCK_Stream : public ACE_SSL_SOCK
{
public:
/// Constructor
/**
* @param context Pointer to @c ACE_SSL_Context instance containing
* the OpenSSL @c SSL data structure to be associated
* with this @c ACE_SSL_SOCK_Stream. The @c SSL data
* structure will be copied to make it at least
* logically independent of the supplied @a context.
*/
ACE_SSL_SOCK_Stream (ACE_SSL_Context *context =
ACE_SSL_Context::instance ());
/// Destructor
~ACE_SSL_SOCK_Stream (void);
/// Send an n byte buffer to the ssl socket using the semantics of
/// send(3n).
/**
* ACE_SSL supports no flags for sending at this time.
*/
ssize_t send (const void *buf,
size_t n,
int flags) const;
/// Recv an n byte buffer from the ssl socket using the semantics of
/// recv(3n).
/**
* ACE_SSL supports MSG_PEEK, but no other flags at this time.
*/
ssize_t recv (void *buf,
size_t n,
int flags) const;
/// Send an n byte buffer to the ssl socket using the semantics of
/// write(2).
ssize_t send (const void *buf,
size_t n) const;
/// Recv an n byte buffer from the ssl socket using the semantics of
/// read(2).
ssize_t recv (void *buf,
size_t n) const;
/// Send an iovec of size n to the ssl socket.
/**
* Note that it is not possible to perform a "scattered" write with
* the underlying OpenSSL implementation. As such, the expected
* semantics are not fully reproduced with this implementation.
*/
ssize_t sendv (const iovec iov[],
size_t n,
const ACE_Time_Value *timeout = 0) const;
/**
* Allows a client to read from a socket without having to provide a
* buffer to read. This method determines how much data is in the
* socket, allocates a buffer of this size, reads in the data, and
* returns the number of bytes read. The caller is responsible for
* deleting the member in the iov_base field of io_vec using
* delete [] io_vec->iov_base.
*/
ssize_t recvv (iovec *io_vec,
const ACE_Time_Value *timeout = 0) const;
/**
* Wait to timeout amount of time to send up to n bytes into buf
* (uses the send() call). If send() times out -1 is returned with
* errno == ETIME. If it succeeds the number of bytes sent is
* returned. No flags are supported.
*/
ssize_t send (const void *buf,
size_t n,
int flags,
const ACE_Time_Value *timeout) const;
/**
* Wait up to timeout amount of time to receive up to n bytes into
* buf (uses the recv() call). If recv() times out -1 is returned
* with errno == ETIME. If it succeeds the number of bytes received
* is returned. MSG_PEEK is the only supported flag.
*/
ssize_t recv (void *buf,
size_t n,
int flags,
const ACE_Time_Value *timeout) const;
/**
* Wait to to timeout amount of time to send up to n bytes into
* buf (uses the send() call). If send() times out
* a -1 is returned with errno == ETIME. If it succeeds the
* number of bytes sent is returned.
*/
ssize_t send (const void *buf,
size_t n,
const ACE_Time_Value *timeout) const;
/**
* Wait up to timeout amount of time to receive up to n bytes
* into buf (uses the recv() call). If recv() times
* out a -1 is returned with @c errno == ETIME. If it succeeds the
* number of bytes received is returned.
*/
ssize_t recv (void *buf,
size_t n,
const ACE_Time_Value *timeout) const;
/// Send n varargs messages to the connected ssl socket.
ssize_t send (size_t n,
...) const;
/// Recv n varargs messages to the connected ssl socket.
ssize_t recv (size_t n,
...) const;
/// Send n bytes, keep trying until n are sent.
ssize_t send_n (const void *buf, int n) const;
/// Recv n bytes, keep trying until n are received.
ssize_t recv_n (void *buf, int n) const;
/**
* @note In the following four methods, only MSG_PEEK is supported
* for recv_n(), and no flags are supported for send_n().
*/
//@{
/// Send n bytes, keep trying until n are sent.
ssize_t send_n (const void *buf, int n, int flags) const;
/// Recv n bytes, keep trying until n are sent.
ssize_t recv_n (void *buf, int n, int flags) const;
/**
* Try to send exactly len bytes into buf (uses the send() call).
* If send() blocks for longer than timeout the number of bytes
* actually sent is returned with errno == ETIME. If a timeout does
* not occur, send_n() return len (i.e., the number of bytes
* requested to be sent).
*/
ssize_t send_n (const void *buf,
size_t len,
int flags,
const ACE_Time_Value *timeout,
size_t *bytes_transferred = 0) const;
/**
* Try to receive exactly len bytes into buf (uses the recv() call).
* The ACE_Time_Value indicates how long to blocking trying to
* receive. If timeout == 0, the caller will block until action is
* possible, else will wait until the relative time specified in
* timeout elapses). If recv() blocks for longer than timeout the
* number of bytes actually read is returned with errno == ETIME.
* If a timeout does not occur, recv_n return len (i.e., the number
* of bytes requested to be read).
*/
ssize_t recv_n (void *buf,
size_t len,
int flags,
const ACE_Time_Value *timeout,
size_t *bytes_transferred = 0) const;
//@}
/**
* Send an iovec of size n to the connected socket. Will block
* until all bytes are sent or an error occurs.
*/
ssize_t sendv_n (const iovec iov[],
size_t n) const;
/// Receive an iovec of size n to the connected socket.
ssize_t recvv_n (iovec iov[],
size_t n) const;
/**
* Selectively close endpoints.
*/
//@{
/// Close down the reader.
int close_reader (void);
/// Close down the writer.
int close_writer (void);
//@}
///Close down the socket.
int close (void);
/// Meta-type info
typedef ACE_INET_Addr PEER_ADDR;
/// Declare the dynamic allocation hooks.
ACE_ALLOC_HOOK_DECLARE;
/// Overridden set_handle() method.
/**
* Only an ACE_SSL_SOCK_Acceptor or ACE_SSL_SOCK_Connector should
* access this method since some state in the underlying "ssl_" data
* structure is set during SSL connection establishment.
*/
void set_handle (ACE_HANDLE fd);
/// Return a pointer to the underlying SSL structure.
SSL *ssl (void) const;
/**
* Return the address of the remotely connected peer (if there is
* one), in the referenced <ACE_Addr>. Returns 0 if successful, else
* -1.
*
* @note If the TCP connection has been completed but the SSL
* connection has not been completed yet, -1 will be
* returned.
*/
int get_remote_addr (ACE_Addr &) const;
/// Return the underlying ACE_SOCK_Stream which ACE_SSL runs atop of.
ACE_SOCK_Stream & peer (void);
protected:
/// Underlying send() helper method common to all public send()
/// methods.
ssize_t send_i (const void *buf,
size_t n,
int flags) const;
/// Underlying send() helper method common to all public send()
/// methods.
ssize_t recv_i (void *buf,
size_t n,
int flags,
const ACE_Time_Value *timeout) const;
private:
ACE_UNIMPLEMENTED_FUNC (void operator= (const ACE_SSL_SOCK_Stream &))
ACE_UNIMPLEMENTED_FUNC (ACE_SSL_SOCK_Stream (const ACE_SSL_SOCK_Stream &))
protected:
/// The SSL session.
SSL *ssl_;
/// The stream which works under the ssl connection.
ACE_SOCK_Stream stream_;
};
ACE_END_VERSIONED_NAMESPACE_DECL
#if defined (__ACE_INLINE__)
#include "SSL_SOCK_Stream.inl"
#endif /* __ACE_INLINE__ */
#include /**/ "ace/post.h"
#endif /* ACE_SSL_SOCK_STREAM_H */

View File

@@ -0,0 +1,330 @@
// -*- C++ -*-
//
// $Id: SSL_SOCK_Stream.inl 82579 2008-08-10 23:03:06Z mitza $
#include "ace/OS_NS_errno.h"
#include "ace/Truncate.h"
ACE_BEGIN_VERSIONED_NAMESPACE_DECL
ACE_INLINE void
ACE_SSL_SOCK_Stream::set_handle (ACE_HANDLE fd)
{
if (this->ssl_ == 0 || fd == ACE_INVALID_HANDLE)
{
this->ACE_SSL_SOCK::set_handle (ACE_INVALID_HANDLE);
return;
}
else
{
(void) ::SSL_set_fd (this->ssl_, (int) fd);
this->ACE_SSL_SOCK::set_handle (fd);
this->stream_.set_handle (fd);
}
}
ACE_INLINE ssize_t
ACE_SSL_SOCK_Stream::send_i (const void *buf,
size_t n,
int flags) const
{
ACE_TRACE ("ACE_SSL_SOCK_Stream::send_i");
// NOTE: Caller must provide thread-synchronization.
// No send flags are supported in SSL.
if (flags != 0)
{
ACE_NOTSUP_RETURN (-1);
}
int const bytes_sent = ::SSL_write (this->ssl_,
static_cast<const char *> (buf),
ACE_Utils::truncate_cast<int> (n));
switch (::SSL_get_error (this->ssl_, bytes_sent))
{
case SSL_ERROR_NONE:
return bytes_sent;
case SSL_ERROR_WANT_READ:
case SSL_ERROR_WANT_WRITE:
errno = EWOULDBLOCK;
return -1;
case SSL_ERROR_ZERO_RETURN:
// The peer has notified us that it is shutting down via the SSL
// "close_notify" message so we need to shutdown, too.
(void) ::SSL_shutdown (this->ssl_);
return bytes_sent;
case SSL_ERROR_SYSCALL:
if (bytes_sent == 0)
// An EOF occured but the SSL "close_notify" message was not
// sent. This is a protocol error, but we ignore it.
return 0;
// If not an EOF, then fall through to "default" case.
// On some platforms (e.g. MS Windows) OpenSSL does not store
// the last error in errno so explicitly do so.
ACE_OS::set_errno_to_last_error ();
break;
default:
// Reset errno to prevent previous values (e.g. EWOULDBLOCK)
// from being associated with fatal SSL errors.
errno = 0;
ACE_SSL_Context::report_error ();
break;
}
return -1;
}
ACE_INLINE ssize_t
ACE_SSL_SOCK_Stream::send (const void *buf,
size_t n,
int flags) const
{
return this->send_i (buf, n, flags);
}
ACE_INLINE ssize_t
ACE_SSL_SOCK_Stream::recv_i (void *buf,
size_t n,
int flags,
const ACE_Time_Value *timeout) const
{
ACE_TRACE ("ACE_SSL_SOCK_Stream::recv_i");
// NOTE: Caller must provide thread-synchronization.
int bytes_read = 0;
ACE_HANDLE const handle = this->get_handle ();
// Value for current I/O mode (blocking/non-blocking)
int val = 0;
if (timeout != 0)
ACE::record_and_set_non_blocking_mode (handle,
val);
// Only block on select() with a timeout if no data in the
// internal OpenSSL buffer is pending read completion for
// the same reasons stated above, i.e. all data must be read
// before blocking on select().
if (timeout != 0
&& !::SSL_pending (this->ssl_))
{
if (ACE::enter_recv_timedwait (handle,
timeout,
val) == -1)
return -1;
}
if (flags)
{
if (ACE_BIT_ENABLED (flags, MSG_PEEK))
{
bytes_read = ::SSL_peek (this->ssl_,
static_cast<char *> (buf),
ACE_Utils::truncate_cast<int> (n));
}
else
{
ACE_NOTSUP_RETURN (-1);
}
}
else
{
bytes_read = ::SSL_read (this->ssl_,
static_cast<char *> (buf),
ACE_Utils::truncate_cast<int> (n));
}
int const status = ::SSL_get_error (this->ssl_, bytes_read);
switch (status)
{
case SSL_ERROR_NONE:
if (timeout != 0)
ACE::restore_non_blocking_mode (handle, val);
return bytes_read;
case SSL_ERROR_WANT_READ:
case SSL_ERROR_WANT_WRITE:
errno = EWOULDBLOCK;
return -1;
case SSL_ERROR_ZERO_RETURN:
if (timeout != 0)
ACE::restore_non_blocking_mode (handle, val);
// The peer has notified us that it is shutting down via the SSL
// "close_notify" message so we need to shutdown, too.
(void) ::SSL_shutdown (this->ssl_);
return bytes_read;
case SSL_ERROR_SYSCALL:
if (bytes_read == 0)
// An EOF occured but the SSL "close_notify" message was not
// sent. This is a protocol error, but we ignore it.
return 0;
// If not an EOF, then fall through to "default" case.
// On some platforms (e.g. MS Windows) OpenSSL does not store
// the last error in errno so explicitly do so.
ACE_OS::set_errno_to_last_error ();
break;
default:
// Reset errno to prevent previous values (e.g. EWOULDBLOCK)
// from being associated with a fatal SSL error.
errno = 0;
ACE_SSL_Context::report_error ();
break;
}
return -1;
}
ACE_INLINE ssize_t
ACE_SSL_SOCK_Stream::recv (void *buf,
size_t n,
int flags) const
{
return this->recv_i (buf, n, flags, 0);
}
ACE_INLINE ssize_t
ACE_SSL_SOCK_Stream::send (const void *buf,
size_t n) const
{
ACE_TRACE ("ACE_SSL_SOCK_Stream::send");
return this->send_i (buf, n, 0);
}
ACE_INLINE ssize_t
ACE_SSL_SOCK_Stream::recv (void *buf,
size_t n) const
{
ACE_TRACE ("ACE_SSL_SOCK_Stream::recv");
return this->recv_i (buf, n, 0, 0);
}
ACE_INLINE ssize_t
ACE_SSL_SOCK_Stream::send (const void *buf,
size_t len,
const ACE_Time_Value *timeout) const
{
ACE_TRACE ("ACE_SSL_SOCK_Stream::send");
return this->send (buf, len, 0, timeout);
}
ACE_INLINE ssize_t
ACE_SSL_SOCK_Stream::recv (void *buf,
size_t n,
const ACE_Time_Value *timeout) const
{
ACE_TRACE ("ACE_SSL_SOCK_Stream::recv");
return this->recv (buf, n, 0, timeout);
}
ACE_INLINE ssize_t
ACE_SSL_SOCK_Stream::recv_n (void *buf, int buf_size) const
{
ACE_TRACE ("ACE_SSL_SOCK_Stream::recv_n");
return this->recv_n (buf, buf_size, 0);
}
ACE_INLINE ssize_t
ACE_SSL_SOCK_Stream::send_n (const void *buf, int len) const
{
ACE_TRACE ("ACE_SSL_SOCK_Stream::send_n");
return this->send_n (buf, len, 0);
}
ACE_INLINE int
ACE_SSL_SOCK_Stream::close_reader (void)
{
ACE_TRACE ("ACE_SSL_SOCK_Stream::close_reader");
return this->stream_.close_reader ();
}
ACE_INLINE int
ACE_SSL_SOCK_Stream::close_writer (void)
{
ACE_TRACE ("ACE_SSL_SOCK_Stream::close_writer");
return this->stream_.close_writer ();
}
ACE_INLINE int
ACE_SSL_SOCK_Stream::close (void)
{
ACE_TRACE ("ACE_SSL_SOCK_Stream::close");
if (this->ssl_ == 0 || this->get_handle () == ACE_INVALID_HANDLE)
return 0; // SSL_SOCK_Stream was never opened.
// SSL_shutdown() returns 1 on successful shutdown of the SSL
// connection, not 0.
int const status = ::SSL_shutdown (this->ssl_);
switch (::SSL_get_error (this->ssl_, status))
{
case SSL_ERROR_NONE:
case SSL_ERROR_SYSCALL: // Ignore this error condition.
// Reset the SSL object to allow another connection to be made
// using this ACE_SSL_SOCK_Stream instance. This prevents the
// previous SSL session state from being associated with the new
// SSL session/connection.
(void) ::SSL_clear (this->ssl_);
this->set_handle (ACE_INVALID_HANDLE);
return this->stream_.close ();
case SSL_ERROR_WANT_READ:
case SSL_ERROR_WANT_WRITE:
errno = EWOULDBLOCK;
break;
default:
ACE_SSL_Context::report_error ();
ACE_Errno_Guard error (errno); // Save/restore errno
(void) this->stream_.close ();
return -1;
}
return -1;
}
ACE_INLINE ACE_SOCK_Stream &
ACE_SSL_SOCK_Stream::peer (void)
{
ACE_TRACE ("ACE_SSL_SOCK_Stream::peer");
return this->stream_;
}
ACE_INLINE SSL *
ACE_SSL_SOCK_Stream::ssl (void) const
{
return this->ssl_;
}
ACE_END_VERSIONED_NAMESPACE_DECL

View File

@@ -0,0 +1,55 @@
// -*- C++ -*-
//=============================================================================
/**
* @file sslconf.h
*
* $Id: sslconf.h 80826 2008-03-04 14:51:23Z wotte $
*
* @author Carlos O'Ryan <coryan@ece.uci.edu>
*/
//=============================================================================
#ifndef ACE_SSLCONF_H
#define ACE_SSLCONF_H
#include /**/ "ace/pre.h"
#include /**/ "ace/config-all.h"
#if !defined (ACE_DEFAULT_SSL_CERT_FILE)
# ifdef WIN32
# define ACE_DEFAULT_SSL_CERT_FILE "cert.pem"
# else
# define ACE_DEFAULT_SSL_CERT_FILE "/etc/ssl/cert.pem"
# endif /* WIN32 */
#endif /* ACE_DEFAULT_SSL_CERT_FILE */
#if !defined (ACE_DEFAULT_SSL_CERT_DIR)
# ifdef WIN32
# define ACE_DEFAULT_SSL_CERT_DIR "certs"
# else
# define ACE_DEFAULT_SSL_CERT_DIR "/etc/ssl/certs"
# endif /* WIN32 */
#endif /* ACE_DEFAULT_SSL_CERT_DIR */
#if !defined (ACE_SSL_CERT_FILE_ENV)
#define ACE_SSL_CERT_FILE_ENV "SSL_CERT_FILE"
#endif /* ACE_SSL_CERT_FILE_ENV */
#if !defined (ACE_SSL_CERT_DIR_ENV)
#define ACE_SSL_CERT_DIR_ENV "SSL_CERT_DIR"
#endif /* ACE_SSL_CERT_DIR_ENV */
#if !defined (ACE_SSL_EGD_FILE_ENV)
#define ACE_SSL_EGD_FILE_ENV "SSL_EGD_FILE"
#endif /* ACE_SSL_EGD_FILE_ENV */
#if !defined (ACE_SSL_RAND_FILE_ENV)
#define ACE_SSL_RAND_FILE_ENV "SSL_RAND_FILE"
#endif /* ACE_SSL_RAND_FILE_ENV */
#include /**/ "ace/post.h"
#endif /* ACE_SSLCONF_H */

View File

@@ -51,7 +51,7 @@
Name="VCCLCompilerTool"
AdditionalOptions="/MP /wd 4748 /wd 4244"
Optimization="0"
AdditionalIncludeDirectories="..\..\dep\ACE_wrappers"
AdditionalIncludeDirectories="..\..\dep\include;..\..\dep\ACE_wrappers"
PreprocessorDefinitions="ACE_BUILD_DLL;_DEBUG;WIN32;_WINDOWS;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE"
MinimalRebuild="false"
BasicRuntimeChecks="3"
@@ -76,7 +76,7 @@
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies=""
AdditionalDependencies="..\..\dep\lib\$(PlatformName)_$(ConfigurationName)\ssleay32.lib ..\..\dep\lib\$(PlatformName)_$(ConfigurationName)\libeay32.lib"
OutputFile="$(OutDir)\ACEd.dll"
LinkIncremental="1"
SuppressStartupBanner="true"
@@ -140,7 +140,7 @@
Name="VCCLCompilerTool"
AdditionalOptions="/MP /wd 4748 /wd 4244"
Optimization="0"
AdditionalIncludeDirectories="..\..\dep\ACE_wrappers"
AdditionalIncludeDirectories="..\..\dep\include;..\..\dep\ACE_wrappers"
PreprocessorDefinitions="ACE_BUILD_DLL;_DEBUG;WIN32;_WINDOWS;_CRT_NONSTDC_NO_WARNINGS;_AMD64_;_WIN64;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE"
MinimalRebuild="false"
BasicRuntimeChecks="3"
@@ -166,7 +166,7 @@
<Tool
Name="VCLinkerTool"
AdditionalOptions="/machine:AMD64"
AdditionalDependencies=""
AdditionalDependencies="..\..\dep\lib\$(PlatformName)_$(ConfigurationName)\ssleay32.lib ..\..\dep\lib\$(PlatformName)_$(ConfigurationName)\libeay32.lib"
OutputFile="$(OutDir)\ACEd.dll"
LinkIncremental="1"
SuppressStartupBanner="true"
@@ -230,7 +230,7 @@
Name="VCCLCompilerTool"
AdditionalOptions="/MP /wd 4748 /wd 4244"
Optimization="2"
AdditionalIncludeDirectories="..\..\dep\ACE_wrappers"
AdditionalIncludeDirectories="..\..\dep\include;..\..\dep\ACE_wrappers"
PreprocessorDefinitions="ACE_BUILD_DLL;NDEBUG;WIN32;_WINDOWS;_CRT_NONSTDC_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;_SECURE_SCL=0"
RuntimeLibrary="2"
RuntimeTypeInfo="true"
@@ -252,7 +252,7 @@
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies=""
AdditionalDependencies="..\..\dep\lib\$(PlatformName)_$(ConfigurationName)\ssleay32.lib ..\..\dep\lib\$(PlatformName)_$(ConfigurationName)\libeay32.lib"
OutputFile="$(OutDir)\ACE.dll"
LinkIncremental="1"
SuppressStartupBanner="true"
@@ -318,7 +318,7 @@
Name="VCCLCompilerTool"
AdditionalOptions="/MP /wd 4748 /wd 4244"
Optimization="2"
AdditionalIncludeDirectories="..\..\dep\ACE_wrappers"
AdditionalIncludeDirectories="..\..\dep\include;..\..\dep\ACE_wrappers"
PreprocessorDefinitions="ACE_BUILD_DLL;NDEBUG;WIN32;_WINDOWS;_CRT_NONSTDC_NO_WARNINGS;_AMD64_;_WIN64;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;_SECURE_SCL=0"
RuntimeLibrary="2"
RuntimeTypeInfo="true"
@@ -342,7 +342,7 @@
<Tool
Name="VCLinkerTool"
AdditionalOptions="/machine:AMD64"
AdditionalDependencies=""
AdditionalDependencies="..\..\dep\lib\$(PlatformName)_$(ConfigurationName)\ssleay32.lib ..\..\dep\lib\$(PlatformName)_$(ConfigurationName)\libeay32.lib"
OutputFile="$(OutDir)\ACE.dll"
LinkIncremental="1"
SuppressStartupBanner="true"
@@ -1400,6 +1400,34 @@
RelativePath="..\..\dep\ACE_wrappers\ace\SPIPE_Stream.cpp"
>
</File>
<File
RelativePath="..\..\dep\ACE_wrappers\ace\SSL\SSL_Asynch_BIO.cpp"
>
</File>
<File
RelativePath="..\..\dep\ACE_wrappers\ace\SSL\SSL_Asynch_Stream.cpp"
>
</File>
<File
RelativePath="..\..\dep\ACE_wrappers\ace\SSL\SSL_Context.cpp"
>
</File>
<File
RelativePath="..\..\dep\ACE_wrappers\ace\SSL\SSL_SOCK.cpp"
>
</File>
<File
RelativePath="..\..\dep\ACE_wrappers\ace\SSL\SSL_SOCK_Acceptor.cpp"
>
</File>
<File
RelativePath="..\..\dep\ACE_wrappers\ace\SSL\SSL_SOCK_Connector.cpp"
>
</File>
<File
RelativePath="..\..\dep\ACE_wrappers\ace\SSL\SSL_SOCK_Stream.cpp"
>
</File>
<File
RelativePath="..\..\dep\ACE_wrappers\ace\SString.cpp"
>
@@ -3689,6 +3717,42 @@
RelativePath="..\..\dep\ACE_wrappers\ace\SPIPE_Stream.h"
>
</File>
<File
RelativePath="..\..\dep\ACE_wrappers\ace\SSL\SSL_Asynch_BIO.h"
>
</File>
<File
RelativePath="..\..\dep\ACE_wrappers\ace\SSL\SSL_Asynch_Stream.h"
>
</File>
<File
RelativePath="..\..\dep\ACE_wrappers\ace\SSL\SSL_Context.h"
>
</File>
<File
RelativePath="..\..\dep\ACE_wrappers\ace\SSL\SSL_Export.h"
>
</File>
<File
RelativePath="..\..\dep\ACE_wrappers\ace\SSL\SSL_SOCK.h"
>
</File>
<File
RelativePath="..\..\dep\ACE_wrappers\ace\SSL\SSL_SOCK_Acceptor.h"
>
</File>
<File
RelativePath="..\..\dep\ACE_wrappers\ace\SSL\SSL_SOCK_Connector.h"
>
</File>
<File
RelativePath="..\..\dep\ACE_wrappers\ace\SSL\SSL_SOCK_Stream.h"
>
</File>
<File
RelativePath="..\..\dep\ACE_wrappers\ace\SSL\sslconf.h"
>
</File>
<File
RelativePath="..\..\dep\ACE_wrappers\ace\SString.h"
>
@@ -4990,6 +5054,30 @@
RelativePath="..\..\dep\ACE_wrappers\ace\SPIPE_Stream.inl"
>
</File>
<File
RelativePath="..\..\dep\ACE_wrappers\ace\SSL\SSL_Asynch_Stream.inl"
>
</File>
<File
RelativePath="..\..\dep\ACE_wrappers\ace\SSL\SSL_Context.inl"
>
</File>
<File
RelativePath="..\..\dep\ACE_wrappers\ace\SSL\SSL_SOCK.inl"
>
</File>
<File
RelativePath="..\..\dep\ACE_wrappers\ace\SSL\SSL_SOCK_Acceptor.inl"
>
</File>
<File
RelativePath="..\..\dep\ACE_wrappers\ace\SSL\SSL_SOCK_Connector.inl"
>
</File>
<File
RelativePath="..\..\dep\ACE_wrappers\ace\SSL\SSL_SOCK_Stream.inl"
>
</File>
<File
RelativePath="..\..\dep\ACE_wrappers\ace\SString.inl"
>