diff --git a/retroshare-gui/src/TorControl/TorControl.h b/retroshare-gui/src/TorControl/TorControl.h index 93be0099c..3b897eb63 100644 --- a/retroshare-gui/src/TorControl/TorControl.h +++ b/retroshare-gui/src/TorControl/TorControl.h @@ -78,6 +78,7 @@ public: TorReady }; + explicit TorControl(QObject *parent = 0); /* Information */ diff --git a/retroshare-gui/src/TorControl/TorControlWindow.cpp b/retroshare-gui/src/TorControl/TorControlWindow.cpp index dfe34eb05..ee9bd6a9d 100644 --- a/retroshare-gui/src/TorControl/TorControlWindow.cpp +++ b/retroshare-gui/src/TorControl/TorControlWindow.cpp @@ -37,96 +37,6 @@ void TorControlDialog::onIncomingConnection() std::cerr << "Incoming connection !!" << std::endl; } -void TorControlDialog::setupHiddenService() -{ - /* - 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)) - { - qWarning() << "Cannot load service key from configuration"; - return; - } - - 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)) - { - qWarning() << "Cannot load legacy format key from" << legacyDir << "for conversion"; - return; - } - else - { - keyData = QString::fromLatin1(key.encodedPrivateKey(CryptoKey::DER).toBase64()); - m_settings->write("serviceKey", keyData); - mHiddenService = new Tor::HiddenService(key, legacyDir, this); - } - } - else if (!m_settings->read("initializing").toBool()) - { - qWarning() << "Missing private key for initialized identity"; - return; - } - else - { - mHiddenService = new Tor::HiddenService(legacyDir, this); - - connect(mHiddenService, &Tor::HiddenService::privateKeyChanged, this, [&]() - { - QString key = QString::fromLatin1(mHiddenService->privateKey().encodedPrivateKey(CryptoKey::DER).toBase64()); - m_settings->write("serviceKey", key); - } - ); - } - - 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(); - - if (!mIncomingServer->listen(address, port)) - { - // XXX error case - qWarning() << "Failed to open incoming socket:" << mIncomingServer->errorString(); - return; - } - - 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::statusChanged() { int status = mTorManager->control()->status(); @@ -210,9 +120,32 @@ TorControlDialog::TorStatus TorControlDialog::checkForTor() TorControlDialog::HiddenServiceStatus TorControlDialog::checkForHiddenService() { - return HIDDEN_SERVICE_STATUS_UNKNOWN ; + std::cerr << "Checking for hidden services:" << std::endl; + + switch(mHiddenServiceStatus) + { + case HIDDEN_SERVICE_STATUS_UNKNOWN: { + + if(!mTorManager->setupHiddenService()) + { + mHiddenServiceStatus = HIDDEN_SERVICE_STATUS_FAIL ; + return mHiddenServiceStatus ; + } + mHiddenServiceStatus = HIDDEN_SERVICE_STATUS_REQUESTED ; + break ; + } + + case HIDDEN_SERVICE_STATUS_REQUESTED: { + QList hidden_services = mTorManager->control()->hiddenServices(); + + if(mHiddenService == NULL) + mHiddenService = *(hidden_services.begin()) ; + } + case HIDDEN_SERVICE_STATUS_OK : break; + + default: break ; + } + + return mHiddenServiceStatus ; } - - - diff --git a/retroshare-gui/src/TorControl/TorControlWindow.h b/retroshare-gui/src/TorControl/TorControlWindow.h index 86d82159a..ac70877b9 100644 --- a/retroshare-gui/src/TorControl/TorControlWindow.h +++ b/retroshare-gui/src/TorControl/TorControlWindow.h @@ -21,9 +21,10 @@ public: }; enum HiddenServiceStatus { - HIDDEN_SERVICE_STATUS_UNKNOWN = 0x00, - HIDDEN_SERVICE_STATUS_OK = 0x01, - HIDDEN_SERVICE_STATUS_FAIL = 0x02 + HIDDEN_SERVICE_STATUS_UNKNOWN = 0x00, // no information known. + HIDDEN_SERVICE_STATUS_FAIL = 0x01, // some error occurred + HIDDEN_SERVICE_STATUS_REQUESTED = 0x02, // one service at least has been requested. Still being tested. + HIDDEN_SERVICE_STATUS_OK = 0x03 // one service responds and has been tested }; // Should be called multiple times in a loop until it returns something else than *_UNKNOWN @@ -34,11 +35,10 @@ public: protected slots: void showLog(); void statusChanged(); -// void checkForHiddenService(); void onIncomingConnection(); private: - void setupHiddenService(); + HiddenServiceStatus mHiddenServiceStatus ; Tor::TorManager *mTorManager ; Tor::HiddenService *mHiddenService ; diff --git a/retroshare-gui/src/TorControl/TorManager.cpp b/retroshare-gui/src/TorControl/TorManager.cpp index 47fef939d..6cf5ae808 100644 --- a/retroshare-gui/src/TorControl/TorManager.cpp +++ b/retroshare-gui/src/TorControl/TorManager.cpp @@ -35,11 +35,15 @@ #include "TorManager.h" #include "TorProcess.h" #include "TorControl.h" +#include "CryptoKey.h" +#include "HiddenService.h" #include "GetConfCommand.h" #include "Settings.h" #include #include #include +#include +#include using namespace Tor; @@ -55,10 +59,13 @@ public: TorProcess *process; TorControl *control; QString dataDir; + QString hiddenServiceDir; QStringList logMessages; QString errorMessage; bool configNeeded; + HiddenService *hiddenService ; + explicit TorManagerPrivate(TorManager *parent = 0); QString torExecutablePath() const; @@ -123,6 +130,100 @@ void TorManager::setDataDirectory(const QString &path) d->dataDir.append(QLatin1Char('/')); } +QString TorManager::hiddenServiceDirectory() const +{ + return d->hiddenServiceDir; +} +void TorManager::setHiddenServiceDirectory(const QString &path) +{ + d->hiddenServiceDir = QDir::fromNativeSeparators(path); + + if (!d->hiddenServiceDir.isEmpty() && !d->hiddenServiceDir.endsWith(QLatin1Char('/'))) + d->hiddenServiceDir.append(QLatin1Char('/')); +} + +bool TorManager::setupHiddenService() +{ + QString keyData ;//= m_settings->read("serviceKey").toString(); + QString legacyDir = d->hiddenServiceDir; + +// if (!keyData.isEmpty()) +// { +// CryptoKey key; +// if (!key.loadFromData(QByteArray::fromBase64(keyData.toLatin1()), CryptoKey::PrivateKey, CryptoKey::DER)) +// { +// qWarning() << "Cannot load service key from configuration"; +// return; +// } +// +// 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)) + { + qWarning() << "Cannot load legacy format key from" << legacyDir << "for conversion"; + return false; + } + else + { + keyData = QString::fromLatin1(key.encodedPrivateKey(CryptoKey::DER).toBase64()); + d->hiddenService = new Tor::HiddenService(key, legacyDir, this); + } + } +// else if (!m_settings->read("initializing").toBool()) +// { +// qWarning() << "Missing private key for initialized identity"; +// return; +// } + else + { + d->hiddenService = new Tor::HiddenService(legacyDir, this); + + connect(d->hiddenService, SIGNAL(Tor::HiddenService::privateKeyChanged), this, SLOT(hiddenServicePrivateKeyChanged())) ; + } + + Q_ASSERT(d->hiddenService); + connect(d->hiddenService, 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 = QHostAddress::LocalHost; // we only listen from localhost + + quint16 port = 7934;//(quint16)m_settings->read("localListenPort").toInt(); + + if (!QTcpServer().listen(address, port)) + { + // XXX error case + qWarning() << "Failed to open incoming socket on port :" << port; + return false; + } + + //d->hiddenService->addTarget(9878, mIncomingServer->serverAddress(), mIncomingServer->serverPort()); + d->hiddenService->addTarget(9878, QHostAddress::LocalHost,7934); + torControl->addHiddenService(d->hiddenService); + + return true ; +} + +void TorManager::hiddenServicePrivateKeyChanged() +{ + QString key = QString::fromLatin1(d->hiddenService->privateKey().encodedPrivateKey(CryptoKey::DER).toBase64()); + + QFile outfile(d->hiddenServiceDir + QLatin1String("/private_key")) ; + outfile.open( QIODevice::WriteOnly | QIODevice::Text ); + QTextStream s(&outfile); + + s << key ; + outfile.close(); +} + bool TorManager::configurationNeeded() const { return d->configNeeded; diff --git a/retroshare-gui/src/TorControl/TorManager.h b/retroshare-gui/src/TorControl/TorManager.h index 86b4327a0..883159efb 100644 --- a/retroshare-gui/src/TorControl/TorManager.h +++ b/retroshare-gui/src/TorControl/TorManager.h @@ -60,6 +60,7 @@ class TorManager : public QObject Q_PROPERTY(QString dataDirectory READ dataDirectory WRITE setDataDirectory) public: + explicit TorManager(QObject *parent = 0); static TorManager *instance(); @@ -69,6 +70,12 @@ public: QString dataDirectory() const; void setDataDirectory(const QString &path); + QString hiddenServiceDirectory() const; + void setHiddenServiceDirectory(const QString &path); + + // Starts a hidden service, loading it from the config directory that has been set earlier. + bool setupHiddenService() ; + // True on first run or when the Tor configuration wizard needs to be shown bool configurationNeeded() const; @@ -80,6 +87,9 @@ public: public slots: void start(); +private slots: + void hiddenServicePrivateKeyChanged(); + signals: void configurationNeededChanged(); void errorChanged(); diff --git a/retroshare-gui/src/main.cpp b/retroshare-gui/src/main.cpp index 3357bd688..b12ca021d 100644 --- a/retroshare-gui/src/main.cpp +++ b/retroshare-gui/src/main.cpp @@ -379,7 +379,7 @@ feenableexcept(FE_INVALID | FE_DIVBYZERO); // Now that we know the Tor service running, and we know the SSL id, we can make sure it provides a viable hidden service { - torManager->setDataDirectory(Rshare::dataDirectory() + QString("/tor/")); // re-set it, because now it's changed to the specific location that is run + torManager->setDataDirectory(Rshare::dataDirectory() + QString("/hidden_service/")); // re-set it, because now it's changed to the specific location that is run TorControlDialog tcd(torManager) ; tcd.show();