diff --git a/src/lib/plugin/ns/SecureSocket.cpp b/src/lib/plugin/ns/SecureSocket.cpp index 4aa42114..4abd4c03 100644 --- a/src/lib/plugin/ns/SecureSocket.cpp +++ b/src/lib/plugin/ns/SecureSocket.cpp @@ -71,6 +71,7 @@ SecureSocket::~SecureSocket() } delete m_ssl; + delete[] m_error; } void @@ -104,7 +105,7 @@ SecureSocket::secureRead(void* buffer, UInt32 n) int r = 0; if (m_ssl->m_ssl != NULL) { r = SSL_read(m_ssl->m_ssl, buffer, n); - retry = checkResult(r, false); + retry = checkResult(r); if (retry) { r = 0; } @@ -120,7 +121,7 @@ SecureSocket::secureWrite(const void* buffer, UInt32 n) int r = 0; if (m_ssl->m_ssl != NULL) { r = SSL_write(m_ssl->m_ssl, buffer, n); - retry = checkResult(r, false); + retry = checkResult(r); if (retry) { r = 0; } @@ -141,6 +142,7 @@ SecureSocket::initSsl(bool server) m_ssl = new Ssl(); m_ssl->m_context = NULL; m_ssl->m_ssl = NULL; + m_error = new char[MAX_ERROR_SIZE]; initContext(server); } @@ -151,17 +153,18 @@ SecureSocket::loadCertificates(const char* filename) int r = 0; r = SSL_CTX_use_certificate_file(m_ssl->m_context, filename, SSL_FILETYPE_PEM); if (r <= 0) { - throwError("failed to use ssl certificate"); + showError(); } r = SSL_CTX_use_PrivateKey_file(m_ssl->m_context, filename, SSL_FILETYPE_PEM); if (r <= 0) { - throwError("failed to use ssl private key"); + showError(); } + //verify private key r = SSL_CTX_check_private_key(m_ssl->m_context); if (!r) { - throwError("check ssl private key failed"); + showError(); } } @@ -191,7 +194,7 @@ SecureSocket::initContext(bool server) SSL_METHOD* m = const_cast(method); m_ssl->m_context = SSL_CTX_new(m); if (m_ssl->m_context == NULL) { - throwError("failed to create ssl context"); + showError(); } } @@ -208,8 +211,6 @@ SecureSocket::createSSL() bool SecureSocket::secureAccept(int socket) { - LOG((CLOG_DEBUG "accepting secure connection")); - createSSL(); // set connection socket to SSL state @@ -218,25 +219,15 @@ SecureSocket::secureAccept(int socket) // do SSL-protocol accept LOG((CLOG_DEBUG1 "secureAccept")); int r = SSL_accept(m_ssl->m_ssl); + bool retry = checkResult(r); - bool retry = false; - try { - retry = checkResult(r, true); - m_secureReady = !retry; - } - catch (XSocket& e) { - LOG((CLOG_ERR "failed to accept secure connection")); - LOG((CLOG_INFO "client may have encryption disabled")); - } - + m_secureReady = !retry; return retry; } bool SecureSocket::secureConnect(int socket) { - LOG((CLOG_DEBUG "establishing secure connection")); - createSSL(); // attach the socket descriptor @@ -244,15 +235,7 @@ SecureSocket::secureConnect(int socket) LOG((CLOG_DEBUG1 "secureConnect")); int r = SSL_connect(m_ssl->m_ssl); - - bool retry = false; - try { - retry = checkResult(r, true); - } - catch (XSocket& e) { - LOG((CLOG_ERR "failed to establish secure connection")); - LOG((CLOG_INFO "server may have encryption disabled")); - } + bool retry = checkResult(r); m_secureReady = !retry; @@ -272,92 +255,107 @@ SecureSocket::showCertificate() // get the server's certificate cert = SSL_get_peer_certificate(m_ssl->m_ssl); if (cert != NULL) { - LOG((CLOG_DEBUG "checking ssl certificate")); + LOG((CLOG_INFO "server certificate")); line = X509_NAME_oneline(X509_get_subject_name(cert), 0, 0); - LOG((CLOG_INFO "ssl certificate: %s", line)); + LOG((CLOG_INFO "subject: %s", line)); OPENSSL_free(line); X509_free(cert); } else { - LOG((CLOG_ERR "could not find ssl certificate")); + LOG((CLOG_INFO "no certificates")); } } bool -SecureSocket::checkResult(int n, bool canThrow) +SecureSocket::checkResult(int n) { + bool retry = false; int errorCode = SSL_get_error(m_ssl->m_ssl, n); - + switch (errorCode) { case SSL_ERROR_NONE: - return false; + // the TLS/SSL I/O operation completed + break; case SSL_ERROR_ZERO_RETURN: - LOG((CLOG_WARN "secure socket error: SSL_ERROR_ZERO_RETURN")); + // the TLS/SSL connection has been closed + LOG((CLOG_DEBUG2 "SSL_ERROR_ZERO_RETURN")); break; case SSL_ERROR_WANT_READ: - LOG((CLOG_WARN "secure socket error: SSL_ERROR_WANT_READ")); + LOG((CLOG_DEBUG2 "secure socket error: SSL_ERROR_WANT_READ")); + retry = true; break; case SSL_ERROR_WANT_WRITE: - LOG((CLOG_WARN "secure socket error: SSL_ERROR_WANT_WRITE")); + LOG((CLOG_DEBUG2 "secure socket error: SSL_ERROR_WANT_WRITE")); + retry = true; break; case SSL_ERROR_WANT_CONNECT: - LOG((CLOG_WARN "secure socket error: SSL_ERROR_WANT_CONNECT")); + LOG((CLOG_DEBUG2 "secure socket error: SSL_ERROR_WANT_CONNECT")); + retry = true; break; case SSL_ERROR_WANT_ACCEPT: - LOG((CLOG_WARN "secure socket error: SSL_ERROR_WANT_ACCEPT")); + LOG((CLOG_DEBUG2 "secure socket error: SSL_ERROR_WANT_ACCEPT")); + retry = true; break; case SSL_ERROR_SYSCALL: - LOG((CLOG_WARN "secure socket error: SSL_ERROR_SYSCALL")); + // some I/O error occurred + throwError("Secure socket syscall error"); break; - case SSL_ERROR_SSL: - LOG((CLOG_WARN "secure socket error: SSL_ERROR_SSL")); + // a failure in the SSL library occurred + LOG((CLOG_DEBUG2 "SSL_ERROR_SSL")); + sendEvent(getEvents()->forISocket().disconnected()); + sendEvent(getEvents()->forIStream().inputShutdown()); + showError(); + retry = true; break; default: - LOG((CLOG_WARN "secure socket error: unknown")); + // possible cases: + // SSL_ERROR_WANT_X509_LOOKUP + showError(); } - if (canThrow) { - sendEvent(getEvents()->forISocket().disconnected()); - sendEvent(getEvents()->forIStream().inputShutdown()); - throwError("secure socket failed"); - } + return retry; +} - return false; +void +SecureSocket::showError() +{ + if (getError()) { + LOG((CLOG_ERR "secure socket error: %s", m_error)); + } } void SecureSocket::throwError(const char* reason) { - String error = getError(); - if (error.empty()) { - throw XSocket(reason); - } - else { + if (getError()) { throw XSocket(synergy::string::sprintf( - "%s: %s", reason, getError().c_str())); + "%s: %s", reason, m_error)); } } -String +bool SecureSocket::getError() { unsigned long e = ERR_get_error(); + bool errorUpdated = false; + if (e != 0) { - char error[MAX_ERROR_SIZE]; - ERR_error_string_n(e, error, MAX_ERROR_SIZE); - return error; + ERR_error_string_n(e, m_error, MAX_ERROR_SIZE); + errorUpdated = true; } else { - return ""; + LOG((CLOG_DEBUG2 "can not detect any error in secure socket")); } + + return errorUpdated; } ISocketMultiplexerJob* diff --git a/src/lib/plugin/ns/SecureSocket.h b/src/lib/plugin/ns/SecureSocket.h index 09777c7a..7d09ed21 100644 --- a/src/lib/plugin/ns/SecureSocket.h +++ b/src/lib/plugin/ns/SecureSocket.h @@ -58,9 +58,10 @@ private: bool secureAccept(int s); bool secureConnect(int s); void showCertificate(); - bool checkResult(int n, bool canThrow); + bool checkResult(int n); + void showError(); void throwError(const char* reason); - String getError(); + bool getError(); ISocketMultiplexerJob* serviceConnect(ISocketMultiplexerJob*, @@ -73,4 +74,5 @@ private: private: Ssl* m_ssl; bool m_secureReady; + char* m_error; };