moved TorControl files into libretroshare. Not compiling yet.

This commit is contained in:
csoler 2021-06-19 15:34:46 +02:00
parent 20c0032ca8
commit d7fb3d8bf4
42 changed files with 294 additions and 175 deletions

View File

@ -719,6 +719,46 @@ SOURCES += rsitems/rsnxsitems.cc \
gxs/rsgxsutil.cc \
gxs/rsgxsrequesttypes.cc
# Tor
HEADERS += tor/AddOnionCommand.h \
tor/AuthenticateCommand.h \
tor/CryptoKey.h \
tor/GetConfCommand.h \
tor/HiddenService.h \
tor/PendingOperation.h \
tor/ProtocolInfoCommand.h \
tor/SecureRNG.h \
tor/TorTypes.h \
tor/SetConfCommand.h \
tor/Settings.h \
tor/StrUtil.h \
tor/TorControl.h \
tor/TorControlCommand.h \
tor/TorControlSocket.h \
tor/TorManager.h \
tor/TorProcess.h \
tor/TorProcess_p.h \
tor/TorSocket.h \
tor/Useful.h
SOURCES += tor/AddOnionCommand.cpp \
tor/AuthenticateCommand.cpp \
tor/GetConfCommand.cpp \
tor/HiddenService.cpp \
tor/ProtocolInfoCommand.cpp \
tor/SetConfCommand.cpp \
tor/TorControlCommand.cpp \
tor/TorControl.cpp \
tor/TorControlSocket.cpp \
tor/TorManager.cpp \
tor/TorProcess.cpp \
tor/TorSocket.cpp \
tor/CryptoKey.cpp \
tor/PendingOperation.cpp \
tor/SecureRNG.cpp \
tor/Settings.cpp \
tor/StrUtil.cpp
# gxs tunnels
HEADERS += gxstunnel/p3gxstunnel.h \
gxstunnel/rsgxstunnelitems.h \

View File

