aboutsummaryrefslogtreecommitdiff
path: root/Src/replicant/jnetlib/sslconnection.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Src/replicant/jnetlib/sslconnection.cpp')
-rw-r--r--Src/replicant/jnetlib/sslconnection.cpp329
1 files changed, 329 insertions, 0 deletions
diff --git a/Src/replicant/jnetlib/sslconnection.cpp b/Src/replicant/jnetlib/sslconnection.cpp
new file mode 100644
index 00000000..5362c445
--- /dev/null
+++ b/Src/replicant/jnetlib/sslconnection.cpp
@@ -0,0 +1,329 @@
+//#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 \ No newline at end of file