split tor control into two parts

This commit is contained in:
csoler 2017-12-21 18:16:32 +01:00
parent e87b25794f
commit 5b5a2bef81
4 changed files with 151 additions and 49 deletions

View file

@ -1,8 +1,13 @@
#include <unistd.h>
#include <QTimer> #include <QTimer>
#include <QFile> #include <QFile>
#include <QTcpServer>
#include <iostream> #include <iostream>
#include "TorControlWindow.h" #include "TorControlWindow.h"
#include "TorManager.h"
#include "TorControl.h" #include "TorControl.h"
#include "HiddenService.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(bootstrapStatusChanged()),this,SLOT(statusChanged()));
QObject::connect(tm->control(),SIGNAL(connectivityChanged()),this,SLOT(statusChanged())); QObject::connect(tm->control(),SIGNAL(connectivityChanged()),this,SLOT(statusChanged()));
QTimer::singleShot(2000,this,SLOT(checkForHiddenService())) ; //QTimer::singleShot(2000,this,SLOT(checkForHiddenService())) ;
//void configurationNeededChanged();
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() void TorControlDialog::setupHiddenService()
{ {
/*
QString keyData = m_settings->read("serviceKey").toString(); QString keyData = m_settings->read("serviceKey").toString();
QString legacyDir = m_settings->read("dataDirectory").toString(); QString legacyDir = m_settings->read("dataDirectory").toString();
if (!keyData.isEmpty()) if (!keyData.isEmpty())
{ {
CryptoKey key; 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"; qWarning() << "Cannot load service key from configuration";
return; 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"))) else if (!legacyDir.isEmpty() && QFile::exists(legacyDir + QLatin1String("/private_key")))
{ {
qDebug() << "Attempting to load key from legacy filesystem format in" << legacyDir; qDebug() << "Attempting to load key from legacy filesystem format in" << legacyDir;
CryptoKey key; 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"; qWarning() << "Cannot load legacy format key from" << legacyDir << "for conversion";
return; return;
} else { }
else
{
keyData = QString::fromLatin1(key.encodedPrivateKey(CryptoKey::DER).toBase64()); keyData = QString::fromLatin1(key.encodedPrivateKey(CryptoKey::DER).toBase64());
m_settings->write("serviceKey", keyData); 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()) else if (!m_settings->read("initializing").toBool())
@ -59,52 +78,54 @@ void TorControlDialog::setupHiddenService()
} }
else 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); m_settings->write("serviceKey", key);
} }
); );
} }
Q_ASSERT(m_hiddenService); Q_ASSERT(mHiddenService);
connect(m_hiddenService, SIGNAL(statusChanged(int,int)), SLOT(onStatusChanged(int,int))); connect(mHiddenService, SIGNAL(statusChanged(int,int)), SLOT(onStatusChanged(int,int)));
// Generally, these are not used, and we bind to localhost and port 0 // Generally, these are not used, and we bind to localhost and port 0
// for an automatic (and portable) selection. // for an automatic (and portable) selection.
QHostAddress address(m_settings->read("localListenAddress").toString()); QHostAddress address(m_settings->read("localListenAddress").toString());
if (address.isNull()) if (address.isNull())
address = QHostAddress::LocalHost; address = QHostAddress::LocalHost;
quint16 port = (quint16)m_settings->read("localListenPort").toInt(); quint16 port = (quint16)m_settings->read("localListenPort").toInt();
m_incomingServer = new QTcpServer(this); if (!mIncomingServer->listen(address, port))
if (!m_incomingServer->listen(address, port)) { {
// XXX error case // XXX error case
qWarning() << "Failed to open incoming socket:" << m_incomingServer->errorString(); qWarning() << "Failed to open incoming socket:" << mIncomingServer->errorString();
return; return;
} }
connect(m_incomingServer, &QTcpServer::newConnection, this, &UserIdentity::onIncomingConnection); mHiddenService->addTarget(9878, mIncomingServer->serverAddress(), mIncomingServer->serverPort());
torControl->addHiddenService(mHiddenService);
m_hiddenService->addTarget(9878, m_incomingServer->serverAddress(), m_incomingServer->serverPort()); */
torControl->addHiddenService(m_hiddenService);
} }
void TorControlDialog::checkForHiddenService() // void TorControlDialog::checkForHiddenService()
{ // {
QList<Tor::HiddenService*> hidden_services = mTorManager->control()->hiddenServices(); // QList<Tor::HiddenService*> hidden_services = mTorManager->control()->hiddenServices();
//
std::cerr << "Checking for hidden services:" << std::endl; // std::cerr << "Checking for hidden services:" << std::endl;
//
if(hidden_services.empty()) // if(hidden_services.empty())
{ // {
setupHiddenService(); // setupHiddenService();
//
QTimer::singleShot(2000,this,SLOT(checkForHiddenService())) ; // QTimer::singleShot(2000,this,SLOT(checkForHiddenService())) ;
} // }
} // }
void TorControlDialog::statusChanged() void TorControlDialog::statusChanged()
{ {
@ -174,3 +195,24 @@ void TorControlDialog::showLog()
torLog_TB->setText(s) ; torLog_TB->setText(s) ;
QCoreApplication::processEvents() ; 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 ;
}

View file

@ -1,5 +1,11 @@
#include "ui_TorControlWindow.h" #include "ui_TorControlWindow.h"
#include "TorManager.h"
class QTcpServer ;
namespace Tor {
class HiddenService ;
class TorManager ;
}
class TorControlDialog: public QDialog, public Ui::TorControlDialog class TorControlDialog: public QDialog, public Ui::TorControlDialog
{ {
@ -8,13 +14,34 @@ class TorControlDialog: public QDialog, public Ui::TorControlDialog
public: public:
TorControlDialog(Tor::TorManager *tm,QWidget *parent =NULL); 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: protected slots:
void showLog(); void showLog();
void statusChanged(); void statusChanged();
void checkForHiddenService(); // void checkForHiddenService();
void onIncomingConnection();
private: private:
void setupHiddenService(); void setupHiddenService();
Tor::TorManager *mTorManager ; Tor::TorManager *mTorManager ;
Tor::HiddenService *mHiddenService ;
QTcpServer *mIncomingServer ;
}; };

View file

@ -187,6 +187,10 @@ public:
/** Sets whether the bandwidth graph is always on top. */ /** Sets whether the bandwidth graph is always on top. */
void setBWGraphAlwaysOnTop(bool alwaysOnTop); void setBWGraphAlwaysOnTop(bool alwaysOnTop);
#ifdef RETROTOR
void setHiddenServiceKey() ;
#endif
uint getNewsFeedFlags(); uint getNewsFeedFlags();
void setNewsFeedFlags(uint flags); void setNewsFeedFlags(uint flags);

View file

@ -282,23 +282,29 @@ feenableexcept(FE_INVALID | FE_DIVBYZERO);
Rshare rshare(args, argc, argv, QString::fromUtf8(RsAccounts::ConfigDirectory().c_str())); Rshare rshare(args, argc, argv, QString::fromUtf8(RsAccounts::ConfigDirectory().c_str()));
#ifdef RETROTOR #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 control manager */
Tor::TorManager *torManager = Tor::TorManager::instance(); Tor::TorManager *torManager = Tor::TorManager::instance();
torManager->setDataDirectory(Rshare::dataDirectory() + QString("/tor/")); torManager->setDataDirectory(Rshare::dataDirectory() + QString("/tor/"));
//torManager->setDataDirectory(QString("./tor"));//settings->filePath()).path() + QString("/tor/"));
torManager->start(); torManager->start();
TorControlDialog tcd(torManager) ; TorControlDialog tcd(torManager) ;
tcd.exec(); tcd.show();
// tcd.show() ;
// while(tcd.checkForTor() == TorControlDialog::TOR_STATUS_UNKNOWN) // runs until some status is reached: either tor works, or it fails.
// while(true) {
// { QCoreApplication::processEvents();
// 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 #endif
/* Start RetroShare */ /* Start RetroShare */
@ -330,9 +336,10 @@ feenableexcept(FE_INVALID | FE_DIVBYZERO);
if (genCert) if (genCert)
{ {
GenCertDialog gd(false); GenCertDialog gd(false);
if (gd.exec () == QDialog::Rejected) {
if (gd.exec () == QDialog::Rejected)
return 1; return 1;
}
sDefaultGXSIdToCreate = gd.getGXSNickname(); sDefaultGXSIdToCreate = gd.getGXSNickname();
} }
@ -364,6 +371,28 @@ feenableexcept(FE_INVALID | FE_DIVBYZERO);
SoundManager::create(); 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); splashScreen.showMessage(rshare.translate("SplashScreen", "Load configuration"), Qt::AlignHCenter | Qt::AlignBottom);
/* stop Retroshare if startup fails */ /* stop Retroshare if startup fails */