123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329 |
- //#ifdef USE_SSL
- //#include "netinc.h"
- //#include "util.h"
- //#include "connection.h"
- #include "wac_network_ssl_connection.h"
- SSL_CTX *sslContext = 0;
- #ifdef _DEBUG
- extern "C" void apps_ssl_info_callback( const SSL * s, int where, int ret )
- {
- /*
- ** DEBUG INFO HERE
- */
- }
- #endif
- /*
- ** Well, you should probably change this based on like...
- ** well, you're level of trust heh
- ** For now, this basically trusts all certs :)
- **
- */
- #if 0
- extern "C" int verify_callback( int ok, X509_STORE_CTX * ctx )
- {
- /* For certificate verification */
- int verify_depth = 0;
- int verify_error = X509_V_OK;
- char buf[ 1024 ] = { 0 };
- X509 *err_cert = X509_STORE_CTX_get_current_cert( ctx );
- int err = X509_STORE_CTX_get_error( ctx );
- int depth = X509_STORE_CTX_get_error_depth( ctx );
- X509_NAME_oneline( X509_get_subject_name( err_cert ), buf, sizeof( buf ) );
- if ( !ok )
- {
- if ( verify_depth >= depth )
- {
- ok = 1;
- verify_error = X509_V_OK;
- }
- else
- {
- ok = 0;
- verify_error = X509_V_ERR_CERT_CHAIN_TOO_LONG;
- }
- }
- switch ( ctx->error )
- {
- case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
- X509_NAME_oneline( X509_get_issuer_name( ctx->current_cert ), buf, sizeof( buf ) );
- break;
- case X509_V_ERR_CERT_NOT_YET_VALID:
- case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
- break;
- case X509_V_ERR_CERT_HAS_EXPIRED:
- case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
- break;
- }
- return ok;
- }
- #endif
- JNL_SSL_Connection::JNL_SSL_Connection() : forceConnect( false ), m_ssl( 0 ), m_bsslinit( false ), m_bcontextowned( true )
- {
- m_bsslinit = true;
- }
- JNL_SSL_Connection::JNL_SSL_Connection( SSL *pssl, api_dns *dns, size_t sendbufsize, size_t recvbufsize ) : WAC_Network_Connection( dns, sendbufsize, recvbufsize ), forceConnect( false )
- {
- m_ssl = pssl;
- m_bsslinit = false;
- if ( m_ssl )
- {
- m_bcontextowned = false;
- }
- else
- {
- m_bcontextowned = true;
- }
- if ( m_bcontextowned == false )
- {
- return;
- }
- m_bsslinit = true;
- /* See the SSL states in our own callback */
- #ifdef _DEBUG
- // SSL_CTX_set_info_callback(m_app_ctx, apps_ssl_info_callback);
- #endif
- /* Set the certificate verification callback */
- //SSL_CTX_set_verify(sslContext, SSL_VERIFY_PEER, verify_callback);
- /* Not sure what this does */
- //SSL_CTX_set_session_cache_mode(sslContext, SSL_SESS_CACHE_CLIENT);
- return;
- }
- int JNL_SSL_Connection::socket_connect()
- {
- int retval;
- if ( m_bcontextowned == false )
- {
- /*
- ** WTF?
- */
- return -1;
- }
- if ( m_ssl != NULL )
- {
- return -1;
- }
- retval = WAC_Network_Connection::socket_connect();
- if ( retval != 0 )
- {
- if ( ERRNO != EINPROGRESS )
- {
- return retval; // benski> if the underlying socket hasn't connected yet, then we can't start the SSL connection
- /*
- ** Joshua Teitelbaum 3/2/2006
- ** Fatal error here
- */
- }
- }
- // moved from InitSSL() as no need to create this unless
- // we're actually going to use it which helps slow loads
- if ( !sslContext )
- {
- sslContext = SSL_CTX_new( SSLv23_client_method() );
- if ( sslContext )
- {
- SSL_CTX_set_verify( sslContext, SSL_VERIFY_NONE, NULL );
- }
- else
- {
- return -1;
- }
- }
- m_ssl = SSL_new( sslContext );
- if ( m_ssl == NULL )
- {
- return -1;
- }
- /* Tell that we are in connect mode */
- SSL_set_connect_state( m_ssl );
- /* Set socket descriptor with the socket we already have open */
- if ( SSL_set_fd( m_ssl, m_socket ) != 0 )
- return -1;
- return retval;
- }
- void JNL_SSL_Connection::socket_shutdown()
- {
- if ( m_ssl )
- SSL_shutdown( m_ssl );
- WAC_Network_Connection::socket_shutdown();
- if ( m_ssl )
- {
- SSL_free( m_ssl );
- m_ssl = NULL;
- }
- return;
- }
- void JNL_SSL_Connection::run( size_t max_send_bytes, size_t max_recv_bytes, size_t *bytes_sent, size_t *bytes_rcvd )
- {
- if ( !m_bsslinit )
- {
- int rval = SSL_accept( m_ssl );
- if ( rval == -1 )
- {
- int e = SSL_get_error( m_ssl, rval );
- if ( !( ( e == SSL_ERROR_WANT_READ ) || ( e == SSL_ERROR_WANT_WRITE ) ) )
- {
- m_state = STATE_ERROR;
- }
- return;
- }
- else
- {
- m_bsslinit = true;
- }
- }
- /**
- ** benski - march 2, 2006
- **if the underlying socket didn't connected yet, we need to try the SSL connection again
- */
- if ( forceConnect )
- {
- if ( init_ssl_connection() == false )
- {
- return;
- }
- }
- WAC_Network_Connection::run( max_send_bytes, max_recv_bytes, bytes_sent, bytes_rcvd );
- }
- /*
- ** init_ssl_connection:
- ** Returns true, meaning can continue
- ** Else, cannot continue with underlying run
- ** side effects:
- ** sets forceConnect
- */
- bool JNL_SSL_Connection::init_ssl_connection()
- {
- if ( m_ssl == NULL )
- {
- /*
- ** WTF?
- ** cascade up.
- */
- return true;
- }
- int retval = SSL_connect( m_ssl );
- if ( retval < 0 )
- {
- int err = SSL_get_error( m_ssl, retval );
- switch ( err )
- {
- case SSL_ERROR_WANT_READ:
- case SSL_ERROR_WANT_WRITE:
- case SSL_ERROR_WANT_CONNECT:
- forceConnect = true;
- break;
- // fall through
- default: // TODO: benski> MOST other errors are OK, (especially "want read" and "want write", but we need to think through all the scenarios here
- forceConnect = false;
- }
- }
- else if ( retval )
- {
- /*
- ** success
- */
- forceConnect = false;
- }
- /*
- ** If retval == 0
- ** socket is closed, or serious error occurred.
- ** cascade up.
- */
- return forceConnect == false;
- }
- void JNL_SSL_Connection::on_socket_connected( void )
- {
- init_ssl_connection();
- }
- void JNL_SSL_Connection::connect( SOCKET s, sockaddr *addr, socklen_t length )
- {
- /*
- ** Joshua Teitelbaum 2/01/2006
- ** No need to close
- ** This is the reason for divergence as well as setting
- ** the connect state
- */
- m_socket = s;
- address = (sockaddr *)malloc( length );
- memcpy( address, addr, length );
- m_remote_port = 0;
- if ( m_socket != -1 )
- {
- SET_SOCK_BLOCK( m_socket, 0 );
- m_state = STATE_CONNECTED;
- SSL_set_fd( m_ssl, m_socket );
- }
- else
- {
- m_errorstr = _strdup( "invalid socket passed to connect" );
- m_state = STATE_ERROR;
- }
- }
- ssize_t JNL_SSL_Connection::socket_recv( char *buf, size_t len, int options )
- {
- return SSL_read( m_ssl, buf, (int)len );
- }
- ssize_t JNL_SSL_Connection::socket_send( const char *buf, size_t len, int options )
- {
- return SSL_write( m_ssl, buf, (int)len );
- }
- JNL_SSL_Connection::~JNL_SSL_Connection()
- {
- if ( m_ssl )
- {
- SSL_free( m_ssl );
- m_ssl = NULL;
- }
- }
- //#endif
|