@ -34,9 +34,7 @@
#define ADDONIONCOMMAND_H
#include "TorControlCommand.h"
#include <QList>
#include <QPair>
#include <QVariant>
#include <list>
namespace Tor
{
@ -45,27 +43,28 @@ class HiddenService;
class AddOnionCommand : public TorControlCommand
{
Q_OBJECT
Q_DISABLE_COPY(AddOnionCommand)
Q_PROPERTY(QString errorMessage READ errorMessage CONSTANT)
#ifdef NO_TOR_CONTROL_PROPERTIES
Q_PROPERTY(std::string errorMessage READ errorMessage CONSTANT)
Q_PROPERTY(bool successful READ isSuccessful CONSTANT)
#endif
public:
AddOnionCommand(HiddenService *service);
QByteArray build();
QString errorMessage() const { return m_errorMessage; }
std::string errorMessage() const { return m_errorMessage; }
bool isSuccessful() const;
#ifdef NO_TOR_CONTROL_SIGNALS
signals:
void succeeded();
void failed(int code);
#endif
protected:
HiddenService *m_service;
QString m_errorMessage;
std::string m_errorMessage;
virtual void onReply(int statusCode, const QByteArray &data);
virtual void onFinished(int statusCode);

View File

@ -31,13 +31,13 @@
*/
#include <iostream>
#include <stdio.h>
#include "CryptoKey.h"
#include "SecureRNG.h"
#include "Useful.h"
#include <QtDebug>
#include <QFile>
#include <QByteArray>
#include "TorTypes.h"
#include <openssl/bn.h>
#include <openssl/bio.h>
#include <openssl/pem.h>
@ -120,17 +120,23 @@ bool CryptoKey::loadFromData(const QByteArray &data, KeyType type, KeyFormat for
}
#endif
bool CryptoKey::loadFromFile(const QString& path)
bool CryptoKey::loadFromFile(const std::string &path)
{
QFile file(path);
if (!file.open(QIODevice::ReadOnly))
FILE *f = fopen(path.c_str(),"r");
if(!f)
{
qWarning() << "Failed to open Tor key file " << path << ": " << file.errorString();
std::cerr << "Failed to open Tor key file " << path << std::endl;
return false;
}
QByteArray data = file.readAll();
file.close();
Tor::TorByteArray data ;
int c;
while( EOF != (c=fgetc(f)))
data += (unsigned char)c;
fclose(f);
if(data.contains("-----BEGIN RSA PRIVATE KEY-----"))
{
@ -146,14 +152,14 @@ bool CryptoKey::loadFromFile(const QString& path)
}
std::cerr << "Have read the following key: " << std::endl;
std::cerr << QString(data).toStdString() << std::endl;
std::cerr << data.toStdString() << std::endl;
key_data = data;
return true;
}
bool CryptoKey::loadFromTorMessage(const QByteArray& b)
bool CryptoKey::loadFromTorMessage(const Tor::TorByteArray& b)
{
// note: We should probably check the structure a bit more, for security.
@ -163,7 +169,7 @@ bool CryptoKey::loadFromTorMessage(const QByteArray& b)
std::cerr << " type: RSA-1024 (Tor v2)" << std::endl;
else if(b.startsWith("ED25519-V3"))
std::cerr << " type: ED25519-V3 (Tor v3)" << std::endl;
else if(b.indexOf(':'))
else if(b.indexOf(':') >= 0)
{
std::cerr << " unknown type, or bad syntax in key: \"" << b.left(b.indexOf(':')).toStdString() << "\". Not accepted." << std::endl;
return false;
@ -174,22 +180,22 @@ bool CryptoKey::loadFromTorMessage(const QByteArray& b)
}
/* Cryptographic hash of a password as expected by Tor's HashedControlPassword */
QByteArray torControlHashedPassword(const QByteArray &password)
Tor::TorByteArray torControlHashedPassword(const Tor::TorByteArray& password)
{
QByteArray salt = SecureRNG::random(8);
Tor::TorByteArray salt = SecureRNG::random(8);
if (salt.isNull())
return QByteArray();
return Tor::TorByteArray();
int count = ((quint32)16 + (96 & 15)) << ((96 >> 4) + 6);
SHA_CTX hash;
SHA1_Init(&hash);
QByteArray tmp = salt + password;
Tor::TorByteArray tmp = salt + password;
while (count)
{
int c = qMin(count, tmp.size());
SHA1_Update(&hash, reinterpret_cast<const void*>(tmp.constData()), c);
int c = std::min(count, tmp.size());
SHA1_Update(&hash, reinterpret_cast<const void*>(tmp.data()), c);
count -= c;
}
@ -197,8 +203,8 @@ QByteArray torControlHashedPassword(const QByteArray &password)
SHA1_Final(md, &hash);
/* 60 is the hex-encoded value of 96, which is a constant used by Tor's algorithm. */
return QByteArray("16:") + salt.toHex().toUpper() + QByteArray("60") +
QByteArray::fromRawData(reinterpret_cast<const char*>(md), 20).toHex().toUpper();
return Tor::TorByteArray("16:") + salt.toHex().toUpper() + Tor::TorByteArray("60") +
Tor::TorByteArray::fromRawData(reinterpret_cast<const char*>(md), 20).toHex().toUpper();
}

View File

@ -33,9 +33,7 @@
#ifndef CRYPTOKEY_H
#define CRYPTOKEY_H
#include <QString>
#include <QSharedData>
#include <QExplicitlySharedDataPointer>
#include "tor/TorTypes.h"
class CryptoKey
{
@ -57,12 +55,13 @@ public:
bool loadFromData(const QByteArray &data, KeyType type, KeyFormat format = PEM);
bool loadFromFile(const QString &path, KeyType type, KeyFormat format = PEM);
#endif
bool loadFromFile(const QString &path);
bool loadFromFile(const std::string& path);
void clear();
const QByteArray bytes() const { return key_data; }
bool loadFromTorMessage(const QByteArray& b);
bool isLoaded() const { return !key_data.isNull(); }
const Tor::TorByteArray& bytes() const { return key_data; }
bool loadFromTorMessage(const Tor::TorByteArray& b);
bool isLoaded() const { return !key_data.empty(); }
#ifdef TO_REMOVE
bool isPrivate() const;
@ -101,6 +100,6 @@ private:
#endif
};
QByteArray torControlHashedPassword(const QByteArray &password);
Tor::TorByteArray torControlHashedPassword(const Tor::TorByteArray& password);
#endif // CRYPTOKEY_H

View File

@ -30,9 +30,11 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdexcept>
#include "TorTypes.h"
#include "GetConfCommand.h"
#include "StrUtil.h"
#include <QDebug>
using namespace Tor;
@ -43,27 +45,28 @@ GetConfCommand::GetConfCommand(Type t)
QByteArray GetConfCommand::build(const QByteArray &key)
{
return build(QList<QByteArray>() << key);
return build(std::list<QByteArray>{key});
}
QByteArray GetConfCommand::build(const QList<QByteArray> &keys)
QByteArray GetConfCommand::build(const std::list<QByteArray> &keys)
{
QByteArray out;
if (type == GetConf) {
out = "GETCONF";
out = QByteArray("GETCONF");
} else if (type == GetInfo) {
out = "GETINFO";
out = QByteArray("GETINFO");
} else {
Q_ASSERT(false);
throw std::runtime_error("Unsupported build type in GetConfCommand");
return out;
}
foreach (const QByteArray &key, keys) {
out.append(' ');
out.append(key);
for(const QByteArray& key: keys)
{
out += (' ');
out += key;
}
out.append("\r\n");
out += std::string("\r\n");
return out;
}
@ -74,7 +77,7 @@ void GetConfCommand::onReply(int statusCode, const QByteArray &data)
return;
int kep = data.indexOf('=');
QString key = QString::fromLatin1(data.mid(0, kep));
std::string key = QString::fromLatin1(data.mid(0, kep));
QVariant value;
if (kep >= 0)
value = QString::fromLatin1(unquotedString(data.mid(kep + 1)));

View File

@ -34,18 +34,16 @@
#define GETCONFCOMMAND_H
#include "TorControlCommand.h"
#include <QList>
#include <QVariantMap>
#include <list>
namespace Tor
{
class GetConfCommand : public TorControlCommand
{
Q_OBJECT
Q_DISABLE_COPY(GetConfCommand)
#ifdef NO_TOR_CONTROL_PROPERTIES
Q_PROPERTY(QVariantMap results READ results CONSTANT)
#endif
public:
enum Type {
@ -57,10 +55,10 @@ public:
GetConfCommand(Type type);
QByteArray build(const QByteArray &key);
QByteArray build(const QList<QByteArray> &keys);
QByteArray build(const std::list<QByteArray> &keys);
const QVariantMap &results() const { return m_results; }
QVariant get(const QByteArray &key) const;
const QVariantMap& results() const { return m_results; }
QVariant get(const QByteArray& key) const;
protected:
virtual void onReply(int statusCode, const QByteArray &data);
@ -69,7 +67,7 @@ protected:
private:
QVariantMap m_results;
QString m_lastKey;
std::string m_lastKey;
};
}

View File

@ -90,7 +90,7 @@ void HiddenService::addTarget(quint16 servicePort, QHostAddress targetAddress, q
m_targets.append(t);
}
void HiddenService::setServiceId(const QByteArray& sid)
void HiddenService::setServiceId(const TorByteArray &sid)
{
m_service_id = sid;
m_hostname = sid + ".onion";

View File

@ -33,28 +33,25 @@
#ifndef HIDDENSERVICE_H
#define HIDDENSERVICE_H
#include <QObject>
#include <QHostAddress>
#include <QList>
#include "CryptoKey.h"
#include <string>
#include <list>
#include "tor/CryptoKey.h"
#include "tor/TorTypes.h"
namespace Tor
{
class TorSocket;
class HiddenService : public QObject
class HiddenService : public NonCopiable
{
Q_OBJECT
Q_DISABLE_COPY(HiddenService)
friend class TorControlPrivate;
public:
struct Target
{
QHostAddress targetAddress;
quint16 servicePort, targetPort;
TorHostAddress targetAddress;
unsigned short servicePort, targetPort;
};
enum Status
@ -64,24 +61,25 @@ public:
Online /* Published */
};
HiddenService(QObject *parent = 0);
HiddenService(const QString &dataPath, QObject *parent = 0);
HiddenService(const CryptoKey &privateKey, const QString &dataPath = QString(), QObject *parent = 0);
HiddenService();
HiddenService(const std::string& dataPath);
HiddenService(const CryptoKey& privateKey, const std::string& dataPath = std::string());
Status status() const { return m_status; }
const QString& hostname() const { return m_hostname; }
const QString serviceId() const { return QString(m_service_id); }
const QString& dataPath() const { return m_dataPath; }
const std::string& hostname() const { return m_hostname; }
const std::string serviceId() const { return std::string(m_service_id.data()); }
const std::string& dataPath() const { return m_dataPath; }
CryptoKey privateKey() { return m_privateKey; }
void setPrivateKey(const CryptoKey &privateKey);
void setServiceId(const QByteArray& sid);
void setServiceId(const TorByteArray& sid);
const QList<Target> &targets() const { return m_targets; }
const std::list<Target>& targets() const { return m_targets; }
void addTarget(const Target &target);
void addTarget(quint16 servicePort, QHostAddress targetAddress, quint16 targetPort);
void addTarget(unsigned short servicePort, TorHostAddress targetAddress, unsigned short targetPort);
#ifdef NO_TOR_CONTROL_SIGNALS
signals:
void statusChanged(int newStatus, int oldStatus);
void serviceOnline();
@ -90,14 +88,15 @@ signals:
private slots:
void servicePublished();
#endif
private:
QString m_dataPath;
QList<Target> m_targets;
QString m_hostname;
std::string m_dataPath;
std::list<Target> m_targets;
std::string m_hostname;
Status m_status;
CryptoKey m_privateKey;
QByteArray m_service_id;
TorByteArray m_service_id;
void loadPrivateKey();
void setStatus(Status newStatus);

View File

@ -33,8 +33,17 @@
#ifndef PROTOCOLINFOCOMMAND_H
#define PROTOCOLINFOCOMMAND_H
#include <retroshare/rsflags.h>
#include "TorControlCommand.h"
#include <QFlags>
enum class AuthMethods: uint8_t
{
AuthUnknown = 0x0,
AuthNull = 0x1,
AuthHashedPassword = 0x2,
AuthCookie = 0x4
};
RS_REGISTER_ENUM_FLAGS_TYPE(AuthMethods)
namespace Tor
{
@ -43,25 +52,13 @@ class TorControl;
class ProtocolInfoCommand : public TorControlCommand
{
Q_OBJECT
Q_DISABLE_COPY(ProtocolInfoCommand)
public:
enum AuthMethod
{
AuthUnknown = 0,
AuthNull = 0x1,
AuthHashedPassword = 0x2,
AuthCookie = 0x4
};
Q_DECLARE_FLAGS(AuthMethods, AuthMethod)
ProtocolInfoCommand(TorControl *manager);
QByteArray build();
AuthMethods authMethods() const { return m_authMethods; }
QString torVersion() const { return m_torVersion; }
QString cookieFile() const { return m_cookieFile; }
std::string torVersion() const { return m_torVersion; }
std::string cookieFile() const { return m_cookieFile; }
protected:
virtual void onReply(int statusCode, const QByteArray &data);
@ -69,8 +66,8 @@ protected:
private:
TorControl *manager;
AuthMethods m_authMethods;
QString m_torVersion;
QString m_cookieFile;
std::string m_torVersion;
std::string m_cookieFile;
};
}

View File

@ -31,10 +31,12 @@
*/
#include "SecureRNG.h"
#include <QtDebug>
#include <openssl/rand.h>
#include <openssl/err.h>
#include <limits.h>
#include <iostream>
#include <sstream>
#ifdef Q_OS_WIN
#include <wtypes.h>
@ -82,7 +84,7 @@ bool SecureRNG::seed()
#else
if (!RAND_poll())
{
qWarning() << "OpenSSL RNG seed failed:" << ERR_get_error();
std::cerr << "OpenSSL RNG seed failed:" << ERR_get_error();
return false;
}
#endif
@ -94,11 +96,16 @@ bool SecureRNG::seed()
return true;
}
void SecureRNG::random(char *buf, int size)
void SecureRNG::random(unsigned char *buf, int size)
{
int r = RAND_bytes(reinterpret_cast<unsigned char*>(buf), size);
int r = RAND_bytes(buf, size);
if (r <= 0)
qFatal("RNG failed: %lu", ERR_get_error());
{
std::ostringstream s;
s << "RNG failed: " << ERR_get_error() ;
throw std::runtime_error(s.str());
}
}
QByteArray SecureRNG::random(int size)
@ -111,7 +118,7 @@ QByteArray SecureRNG::random(int size)
QByteArray SecureRNG::randomPrintable(int length)
{
QByteArray re(length, 0);
for (int i = 0; i < re.size(); i++)
for (uint32_t i = 0; i < re.size(); i++)
re[i] = randomInt(95) + 32;
return re;
}
@ -123,24 +130,24 @@ unsigned SecureRNG::randomInt(unsigned max)
for (;;)
{
random(reinterpret_cast<char*>(&value), sizeof(value));
random(reinterpret_cast<unsigned char*>(&value), sizeof(value));
if (value < cutoff)
return value % max;
}
}
#ifndef UINT64_MAX
#define UINT64_MAX ((quint64)-1)
#define UINT64_MAX ((uint64_t)-1)
#endif
quint64 SecureRNG::randomInt64(quint64 max)
uint64_t SecureRNG::randomInt64(uint64_t max)
{
quint64 cutoff = UINT64_MAX - (UINT64_MAX % max);
quint64 value = 0;
uint64_t cutoff = UINT64_MAX - (UINT64_MAX % max);
uint64_t value = 0;
for (;;)
{
random(reinterpret_cast<char*>(value), sizeof(value));
random(reinterpret_cast<unsigned char*>(value), sizeof(value));
if (value < cutoff)
return value % max;
}

View File

@ -33,19 +33,19 @@
#ifndef SECURERNG_H
#define SECURERNG_H
#include <QByteArray>
#include "TorTypes.h"
class SecureRNG
{
public:
static bool seed();
static void random(char *buf, int size);
static QByteArray random(int size);
static void random(unsigned char *buf, int size);
static Tor::TorByteArray random(int size);
static QByteArray randomPrintable(int length);
static Tor::TorByteArray randomPrintable(int length);
static unsigned randomInt(unsigned max);
static quint64 randomInt64(quint64 max);
static uint64_t randomInt64(uint64_t max);
};
#endif // SECURERNG_H

View File

@ -32,14 +32,14 @@
#include "StrUtil.h"
QByteArray quotedString(const QByteArray &string)
QByteArray quotedString(const QByteArray& string)
{
QByteArray out;
out.reserve(string.size() * 2);
out.append('"');
out += '"';
for (int i = 0; i < string.size(); ++i)
for (uint32_t i = 0; i < string.size(); ++i)
{
switch (string[i])
{
@ -67,7 +67,7 @@ QByteArray unquotedString(const QByteArray &string)
QByteArray out;
out.reserve(string.size() - 2);
for (int i = 1; i < string.size(); ++i)
for (uint32_t i = 1; i < string.size(); ++i)
{
switch (string[i])
{
@ -85,9 +85,9 @@ QByteArray unquotedString(const QByteArray &string)
return out;
}
QList<QByteArray> splitQuotedStrings(const QByteArray &input, char separator)
std::list<QByteArray> splitQuotedStrings(const QByteArray &input, char separator)
{
QList<QByteArray> out;
std::list<QByteArray> out;
bool inquote = false;
int start = 0;

View File

@ -33,14 +33,14 @@
#ifndef STRINGUTIL_H
#define STRINGUTIL_H
#include <QByteArray>
#include <QList>
#include "TorTypes.h"
#include <list>
QByteArray quotedString(const QByteArray &string);
/* Return the unquoted contents of a string, either until an end quote or an unescaped separator character. */
QByteArray unquotedString(const QByteArray &string);
QList<QByteArray> splitQuotedStrings(const QByteArray &input, char separator);
std::list<QByteArray> splitQuotedStrings(const QByteArray &input, char separator);
#endif // STRINGUTIL_H

View File

@ -33,32 +33,31 @@
#ifndef TORCONTROLCOMMAND_H
#define TORCONTROLCOMMAND_H
#include <QObject>
#include <QByteArray>
#include <vector>
#include "tor/TorTypes.h"
namespace Tor
{
class TorControlCommand : public QObject
class TorControlCommand : public NonCopiable
{
Q_OBJECT
Q_DISABLE_COPY(TorControlCommand)
friend class TorControlSocket;
public:
TorControlCommand();
virtual ~TorControlCommand() {}
int statusCode() const { return m_finalStatus; }
#ifdef NO_TOR_CONTROL_SIGNALS
signals:
void replyLine(int statusCode, const QByteArray &data);
void replyLine(int statusCode, const TorByteArray& data);
void finished();
#endif
protected:
virtual void onReply(int statusCode, const QByteArray &data);
virtual void onReply(int statusCode, const TorByteArray& data);
virtual void onFinished(int statusCode);
virtual void onDataLine(const QByteArray &data);
virtual void onDataLine(const TorByteArray& data);
virtual void onDataFinished();
private:

View File

@ -0,0 +1,112 @@
#pragma once
#include <vector>
#include <string>
namespace Tor
{
class NonCopiable {
public:
NonCopiable(){}
virtual ~NonCopiable()=default;
private:
NonCopiable(const NonCopiable& nc) {}
virtual NonCopiable& operator=(const NonCopiable& nc) { return *this ; }
};
class TorByteArray: public std::vector<unsigned char>
{
public:
TorByteArray(const std::string& s = std::string())
{
clear();
for(uint32_t i=0;i<s.length();++i)
push_back(s[i]);
}
TorByteArray(uint32_t s,unsigned char c)
{
clear();
resize(s,c);
}
bool startsWith(const std::string& s) const
{
if(s.length() > size())
return false;
for(uint32_t i=0;i<s.length();++i)
if(s[i] != data()[i])
return false;
return true;
}
int indexOf(unsigned char c) const
{
for(uint32_t i=0;i<size();++i)
if(data()[i] == c)
return i;
return -1;
}
const TorByteArray& operator+= (unsigned char s) { push_back(s); return *this ;}
TorByteArray left(uint32_t n) const
{
auto res = TorByteArray();
for(size_t i=0;i<std::min((size_t)n,size());++i)
res.push_back(data()[i]);
return res;
}
const TorByteArray& operator+=(const TorByteArray& t)
{
for(uint32_t i=0;i<t.size();++i)
push_back(t.data()[i]);
return *this;
}
const TorByteArray& append(const std::string& s) { return operator+=(s); }
const TorByteArray& append(char s) { return operator+=(s); }
TorByteArray operator+(const TorByteArray& t) const
{
auto res = *this;
for(uint32_t i=0;i<t.size();++i)
res.push_back(t[i]);
return res;
}
std::string toStdString() const
{
return std::string((const char *)data(),size());
}
bool contains(const TorByteArray& b) const
{
if(b.size() > size())
return false;
for(uint32_t i=0;i<size()-b.size();++i)
{
bool c = true;
for(uint32_t j=0;j<b.size();++j)
if(b[j] != data()[i+j])
{
c = false;
break;
}
if(c)
return true;
}
return false;
}
};
typedef std::string TorHostAddress;
}
typedef Tor::TorByteArray QByteArray; // to be removed

View File

@ -364,46 +364,6 @@ wikipoos {
################################### HEADERS & SOURCES #############################
# Tor controller
HEADERS += TorControl/AddOnionCommand.h \
TorControl/AuthenticateCommand.h \
TorControl/CryptoKey.h \
TorControl/GetConfCommand.h \
TorControl/HiddenService.h \
TorControl/PendingOperation.h \
TorControl/ProtocolInfoCommand.h \
TorControl/SecureRNG.h \
TorControl/SetConfCommand.h \
TorControl/Settings.h \
TorControl/StrUtil.h \
TorControl/TorControl.h \
TorControl/TorControlCommand.h \
TorControl/TorControlSocket.h \
TorControl/TorManager.h \
TorControl/TorProcess.h \
TorControl/TorProcess_p.h \
TorControl/TorSocket.h \
TorControl/Useful.h
SOURCES += TorControl/AddOnionCommand.cpp \
TorControl/AuthenticateCommand.cpp \
TorControl/GetConfCommand.cpp \
TorControl/HiddenService.cpp \
TorControl/ProtocolInfoCommand.cpp \
TorControl/SetConfCommand.cpp \
TorControl/TorControlCommand.cpp \
TorControl/TorControl.cpp \
TorControl/TorControlSocket.cpp \
TorControl/TorManager.cpp \
TorControl/TorProcess.cpp \
TorControl/TorSocket.cpp \
TorControl/CryptoKey.cpp \
TorControl/PendingOperation.cpp \
TorControl/SecureRNG.cpp \
TorControl/Settings.cpp \
TorControl/StrUtil.cpp
# Input
HEADERS += rshare.h \
retroshare-gui/configpage.h \