diff options
author | jwh1 <jwh1@ae88bc3d-4319-0410-8dbf-d08b4c9d3795> | 1999-07-21 21:26:37 +0000 |
---|---|---|
committer | jwh1 <jwh1@ae88bc3d-4319-0410-8dbf-d08b4c9d3795> | 1999-07-21 21:26:37 +0000 |
commit | cf4b3d804c96942b14d6a247827eb39d027fd208 (patch) | |
tree | c9dc6f60aad359c7a845c97a7c32ce62a7a3c1d1 | |
parent | aff4123c1793ff5d244f33b9836064395ca4574c (diff) | |
download | ATCD-cf4b3d804c96942b14d6a247827eb39d027fd208.tar.gz |
*** empty log message ***
-rw-r--r-- | ace/Secure_SOCK_Acceptor.cpp | 165 | ||||
-rw-r--r-- | ace/Secure_SOCK_Acceptor.h | 125 | ||||
-rw-r--r-- | ace/Secure_SOCK_Connector.cpp | 251 | ||||
-rw-r--r-- | ace/Secure_SOCK_Connector.h | 186 | ||||
-rw-r--r-- | ace/Secure_SOCK_Stream.cpp | 777 | ||||
-rw-r--r-- | ace/Secure_SOCK_Stream.h | 204 |
6 files changed, 1708 insertions, 0 deletions
diff --git a/ace/Secure_SOCK_Acceptor.cpp b/ace/Secure_SOCK_Acceptor.cpp new file mode 100644 index 00000000000..d164e4f0671 --- /dev/null +++ b/ace/Secure_SOCK_Acceptor.cpp @@ -0,0 +1,165 @@ +// Secure_SOCK_Acceptor.cpp +// $Id$ +#define ACE_BUILD_DLL +#include "Secure_SOCK_Acceptor.h" + +#define ACE_HAS_OPENSSL +#if defined (ACE_HAS_OPENSSL) + +#include <ace/Synch.h> +#include <openssl/err.h> + +ACE_ALLOC_HOOK_DEFINE(ACE_Secure_SOCK_Acceptor) + +// Do nothing routine for constructor. + +ACE_Secure_SOCK_Acceptor::ACE_Secure_SOCK_Acceptor (void) +{ + ACE_TRACE ("ACE_Secure_SOCK_Acceptor::ACE_Secure_SOCK_Acceptor"); +} + +ACE_Secure_SOCK_Acceptor::ACE_Secure_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_Secure_SOCK_Acceptor::ACE_Secure_SOCK_Acceptor"); +} +// Performs the timed accept operation. + +ACE_Secure_SOCK_Acceptor::ACE_Secure_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 = ACE_DEFAULT_BACKLOG, + int protocol = 0) + : acceptor_ (local_sap, protocolinfo, g, flags, reuse_addr, protocol_family, backlog, protocol) +{ + ACE_TRACE ("ACE_Secure_SOCK_Acceptor::ACE_Secure_SOCK_Acceptor"); +} + +int +ACE_Secure_SOCK_Acceptor::open (const ACE_Addr &local_sap, + int reuse_addr, + int protocol_family, + int backlog, + int protocol) +{ + ACE_TRACE ("ACE_Secure_SOCK_Acceptor::open"); + return acceptor_.open (local_sap, + reuse_addr, + protocol_family, + backlog, + protocol); +} + +ACE_Secure_SOCK_Acceptor::~ACE_Secure_SOCK_Acceptor (void) +{ + ACE_TRACE ("ACE_Secure_SOCK_Acceptor::~ACE_Secure_SOCK_Acceptor"); +} + +// General purpose routine for accepting new connections. +int +ACE_Secure_SOCK_Acceptor::accept (ACE_Secure_SOCK_Stream &new_stream, + ACE_Addr *remote_addr, + ACE_Time_Value *timeout, + int restart, + int reset_new_handle) const +{ + ACE_TRACE ("ACE_Secure_SOCK_Acceptor::accept"); + shared_ssl_init_one (new_stream); + if (acceptor_.accept (new_stream.peer (), + remote_addr, + timeout, + restart, + reset_new_handle) == -1) { + return -1; + } + return shared_ssl_init_two (new_stream); +} + +int +ACE_Secure_SOCK_Acceptor::accept (ACE_Secure_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_Secure_SOCK_Acceptor::accept"); + shared_ssl_init_one (new_stream); + if (acceptor_.accept (new_stream.peer (), + qos_params, + remote_addr, + timeout, + restart, + reset_new_handle) == -1) { + return -1; + } + return shared_ssl_init_two (new_stream); +} + +int +ACE_Secure_SOCK_Acceptor::get_local_addr (ACE_Addr &addr) const +{ + ACE_TRACE ("ACE_SECURE_SOCK_Acceptor::get_local_addr"); + return acceptor_.get_local_addr (addr); +} + +void +ACE_Secure_SOCK_Acceptor::dump (void) const +{ + ACE_TRACE ("ACE_Secure_SOCK_Acceptor::dump"); + acceptor_.dump (); +} + +#define HOME "./" +/* Make these what you want for cert & key files */ +#define CERTF HOME "jwh1.cert" +#define KEYF HOME "key" + +#define CHK_NULL(x) if ((x)==NULL) exit (1) +#define CHK_ERR(err,s) if ((err)==-1) { perror(s); exit(1); } +#define CHK_SSL(err) if ((err)==-1) { ERR_print_errors_fp(stderr); exit(2);} + +int +ACE_Secure_SOCK_Acceptor::shared_ssl_init_one (ACE_Secure_SOCK_Stream& new_stream) const{ + SSL_load_error_strings (); + SSL_library_init (); + SSL_METHOD* meth = SSLv23_server_method (); + SSL_CTX* ctx = SSL_CTX_new (meth); + if (!ctx) { + ERR_print_errors_fp (stderr); + exit (2); + } + + if (SSL_CTX_use_certificate_file (ctx, CERTF, SSL_FILETYPE_PEM) <= 0) { + ERR_print_errors_fp (stderr); + exit (3); + } + if (SSL_CTX_use_PrivateKey_file (ctx, KEYF, SSL_FILETYPE_PEM) <= 0) { + ERR_print_errors_fp (stderr); + exit(4); + } + + if (!SSL_CTX_check_private_key (ctx)) { + fprintf (stderr,"Private key does not match the certificate public key\n"); + exit (5); + } + + new_stream.session (SSL_new (ctx)); CHK_NULL(new_stream.session ()); + return 0; +} + +int +ACE_Secure_SOCK_Acceptor::shared_ssl_init_two (ACE_Secure_SOCK_Stream& new_stream) const{ + SSL_set_fd (new_stream.session (), new_stream.get_handle ()); + int err = SSL_accept (new_stream.session ()); CHK_SSL (err); + return 0; +} + +#endif /* defined (ACE_HAS_OPENSSL) */ diff --git a/ace/Secure_SOCK_Acceptor.h b/ace/Secure_SOCK_Acceptor.h new file mode 100644 index 00000000000..287d1a27d26 --- /dev/null +++ b/ace/Secure_SOCK_Acceptor.h @@ -0,0 +1,125 @@ +/* -*- C++ -*- */ +// $Id$ + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// Secure_SOCK_Acceptor.h +// +// = AUTHOR +// John Heitmann +// +// ============================================================================ + +#define ACE_HAS_OPENSSL +#if defined (ACE_HAS_OPENSSL) + +#ifndef ACE_SECURE_SOCK_ACCEPTOR_H +#define ACE_SECURE_SOCK_ACCEPTOR_H + +#include "Secure_SOCK_Stream.h" +#include <ace/SOCK_Acceptor.h> + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +class ACE_Export ACE_Secure_SOCK_Acceptor +{ + // = TITLE + // Defines a factory that creates new <ACE_Secure_SOCK_Stream>s passively. + // + // = DESCRIPTION + // The <ACE_Secure_SOCK_Acceptor> has its own <ACE_SOCK_Acceptor> which + // handles virtually all of the socket acceptance. This class is a wrapper + // which only adds the ssl acceptance. +public: + // = Initialization and termination methods. + ACE_Secure_SOCK_Acceptor (void); + // Default constructor. + + ACE_Secure_SOCK_Acceptor (const ACE_Addr &local_sap, + int reuse_addr = 0, + int protocol_family = PF_INET, + int backlog = ACE_DEFAULT_BACKLOG, + int protocol = 0); + // Initiate a passive mode ssl/BSD-style acceptor socket. + // <local_sap> is the address that we-re going to listen for + // connections on. jwh1: can reuse be used w/ ssl? + + ACE_Secure_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 = ACE_DEFAULT_BACKLOG, + int protocol = 0); + // Initialize a passive-mode QoS-enabled acceptor socket. Returns 0 + // on success and -1 on failure. + + int open (const ACE_Addr &local_sap, + int reuse_addr = 0, + int protocol_family = PF_INET, + int backlog = ACE_DEFAULT_BACKLOG, + int protocol = 0); + // Initiate a passive mode ssl/BSD-style acceptor socket. + // <local_sap> is the address that we-re going to listen for + // connections on. jwh1: can reuse be used w/ ssl? + + ~ACE_Secure_SOCK_Acceptor (void); + // Default dtor. + + // = Passive connection <accept> methods. + int accept (ACE_Secure_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_Secure_SOCK_Stream> connection. A <timeout> of 0 + // means block forever, a <timeout> of {0, 0} means poll. <restart> + // == 1 means "restart if interrupted," i.e., if errno == EINTR. + + int accept (ACE_Secure_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; + // Accept a new <ACE_Secure_SOCK_Stream> connection using the RVSP QoS + // information in <qos_params>. A <timeout> of 0 means block + // forever, a <timeout> of {0, 0} means poll. <restart> == 1 means + // "restart if interrupted," i.e., if errno == EINTR. + + + int get_local_addr (ACE_Addr &) const; + // Gets the address which is being listened on. + + // = Meta-type info + typedef ACE_INET_Addr PEER_ADDR; + typedef ACE_Secure_SOCK_Stream PEER_STREAM; + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + +protected: + int shared_ssl_init_one (ACE_Secure_SOCK_Stream& new_stream) const; + // SSL init method which gets called before the socket acceptance. + + int shared_ssl_init_two (ACE_Secure_SOCK_Stream& new_stream) const; + // SSL init method which gets calles after the socket acceptance, + // SSL_accept is called here. + +public: + ACE_SOCK_Acceptor acceptor_; + // The BSD-socket workhorse +}; + +#endif /* ACE_SECURE_SOCK_ACCEPTOR_H */ +#endif /* defined (ACE_HAS_OPENSSL) */ diff --git a/ace/Secure_SOCK_Connector.cpp b/ace/Secure_SOCK_Connector.cpp new file mode 100644 index 00000000000..126cc2eadc7 --- /dev/null +++ b/ace/Secure_SOCK_Connector.cpp @@ -0,0 +1,251 @@ +// Secure_SOCK_Connector.cpp +// $Id$ + +#define ACE_HAS_OPENSSL +#if defined (ACE_HAS_OPENSSL) + +#define ACE_BUILD_DLL + +#include "Secure_SOCK_Connector.h" +#include "ace/Handle_Set.h" +#include "ace/INET_Addr.h" +#include <openssl/err.h> + +#if defined (ACE_LACKS_INLINE_FUNCTIONS) +#include "ace/Secure_SOCK_Connector.i" +#endif /* ACE_LACKS_INLINE_FUNCTIONS */ + +ACE_Secure_SOCK_Connector::ACE_Secure_SOCK_Connector (void) +{ + ACE_TRACE ("ACE_Secure_SOCK_Connector::ACE_Secure_SOCK_Connector"); +} + +ACE_Secure_SOCK_Connector::~ACE_Secure_SOCK_Connector (void) +{ + ACE_TRACE ("ACE_Secure_SOCK_Connector::~ACE_Secure_SOCK_Connector"); +} + +int +ACE_Secure_SOCK_Connector::reset_new_handle (ACE_HANDLE handle) +{ + ACE_TRACE ("ACE_Secure_SOCK_Connector::reset_new_handle"); + connector_.reset_new_handle (handle); +} + +ACE_ALLOC_HOOK_DEFINE(ACE_Secure_SOCK_Connector) + +void +ACE_Secure_SOCK_Connector::dump (void) const +{ + ACE_TRACE ("ACE_Secure_SOCK_Connector::dump"); +} +/* +int +ACE_Secure_SOCK_Connector::shared_connect_start ( + ACE_Secure_SOCK_Stream &new_stream, + ACE_Time_Value *timeout, + const ACE_Addr &local_sap, + int reuse_addr, + int protocol_family, + int protocol) +{ + ACE_TRACE ("ACE_Secure_SOCK_Connector::shared_connect_start"); + return connector_.shared_connect_start (new_stream.peer (), + timeout, + local_sap, + reuse_addr, + protocol_family, + protocol); +} + +int +ACE_Secure_SOCK_Connector::shared_connect_finish ( + ACE_Secure_SOCK_Stream &new_stream, + ACE_Time_Value *timeout, + int result) +{ + ACE_TRACE ("ACE_Secure_SOCK_Connector::shared_connect_finish"); + return connector_.shared_connect_finish (new_stream.peer (), + timeout, + result); + // Never add anything else in here, it will be bypassed. +} +// Actively connect and produce a new ACE_Secure_SOCK_Stream if things go well... +*/ +int +ACE_Secure_SOCK_Connector::connect (ACE_Secure_SOCK_Stream &new_stream, + const ACE_Addr &remote_sap, + ACE_Time_Value *timeout, + const ACE_Addr &local_sap, + int reuse_addr, + int flags, + int perms, + int protocol_family, + int protocol) +{ + ACE_TRACE ("ACE_Secure_SOCK_Connector::connect"); + if (connector_.connect (new_stream.peer (), + remote_sap, + timeout, + local_sap, + reuse_addr, + flags, + perms, + protocol_family, + protocol) == -1) { + return -1; + } + return shared_ssl_init (new_stream); + +} + +int +ACE_Secure_SOCK_Connector::connect (ACE_Secure_SOCK_Stream &new_stream, + const ACE_Addr &remote_sap, + ACE_QoS_Params qos_params, + 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, + int protocol_family, + int protocol) +{ + ACE_TRACE ("ACE_Secure_SOCK_Connector::connect"); + if (connector_.connect (new_stream.peer (), + remote_sap, + qos_params, + timeout, + local_sap, + protocolinfo, + g, + flags, + reuse_addr, + perms, + protocol_family, + protocol) == -1) { + return -1; + } + return shared_ssl_init (new_stream); +} + +// Try to complete a non-blocking connection. + +int +ACE_Secure_SOCK_Connector::complete (ACE_Secure_SOCK_Stream &new_stream, + ACE_Addr *remote_sap, + ACE_Time_Value *tv) +{ + ACE_TRACE ("ACE_Secure_SOCK_Connector::complete"); + if (connector_.complete (new_stream.peer (), + remote_sap, + tv) == -1) { + return -1; + } + else { + //jwh1: Check to see if ssl stuff has completed. + } + return 0; +} + +ACE_Secure_SOCK_Connector::ACE_Secure_SOCK_Connector ( + ACE_Secure_SOCK_Stream &new_stream, + const ACE_Addr &remote_sap, + ACE_Time_Value *timeout, + const ACE_Addr &local_sap, + int reuse_addr, + int flags, + int perms, + int protocol_family, + int protocol) +{ + ACE_TRACE ("ACE_Secure_SOCK_Connector::ACE_Secure_SOCK_Connector"); + + if (this->connect (new_stream, + remote_sap, + timeout, + local_sap, + reuse_addr, + flags, + perms, + protocol_family, + protocol) == -1 + && timeout != 0 + && !(errno == EWOULDBLOCK || errno == ETIME)) + ACE_ERROR ((LM_ERROR, + ASYS_TEXT ("%p\n"), + ASYS_TEXT ( + "ACE_Secure_SOCK_Connector::ACE_Secure_SOCK_Connector" + ))); + + shared_ssl_init (new_stream); + //jwh1: Wrap this in error catching code +} + + + +ACE_Secure_SOCK_Connector::ACE_Secure_SOCK_Connector ( + ACE_Secure_SOCK_Stream &new_stream, + const ACE_Addr &remote_sap, + ACE_QoS_Params qos_params, + ACE_Time_Value *timeout, + const ACE_Addr &local_sap, + ACE_Protocol_Info *protocolinfo = 0, + ACE_SOCK_GROUP g = 0, + u_long flags, + int reuse_addr, + int perms, + int protocol_family, + int protocol) +{ + ACE_TRACE ("ACE_Secure_SOCK_Connector::ACE_Secure_SOCK_Connector"); + + if (this->connect (new_stream, + remote_sap, + qos_params, + timeout, + local_sap, + protocolinfo, + g, + flags, + reuse_addr, + perms, + protocol_family, + protocol) == -1 + && timeout != 0 + && !(errno == EWOULDBLOCK || errno == ETIME)) + ACE_ERROR ((LM_ERROR, + ASYS_TEXT ("%p\n"), + ASYS_TEXT ( + "ACE_Secure_SOCK_Connector::ACE_Secure_SOCK_Connector" + ))); + + shared_ssl_init (new_stream); + //jwh1: Wrap this in error catching code. +} +#define CHK_NULL(x) if ((x)==NULL) exit (1) +#define CHK_ERR(err,s) if ((err)==-1) { perror(s); exit(1); } +#define CHK_SSL(err) if ((err)==-1) { ERR_print_errors_fp(stderr); exit(2);} + +int +ACE_Secure_SOCK_Connector::shared_ssl_init (ACE_Secure_SOCK_Stream& new_stream) +{ + + SSL_library_init(); + SSL_METHOD* meth = SSLv2_client_method(); + SSL_load_error_strings(); + SSL_CTX* ctx = SSL_CTX_new (meth); CHK_NULL(ctx); + + SSL* ssl = SSL_new (ctx); CHK_NULL(ssl); + SSL_set_fd (ssl, new_stream.get_handle ()); + + int err = SSL_connect (ssl); CHK_SSL(err); + + new_stream.session (ssl); + + return err; +} + +#endif /* defined (ACE_HAS_OPENSSL) */ diff --git a/ace/Secure_SOCK_Connector.h b/ace/Secure_SOCK_Connector.h new file mode 100644 index 00000000000..d2126330845 --- /dev/null +++ b/ace/Secure_SOCK_Connector.h @@ -0,0 +1,186 @@ +/* -*- C++ -*- */ +// $Id$ + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// Secure_SOCK_Connector.h +// +// = AUTHOR +// John Heitmann +// +// ============================================================================ + +#define ACE_HAS_OPENSSL +#if defined (ACE_HAS_OPENSSL) + +#ifndef ACE_SECURE_SOCK_CONNECTOR_H +#define ACE_SECURE_SOCK_CONNECTOR_H + +#include "ace/SOCK_Connector.h" +#include "Secure_SOCK_Stream.h" + + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +class ACE_Export ACE_Secure_SOCK_Connector +{ + // = TITLE + // Defines a factory that creates new <ACE_Stream>s actively. + // + // = DESCRIPTION + // The <ACE_SOCK_Connector> doesn't have a socket of its own, + // i.e., it simply "borrows" the one from the ACE_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_SOCK_Connector> from <ACE_SOCK>. A nice side-effect of + // this is that <ACE_SOCK_Connector>'s do not store state so they + // can be used reentrantly in multi-threaded programs. +public: + // = Initialization and termination methods. + ACE_Secure_SOCK_Connector (void); + // Default constructor. + + ACE_Secure_SOCK_Connector (ACE_Secure_SOCK_Stream &new_stream, + const ACE_Addr &remote_sap, + ACE_Time_Value *timeout = 0, + const ACE_Addr &local_sap = ACE_Addr::sap_any, + int reuse_addr = 0, + int flags = 0, + int perms = 0, + int protocol_family = PF_INET, + int protocol = 0); + // Actively connect and produce a <new_stream> if things go well. + // The <remote_sap> is the address that we are trying to connect + // with. The <timeout> is the amount of time to wait to connect. + // If it's 0 then we block indefinitely. If *timeout == {0, 0} then + // the connection is done using non-blocking mode. In this case, if + // the connection can't be made immediately the value of -1 is + // returned with <errno == EWOULDBLOCK>. If *timeout > {0, 0} then + // this is the amount of time to wait before timing out. If the + // time expires before the connection is made <errno == ETIME>. The + // <local_sap> is the value of local address to bind to. If it's + // the default value of <ACE_Addr::sap_any> then the user is letting + // the OS do the binding. If <reuse_addr> == 1 then the + // <local_addr> is reused, even if it hasn't been cleanedup yet. + + ACE_Secure_SOCK_Connector (ACE_Secure_SOCK_Stream &new_stream, + const ACE_Addr &remote_sap, + ACE_QoS_Params qos_params, + 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, + int protocol_family = PF_INET, + int protocol = 0); + // Actively connect and produce a <new_stream> if things go well. + // The <remote_sap> is the address that we are trying to connect + // with. The <qos_params> contains QoS parameters that are passed + // to RSVP. The <timeout> is the amount of time to wait to connect. + // If it's 0 then we block indefinitely. If *timeout == {0, 0} then + // the connection is done using non-blocking mode. In this case, if + // the connection can't be made immediately the value of -1 is + // returned with <errno == EWOULDBLOCK>. If *timeout > {0, 0} then + // this is the amount of time to wait before timing out. If the + // time expires before the connection is made <errno == ETIME>. The + // <local_sap> is the value of local address to bind to. If it's + // the default value of <ACE_Addr::sap_any> then the user is letting + // the OS do the binding. If <reuse_addr> == 1 then the + // <local_addr> is reused, even if it hasn't been cleanedup yet. + + int connect (ACE_Secure_SOCK_Stream &new_stream, + const ACE_Addr &remote_sap, + ACE_Time_Value *timeout = 0, + const ACE_Addr &local_sap = ACE_Addr::sap_any, + int reuse_addr = 0, + int flags = 0, + int perms = 0, + int protocol_family = PF_INET, + int protocol = 0); + // Actively connect and produce a <new_stream> if things go well. + // The <remote_sap> is the address that we are trying to connect + // with. The <timeout> is the amount of time to wait to connect. + // If it's 0 then we block indefinitely. If *timeout == {0, 0} then + // the connection is done using non-blocking mode. In this case, if + // the connection can't be made immediately the value of -1 is + // returned with <errno == EWOULDBLOCK>. If *timeout > {0, 0} then + // this is the amount of time to wait before timing out. If the + // time expires before the connection is made <errno == ETIME>. The + // <local_sap> is the value of local address to bind to. If it's + // the default value of <ACE_Addr::sap_any> then the user is letting + // the OS do the binding. If <reuse_addr> == 1 then the + // <local_addr> is reused, even if it hasn't been cleanedup yet. + + int connect (ACE_Secure_SOCK_Stream &new_stream, + const ACE_Addr &remote_sap, + ACE_QoS_Params qos_params, + 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, + int protocol_family = PF_INET, + int protocol = 0); + // Actively connect and produce a <new_stream> if things go well. + // The <remote_sap> is the address that we are trying to connect + // with. The <qos_params> contains QoS parameters that are passed + // to RSVP. The <timeout> is the amount of time to wait to connect. + // If it's 0 then we block indefinitely. If *timeout == {0, 0} then + // the connection is done using non-blocking mode. In this case, if + // the connection can't be made immediately the value of -1 is + // returned with <errno == EWOULDBLOCK>. If *timeout > {0, 0} then + // this is the amount of time to wait before timing out. If the + // time expires before the connection is made <errno == ETIME>. The + // <local_sap> is the value of local address to bind to. If it's + // the default value of <ACE_Addr::sap_any> then the user is letting + // the OS do the binding. If <reuse_addr> == 1 then the + // <local_addr> is reused, even if it hasn't been cleanedup yet. + + ~ACE_Secure_SOCK_Connector (void); + // Default dtor. + + // = Completion routine. + int complete (ACE_Secure_SOCK_Stream &new_stream, + ACE_Addr *remote_sap = 0, + ACE_Time_Value *timeout = 0); + // Try to complete a non-blocking connection. + // If connection completion is successful then <new_stream> contains + // the connected ACE_SOCK_Stream. If <remote_sap> is non-NULL then it + // will contain the address of the connected peer. + + int reset_new_handle (ACE_HANDLE handle); + // Resets any event associations on this handle + + // = Meta-type info + typedef ACE_INET_Addr PEER_ADDR; + typedef ACE_Secure_SOCK_Stream PEER_STREAM; + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. +protected: + // Perform operations that must be called after <ACE_OS::connect>. + + int shared_ssl_init (ACE_Secure_SOCK_Stream& new_stream); + +private: + ACE_SOCK_Connector connector_; + // The class that does all of the non-secure socket connection. + // It is default contructed, and susequently used by connect(). +}; + +#endif /* ACE_SECURE_SOCK_CONNECTOR_H */ +#endif /* defined (ACE_HAS_OPENSSL) */ diff --git a/ace/Secure_SOCK_Stream.cpp b/ace/Secure_SOCK_Stream.cpp new file mode 100644 index 00000000000..ec959ae6478 --- /dev/null +++ b/ace/Secure_SOCK_Stream.cpp @@ -0,0 +1,777 @@ +// Secure_SOCK_Stream.cpp +// $Id$ +#define ACE_HAS_OPENSSL +#if defined (ACE_HAS_OPENSSL) + +#define ACE_BUILD_DLL +#include "Secure_SOCK_Stream.h" +#include <ace/Handle_Set.h> +#include <openssl/ssl.h> +#include <openssl/err.h> + +#if defined (ACE_LACKS_INLINE_FUNCTIONS) +#include "Secure_SOCK_Stream.i" +#endif + +ACE_ALLOC_HOOK_DEFINE(ACE_Secure_SOCK_Stream) + +ACE_Secure_SOCK_Stream::ACE_Secure_SOCK_Stream (void) +{ + ACE_TRACE ("ACE_Secure_SOCK_Stream::ACE_Secure_SOCK_Stream"); +} + +ACE_Secure_SOCK_Stream::ACE_Secure_SOCK_Stream (ACE_HANDLE h) + : stream_ (h) +{ + ACE_TRACE ("ACE_Secure_SOCK_Stream::ACE_Secure_SOCK_Stream"); +} + +ACE_Secure_SOCK_Stream::~ACE_Secure_SOCK_Stream (void) +{ + ACE_TRACE ("ACE_Secure_SOCK_Stream::~ACE_Secure_SOCK_Stream"); +} + +ssize_t +ACE_Secure_SOCK_Stream::send (const void *buf, + size_t n, + int flags) const +{ + ACE_TRACE ("ACE_Secure_SOCK_Stream::send"); + // No send flags are supported in SSL. + if (flags != 0) + { + ACE_NOTSUP_RETURN (-1); + } + else + return SSL_write (ssl_, ACE_static_cast (const char*, buf), n); +} + +ssize_t +ACE_Secure_SOCK_Stream::recv (void *buf, + size_t n, + int flags) const +{ + ACE_TRACE ("ACE_Secure_SOCK_Stream::recv"); + if (flags != 0) + { + if ((flags | MSG_PEEK) == MSG_PEEK) + return SSL_peek (ssl_, ACE_static_cast (char*, buf), n); + else + ACE_NOTSUP_RETURN (-1); + } + return SSL_read (ssl_, ACE_static_cast (char*, buf), n); +} + +ssize_t +ACE_Secure_SOCK_Stream::send (const void *buf, + size_t n) const +{ + ACE_TRACE ("ACE_Secure_SOCK_Stream::send"); + return SSL_write (ssl_, ACE_static_cast (const char*, buf), n); +} + +ssize_t +ACE_Secure_SOCK_Stream::recv (void *buf, + size_t n) const +{ + ACE_TRACE ("ACE_Secure_SOCK_Stream::recv"); + return SSL_read (ssl_, ACE_static_cast (char*, buf), n); +} + +ssize_t +ACE_Secure_SOCK_Stream::sendv (const iovec iov[], + size_t n) const +{ + ACE_TRACE ("ACE_Secure_SOCK_Stream::sendv"); + + // Mimics ACE_OS::sendv. + int result = 0; + ssize_t bytes_sent = 0; + for (size_t i = 0; i < n && result != -1; i++) + { + result = this->send (iov[i].iov_base, + iov[i].iov_len); + bytes_sent += iov[i].iov_len; // Gets ignored on error anyway + } + + if (result == -1) + return -1; + else + return bytes_sent; +} + +ssize_t +ACE_Secure_SOCK_Stream::send (const iovec iov[], + size_t n) const +{ + ACE_TRACE ("ACE_Secure_SOCK_Stream::send"); + return this->sendv (iov, n); +} + +ssize_t +ACE_Secure_SOCK_Stream::recvv (iovec *io_vec, + const ACE_Time_Value *timeout = 0) const +{ + ACE_TRACE ("ACE_Secure_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; + } + + u_long inlen; + + if (ACE_OS::ioctl (this->get_handle (), + FIONREAD, + (u_long *) &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_Secure_SOCK_Stream::recv (iovec *io_vec, + const ACE_Time_Value *timeout = 0) const +{ + ACE_TRACE ("ACE_Secure_SOCK_Stream::recv"); + return this->recvv (io_vec, timeout); +} + +ssize_t +ACE_Secure_SOCK_Stream::send (const void *buf, + size_t len, + int flags, + const ACE_Time_Value *timeout) const +{ + ACE_TRACE ("ACE_Secure_SOCK_Stream::send"); + if (flags !=0) + { + ACE_NOTSUP_RETURN (-1); + } + // Mimics <ACE::send>. + if (timeout == 0) + return this->send (buf, len); + + int val; + if (this->enter_send_timedwait (timeout, val) == -1) + return -1; + ssize_t bytes_written = this->send (buf, len); + this->leave_send_timedwait (timeout, val); + return bytes_written; +} + +ssize_t +ACE_Secure_SOCK_Stream::recv (void *buf, + size_t n, + int flags, + const ACE_Time_Value *timeout) const +{ + ACE_TRACE ("ACE_Secure_SOCK_Stream::recv"); + // Mimics code in <ACE::recv>. + int peek; + if (flags != 0) + { + if ((flags | MSG_PEEK) == MSG_PEEK) + peek = 1; + else + ACE_NOTSUP_RETURN (-1); + } + if (timeout == 0) + return this->recv (buf, n, flags); + int val = 0; + if (this->enter_recv_timedwait (timeout, val) == -1) + return -1; + ssize_t bytes_recv = this->recv (buf, n, flags); + this->leave_recv_timedwait (timeout, val); + return bytes_recv; +} + +ssize_t +ACE_Secure_SOCK_Stream::send (const void *buf, + size_t len, + const ACE_Time_Value *timeout) const +{ + ACE_TRACE ("ACE_Secure_SOCK_Stream::send"); + return this->send (buf, len, 0, timeout); +} + +ssize_t +ACE_Secure_SOCK_Stream::recv (void *buf, + size_t n, + const ACE_Time_Value *timeout) const +{ + ACE_TRACE ("ACE_Secure_SOCK_Stream::recv"); + return this->recv (buf, n, 0, timeout); +} + +ssize_t +ACE_Secure_SOCK_Stream::send (size_t n, + ...) const +{ + ACE_TRACE ("ACE_Secure_SOCK_Stream::send"); + + // Mimics <ACE_SOCK_IO::send (...)>. + va_list argp; + size_t total_tuples = n / 2; + iovec *iovp; +#if defined (ACE_HAS_ALLOCA) + iovp = (iovec *) alloca (total_tuples * sizeof (iovec)); +#else + ACE_NEW_RETURN (iovp, + iovec[total_tuples], + -1); +#endif /* !defined (ACE_HAS_ALLOCA) */ + + va_start (argp, n); + + for (size_t i = 0; i < total_tuples; i++) + { + iovp[i].iov_base = va_arg (argp, char *); + iovp[i].iov_len = va_arg (argp, ssize_t); + } + + ssize_t result = this->sendv (iovp, + total_tuples); +#if !defined (ACE_HAS_ALLOCA) + delete [] iovp; +#endif /* !defined (ACE_HAS_ALLOCA) */ + va_end (argp); + return result; +} + +ssize_t +ACE_Secure_SOCK_Stream::recv (size_t n, + ...) const +{ + ACE_TRACE ("ACE_Secure_SOCK_Stream::recv"); + va_list argp; + size_t total_tuples = n / 2; + iovec *iovp; +#if defined (ACE_HAS_ALLOCA) + iovp = (iovec *) alloca (total_tuples * sizeof (iovec)); +#else + ACE_NEW_RETURN (iovp, + iovec[total_tuples], + -1); +#endif /* !defined (ACE_HAS_ALLOCA) */ + + va_start (argp, n); + + for (size_t i = 0; i < total_tuples; i++) + { + iovp[i].iov_base = va_arg (argp, char *); + iovp[i].iov_len = va_arg (argp, ssize_t); + } + + ssize_t result = this->recvv (iovp,0); +#if !defined (ACE_HAS_ALLOCA) + delete [] iovp; +#endif /* !defined (ACE_HAS_ALLOCA) */ + va_end (argp); + return result; +} + +ssize_t +ACE_Secure_SOCK_Stream::send_n (const void *buf, size_t len, int flags, + const ACE_Time_Value *timeout) const +{ + ACE_TRACE ("ACE_Secure_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 bytes_written; + + // Actual number of bytes written in each <send> attempt + ssize_t n; + + for (bytes_written = 0; + bytes_written < len; + bytes_written += n) + { + n = this->send ((const char*) buf + bytes_written, + len - bytes_written, + flags, + timeout); + if (n == -1) + if (errno == EWOULDBLOCK) + n = 0; // Keep trying to send + else + return -1; + } + return bytes_written; +} + +ssize_t +ACE_Secure_SOCK_Stream::recv_n (void *buf, size_t len, int flags, + const ACE_Time_Value *timeout) const +{ + ACE_TRACE ("ACE_Secure_SOCK_Stream::recv_n"); + if (flags != 0) + { + if ((flags | MSG_PEEK) != MSG_PEEK) + ACE_NOTSUP_RETURN (-1); + } + size_t bytes_received; + + ssize_t n; + + for (bytes_received = 0; + bytes_received < len; + bytes_received += n) + { + n = this->recv ((char*) buf + bytes_received, + len - bytes_received, + flags, + timeout); + if (n == -1 || n == 0) + break; + } + + return bytes_received; +} + +ssize_t +ACE_Secure_SOCK_Stream::recv_n (void *buf, int len, int flags) const +{ + ACE_TRACE ("ACE_Secure_SOCK_Stream::recv_n"); + if (flags != 0) + { + if ((flags | MSG_PEEK) != MSG_PEEK) + ACE_NOTSUP_RETURN (-1); + } + ssize_t bytes_received; + + ssize_t n; + + for (bytes_received = 0; + bytes_received < len; + bytes_received += n) + { + n = this->recv ((char*) buf + bytes_received, + len - bytes_received, + flags); + if (n == -1) + { + if (errno == EWOULDBLOCK) + n = 0; //Keep trying + else + return -1; + } + else if (n == 0) + break; + } + + return bytes_received; +} + +ssize_t +ACE_Secure_SOCK_Stream::send_n (const void *buf, int len, int flags) const +{ + ACE_TRACE ("ACE_Secure_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_written; + ssize_t n; + + for (bytes_written = 0; + bytes_written < (size_t) len; + bytes_written += n) + { + n = this->send ((const char*) buf + bytes_written, + len - bytes_written, + flags); + if (n == -1) + { + if (errno == EWOULDBLOCK) + n = 0; //Keep trying to send. + else + return -1; + } + } + return bytes_written; +} + +ssize_t +ACE_Secure_SOCK_Stream::recv_n (void *buf, int buf_size) const +{ + ACE_TRACE ("ACE_Secure_SOCK_Stream::recv_n"); + return this->recv_n (buf, buf_size, 0); +} + +//jwh1: default this? +ssize_t +ACE_Secure_SOCK_Stream::send_n (const void *buf, int len) const +{ + ACE_TRACE ("ACE_Secure_SOCK_Stream::send_n"); + return this->send_n (buf, len, 0); +} + +//Taken from OS.cpp, writev () +ssize_t +ACE_Secure_SOCK_Stream::sendv_n (const iovec iov[], size_t n) const +{ + ACE_TRACE ("ACE_Secure_SOCK_Stream::sendv_n"); + size_t length = 0; + size_t i; + + // Determine the total length of all the buffers in <iov>. + for (i = 0; i < n; i++) + if (ACE_static_cast (int, iov[i].iov_len) < 0) + return -1; + else + length += iov[i].iov_len; + + char *buf; + +# if defined (ACE_HAS_ALLOCA) + buf = (char *) alloca (length); +# else + ACE_NEW_RETURN (buf, + char[length], + -1); +# endif /* !defined (ACE_HAS_ALLOCA) */ + + char *ptr = buf; + + for (i = 0; i < n; i++) + { + ACE_OS::memcpy (ptr, iov[i].iov_base, iov[i].iov_len); + ptr += iov[i].iov_len; + } + + ssize_t result = this->send_n (buf, length); +# if !defined (ACE_HAS_ALLOCA) + delete [] buf; +# endif /* !defined (ACE_HAS_ALLOCA) */ + return result; +} + +// Taken straight from OS.cpp, readv () +ssize_t +ACE_Secure_SOCK_Stream::recvv_n (iovec iov[], size_t n) const +{ + ACE_TRACE ("ACE_Secure_SOCK_Stream::recvv_n"); + ssize_t length = 0; + size_t i; + + for (i = 0; i < n; i++) + if (ACE_static_cast (int, iov[i].iov_len) < 0) + return -1; + else + length += iov[i].iov_len; + + char *buf; +# if defined (ACE_HAS_ALLOCA) + buf = (char *) alloca (length); +# else + ACE_NEW_RETURN (buf, + char[length], + -1); +# endif /* !defined (ACE_HAS_ALLOCA) */ + + length = this->recv_n (buf, length); + + if (length != -1) + { + char *ptr = buf; + int copyn = length; + + for (i = 0; + i < n && copyn > 0; + i++) + { + ACE_OS::memcpy (iov[i].iov_base, ptr, + // iov_len is int on some platforms, size_t on others + copyn > (int) iov[i].iov_len + ? (size_t) iov[i].iov_len + : (size_t) copyn); + ptr += iov[i].iov_len; + copyn -= iov[i].iov_len; + } + } + +# if !defined (ACE_HAS_ALLOCA) + delete [] buf; +# endif /* !defined (ACE_HAS_ALLOCA) */ + return length; +} + +int +ACE_Secure_SOCK_Stream::close_reader (void) +{ + ACE_TRACE ("ACE_Secure_SOCK_Stream::close_reader"); + return stream_.close_reader (); +} + +int +ACE_Secure_SOCK_Stream::close_writer (void) +{ + ACE_TRACE ("ACE_Secure_SOCK_Stream::close_writer"); + return stream_.close_writer (); +} + +int +ACE_Secure_SOCK_Stream::close (void) +{ + ACE_TRACE ("ACE_Secure_SOCK_Stream::close"); + SSL_free (ssl_); + return stream_.close (); +} + +void +ACE_Secure_SOCK_Stream::dump (void) const +{ + ACE_TRACE ("ACE_Secure_SOCK_Stream::dump"); + stream_.dump (); +} + +ACE_SOCK_Stream& +ACE_Secure_SOCK_Stream::peer () { + return stream_; +} + +int +ACE_Secure_SOCK_Stream::set_option (int level, + int option, + void *optval, + int optlen) const +{ + ACE_TRACE ("ACE_Secure_SOCK_Stream::set_option"); + return stream_.set_option (level, option, optval, optlen); +} + +int +ACE_Secure_SOCK_Stream::get_option (int level, + int option, + void *optval, + int *optlen) const +{ + ACE_TRACE ("ACE_Secure_SOCK_Stream::get_option"); + return stream_.get_option (level, option, optval, optlen); +} + +int +ACE_Secure_SOCK_Stream::get_local_addr (ACE_Addr &addr) const +{ + ACE_TRACE ("ACE_Secure_SOCK_Stream::get_local_addr"); + return stream_.get_local_addr (addr); +} + +int +ACE_Secure_SOCK_Stream::get_remote_addr (ACE_Addr &addr) const +{ + ACE_TRACE ("ACE_Secure_SOCK_Stream::get_remote_addr"); + return stream_.get_remote_addr (addr); +} + +void +ACE_Secure_SOCK_Stream::session (SSL* ssl) { + ssl_ = ssl; +} +SSL* +ACE_Secure_SOCK_Stream::session () const { + return ssl_; +} + +ACE_HANDLE +ACE_Secure_SOCK_Stream::get_handle (void) const +{ + return stream_.get_handle (); +} + +void +ACE_Secure_SOCK_Stream::set_handle (ACE_HANDLE handle) +{ + stream_.set_handle (handle); +} + + +// The following four functions are copied straight from ACE::, I may +// specialize them, or make this class a friend of ACE instead. +int +ACE_Secure_SOCK_Stream::enter_recv_timedwait (const ACE_Time_Value *timeout, + int &val) const +{ + // Give value a default value to keep Purify happy! + val = 0; + ACE_HANDLE handle = this->get_handle (); +#if defined (ACE_HAS_POLL) && defined (ACE_HAS_LIMITED_SELECT) + + struct pollfd fds; + + fds.fd = handle; + fds.events = POLLIN; + fds.revents = 0; + + int a = ACE_OS::poll (&fds, 1, *timeout); + +#else + ACE_Handle_Set handle_set; + handle_set.set_bit (handle); + + // Wait for input to arrive or for the timeout to elapse. + int a = ACE_OS::select (int (handle) + 1, + (fd_set *) handle_set, // read_fds. + (fd_set *) 0, // write_fds. + (fd_set *) 0, // exception_fds. + timeout); +#endif /* ACE_HAS_POLL && ACE_HAS_LIMITED_SELECT */ + + switch ( a ) + { + case 0: // Timer expired. return -1 + errno = ETIME; + /* FALLTHRU */ + case -1: // we got here directly - select() returned -1. + return -1; + case 1: // OK to read now. + /* FALLTHRU */ + default: // default is case a > 0; return a + // really should assert if a != 1 + //assert( a == 1 ); + // We need to record whether we are already *in* nonblocking + // mode, so that we can correctly reset the state when we're + // done. + val = ACE::get_flags (handle); + + if (ACE_BIT_DISABLED (val, ACE_NONBLOCK)) + // Set the handle into non-blocking mode if it's not + // already in it. + ACE::set_flags (handle, ACE_NONBLOCK); + return a; + } +} + +void +ACE_Secure_SOCK_Stream::leave_recv_timedwait (const ACE_Time_Value *timeout, + int val) const +{ + if (timeout != 0 + && ACE_BIT_DISABLED (val, + ACE_NONBLOCK)) + { + // Save/restore errno. + ACE_Errno_Guard error (errno); + // Only disable ACE_NONBLOCK if we weren't in non-blocking mode + // originally. + ACE::clr_flags (this->get_handle (), ACE_NONBLOCK); + } +} + +int +ACE_Secure_SOCK_Stream::enter_send_timedwait (const ACE_Time_Value* timeout, + int &val) const +{ + // Give value a default value to keep Purify happy! + val = 0; + ACE_HANDLE handle = this->get_handle (); +#if defined (ACE_HAS_POLL) && defined (ACE_HAS_LIMITED_SELECT) + + struct pollfd fds; + + fds.fd = handle; + fds.events = POLLOUT; + fds.revents = 0; + + int a = ACE_OS::poll (&fds, 1, *timeout); + +#else + ACE_Handle_Set handle_set; + handle_set.set_bit (handle); + + // On timed writes we always go into select(); only if the + // handle is available for writing within the specified amount + // of time do we put it in non-blocking mode + + int a = ACE_OS::select (int (handle) + 1, + (fd_set *) 0, + (fd_set *) handle_set, + (fd_set *) 0, + timeout); +#endif /* ACE_HAS_POLL && ACE_HAS_LIMITED_SELECT */ + + switch ( a ) + { + case 0: // Timer expired. + errno = ETIME; + /* FALLTHRU */ + case -1: // we got here directly - select() returned -1. + return -1; + case 1: // Ok to write now. + /* FALLTHRU */ + default: // default is case a > 0; return a + // really should assert if a != 1 + //assert( a == 1 ); + // We need to record whether we are already *in* nonblocking + // mode, so that we can correctly reset the state when we're + // done. + val = ACE::get_flags (handle); + + if (ACE_BIT_DISABLED (val, ACE_NONBLOCK)) + // Set the handle into non-blocking mode if it's not + // already in it. + ACE::set_flags (handle, ACE_NONBLOCK); + return a; + } +} + +void +ACE_Secure_SOCK_Stream::leave_send_timedwait (const ACE_Time_Value *timeout, + int val) const +{ + if (timeout != 0 + && ACE_BIT_DISABLED (val, ACE_NONBLOCK)) + { + // Save/restore errno. + ACE_Errno_Guard error (errno); + // Only disable ACE_NONBLOCK if we weren't in non-blocking mode + // originally. + ACE::clr_flags (this->get_handle (), ACE_NONBLOCK); + } +} + + +#endif /* defined (ACE_HAS_OPENSSL) */ diff --git a/ace/Secure_SOCK_Stream.h b/ace/Secure_SOCK_Stream.h new file mode 100644 index 00000000000..b0b80a9e0f0 --- /dev/null +++ b/ace/Secure_SOCK_Stream.h @@ -0,0 +1,204 @@ +/* -*- C++ -*- */ +// $Id$ + +// ============================================================================ +// +// = LIBRARY +// ace +// +// = FILENAME +// Secure_SOCK_Stream.h +// +// = AUTHOR +// John Heitmann +// +// ============================================================================ +#define ACE_HAS_OPENSSL +#if defined (ACE_HAS_OPENSSL) + +#ifndef ACE_Secure_SOCK_STREAM_H +#define ACE_Secure_SOCK_STREAM_H +#include "ace/SOCK_Stream.h" +#include <openssl/ssl.h> + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +class ACE_Export ACE_Secure_SOCK_Stream +{ + // = TITLE + // Defines methods in the <ACE_Secure_SOCK_Stream> abstraction. + // + // = DESCRIPTION + // This adds ssl functionality to an <ACE_SOCK_IO> interface by + // wrapping around an <ACE_Secure_SOCK_Stream> implementation. + // +public: + // = Initializtion and termination functions. + ACE_Secure_SOCK_Stream (void); + // Constructor + + ACE_Secure_SOCK_Stream (ACE_HANDLE h); + // Constructor (sets the underlying <ACE_HANDLE> with <H>) + + ~ACE_Secure_SOCK_Stream (void); + //Destructor + + ssize_t send (const void *buf, + size_t n, + int flags) const; + + ssize_t recv (void *buf, + size_t n, + int flags) const; + + ssize_t send (const void *buf, + size_t n) const; + + ssize_t recv (void *buf, + size_t n) const; + + ssize_t sendv (const iovec iov[], + size_t n) const; + + ssize_t send (const iovec iov[], + size_t n) const; + + ssize_t recvv (iovec *io_vec, + const ACE_Time_Value *timeout = 0) const; + + ssize_t recv (iovec *io_vec, + const ACE_Time_Value *timeout = 0) const; + + ssize_t send (const void *buf, + size_t n, + int flags, + const ACE_Time_Value *timeout) const; + + ssize_t recv (void *buf, + size_t n, + int flags, + const ACE_Time_Value *timeout) const; + + ssize_t send (const void *buf, + size_t n, + const ACE_Time_Value *timeout) const; + + ssize_t recv (void *buf, + size_t n, + const ACE_Time_Value *timeout) const; + + ssize_t send (size_t n, + ...) const; + // Send <n> varargs messages to the connected socket. + + ssize_t recv (size_t n, + ...) const; + // Recv <n> varargs messages to the connected socket. + + // = The following methods all use <SSL_read (SSL*, char*)> + // and <SSL_write (SSL*, char*)> + ssize_t send_n (const void *buf, int n) const; + // Send n bytes, with blocking. + + ssize_t recv_n (void *buf, int n) const; + // Recv n bytes, with blocking. + + ssize_t send_n (const void *buf, int n, int flags) const; + // Send n bytes, with blocking. + + ssize_t recv_n (void *buf, int n, int flags) const; + // Recv n bytes, with blocking. + + ssize_t send_n (const void *buf, + size_t len, + int flags, + const ACE_Time_Value *timeout) const; + // Try to send n bytes, + // jwh1: figure out timeout semantics. + + ssize_t recv_n (void *buf, + size_t len, + int flags, + const ACE_Time_Value *timeout) const; + // Try to send n bytes. + // jwh1: figure out timeout semantics. + + ssize_t sendv_n (const iovec iov[], + size_t n) const; + // Send an <iovec> of size <n>, will block until finished. + + ssize_t recvv_n (iovec iov[], + size_t n) const; + // Recv an <iovec> of size <n>, will block until finished. + + + // = Selectively close endpoints. + int close_reader (void); + // Close down the reader. + // jwh1: is this undefined with ssl? + + int close_writer (void); + // Close down the writer. + // jwh1: is this undefined with ssl? + + int close (void); + //Close down the socket and jwh1: ? free the SSL session. + + // = Meta-type info + typedef ACE_INET_Addr PEER_ADDR; + + void dump (void) const; + // Dump the state of an object. + + ACE_ALLOC_HOOK_DECLARE; + // Declare the dynamic allocation hooks. + + // = Accessor methods + //jwh1: Make me private. + ACE_SOCK_Stream& peer (); + // Return the underlying <ACE_SOCK_Stream> which ssl runs on top of. + + int set_option (int level, + int option, + void *optval, + int optlen) const; + // Wrapper around the setsockopt() system call. + + int get_option (int level, + int option, + void *optval, + int *optlen) const; + // Wrapper around the getsockopt() system call. + + int get_local_addr (ACE_Addr &) const; + // Return the local endpoint address in the referenced <ACE_Addr>. + + int get_remote_addr (ACE_Addr &) const; + // Return the address of the remotely connected peer (if there is + // one), in the referenced ACE_Addr. Returns 0 if successful, else -1. + + // = Accessors for the SSL* session + void session (SSL*); + SSL* session () const; + + ACE_HANDLE get_handle (void) const; + // Get the underlying handle + + void set_handle (ACE_HANDLE handle); + // Set the underlying handle +private: + int enter_recv_timedwait (const ACE_Time_Value* timeout, int& val) const; + void leave_recv_timedwait (const ACE_Time_Value* timeout, int val) const; + int enter_send_timedwait (const ACE_Time_Value* timeout, int& val) const; + void leave_send_timedwait (const ACE_Time_Value* timeout, int val) const; + + ACE_SOCK_Stream stream_; + // The stream which works under the ssl connection. + SSL* ssl_; + // The ssl data structure itself. +}; + +#endif /* ACE_SECURE_SOCK_STREAM_H */ +#endif /* defined (ACE_HAS_OPENSSL) */ |