From 5b5a2bef81533ce3cda3cf46716cf6031eb3f871 Mon Sep 17 00:00:00 2001 From: csoler Date: Thu, 21 Dec 2017 18:16:32 +0100 Subject: [PATCH] split tor control into two parts --- .../src/TorControl/TorControlWindow.cpp | 112 ++++++++++++------ .../src/TorControl/TorControlWindow.h | 31 ++++- .../src/gui/settings/rsharesettings.h | 4 + retroshare-gui/src/main.cpp | 53 +++++++-- 4 files changed, 151 insertions(+), 49 deletions(-) diff --git a/retroshare-gui/src/TorControl/TorControlWindow.cpp b/retroshare-gui/src/TorControl/TorControlWindow.cpp index b6787a625..dfe34eb05 100644 --- a/retroshare-gui/src/TorControl/TorControlWindow.cpp +++ b/retroshare-gui/src/TorControl/TorControlWindow.cpp @@ -1,8 +1,13 @@ +#include + #include #include +#include + #include #include "TorControlWindow.h" +#include "TorManager.h" #include "TorControl.h" #include "HiddenService.h" @@ -19,37 +24,51 @@ TorControlDialog::TorControlDialog(Tor::TorManager *tm,QWidget *parent) QObject::connect(tm->control(),SIGNAL(bootstrapStatusChanged()),this,SLOT(statusChanged())); QObject::connect(tm->control(),SIGNAL(connectivityChanged()),this,SLOT(statusChanged())); - QTimer::singleShot(2000,this,SLOT(checkForHiddenService())) ; - //void configurationNeededChanged(); + //QTimer::singleShot(2000,this,SLOT(checkForHiddenService())) ; + + mIncomingServer = new QTcpServer(this) ; + mHiddenService = NULL ; + + connect(mIncomingServer, SIGNAL(QTcpServer::newConnection()), this, SLOT(onIncomingConnection())); +} + +void TorControlDialog::onIncomingConnection() +{ + std::cerr << "Incoming connection !!" << std::endl; } void TorControlDialog::setupHiddenService() { - QString keyData = m_settings->read("serviceKey").toString(); + /* + QString keyData = m_settings->read("serviceKey").toString(); QString legacyDir = m_settings->read("dataDirectory").toString(); if (!keyData.isEmpty()) { CryptoKey key; - if (!key.loadFromData(QByteArray::fromBase64(keyData.toLatin1()), CryptoKey::PrivateKey, CryptoKey::DER)) { + if (!key.loadFromData(QByteArray::fromBase64(keyData.toLatin1()), CryptoKey::PrivateKey, CryptoKey::DER)) + { qWarning() << "Cannot load service key from configuration"; return; } - m_hiddenService = new Tor::HiddenService(key, legacyDir, this); + mHiddenService = new Tor::HiddenService(key, legacyDir, this); } else if (!legacyDir.isEmpty() && QFile::exists(legacyDir + QLatin1String("/private_key"))) { qDebug() << "Attempting to load key from legacy filesystem format in" << legacyDir; CryptoKey key; - if (!key.loadFromFile(legacyDir + QLatin1String("/private_key"), CryptoKey::PrivateKey)) { + if (!key.loadFromFile(legacyDir + QLatin1String("/private_key"), CryptoKey::PrivateKey)) + { qWarning() << "Cannot load legacy format key from" << legacyDir << "for conversion"; return; - } else { + } + else + { keyData = QString::fromLatin1(key.encodedPrivateKey(CryptoKey::DER).toBase64()); m_settings->write("serviceKey", keyData); - m_hiddenService = new Tor::HiddenService(key, legacyDir, this); + mHiddenService = new Tor::HiddenService(key, legacyDir, this); } } else if (!m_settings->read("initializing").toBool()) @@ -59,52 +78,54 @@ void TorControlDialog::setupHiddenService() } else { - m_hiddenService = new Tor::HiddenService(legacyDir, this); + mHiddenService = new Tor::HiddenService(legacyDir, this); - connect(m_hiddenService, &Tor::HiddenService::privateKeyChanged, this, [&]() + connect(mHiddenService, &Tor::HiddenService::privateKeyChanged, this, [&]() { - QString key = QString::fromLatin1(m_hiddenService->privateKey().encodedPrivateKey(CryptoKey::DER).toBase64()); + QString key = QString::fromLatin1(mHiddenService->privateKey().encodedPrivateKey(CryptoKey::DER).toBase64()); m_settings->write("serviceKey", key); } ); } - Q_ASSERT(m_hiddenService); - connect(m_hiddenService, SIGNAL(statusChanged(int,int)), SLOT(onStatusChanged(int,int))); + Q_ASSERT(mHiddenService); + connect(mHiddenService, SIGNAL(statusChanged(int,int)), SLOT(onStatusChanged(int,int))); // Generally, these are not used, and we bind to localhost and port 0 // for an automatic (and portable) selection. + QHostAddress address(m_settings->read("localListenAddress").toString()); + if (address.isNull()) address = QHostAddress::LocalHost; + quint16 port = (quint16)m_settings->read("localListenPort").toInt(); - m_incomingServer = new QTcpServer(this); - if (!m_incomingServer->listen(address, port)) { + if (!mIncomingServer->listen(address, port)) + { // XXX error case - qWarning() << "Failed to open incoming socket:" << m_incomingServer->errorString(); + qWarning() << "Failed to open incoming socket:" << mIncomingServer->errorString(); return; } - connect(m_incomingServer, &QTcpServer::newConnection, this, &UserIdentity::onIncomingConnection); - - m_hiddenService->addTarget(9878, m_incomingServer->serverAddress(), m_incomingServer->serverPort()); - torControl->addHiddenService(m_hiddenService); + mHiddenService->addTarget(9878, mIncomingServer->serverAddress(), mIncomingServer->serverPort()); + torControl->addHiddenService(mHiddenService); + */ } -void TorControlDialog::checkForHiddenService() -{ - QList hidden_services = mTorManager->control()->hiddenServices(); - - std::cerr << "Checking for hidden services:" << std::endl; - - if(hidden_services.empty()) - { - setupHiddenService(); - - QTimer::singleShot(2000,this,SLOT(checkForHiddenService())) ; - } -} +// void TorControlDialog::checkForHiddenService() +// { +// QList hidden_services = mTorManager->control()->hiddenServices(); +// +// std::cerr << "Checking for hidden services:" << std::endl; +// +// if(hidden_services.empty()) +// { +// setupHiddenService(); +// +// QTimer::singleShot(2000,this,SLOT(checkForHiddenService())) ; +// } +// } void TorControlDialog::statusChanged() { @@ -120,7 +141,7 @@ void TorControlDialog::statusChanged() case Tor::TorControl::NotConnected: status_str = "Not connected" ; break ; case Tor::TorControl::Connecting: status_str = "Connecting" ; break ; case Tor::TorControl::Authenticating: status_str = "Authenticating" ; break ; - case Tor::TorControl::Connected: status_str = "Connected" ; break ; + case Tor::TorControl::Connected: status_str = "Connected" ; break ; } switch(torstatus) @@ -128,7 +149,7 @@ void TorControlDialog::statusChanged() default: case Tor::TorControl::TorUnknown: torstatus_str = "Unknown" ; break ; case Tor::TorControl::TorOffline: torstatus_str = "Tor offline" ; break ; - case Tor::TorControl::TorReady: torstatus_str = "Tor ready" ; break ; + case Tor::TorControl::TorReady: torstatus_str = "Tor ready" ; break ; } torStatus_LB->setText(torstatus_str + "(" + status_str + ")") ; @@ -174,3 +195,24 @@ void TorControlDialog::showLog() torLog_TB->setText(s) ; QCoreApplication::processEvents() ; } + +TorControlDialog::TorStatus TorControlDialog::checkForTor() +{ + switch(mTorManager->control()->status()) + { + case Tor::TorControl::Connected: usleep(2*1000*1000);return TOR_STATUS_OK ; + case Tor::TorControl::Error: return TOR_STATUS_FAIL ; + + default: + return TOR_STATUS_UNKNOWN ; + } +} + +TorControlDialog::HiddenServiceStatus TorControlDialog::checkForHiddenService() +{ + return HIDDEN_SERVICE_STATUS_UNKNOWN ; +} + + + + diff --git a/retroshare-gui/src/TorControl/TorControlWindow.h b/retroshare-gui/src/TorControl/TorControlWindow.h index 79a66d863..86d82159a 100644 --- a/retroshare-gui/src/TorControl/TorControlWindow.h +++ b/retroshare-gui/src/TorControl/TorControlWindow.h @@ -1,5 +1,11 @@ #include "ui_TorControlWindow.h" -#include "TorManager.h" + +class QTcpServer ; + +namespace Tor { + class HiddenService ; + class TorManager ; +} class TorControlDialog: public QDialog, public Ui::TorControlDialog { @@ -8,13 +14,34 @@ class TorControlDialog: public QDialog, public Ui::TorControlDialog public: TorControlDialog(Tor::TorManager *tm,QWidget *parent =NULL); + enum TorStatus { + TOR_STATUS_UNKNOWN = 0x00, + TOR_STATUS_OK = 0x01, + TOR_STATUS_FAIL = 0x02 + }; + + enum HiddenServiceStatus { + HIDDEN_SERVICE_STATUS_UNKNOWN = 0x00, + HIDDEN_SERVICE_STATUS_OK = 0x01, + HIDDEN_SERVICE_STATUS_FAIL = 0x02 + }; + + // Should be called multiple times in a loop until it returns something else than *_UNKNOWN + + TorStatus checkForTor() ; + HiddenServiceStatus checkForHiddenService() ; + protected slots: void showLog(); void statusChanged(); - void checkForHiddenService(); +// void checkForHiddenService(); + void onIncomingConnection(); private: void setupHiddenService(); Tor::TorManager *mTorManager ; + Tor::HiddenService *mHiddenService ; + + QTcpServer *mIncomingServer ; }; diff --git a/retroshare-gui/src/gui/settings/rsharesettings.h b/retroshare-gui/src/gui/settings/rsharesettings.h index 21b1faae9..99e33b5f2 100644 --- a/retroshare-gui/src/gui/settings/rsharesettings.h +++ b/retroshare-gui/src/gui/settings/rsharesettings.h @@ -187,6 +187,10 @@ public: /** Sets whether the bandwidth graph is always on top. */ void setBWGraphAlwaysOnTop(bool alwaysOnTop); +#ifdef RETROTOR + void setHiddenServiceKey() ; +#endif + uint getNewsFeedFlags(); void setNewsFeedFlags(uint flags); diff --git a/retroshare-gui/src/main.cpp b/retroshare-gui/src/main.cpp index 70ef4345f..13f90ed93 100644 --- a/retroshare-gui/src/main.cpp +++ b/retroshare-gui/src/main.cpp @@ -282,23 +282,29 @@ feenableexcept(FE_INVALID | FE_DIVBYZERO); Rshare rshare(args, argc, argv, QString::fromUtf8(RsAccounts::ConfigDirectory().c_str())); #ifdef RETROTOR - // Start the Tor engine, and make sure it provides a viable hidden service + // First check that we can start the Tor engine, if not, quit. /* Tor control manager */ Tor::TorManager *torManager = Tor::TorManager::instance(); torManager->setDataDirectory(Rshare::dataDirectory() + QString("/tor/")); - //torManager->setDataDirectory(QString("./tor"));//settings->filePath()).path() + QString("/tor/")); - torManager->start(); TorControlDialog tcd(torManager) ; - tcd.exec(); -// tcd.show() ; -// -// while(true) -// { -// QCoreApplication::processEvents(); -// } + tcd.show(); + + while(tcd.checkForTor() == TorControlDialog::TOR_STATUS_UNKNOWN) // runs until some status is reached: either tor works, or it fails. + { + QCoreApplication::processEvents(); + usleep(1000) ; + } + + tcd.hide(); + + if(tcd.checkForTor() != TorControlDialog::TOR_STATUS_OK) + { + QMessageBox::critical(NULL,QObject::tr("Tor not found!"),QObject::tr("Tor wasn't found on your system. Please install it and re-start Retroshare.")) ; + return 1 ; + } #endif /* Start RetroShare */ @@ -330,9 +336,10 @@ feenableexcept(FE_INVALID | FE_DIVBYZERO); if (genCert) { GenCertDialog gd(false); - if (gd.exec () == QDialog::Rejected) { + + if (gd.exec () == QDialog::Rejected) return 1; - } + sDefaultGXSIdToCreate = gd.getGXSNickname(); } @@ -364,6 +371,28 @@ feenableexcept(FE_INVALID | FE_DIVBYZERO); SoundManager::create(); +#ifdef RETROTOR + // Now that we know the Tor service running, and we know the SSL id, we can make sure it provides a viable hidden service + + /* Tor control manager */ + + tcd.show(); + + while(tcd.checkForHiddenService() == TorControlDialog::HIDDEN_SERVICE_STATUS_UNKNOWN) // runs until some status is reached: either tor works, or it fails. + { + QCoreApplication::processEvents(); + usleep(1000) ; + } + + tcd.hide(); + + if(tcd.checkForHiddenService() != TorControlDialog::HIDDEN_SERVICE_STATUS_OK) + { + QMessageBox::critical(NULL,QObject::tr("Cannot start a hidden tor service!"),QObject::tr("It was not possible to start a hidden service.")) ; + return 1 ; + } +#endif + splashScreen.showMessage(rshare.translate("SplashScreen", "Load configuration"), Qt::AlignHCenter | Qt::AlignBottom); /* stop Retroshare if startup fails */