bool SSLSocket::waitAccepted(uint64_t millis) { if(!ssl) { if(!Socket::waitAccepted(millis)) { return false; } ssl.reset(SSL_new(ctx)); if(!ssl) checkSSL(-1); if(!verifyData) { SSL_set_verify(ssl, SSL_VERIFY_NONE, NULL); } else SSL_set_ex_data(ssl, CryptoManager::idxVerifyData, verifyData.get()); checkSSL(SSL_set_fd(ssl, static_cast<int>(getSock()))); } if(SSL_is_init_finished(ssl)) { return true; } while(true) { int ret = SSL_accept(ssl); if(ret == 1) { dcdebug("Connected to SSL client using %s\n", SSL_get_cipher(ssl)); return true; } if(!waitWant(ret, millis)) { return false; } } }
bool SSLSocket::waitAccepted(uint64_t millis) { if(!ssl) { if(!Socket::waitAccepted(millis)) { return false; } ssl.reset(SSL_new(ctx)); if(!ssl) checkSSL(-1); checkSSL(SSL_set_fd(ssl, sock)); } if(SSL_is_init_finished(ssl)) { return true; } while(true) { int ret = SSL_accept(ssl); if(ret == 1) { dcdebug("Connected to SSL client using %s\n", SSL_get_cipher(ssl)); #ifndef HEADER_OPENSSLV_H finished = true; #endif return true; } if(!waitWant(ret, millis)) { return false; } } }
bool SSLSocket::waitAccepted(uint32_t millis) { if(!ssl) { if(!Socket::waitAccepted(millis)) { return false; } ssl.reset(SSL_new(ctx)); if(!ssl) checkSSL(-1); checkSSL(SSL_set_fd(ssl, getSock())); } if(SSL_is_init_finished(ssl)) { return true; } while(true) { int ret = SSL_accept(ssl); if(ret == 1) { dcdebug("Connected to SSL client using %s\n", SSL_get_cipher(ssl)); return true; } if(!waitWant(ret, millis)) { return false; } } }
bool SSLSocket::waitConnected(uint64_t millis) { if(!ssl) { if(!Socket::waitConnected(millis)) { return false; } ssl.reset(SSL_new(ctx)); if(!ssl) checkSSL(-1); checkSSL(SSL_set_fd(ssl, sock)); } if(SSL_is_init_finished(ssl)) { return true; } while(true) { // OpenSSL needs server handshake for NAT traversal int ret = ssl->server ? SSL_accept(ssl) : SSL_connect(ssl); if(ret == 1) { dcdebug("Connected to SSL server using %s as %s\n", SSL_get_cipher(ssl), ssl->server?"server":"client"); #ifndef HEADER_OPENSSLV_H finished = true; #endif return true; } if(!waitWant(ret, millis)) { return false; } } }
void SSLSocket::accept(const Socket& listeningSocket) throw(SocketException) { Socket::accept(listeningSocket); if(ssl) SSL_free(ssl); ssl = SSL_new(ctx); if(!ssl) checkSSL(-1); checkSSL(SSL_set_fd(ssl, sock)); checkSSL(SSL_accept(ssl)); dcdebug("Connected to SSL client using %s\n", SSL_get_cipher(ssl)); }
void SSLSocket::connect(const string& aIp, short aPort) throw(SocketException) { Socket::setBlocking(true); Socket::connect(aIp, aPort); if(ssl) SSL_free(ssl); ssl = SSL_new(ctx); if(!ssl) checkSSL(-1); checkSSL(SSL_set_fd(ssl, sock)); checkSSL(SSL_connect(ssl)); dcdebug("Connected to SSL server using %s\n", SSL_get_cipher(ssl)); Socket::setBlocking(false); }
void JabberCreateAccountWidget::sslActivated(int i) { if ((EncryptionMode->itemData(i) == 0 || EncryptionMode->itemData(i) == 2) && !checkSSL()) EncryptionMode->setCurrentIndex(EncryptionMode->findData(1)); else if (EncryptionMode->itemData(i) == 2 && !CustomHostPort->isChecked()) { MessageDialog::show("dialog-warning", tr("Kadu"), tr("Legacy secure connection (SSL) is only available in combination with manual host/port."), QMessageBox::Ok, this); EncryptionMode->setCurrentIndex(EncryptionMode->findData(1)); } }
int SSLSocket::write(const void* aBuffer, int aLen) { if(!ssl) { return -1; } int ret = checkSSL(SSL_write(ssl, aBuffer, aLen)); if(ret > 0) { stats.totalUp += ret; //dcdebug("Out(s): %.*s\n", ret, (char*)aBuffer); } return ret; }
int SSLSocket::read(void* aBuffer, int aBufLen) { if(!ssl) { return -1; } int len = checkSSL(SSL_read(ssl, aBuffer, aBufLen)); if(len > 0) { stats.totalDown += len; //dcdebug("In(s): %.*s\n", len, (char*)aBuffer); } return len; }
bool SSLSocket::waitWant(int ret, uint64_t millis) { int err = SSL_get_error(ssl, ret); switch(err) { case SSL_ERROR_WANT_READ: return wait(millis, true, false).first; case SSL_ERROR_WANT_WRITE: return wait(millis, true, false).second; // Check if this is a fatal error... default: checkSSL(ret); } dcdebug("SSL: Unexpected fallthrough"); // There was no error? return true; }
void AccountModifyDlg::sslActivated(int i) { if ((cb_ssl->itemData(i) == UserAccount::SSL_Yes || cb_ssl->itemData(i) == UserAccount::SSL_Legacy) && !checkSSL()) { cb_ssl->setCurrentIndex(cb_ssl->findData(UserAccount::SSL_Auto)); } else if (cb_ssl->itemData(i) == UserAccount::SSL_Legacy && !ck_host->isChecked()) { QMessageBox::critical(this, tr("Error"), tr("Legacy SSL is only available in combination with manual host/port.")); cb_ssl->setCurrentIndex(cb_ssl->findData(UserAccount::SSL_Auto)); } }
bool SSLSocket::waitWant(int ret, uint64_t millis) { #ifdef HEADER_OPENSSLV_H int err = SSL_get_error(ssl, ret); switch(err) { case SSL_ERROR_WANT_READ: return wait(millis, Socket::WAIT_READ) == WAIT_READ; case SSL_ERROR_WANT_WRITE: return wait(millis, Socket::WAIT_WRITE) == WAIT_WRITE; #else int err = ssl->last_error; switch(err) { case GNUTLS_E_INTERRUPTED: case GNUTLS_E_AGAIN: { int waitFor = wait(millis, Socket::WAIT_READ | Socket::WAIT_WRITE); return (waitFor & Socket::WAIT_READ) || (waitFor & Socket::WAIT_WRITE); } #endif // Check if this is a fatal error... default: checkSSL(ret); } dcdebug("SSL: Unexpected fallthrough"); // There was no error? return true; } int SSLSocket::read(void* aBuffer, int aBufLen) throw(SocketException) { if(!ssl) { return -1; } int len = checkSSL(SSL_read(ssl, aBuffer, aBufLen)); if(len > 0) { stats.totalDown += len; //dcdebug("In(s): %.*s\n", len, (char*)aBuffer); } return len; } int SSLSocket::write(const void* aBuffer, int aLen) throw(SocketException) { if(!ssl) { return -1; } int ret = checkSSL(SSL_write(ssl, aBuffer, aLen)); if(ret > 0) { stats.totalUp += ret; //dcdebug("Out(s): %.*s\n", ret, (char*)aBuffer); } return ret; } int SSLSocket::checkSSL(int ret) throw(SocketException) { if(!ssl) { return -1; } if(ret <= 0) { int err = SSL_get_error(ssl, ret); switch(err) { case SSL_ERROR_NONE: // Fallthrough - YaSSL doesn't for example return an openssl compatible error on recv fail case SSL_ERROR_WANT_READ: // Fallthrough case SSL_ERROR_WANT_WRITE: return -1; case SSL_ERROR_ZERO_RETURN: #ifndef HEADER_OPENSSLV_H if(ssl->last_error == GNUTLS_E_INTERRUPTED || ssl->last_error == GNUTLS_E_AGAIN) return -1; #endif throw SocketException(STRING(CONNECTION_CLOSED)); default: { ssl.reset(); // @todo replace 80 with MAX_ERROR_SZ or whatever's appropriate for yaSSL in some nice way... char errbuf[80]; /* TODO: better message for SSL_ERROR_SYSCALL * If the error queue is empty (i.e. ERR_get_error() returns 0), ret can be used to find out more about the error: * If ret == 0, an EOF was observed that violates the protocol. If ret == -1, the underlying BIO reported an I/O error * (for socket I/O on Unix systems, consult errno for details). */ int error = ERR_get_error(); sprintf(errbuf, "%s %d: %s", CSTRING(SSL_ERROR), err, (error == 0) ? CSTRING(CONNECTION_CLOSED) : ERR_reason_error_string(error)); throw SSLSocketException(errbuf); } } } return ret; } int SSLSocket::wait(uint64_t millis, int waitFor) throw(SocketException) { #ifdef HEADER_OPENSSLV_H if(ssl && (waitFor & Socket::WAIT_READ)) { /** @todo Take writing into account as well if reading is possible? */ char c; if(SSL_peek(ssl, &c, 1) > 0) return WAIT_READ; } #endif return Socket::wait(millis, waitFor); } bool SSLSocket::isTrusted() throw() { if(!ssl) { return false; } #ifdef HEADER_OPENSSLV_H if(SSL_get_verify_result(ssl) != X509_V_OK) { return false; } #else if(gnutls_certificate_verify_peers(((SSL*)ssl)->gnutls_state) != 0) { return false; } #endif X509* cert = SSL_get_peer_certificate(ssl); if(!cert) { return false; } X509_free(cert); return true; } std::string SSLSocket::getCipherName() throw() { if(!ssl) return Util::emptyString; return SSL_get_cipher_name(ssl); } std::string SSLSocket::getDigest() const throw() { #ifdef HEADER_OPENSSLV_H if(!ssl) return Util::emptyString; X509* x509 = SSL_get_peer_certificate(ssl); if(!x509) return Util::emptyString; return ssl::X509_digest(x509, EVP_sha1()); #else return Util::emptyString; #endif } void SSLSocket::shutdown() throw() { if(ssl) SSL_shutdown(ssl); } void SSLSocket::close() throw() { if(ssl) { ssl.reset(); } Socket::shutdown(); Socket::close(); } } // namespace dcpp
void JabberEditAccountWidget::sslActivated(int i) { if ((EncryptionMode->itemData(i) == JabberAccountDetails::Encryption_Auto || EncryptionMode->itemData(i) == JabberAccountDetails::Encryption_Legacy) && !checkSSL()) EncryptionMode->setCurrentIndex(EncryptionMode->findData(JabberAccountDetails::Encryption_No)); else if (EncryptionMode->itemData(i) == JabberAccountDetails::Encryption_Legacy && !CustomHostPort->isChecked()) { MessageDialog::show("dialog-warning", tr("Kadu"), tr("Legacy SSL is only available in combination with manual host/port.")); EncryptionMode->setCurrentIndex(EncryptionMode->findData(JabberAccountDetails::Encryption_Auto)); } }