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 <QFile>
#include <QTcpServer>
#include <iostream>
#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<Tor::HiddenService*> 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<Tor::HiddenService*> 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 ;
}

View File

@ -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 ;
};

View File

@ -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);

View File

@ -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 */