summaryrefslogtreecommitdiff
path: root/ACE/ace/SSL
diff options
context:
space:
mode:
Diffstat (limited to 'ACE/ace/SSL')
-rw-r--r--ACE/ace/SSL/ACE_SSL.pc.in11
-rw-r--r--ACE/ace/SSL/Makefile.am83
-rw-r--r--ACE/ace/SSL/SSL_Asynch_BIO.cpp252
-rw-r--r--ACE/ace/SSL/SSL_Asynch_BIO.h42
-rw-r--r--ACE/ace/SSL/SSL_Asynch_Stream.cpp1038
-rw-r--r--ACE/ace/SSL/SSL_Asynch_Stream.h425
-rw-r--r--ACE/ace/SSL/SSL_Context.cpp612
-rw-r--r--ACE/ace/SSL/SSL_Context.h387
-rw-r--r--ACE/ace/SSL/SSL_Context.inl112
-rw-r--r--ACE/ace/SSL/SSL_Export.h44
-rw-r--r--ACE/ace/SSL/SSL_SOCK.cpp72
-rw-r--r--ACE/ace/SSL/SSL_SOCK.h103
-rw-r--r--ACE/ace/SSL/SSL_SOCK.i71
-rw-r--r--ACE/ace/SSL/SSL_SOCK_Acceptor.cpp249
-rw-r--r--ACE/ace/SSL/SSL_SOCK_Acceptor.h198
-rw-r--r--ACE/ace/SSL/SSL_SOCK_Acceptor.i85
-rw-r--r--ACE/ace/SSL/SSL_SOCK_Connector.cpp411
-rw-r--r--ACE/ace/SSL/SSL_SOCK_Connector.h318
-rw-r--r--ACE/ace/SSL/SSL_SOCK_Connector.i28
-rw-r--r--ACE/ace/SSL/SSL_SOCK_Stream.cpp586
-rw-r--r--ACE/ace/SSL/SSL_SOCK_Stream.h321
-rw-r--r--ACE/ace/SSL/SSL_SOCK_Stream.i323
-rw-r--r--ACE/ace/SSL/ssl.mpc12
-rw-r--r--ACE/ace/SSL/sslconf.h55
24 files changed, 5838 insertions, 0 deletions
diff --git a/ACE/ace/SSL/ACE_SSL.pc.in b/ACE/ace/SSL/ACE_SSL.pc.in
new file mode 100644
index 00000000000..51c04a18ff1
--- /dev/null
+++ b/ACE/ace/SSL/ACE_SSL.pc.in
@@ -0,0 +1,11 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: ACE_SSL
+Description: ACE SSL Library
+Requires: ACE
+Version: @VERSION@
+Libs: -L${libdir} @ACE_TLS_LDFLAGS@ -lACE_SSL @ACE_TLS_LIBS@
+Cflags: -I${includedir} @ACE_TLS_CPPFLAGS@
diff --git a/ACE/ace/SSL/Makefile.am b/ACE/ace/SSL/Makefile.am
new file mode 100644
index 00000000000..a3d9bf94fd8
--- /dev/null
+++ b/ACE/ace/SSL/Makefile.am
@@ -0,0 +1,83 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+includedir = @includedir@/ace/SSL
+pkgconfigdir = @libdir@/pkgconfig
+
+ACE_BUILDDIR = $(top_builddir)
+ACE_ROOT = $(top_srcdir)
+
+
+## Makefile.SSL.am
+
+if BUILD_SSL
+
+lib_LTLIBRARIES = libACE_SSL.la
+
+libACE_SSL_la_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR) \
+ @ACE_TLS_CPPFLAGS@ \
+ -DACE_SSL_BUILD_DLL
+
+libACE_SSL_la_SOURCES = \
+ SSL_Asynch_BIO.cpp \
+ SSL_Asynch_Stream.cpp \
+ SSL_Context.cpp \
+ SSL_SOCK.cpp \
+ SSL_SOCK_Acceptor.cpp \
+ SSL_SOCK_Connector.cpp \
+ SSL_SOCK_Stream.cpp
+
+libACE_SSL_la_LDFLAGS = \
+ -release @ACE_VERSION_NAME@ @ACE_TLS_LDFLAGS@
+
+libACE_SSL_la_LIBADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la \
+ @ACE_TLS_LIBS@
+
+nobase_include_HEADERS = \
+ SSL_Asynch_BIO.h \
+ SSL_Asynch_Stream.h \
+ SSL_Context.h \
+ SSL_Context.inl \
+ SSL_Export.h \
+ SSL_SOCK.h \
+ SSL_SOCK.i \
+ SSL_SOCK_Acceptor.h \
+ SSL_SOCK_Acceptor.i \
+ SSL_SOCK_Connector.h \
+ SSL_SOCK_Connector.i \
+ SSL_SOCK_Stream.h \
+ SSL_SOCK_Stream.i \
+ sslconf.h
+
+pkgconfig_DATA = \
+ ACE_SSL.pc
+
+CLEANFILES = \
+ ACE_SSL.pc
+
+ACE_SSL.pc: ${top_builddir}/config.status ${srcdir}/ACE_SSL.pc.in
+ ${top_builddir}/config.status --file "$@":${srcdir}/ACE_SSL.pc.in
+
+endif BUILD_SSL
+
+EXTRA_DIST = \
+ ACE_SSL.pc.in
+
+
+## Clean up template repositories, etc.
+clean-local:
+ -rm -f *~ *.bak *.rpo *.sym lib*.*_pure_* core core.*
+ -rm -f gcctemp.c gcctemp so_locations *.ics
+ -rm -rf cxx_repository ptrepository ti_files
+ -rm -rf templateregistry ir.out
+ -rm -rf ptrepository SunWS_cache Templates.DB
diff --git a/ACE/ace/SSL/SSL_Asynch_BIO.cpp b/ACE/ace/SSL/SSL_Asynch_BIO.cpp
new file mode 100644
index 00000000000..9e27ab1348f
--- /dev/null
+++ b/ACE/ace/SSL/SSL_Asynch_BIO.cpp
@@ -0,0 +1,252 @@
+// -*- 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"
+
+
+ACE_RCSID (ACE_SSL,
+ SSL_Asynch_BIO,
+ "$Id$")
+
+
+#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,
+ NULL, /* ACE_ASYNCH_BIO_GETS_NAME, */
+ ACE_ASYNCH_BIO_CTRL_NAME,
+ ACE_ASYNCH_BIO_NEW_NAME,
+ ACE_ASYNCH_BIO_FREE_NAME,
+ NULL
+ };
+
+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, n);
+}
+
+#endif /* OPENSSL_VERSION_NUMBER > 0x0090581fL && (ACE_WIN32 ||
+ ACE_HAS_AIO_CALLS) */
diff --git a/ACE/ace/SSL/SSL_Asynch_BIO.h b/ACE/ace/SSL/SSL_Asynch_BIO.h
new file mode 100644
index 00000000000..22c6202754b
--- /dev/null
+++ b/ACE/ace/SSL/SSL_Asynch_BIO.h
@@ -0,0 +1,42 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file SSL_Asynch_BIO.h
+ *
+ * $Id$
+ *
+ * @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 */
diff --git a/ACE/ace/SSL/SSL_Asynch_Stream.cpp b/ACE/ace/SSL/SSL_Asynch_Stream.cpp
new file mode 100644
index 00000000000..ce7e9ff05ad
--- /dev/null
+++ b/ACE/ace/SSL/SSL_Asynch_Stream.cpp
@@ -0,0 +1,1038 @@
+#include "SSL_Asynch_Stream.h"
+
+ACE_RCSID (ACE_SSL,
+ SSL_Asynch_Stream,
+ "$Id$")
+
+// This only works on platforms with Asynchronous IO support.
+#if OPENSSL_VERSION_NUMBER > 0x0090581fL && ((defined (ACE_WIN32) && !defined (ACE_HAS_WINCE)) || (defined (ACE_HAS_AIO_CALLS)))
+
+#if defined (ACE_WIN32)
+# include "ace/WIN32_Proactor.h"
+#else
+# include "ace/POSIX_Proactor.h"
+#endif /* ACE_WIN32 */
+
+#include "ace/OS_NS_string.h"
+#include "ace/Proactor.h"
+
+#include <openssl/err.h>
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_SSL_Asynch_Write_Stream_Result::ACE_SSL_Asynch_Write_Stream_Result
+ (ACE_Handler & handler,
+ ACE_HANDLE handle,
+ ACE_Message_Block & message_block,
+ size_t bytes_to_write,
+ const void * act,
+ ACE_HANDLE event,
+ int priority,
+ int signal_number
+ )
+ : AWS_RESULT (handler.proxy (),
+ handle,
+ message_block,
+ bytes_to_write,
+ act,
+ event,
+ priority,
+ signal_number
+ )
+{
+}
+
+ACE_SSL_Asynch_Read_Stream_Result::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
+ )
+ : ARS_RESULT (handler.proxy (),
+ handle,
+ message_block,
+ bytes_to_read,
+ act,
+ event,
+ priority,
+ signal_number
+ )
+{
+}
+
+ACE_SSL_Asynch_Result::ACE_SSL_Asynch_Result (ACE_Handler & handler)
+ : A_RESULT (handler.proxy (),
+ 0, // act,
+ ACE_INVALID_HANDLE,
+ 0, // Offset
+ 0, // OffsetHigh
+ 0, // Priority
+ ACE_SIGRTMIN //signal_number
+ )
+{
+}
+
+void
+ACE_SSL_Asynch_Result::complete (size_t /* bytes_transferred */,
+ int /* success */,
+ const void * /* completion_key */,
+ u_long /* error */)
+{
+ this->handler_proxy_->handler ()->handle_wakeup ();
+}
+
+// ************************************************************
+// ACE_SSL_Asynch_Stream Constructor / Destructor
+// ************************************************************
+ACE_SSL_Asynch_Stream::ACE_SSL_Asynch_Stream (
+ ACE_SSL_Asynch_Stream::Stream_Type s_type,
+ ACE_SSL_Context * context)
+ : type_ (s_type),
+ handle_ (ACE_INVALID_HANDLE),
+ proactor_ (0),
+ ext_handler_ (0),
+ ext_read_result_ (0),
+ ext_write_result_(0),
+ flags_ (0),
+ ssl_ (0),
+ bio_ (0),
+ bio_istream_ (),
+ bio_inp_msg_ (),
+ bio_inp_errno_(0),
+ bio_inp_flag_ (0),
+ bio_ostream_ (),
+ bio_out_msg_ (),
+ bio_out_errno_(0),
+ bio_out_flag_ (0),
+ mutex_ ()
+{
+ ACE_TRACE ("ACE_SSL_Asynch_Stream::ACE_SSL_Asynch_Stream");
+ // was honestly copied from 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,
+ ACE_TEXT ("(%P|%t) ACE_SSL_Asynch_Stream %p\n"),
+ ACE_TEXT ("- cannot allocate new SSL structure")
+ ));
+
+}
+
+ACE_SSL_Asynch_Stream::~ACE_SSL_Asynch_Stream (void)
+{
+ ACE_TRACE ("ACE_SSL_Asynch_Stream::~ACE_SSL_Asynch_Stream");
+
+
+ // It is safe to delete stream if all notifications are received,
+ // i.e., state is SF_DELETE_ENABLE or if proactor event loop is
+ // done.
+ if (this->flags_ & SF_STREAM_OPEN) // open
+ if ((this->flags_ & SF_DELETE_ENABLE) == 0) // but ..
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT("ACE_SSL_Asynch_Stream::DTOR-")
+ ACE_TEXT("possible access violation ")
+ ACE_TEXT("if proactor still handles events\n")));
+
+ ::SSL_free (this->ssl_);
+
+ // Was honestly copied from ACE_SSL_SOCK_Stream :)
+
+ // @@ 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!
+}
+
+// ************************************************************
+// close ()
+// returns :
+// 0 - Stream is in the state SF_DELETE_ENABLE,
+// so it is safe to delete stream
+// -1 - Stream has pending AIO requests,
+// close should be repeated later one more
+// ************************************************************
+
+int
+ACE_SSL_Asynch_Stream::close (void)
+{
+ ACE_MT (ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, ace_mon, this->mutex_, -1));
+
+ if ((flags_ & SF_STREAM_OPEN) == 0) // not open
+ flags_ |= SF_DELETE_ENABLE;
+
+ if (flags_ & SF_DELETE_ENABLE)
+ return 0;
+
+ flags_ |= SF_REQ_SHUTDOWN;
+
+ this->do_SSL_state_machine ();
+
+ return -1;
+}
+
+// ************************************************************
+// Asynch_Operation interface
+// cancel
+// ************************************************************
+int
+ACE_SSL_Asynch_Stream::cancel (void)
+{
+ ACE_MT (ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, ace_mon, this->mutex_, -1));
+
+ if ((flags_ & SF_STREAM_OPEN) == 0) // not open
+ return 1; // AIO_ALLDONE
+
+ // attempt to cancel internal, i.e. user's read/write
+ int rc_r_int = bio_istream_.cancel();
+ int rc_w_int = bio_ostream_.cancel();
+
+ // attempt to cancel external, i.e. bio_ssl read/write
+ int rc_r_ext = notify_read (0, ERR_CANCELED);
+ int rc_w_ext = notify_write (0, ERR_CANCELED);
+
+ if (rc_r_int < 0 || rc_w_int < 0
+ && rc_r_ext < 0 || rc_w_ext < 0)
+ return -1; // at least one error
+
+ if (rc_r_int == 1 && rc_w_int == 1
+ && rc_r_ext == 1 && rc_w_ext == 1)
+ return 1; // AIO_ALLDONE
+
+ if (rc_r_int == 2 || rc_w_int == 2
+ && rc_r_ext == 2 || rc_w_ext == 2)
+ return 2; // AIO_NOT_CANCELED , at least one not canceled
+
+ return 0; // AIO_CANCELED, at least will be one notification
+}
+
+// ************************************************************
+// Asynch_Operation interface
+// open
+// ************************************************************
+int
+ACE_SSL_Asynch_Stream::open (ACE_Handler & handler,
+ ACE_HANDLE handle,
+ const void * completion_key,
+ ACE_Proactor * proactor)
+{
+ ACE_MT (ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, ace_mon, this->mutex_, -1));
+
+ if (this->flags_ & SF_STREAM_OPEN)
+ ACE_ERROR_RETURN
+ ((LM_ERROR,
+ ACE_TEXT ("(%P|%t) ACE_SSL_Asynch_Stream::open() %p\n"),
+ ACE_TEXT ("- already opened")),
+ -1);
+
+ if (this->ssl_ == 0)
+ ACE_ERROR_RETURN
+ ((LM_ERROR,
+ ACE_TEXT ("(%P|%t) ACE_SSL_Asynch_Stream::open() %p\n"),
+ ACE_TEXT ("- SSL structure is absent")),
+ -1);
+
+ if (handle == ACE_INVALID_HANDLE)
+ ACE_ERROR_RETURN
+ ((LM_ERROR,
+ ACE_TEXT ("(%P|%t) ACE_SSL_Asynch_Stream::open() %p\n"),
+ ACE_TEXT ("- invalid handle")),
+ -1);
+
+
+ // Get a proactor for/from the user.
+ this->proactor_ = this->get_proactor (proactor, handler);
+ this->ext_handler_ = & handler;
+ this->handle_ = handle;
+
+ // Open internal input stream
+ if (this->bio_istream_.open (*this, // real callbacks to this
+ handle,
+ completion_key,
+ this->proactor_) != 0)
+ return -1;
+
+ // Open internal output stream
+ if (this->bio_ostream_.open (*this, // real callbacks to this
+ handle,
+ completion_key,
+ this->proactor_) != 0)
+ return -1;
+
+ this->bio_ = ACE_SSL_make_BIO (this);
+
+ if (this->bio_ == 0)
+ ACE_ERROR_RETURN
+ ((LM_ERROR,
+ ACE_TEXT ("(%P|%t) ACE_SSL_Asynch_Stream::open() %p\n"),
+ ACE_TEXT ("- cannot allocate new BIO structure")),
+ -1);
+
+ ::SSL_set_bio (this->ssl_ , this->bio_ , this->bio_);
+
+ switch (this->type_)
+ {
+ case ST_CLIENT:
+ ::SSL_set_connect_state (this->ssl_);
+ break;
+
+ case ST_SERVER:
+ ::SSL_set_accept_state (this->ssl_);
+ break;
+
+ default:
+ ACE_ERROR_RETURN
+ ((LM_ERROR,
+ ACE_TEXT ("(%P|%t) ACE_SSL_Asynch_Stream::open() %p\n"),
+ ACE_TEXT ("- invalid stream type")),
+ -1);
+ }
+
+ this->flags_ |= SF_STREAM_OPEN;
+
+ this->do_SSL_state_machine ();
+
+ return 0;
+}
+
+
+// ************************************************************
+// Asynch_Operation interface
+// read
+// ************************************************************
+int
+ACE_SSL_Asynch_Stream::read (ACE_Message_Block & message_block,
+ size_t bytes_to_read,
+ const void * act,
+ int priority,
+ int signal_number)
+{
+ ACE_MT (ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, ace_mon, this->mutex_, -1));
+
+ if ((this->flags_ & SF_STREAM_OPEN) == 0) // not open
+ return -1;
+
+ if (this->flags_ & SF_REQ_SHUTDOWN)
+ return -1;
+
+ // only one read operation is allowed now
+ // later it will be possible to make a queue
+
+ if (this->ext_read_result_ != 0)
+ return -1;
+
+ // create result for future notification
+ ACE_NEW_RETURN (this->ext_read_result_,
+ ACE_SSL_Asynch_Read_Stream_Result (
+ *this->ext_handler_,
+ this->handle_,
+ message_block,
+ bytes_to_read,
+ act,
+ this->proactor_->get_handle(),
+ priority,
+ signal_number),
+ -1);
+
+ this->do_SSL_state_machine (); // ignore return code
+
+ return 0;
+}
+
+// ************************************************************
+// Asynch_Operation interface
+// write
+// ************************************************************
+int
+ACE_SSL_Asynch_Stream::write (ACE_Message_Block & message_block,
+ size_t bytes_to_write,
+ const void * act,
+ int priority,
+ int signal_number)
+{
+ ACE_MT (ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, ace_mon, this->mutex_, -1));
+
+ if ((this->flags_ & SF_STREAM_OPEN) == 0) // not open
+ return -1;
+
+ if (this->flags_ & SF_REQ_SHUTDOWN)
+ return -1;
+
+ // only one read operation is allowed now
+ // later it will be possible to make a queue
+
+ if (this->ext_write_result_ != 0)
+ return -1;
+
+ // create result for future notification
+ ACE_NEW_RETURN (this->ext_write_result_,
+ ACE_SSL_Asynch_Write_Stream_Result (
+ *this->ext_handler_,
+ this->handle_,
+ message_block,
+ bytes_to_write,
+ act,
+ this->proactor_->get_handle(),
+ priority,
+ signal_number),
+ -1);
+
+ this->do_SSL_state_machine ();
+
+ return 0;
+}
+
+// ************************************************************
+// Main SSL engine
+// ************************************************************
+int
+ACE_SSL_Asynch_Stream::do_SSL_state_machine (void)
+{
+ // this protected member should be called
+ // with locked mutex_
+
+ int retval = this->do_SSL_handshake ();
+
+ if (retval == 0) // handshake in progress ?
+ return 0;
+
+ if (retval < 0)
+ this->flags_ |= SF_REQ_SHUTDOWN;
+
+ this->do_SSL_read (); // execute user read request
+ this->do_SSL_write (); // execute user write request
+
+ if ((this->flags_ & SF_REQ_SHUTDOWN) == 0) // Do we have any errors
+ return 0;
+
+ this->do_SSL_shutdown ();
+
+ this->notify_close ();
+
+ return 0;
+}
+
+// ************************************************************
+// do_SSL_shutdown
+// return code:
+// 1 SSL shutdown is finished already, success
+// 0 SSL shutdown in progress
+// -1 failure
+// ************************************************************
+int
+ACE_SSL_Asynch_Stream::do_SSL_shutdown (void)
+{
+ if (this->flags_ & SF_SHUTDOWN_DONE) // already done
+ return 1;
+
+ this->flags_ |= SF_REQ_SHUTDOWN;
+
+ // if we have any uncompleted user requests
+ // than cancel its
+ this->notify_read (0, ERR_CANCELED);
+ this->notify_write (0, ERR_CANCELED);
+
+ int retval = ::SSL_shutdown (this->ssl_);
+
+ int status = ::SSL_get_error (this->ssl_, retval);
+
+ switch (status)
+ {
+ case SSL_ERROR_NONE:
+ case SSL_ERROR_ZERO_RETURN:
+ case SSL_ERROR_SYSCALL:
+ retval = 1;
+ break;
+
+ case SSL_ERROR_WANT_READ:
+ case SSL_ERROR_WANT_WRITE:
+ case SSL_ERROR_WANT_CONNECT:
+ // case SSL_ERROR_WANT_ACCEPT:
+ case SSL_ERROR_WANT_X509_LOOKUP:
+ return 0;
+
+ default:
+ this->print_error (status,
+ ACE_TEXT ("Shutdown error"));
+ retval = -1;
+ break;
+ }
+
+ this->flags_ |= SF_SHUTDOWN_DONE;
+
+ return retval;
+}
+
+// ************************************************************
+// Do SSL handshake if necessary
+// return code:
+// 1 SSL handshake is finished already, success
+// 0 SSL handshake in progress
+// -1 failure
+// ************************************************************
+int
+ACE_SSL_Asynch_Stream::do_SSL_handshake (void)
+{
+ if (SSL_is_init_finished (this->ssl_))
+ return 1;
+
+ if (this->flags_ & SF_REQ_SHUTDOWN)
+ return -1;
+
+ int retval = -1;
+
+ switch (this->type_)
+ {
+ case ST_CLIENT:
+ retval = ::SSL_connect (this->ssl_);
+ break;
+
+ case ST_SERVER:
+ retval = ::SSL_accept (this->ssl_);
+ break;
+
+ default:
+ ACE_ERROR_RETURN
+ ((LM_ERROR,
+ ACE_TEXT ("(%P|%t) ACE_SSL_Asynch_Stream %p\n"),
+ ACE_TEXT ("- invalid stream type")),
+ -1);
+ }
+
+ int status = ::SSL_get_error (this->ssl_, retval);
+
+ switch (status)
+ {
+ case SSL_ERROR_NONE:
+ break;
+
+ case SSL_ERROR_WANT_READ:
+ case SSL_ERROR_WANT_WRITE:
+ case SSL_ERROR_WANT_CONNECT:
+ //case SSL_ERROR_WANT_ACCEPT:
+ case SSL_ERROR_WANT_X509_LOOKUP:
+ return 0;
+
+ case SSL_ERROR_ZERO_RETURN:
+ case SSL_ERROR_SYSCALL:
+ default:
+ this->print_error (status,
+ ACE_TEXT ("Handshake error"));
+ return -1;
+ }
+
+ return 1;
+}
+
+// ************************************************************
+// Perform SSL_read call if necessary and notify user
+// ************************************************************
+int
+ACE_SSL_Asynch_Stream::do_SSL_read (void)
+{
+ if (this->ext_read_result_ == 0) // nothing to do
+ return 0;
+
+ if (this->flags_ & SF_REQ_SHUTDOWN)
+ {
+ this->notify_read (0, ERR_CANCELED);
+ return -1;
+ }
+
+ ACE_Message_Block & mb = this->ext_read_result_->message_block ();
+ size_t bytes_req = this->ext_read_result_->bytes_to_read ();
+
+ const int bytes_trn = ::SSL_read (this->ssl_,
+ mb.wr_ptr (),
+ bytes_req);
+
+ int status = ::SSL_get_error (this->ssl_, bytes_trn);
+
+ switch (status)
+ {
+ case SSL_ERROR_NONE:
+ this->notify_read (bytes_trn, 0);
+ return 1;
+
+ case SSL_ERROR_WANT_READ:
+ case SSL_ERROR_WANT_WRITE:
+ return 0;
+
+ case SSL_ERROR_ZERO_RETURN:
+ this->notify_read (0, 0);
+ return 1;
+
+ case SSL_ERROR_SYSCALL:
+ if (bytes_trn == 0)
+ {
+ this->notify_read (0, 0);
+ return 1;
+ }
+ // If not an EOF, then fall through to "default" case.
+
+ default:
+ break;
+ }
+
+ this->notify_read (0, EFAULT);
+ this->print_error (status,
+ ACE_TEXT ("SSL_read error"));
+
+ return -1;
+}
+
+// ************************************************************
+// Perform SSL_write call if necessary and notify user
+// ************************************************************
+int
+ACE_SSL_Asynch_Stream::do_SSL_write (void)
+{
+ if (this->ext_write_result_ == 0) // nothing to do
+ return 0;
+
+ if (this->flags_ & SF_REQ_SHUTDOWN)
+ {
+ this->notify_write (0, ERR_CANCELED);
+ return -1;
+ }
+
+ ACE_Message_Block & mb = this->ext_write_result_->message_block ();
+ size_t bytes_req = this->ext_write_result_->bytes_to_write ();
+
+ const int bytes_trn = ::SSL_write (this->ssl_,
+ mb.rd_ptr (),
+ bytes_req);
+
+ int status = ::SSL_get_error (this->ssl_, bytes_trn);
+
+ switch (status)
+ {
+ case SSL_ERROR_NONE:
+ this->notify_write (bytes_trn, 0);
+ return 1;
+
+ case SSL_ERROR_WANT_READ:
+ case SSL_ERROR_WANT_WRITE:
+ return 0;
+
+ case SSL_ERROR_ZERO_RETURN:
+ this->notify_write (bytes_trn, 0);
+ return 1;
+
+ case SSL_ERROR_SYSCALL:
+ default:
+ break;
+ }
+
+ this->notify_write(0, EFAULT);
+ this->print_error (status,
+ ACE_TEXT ("SSL_write error"));
+
+ return -1;
+}
+
+// ************************************************************
+// notify external user handler that
+// it is now to safe destroy stream
+// Return code looks like cancel() return code
+// 0 - notified NOTIFIED
+// 1 - nothing to notify ALLDONE
+// 2 - unable to notify NOT NOTIFIED
+// ************************************************************
+int
+ACE_SSL_Asynch_Stream::notify_close (void)
+{
+ if (this->flags_ & SF_CLOSE_NTF_SENT) // already sent
+ return 1;
+
+ if ((this->flags_ & SF_SHUTDOWN_DONE) == 0) // only after shutdown
+ return 2; // too early , we will do later
+
+ if (this->pending_BIO_count () != 0) // wait for all internal IO
+ return 2; // too early , we will do later
+
+ // create result for future notification
+ ACE_SSL_Asynch_Result * close_result = 0;
+
+ ACE_NEW_RETURN (close_result,
+ ACE_SSL_Asynch_Result (*this),
+ 2);
+ //@@ Not exception safe!
+
+ int retval =
+ close_result->post_completion (this->proactor_->implementation ());
+
+ if (retval == 0)
+ {
+ this->flags_ |= SF_CLOSE_NTF_SENT;
+ return 0;
+ }
+
+ delete close_result;
+ return 2;
+}
+
+// ************************************************************
+// notify external user handler about user write completion
+// Return code looks like cancel() return code
+// 0 - notified NOTIFIED/CANCELED
+// 1 - nothing to notify ALLDONE
+// 2 - unable to notify NOT NOTIFIED/CANCELED
+// ************************************************************
+
+int
+ACE_SSL_Asynch_Stream::notify_read (int bytes_transferred,
+ int error)
+{
+ if (ext_read_result_ == 0) //nothing to notify
+ return 1;
+
+ this->ext_read_result_->set_bytes_transferred (bytes_transferred);
+ this->ext_read_result_->set_error (error);
+
+ int retval =
+ this->ext_read_result_->post_completion (proactor_->implementation ());
+
+ if (retval == 0)
+ {
+ this->ext_read_result_ = 0;
+ return 0; // success
+ }
+
+ return 2; // unable to notify
+}
+
+// ************************************************************
+// notify external user handler about user write completion
+// Return code looks like cancel() return code
+// 0 - notified NOTIFIED/CANCELED
+// 1 - nothing to notify ALLDONE
+// 2 - unable to notify NOT NOTIFIED/CANCELED
+// ************************************************************
+
+int
+ACE_SSL_Asynch_Stream::notify_write (int bytes_transferred,
+ int error)
+{
+ if (this->ext_write_result_ == 0) //nothing to notify
+ return 1;
+
+ this->ext_write_result_->set_bytes_transferred (bytes_transferred);
+ this->ext_write_result_->set_error (error);
+
+ int retval =
+ this->ext_write_result_->post_completion (
+ this->proactor_->implementation ());
+
+ if (retval == 0)
+ {
+ this->ext_write_result_ = 0;
+ return 0; // success
+ }
+
+ return 2; // unable to notify
+}
+
+// ************************************************************
+// Print SSL errors
+// ************************************************************
+void
+ACE_SSL_Asynch_Stream::print_error (int err_ssl,
+ const ACE_TCHAR * pText)
+{
+ ACE_DEBUG ((LM_DEBUG,
+ "SSL-error:%d %s\n" ,
+ err_ssl,
+ pText));
+
+#if OPENSSL_VERSION_NUMBER >= 0x0090601fL
+ // OpenSSL < 0.9.6a doesn't have ERR_error_string_n() function.
+ unsigned long lerr = 0;
+ char buf[1024];
+
+ while ((lerr = ERR_get_error()) != 0)
+ {
+ ERR_error_string_n (lerr, buf, sizeof buf);
+
+ ACE_DEBUG ((LM_DEBUG, "%s\n", buf));
+ }
+#endif /* OPENSSL_VERSION_NUMBER */
+}
+
+// ************************************************************
+// BIO helper functions
+// SSL library will ask BIO to do raw I/O
+// BIO will call us to do this
+// ************************************************************
+int
+ACE_SSL_Asynch_Stream::ssl_bio_read (char * buf,
+ size_t len,
+ int & errval)
+{
+ // We do not have to acquire mutex
+ // as we called already with locked mutex
+ // from do_SSL_state_machine()
+
+ errval = 0;
+
+ size_t cur_len = this->bio_inp_msg_.length ();
+
+ if (cur_len > 0) // there are more data buffered
+ {
+ const char * rd_ptr = this->bio_inp_msg_.rd_ptr ();
+
+ if (cur_len > len)
+ cur_len = len;
+
+ ACE_OS::memcpy (buf, rd_ptr, cur_len);
+
+ this->bio_inp_msg_.rd_ptr (cur_len); // go ahead
+
+ return cur_len;
+ }
+
+ if (this->bio_inp_errno_ != 0) // if was error - it is permanent !
+ {
+ errval = this->bio_inp_errno_;
+ return -1;
+ }
+
+ if (this->bio_inp_flag_ & BF_EOS) // End of stream
+ return 0;
+
+ errval = EINPROGRESS; // SSL will try later
+
+ if (this->bio_inp_flag_ & BF_AIO) // we are busy
+ return -1;
+
+ if (this->bio_inp_msg_.size (len) != 0)
+ {
+ ACE_ERROR
+ ((LM_ERROR,
+ ACE_TEXT ("%N:%l ((%P|%t) ACE_SSL_Asynch_Stream %p\n"),
+ ACE_TEXT ("error in ACE_Message_Block::size() ")
+ ));
+
+ errval = EINVAL;
+ return -1;
+ }
+
+ char * base = this->bio_inp_msg_.base ();
+
+ this->bio_inp_msg_.rd_ptr (base);
+ this->bio_inp_msg_.wr_ptr (base);
+
+ if (this->bio_istream_.read (
+ bio_inp_msg_, // message block
+ len, // priority
+ 0, // act
+ 0, // priority
+ ACE_SIGRTMIN // default signal
+ ) == -1)
+ {
+ ACE_ERROR
+ ((LM_ERROR,
+ ACE_TEXT ("%N:%l (%P|%t) ACE_SSL_Asynch_Stream %p\n"),
+ ACE_TEXT ("attempt read failed")
+ ));
+
+ errval = EINVAL; // may be leave EINPROGRESS ??
+ return -1; // to try later
+ }
+
+ this->bio_inp_flag_ |= BF_AIO; // AIO is active
+
+ return -1;
+}
+
+
+int
+ACE_SSL_Asynch_Stream::ssl_bio_write (const char * buf,
+ size_t len,
+ int & errval)
+{
+ // We do not have to acquire mutex
+ // as we called already with locked mutex
+ // from do_SSL_state_machine
+
+ errval = 0;
+
+ if (this->bio_out_flag_ & BF_AIO) // sorry, we are busy
+ {
+ errval = EINPROGRESS; // try later
+ return -1;
+ }
+
+ if (this->bio_out_errno_ != 0) // no recovery
+ {
+ errval = this->bio_out_errno_;
+ return -1;
+ }
+
+ if (this->bio_out_msg_.size (len) != 0)
+ {
+ ACE_ERROR
+ ((LM_ERROR,
+ ACE_TEXT ("%N:%l ((%P|%t) ACE_SSL_Asynch_Stream %p\n"),
+ ACE_TEXT ("error in ACE_Message_Block::size() ")
+ ));
+
+ errval = EINVAL;
+ return -1;
+ }
+
+ char * base = this->bio_out_msg_.base ();
+
+ this->bio_out_msg_.rd_ptr (base);
+ this->bio_out_msg_.wr_ptr (base);
+
+ if (this->bio_out_msg_.copy (buf, len) == -1)
+ {
+ ACE_ERROR
+ ((LM_ERROR,
+ ACE_TEXT ("%N:%l ((%P|%t) ACE_SSL_Asynch_Stream %p\n"),
+ ACE_TEXT ("error in ACE_Message_Block::copy() ")
+ ));
+
+ errval = EINVAL;
+ return -1;
+ }
+
+
+ if (this->bio_ostream_.write (
+ this->bio_out_msg_, // message block
+ len, // priority
+ 0, // act
+ 0, // priority
+ ACE_SIGRTMIN // default signal
+ ) == -1)
+ {
+ ACE_ERROR
+ ((LM_ERROR,
+ ACE_TEXT ("%N:%l ((%P|%t) ACE_SSL_Asynch_Stream %p\n"),
+ ACE_TEXT ("attempt write failed")
+ ));
+
+ errval = EINVAL; // may be leave EINPROGRESS ??
+ return -1; // to try later
+ }
+
+ this->bio_out_flag_ |= BF_AIO; // AIO is active
+ errval = 0; // Ok, go ahead
+
+ return len;
+}
+
+// ************************************************************
+// Internal IO handlers
+// virtual from ACE_Service_Handler
+// ************************************************************
+void
+ACE_SSL_Asynch_Stream::handle_write_stream (
+ const ACE_Asynch_Write_Stream::Result &result)
+{
+ ACE_MT (ACE_GUARD (ACE_SYNCH_MUTEX, ace_mon, this->mutex_));
+
+ this->bio_out_flag_ &= ~BF_AIO;
+
+ ACE_Message_Block & mb = result.message_block ();
+
+ size_t bytes_req = result.bytes_to_write ();
+ size_t bytes_trn = result.bytes_transferred ();
+ u_long errval = result.error ();
+ size_t len = bytes_req - bytes_trn;
+
+ if (errval != 0) // error ?
+ this->bio_out_errno_ = errval; // save error code
+ else if (len > 0) // TCP/IP overloaded ?
+ { // continue, rd_ptr at right place
+ if (this->bio_ostream_.write (
+ mb, // message block
+ len, // priority
+ 0, // act
+ 0, // priority
+ ACE_SIGRTMIN // default signal
+ ) == 0)
+ {
+ this->bio_out_flag_ |= BF_AIO;
+ return;
+ }
+
+ ACE_ERROR
+ ((LM_ERROR,
+ ACE_TEXT ("(%P|%t) ACE_SSL_Asynch_Stream %p\n"),
+ ACE_TEXT ("attempt write failed")
+ ));
+
+ this->bio_out_errno_ = EINVAL;
+ }
+
+ this->do_SSL_state_machine ();
+
+ return;
+}
+
+void
+ACE_SSL_Asynch_Stream::handle_read_stream (
+ const ACE_Asynch_Read_Stream::Result &result)
+{
+ ACE_MT (ACE_GUARD (ACE_SYNCH_MUTEX, ace_mon, this->mutex_));
+
+ this->bio_inp_flag_ &= ~BF_AIO;
+
+ size_t bytes_trn = result.bytes_transferred ();
+ u_long errval = result.error ();
+
+ if (errval != 0) // error ?
+ this->bio_inp_errno_ = errval; // save error code
+ else if (bytes_trn == 0) // end of stream ?
+ this->bio_inp_flag_ |= BF_EOS; // set flag EOS
+
+ this->do_SSL_state_machine ();
+
+ return;
+}
+
+void
+ACE_SSL_Asynch_Stream::handle_wakeup (void)
+{
+ ACE_Handler * user_handler = 0;
+
+ {
+ ACE_MT (ACE_GUARD (ACE_SYNCH_MUTEX, ace_mon, this->mutex_));
+
+ this->flags_ |= SF_DELETE_ENABLE;
+
+ user_handler = this->ext_handler_;
+ }
+
+ if (user_handler != 0)
+ user_handler->handle_wakeup();
+}
+
+int
+ACE_SSL_Asynch_Stream::pending_BIO_count (void)
+{
+ int ret = 0;
+
+ if (this->bio_inp_flag_ & BF_AIO)
+ ++ret;
+
+ if (this->bio_out_flag_ & BF_AIO)
+ ++ret;
+
+ return ret;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* OPENSSL_VERSION_NUMBER > 0x0090581fL && (ACE_WIN32 ||
+ ACE_HAS_AIO_CALLS) */
diff --git a/ACE/ace/SSL/SSL_Asynch_Stream.h b/ACE/ace/SSL/SSL_Asynch_Stream.h
new file mode 100644
index 00000000000..671cca46c24
--- /dev/null
+++ b/ACE/ace/SSL/SSL_Asynch_Stream.h
@@ -0,0 +1,425 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file SSL_Asynch_Stream.h
+ *
+ * $Id$
+ *
+ * @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 */
diff --git a/ACE/ace/SSL/SSL_Context.cpp b/ACE/ace/SSL/SSL_Context.cpp
new file mode 100644
index 00000000000..18dd760e110
--- /dev/null
+++ b/ACE/ace/SSL/SSL_Context.cpp
@@ -0,0 +1,612 @@
+#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/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$")
+
+
+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;
+ 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 (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_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;
+}
+
+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)
+{
+ ::RAND_seed (seed, ACE_OS::strlen (seed));
+
+#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 error = ::ERR_get_error ();
+ ACE_SSL_Context::report_error (error);
+ ACE_OS::last_error (error);
+}
+
+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")) == NULL)
+ {
+ this->dh_params_ = ACE_SSL_Data_File ();
+ return -1;
+ }
+
+ ret = PEM_read_bio_DHparams (bio, NULL, NULL, NULL);
+ 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
diff --git a/ACE/ace/SSL/SSL_Context.h b/ACE/ace/SSL/SSL_Context.h
new file mode 100644
index 00000000000..338fc679dd1
--- /dev/null
+++ b/ACE/ace/SSL/SSL_Context.h
@@ -0,0 +1,387 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file SSL_Context.h
+ *
+ * $Id$
+ *
+ * @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 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 */
diff --git a/ACE/ace/SSL/SSL_Context.inl b/ACE/ace/SSL/SSL_Context.inl
new file mode 100644
index 00000000000..295a0fab8b2
--- /dev/null
+++ b/ACE/ace/SSL/SSL_Context.inl
@@ -0,0 +1,112 @@
+// -*- C++ -*-
+//
+// $Id$
+
+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
diff --git a/ACE/ace/SSL/SSL_Export.h b/ACE/ace/SSL/SSL_Export.h
new file mode 100644
index 00000000000..ec478095d18
--- /dev/null
+++ b/ACE/ace/SSL/SSL_Export.h
@@ -0,0 +1,44 @@
+// -*- C++ -*-
+// $Id$
+// 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
+
+#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.
diff --git a/ACE/ace/SSL/SSL_SOCK.cpp b/ACE/ace/SSL/SSL_SOCK.cpp
new file mode 100644
index 00000000000..c6f1af15388
--- /dev/null
+++ b/ACE/ace/SSL/SSL_SOCK.cpp
@@ -0,0 +1,72 @@
+// $Id$
+
+#include "SSL_SOCK.h"
+
+#if !defined (__ACE_INLINE__)
+#include "SSL_SOCK.i"
+#endif /* __ACE_INLINE__ */
+
+#include "ace/OS_NS_errno.h"
+#include "ace/os_include/os_signal.h"
+
+ACE_RCSID (ACE_SSL,
+ SSL_SOCK,
+ "$Id$")
+
+
+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
diff --git a/ACE/ace/SSL/SSL_SOCK.h b/ACE/ace/SSL/SSL_SOCK.h
new file mode 100644
index 00000000000..0a86a1f5c9f
--- /dev/null
+++ b/ACE/ace/SSL/SSL_SOCK.h
@@ -0,0 +1,103 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file SSL_SOCK.h
+ *
+ * $Id$
+ *
+ * @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.i"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_SSL_SOCK_H */
+
+
+
+
diff --git a/ACE/ace/SSL/SSL_SOCK.i b/ACE/ace/SSL/SSL_SOCK.i
new file mode 100644
index 00000000000..1a39d5214dc
--- /dev/null
+++ b/ACE/ace/SSL/SSL_SOCK.i
@@ -0,0 +1,71 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#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
diff --git a/ACE/ace/SSL/SSL_SOCK_Acceptor.cpp b/ACE/ace/SSL/SSL_SOCK_Acceptor.cpp
new file mode 100644
index 00000000000..61c91e999e4
--- /dev/null
+++ b/ACE/ace/SSL/SSL_SOCK_Acceptor.cpp
@@ -0,0 +1,249 @@
+// -*- C++ -*-
+//
+// $Id$
+
+
+#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"
+
+#if !defined (__ACE_INLINE__)
+#include "SSL_SOCK_Acceptor.i"
+#endif /* __ACE_INLINE__ */
+
+ACE_RCSID (ACE_SSL,
+ SSL_SOCK_Acceptor,
+ "$Id$")
+
+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
diff --git a/ACE/ace/SSL/SSL_SOCK_Acceptor.h b/ACE/ace/SSL/SSL_SOCK_Acceptor.h
new file mode 100644
index 00000000000..0428365a753
--- /dev/null
+++ b/ACE/ace/SSL/SSL_SOCK_Acceptor.h
@@ -0,0 +1,198 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file SSL_SOCK_Acceptor.h
+ *
+ * $Id$
+ *
+ * @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.i"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_SSL_SOCK_ACCEPTOR_H */
diff --git a/ACE/ace/SSL/SSL_SOCK_Acceptor.i b/ACE/ace/SSL/SSL_SOCK_Acceptor.i
new file mode 100644
index 00000000000..7fd8cb04095
--- /dev/null
+++ b/ACE/ace/SSL/SSL_SOCK_Acceptor.i
@@ -0,0 +1,85 @@
+// -*- C++ -*-
+//
+// $Id$
+
+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
diff --git a/ACE/ace/SSL/SSL_SOCK_Connector.cpp b/ACE/ace/SSL/SSL_SOCK_Connector.cpp
new file mode 100644
index 00000000000..41e00ff6f4a
--- /dev/null
+++ b/ACE/ace/SSL/SSL_SOCK_Connector.cpp
@@ -0,0 +1,411 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#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 <openssl/err.h>
+
+#if !defined (__ACE_INLINE__)
+#include "SSL_SOCK_Connector.i"
+#endif /* __ACE_INLINE__ */
+
+ACE_RCSID (ACE_SSL,
+ SSL_SOCK_Connector,
+ "$Id$")
+
+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
diff --git a/ACE/ace/SSL/SSL_SOCK_Connector.h b/ACE/ace/SSL/SSL_SOCK_Connector.h
new file mode 100644
index 00000000000..702dbbf82ec
--- /dev/null
+++ b/ACE/ace/SSL/SSL_SOCK_Connector.h
@@ -0,0 +1,318 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file SSL_SOCK_Connector.h
+ *
+ * $Id$
+ *
+ * @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.i"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_SSL_SOCK_CONNECTOR_H */
diff --git a/ACE/ace/SSL/SSL_SOCK_Connector.i b/ACE/ace/SSL/SSL_SOCK_Connector.i
new file mode 100644
index 00000000000..67b5ef01540
--- /dev/null
+++ b/ACE/ace/SSL/SSL_SOCK_Connector.i
@@ -0,0 +1,28 @@
+// -*- C++ -*-
+//
+// $Id$
+
+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
diff --git a/ACE/ace/SSL/SSL_SOCK_Stream.cpp b/ACE/ace/SSL/SSL_SOCK_Stream.cpp
new file mode 100644
index 00000000000..096528e543b
--- /dev/null
+++ b/ACE/ace/SSL/SSL_SOCK_Stream.cpp
@@ -0,0 +1,586 @@
+// $Id$
+
+#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.i"
+#endif /* __ACE_INLINE__ */
+
+ACE_RCSID (ACE_SSL,
+ SSL_SOCK_Stream,
+ "$Id$")
+
+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)
+ {
+ const ssize_t 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) < 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 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");
+
+ const size_t 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)
+ {
+ const ssize_t data_len = va_arg (argp, ssize_t);
+ const ssize_t 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");
+
+ const size_t 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)
+ {
+ const ssize_t data_len = va_arg (argp, ssize_t);
+ const ssize_t 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 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 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 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 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 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
diff --git a/ACE/ace/SSL/SSL_SOCK_Stream.h b/ACE/ace/SSL/SSL_SOCK_Stream.h
new file mode 100644
index 00000000000..a58d91e7c4b
--- /dev/null
+++ b/ACE/ace/SSL/SSL_SOCK_Stream.h
@@ -0,0 +1,321 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file SSL_SOCK_Stream.h
+ *
+ * $Id$
+ *
+ * @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.i"
+#endif /* __ACE_INLINE__ */
+
+#include /**/ "ace/post.h"
+
+#endif /* ACE_SSL_SOCK_STREAM_H */
diff --git a/ACE/ace/SSL/SSL_SOCK_Stream.i b/ACE/ace/SSL/SSL_SOCK_Stream.i
new file mode 100644
index 00000000000..352aca04b3e
--- /dev/null
+++ b/ACE/ace/SSL/SSL_SOCK_Stream.i
@@ -0,0 +1,323 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#include "ace/OS_NS_errno.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);
+
+ const int bytes_sent = ::SSL_write (this->ssl_,
+ static_cast<const char *> (buf),
+ 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;
+ const ACE_HANDLE 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),
+ n);
+ else
+ ACE_NOTSUP_RETURN (-1);
+ }
+ else
+ {
+ bytes_read = ::SSL_read (this->ssl_,
+ static_cast<char *> (buf),
+ n);
+ }
+
+ const int 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.
+ const int 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
diff --git a/ACE/ace/SSL/ssl.mpc b/ACE/ace/SSL/ssl.mpc
new file mode 100644
index 00000000000..5234547fc09
--- /dev/null
+++ b/ACE/ace/SSL/ssl.mpc
@@ -0,0 +1,12 @@
+// -*- MPC -*-
+// $Id$
+
+project(SSL) : acelib, core, ace_openssl {
+ requires += ssl
+ sharedname = ACE_SSL
+ dynamicflags = ACE_SSL_BUILD_DLL
+
+ pkgconfig_files {
+ ACE_SSL.pc.in
+ }
+}
diff --git a/ACE/ace/SSL/sslconf.h b/ACE/ace/SSL/sslconf.h
new file mode 100644
index 00000000000..0824ea05e1b
--- /dev/null
+++ b/ACE/ace/SSL/sslconf.h
@@ -0,0 +1,55 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file sslconf.h
+ *
+ * $Id$
+ *
+ * @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 */