123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329 |
- //#ifdef USE_SSL
- //#include "netinc.h"
- //#include "util.h"
- //#include "connection.h"
- #include "sslconnection.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, JNL_AsyncDNS *dns, size_t sendbufsize, size_t recvbufsize) : JNL_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 = JNL_Connection::socket_connect();
- if (retval != 0)
- {
- if (ERRNO != JNL_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);
- JNL_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;
- }
- }
- JNL_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 = "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
|