mirror of
https://github.com/RetroShare/RetroShare.git
synced 2025-01-18 10:57:18 -05:00
switching QString to std::string and QByteArray to ByteArray. Unfinished yet.
This commit is contained in:
parent
3845dc1ea7
commit
e4ce32bef8
@ -369,6 +369,8 @@ HEADERS += pqi/authssl.h \
|
||||
pqi/authgpg.h \
|
||||
pgp/pgphandler.h \
|
||||
pgp/pgpkeyutil.h \
|
||||
pqi/pqifdbin.h \
|
||||
pqi/rstcpsocket.h \
|
||||
pgp/rscertificate.h \
|
||||
pgp/pgpauxutils.h \
|
||||
pqi/p3cfgmgr.h \
|
||||
@ -545,6 +547,8 @@ SOURCES += pqi/authgpg.cc \
|
||||
pqi/p3cfgmgr.cc \
|
||||
pqi/p3peermgr.cc \
|
||||
pqi/p3linkmgr.cc \
|
||||
pqi/pqifdbin.cc \
|
||||
pqi/rstcpsocket.cc \
|
||||
pqi/p3netmgr.cc \
|
||||
pqi/p3notify.cc \
|
||||
pqi/pqiqos.cc \
|
||||
@ -733,6 +737,7 @@ HEADERS += tor/AddOnionCommand.h \
|
||||
tor/SetConfCommand.h \
|
||||
tor/Settings.h \
|
||||
tor/StrUtil.h \
|
||||
tor/bytearray.h \
|
||||
tor/TorControl.h \
|
||||
tor/TorControlCommand.h \
|
||||
tor/TorControlSocket.h \
|
||||
|
@ -38,27 +38,29 @@ AuthenticateCommand::AuthenticateCommand()
|
||||
{
|
||||
}
|
||||
|
||||
QByteArray AuthenticateCommand::build(const QByteArray &data)
|
||||
ByteArray AuthenticateCommand::build(const ByteArray& data)
|
||||
{
|
||||
if (data.isNull())
|
||||
return QByteArray("AUTHENTICATE\r\n");
|
||||
return ByteArray("AUTHENTICATE\r\n");
|
||||
|
||||
return QByteArray("AUTHENTICATE ") + data.toHex() + "\r\n";
|
||||
return ByteArray("AUTHENTICATE ") + data.toHex() + "\r\n";
|
||||
}
|
||||
|
||||
void AuthenticateCommand::onReply(int statusCode, const QByteArray &data)
|
||||
void AuthenticateCommand::onReply(int statusCode, const ByteArray &data)
|
||||
{
|
||||
TorControlCommand::onReply(statusCode, data);
|
||||
m_statusMessage = QString::fromLatin1(data);
|
||||
m_statusMessage = data.toString();
|
||||
}
|
||||
|
||||
void AuthenticateCommand::onFinished(int statusCode)
|
||||
{
|
||||
if (statusCode == 515) {
|
||||
m_statusMessage = QStringLiteral("Authentication failed - incorrect password");
|
||||
} else if (statusCode != 250) {
|
||||
if (m_statusMessage.isEmpty())
|
||||
m_statusMessage = QStringLiteral("Authentication failed (error %1").arg(statusCode);
|
||||
m_statusMessage = "Authentication failed - incorrect password";
|
||||
}
|
||||
else if (statusCode != 250)
|
||||
{
|
||||
if (m_statusMessage.empty())
|
||||
m_statusMessage = "Authentication failed (error " + RsUtil::NumberToString(statusCode) + ")";
|
||||
}
|
||||
TorControlCommand::onFinished(statusCode);
|
||||
}
|
||||
|
@ -33,6 +33,7 @@
|
||||
#ifndef AUTHENTICATECOMMAND_H
|
||||
#define AUTHENTICATECOMMAND_H
|
||||
|
||||
#include "bytearray.h"
|
||||
#include "TorControlCommand.h"
|
||||
|
||||
namespace Tor
|
||||
@ -45,17 +46,17 @@ class AuthenticateCommand : public TorControlCommand
|
||||
public:
|
||||
AuthenticateCommand();
|
||||
|
||||
QByteArray build(const QByteArray &data = QByteArray());
|
||||
ByteArray build(const ByteArray& data = ByteArray());
|
||||
|
||||
bool isSuccessful() const { return statusCode() == 250; }
|
||||
QString errorMessage() const { return m_statusMessage; }
|
||||
std::string errorMessage() const { return m_statusMessage; }
|
||||
|
||||
protected:
|
||||
virtual void onReply(int statusCode, const QByteArray &data);
|
||||
virtual void onReply(int statusCode, const ByteArray &data);
|
||||
virtual void onFinished(int statusCode);
|
||||
|
||||
private:
|
||||
QString m_statusMessage;
|
||||
std::string m_statusMessage;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -35,13 +35,18 @@
|
||||
#include "CryptoKey.h"
|
||||
#include "SecureRNG.h"
|
||||
#include "Useful.h"
|
||||
#include <QtDebug>
|
||||
#include <QFile>
|
||||
#include <QByteArray>
|
||||
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/bio.h>
|
||||
#include <openssl/pem.h>
|
||||
|
||||
#include "stdio.h"
|
||||
#include "util/rsdebug.h"
|
||||
#include "util/rsrandom.h"
|
||||
#include "util/rsdir.h"
|
||||
#include "retroshare/rsids.h"
|
||||
#include "bytearray.h"
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
|
||||
void RSA_get0_factors(const RSA *r, const BIGNUM **p, const BIGNUM **q)
|
||||
{
|
||||
@ -51,11 +56,6 @@ void RSA_get0_factors(const RSA *r, const BIGNUM **p, const BIGNUM **q)
|
||||
#define RSA_bits(o) (BN_num_bits((o)->n))
|
||||
#endif
|
||||
|
||||
#ifdef TO_REMOVE
|
||||
void base32_encode(char *dest, unsigned destlen, const char *src, unsigned srclen);
|
||||
bool base32_decode(char *dest, unsigned destlen, const char *src, unsigned srclen);
|
||||
#endif
|
||||
|
||||
CryptoKey::CryptoKey()
|
||||
{
|
||||
}
|
||||
@ -65,95 +65,50 @@ CryptoKey::~CryptoKey()
|
||||
clear();
|
||||
}
|
||||
|
||||
#ifdef TO_REMOVE
|
||||
CryptoKey::Data::~Data()
|
||||
{
|
||||
if (key)
|
||||
{
|
||||
RSA_free(key);
|
||||
key = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void CryptoKey::clear()
|
||||
{
|
||||
key_data.clear();
|
||||
}
|
||||
|
||||
#ifdef TO_REMOVE
|
||||
bool CryptoKey::loadFromData(const QByteArray &data, KeyType type, KeyFormat format)
|
||||
bool CryptoKey::loadFromFile(const std::string& path)
|
||||
{
|
||||
RSA *key = NULL;
|
||||
clear();
|
||||
FILE *file = fopen(path.c_str(),"r");
|
||||
|
||||
if (data.isEmpty())
|
||||
return false;
|
||||
|
||||
if (format == PEM) {
|
||||
BIO *b = BIO_new_mem_buf((void*)data.constData(), -1);
|
||||
|
||||
if (type == PrivateKey)
|
||||
key = PEM_read_bio_RSAPrivateKey(b, NULL, NULL, NULL);
|
||||
else
|
||||
key = PEM_read_bio_RSAPublicKey(b, NULL, NULL, NULL);
|
||||
|
||||
BIO_free(b);
|
||||
} else if (format == DER) {
|
||||
const uchar *dp = reinterpret_cast<const uchar*>(data.constData());
|
||||
|
||||
if (type == PrivateKey)
|
||||
key = d2i_RSAPrivateKey(NULL, &dp, data.size());
|
||||
else
|
||||
key = d2i_RSAPublicKey(NULL, &dp, data.size());
|
||||
} else {
|
||||
Q_UNREACHABLE();
|
||||
}
|
||||
|
||||
if (!key) {
|
||||
qWarning() << "Failed to parse" << (type == PrivateKey ? "private" : "public") << "key from data";
|
||||
return false;
|
||||
}
|
||||
|
||||
d = new Data(key);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool CryptoKey::loadFromFile(const QString& path)
|
||||
{
|
||||
QFile file(path);
|
||||
if (!file.open(QIODevice::ReadOnly))
|
||||
if (!file)
|
||||
{
|
||||
qWarning() << "Failed to open Tor key file " << path << ": " << file.errorString();
|
||||
RsWarn() << "Failed to open Tor key file " << path << ": errno = " << errno ;
|
||||
return false;
|
||||
}
|
||||
|
||||
QByteArray data = file.readAll();
|
||||
file.close();
|
||||
ByteArray data ;
|
||||
int c;
|
||||
while(EOF != (c=fgetc(file)))
|
||||
data.append((unsigned char)c);
|
||||
|
||||
if(data.contains("-----BEGIN RSA PRIVATE KEY-----"))
|
||||
fclose(file);
|
||||
|
||||
if(data.startsWith("-----BEGIN RSA PRIVATE KEY-----"))
|
||||
{
|
||||
std::cerr << "Note: Reading/converting Tor v2 key format." << std::endl;
|
||||
|
||||
// This to be compliant with old format. New format is oblivious to the type of key so we dont need a header
|
||||
data = data.replace("-----BEGIN RSA PRIVATE KEY-----",nullptr);
|
||||
data = data.replace("-----END RSA PRIVATE KEY-----",nullptr);
|
||||
data = data.replace("\n",nullptr);
|
||||
data = data.replace("\t",nullptr);
|
||||
data = data.replace(ByteArray("-----BEGIN RSA PRIVATE KEY-----"),ByteArray());
|
||||
data = data.replace(ByteArray("-----END RSA PRIVATE KEY-----"),ByteArray());
|
||||
data = data.replace(ByteArray("\n"),ByteArray());
|
||||
data = data.replace(ByteArray("\t"),ByteArray());
|
||||
|
||||
data = "RSA1024:"+data;
|
||||
data = ByteArray("RSA1024:")+data;
|
||||
}
|
||||
|
||||
std::cerr << "Have read the following key: " << std::endl;
|
||||
std::cerr << QString(data).toStdString() << std::endl;
|
||||
std::cerr << data.toString() << std::endl;
|
||||
|
||||
key_data = data;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CryptoKey::loadFromTorMessage(const QByteArray& b)
|
||||
bool CryptoKey::loadFromTorMessage(const ByteArray& b)
|
||||
{
|
||||
// note: We should probably check the structure a bit more, for security.
|
||||
|
||||
@ -165,7 +120,7 @@ bool CryptoKey::loadFromTorMessage(const QByteArray& b)
|
||||
std::cerr << " type: ED25519-V3 (Tor v3)" << std::endl;
|
||||
else if(b.indexOf(':'))
|
||||
{
|
||||
std::cerr << " unknown type, or bad syntax in key: \"" << b.left(b.indexOf(':')).toStdString() << "\". Not accepted." << std::endl;
|
||||
std::cerr << " unknown type, or bad syntax in key: \"" << b.left(b.indexOf(':')).toString() << "\". Not accepted." << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -174,354 +129,15 @@ bool CryptoKey::loadFromTorMessage(const QByteArray& b)
|
||||
}
|
||||
|
||||
/* Cryptographic hash of a password as expected by Tor's HashedControlPassword */
|
||||
QByteArray torControlHashedPassword(const QByteArray &password)
|
||||
ByteArray torControlHashedPassword(const ByteArray &password)
|
||||
{
|
||||
QByteArray salt = SecureRNG::random(8);
|
||||
if (salt.isNull())
|
||||
return QByteArray();
|
||||
ByteArray salt(8);
|
||||
RsRandom::random_bytes(&salt[0],8);
|
||||
|
||||
int count = ((quint32)16 + (96 & 15)) << ((96 >> 4) + 6);
|
||||
uint32_t count = ((quint32)16 + (96 & 15)) << ((96 >> 4) + 6);
|
||||
|
||||
SHA_CTX hash;
|
||||
SHA1_Init(&hash);
|
||||
|
||||
QByteArray tmp = salt + password;
|
||||
while (count)
|
||||
{
|
||||
int c = qMin(count, tmp.size());
|
||||
SHA1_Update(&hash, reinterpret_cast<const void*>(tmp.constData()), c);
|
||||
count -= c;
|
||||
}
|
||||
|
||||
unsigned char md[20];
|
||||
SHA1_Final(md, &hash);
|
||||
Sha1CheckSum md = RsDirUtil::sha1sum((salt+password).data(),count);
|
||||
|
||||
/* 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 ByteArray("16:") + salt.toHex().toUpper() + ByteArray("60") + ByteArray(md.toByteArray(), md.SIZE_IN_BYTES).toHex().toUpper();
|
||||
}
|
||||
|
||||
|
||||
#ifdef TO_REMOVE
|
||||
bool CryptoKey::isPrivate() const
|
||||
{
|
||||
if (!isLoaded()) {
|
||||
return false;
|
||||
} else {
|
||||
const BIGNUM *p, *q;
|
||||
RSA_get0_factors(d->key, &p, &q);
|
||||
return (p != 0);
|
||||
}
|
||||
}
|
||||
|
||||
int CryptoKey::bits() const
|
||||
{
|
||||
return isLoaded() ? RSA_bits(d->key) : 0;
|
||||
}
|
||||
|
||||
QByteArray CryptoKey::publicKeyDigest() const
|
||||
{
|
||||
if (!isLoaded())
|
||||
return QByteArray();
|
||||
|
||||
QByteArray buf = encodedPublicKey(DER);
|
||||
|
||||
QByteArray re(20, 0);
|
||||
bool ok = SHA1(reinterpret_cast<const unsigned char*>(buf.constData()), buf.size(),
|
||||
reinterpret_cast<unsigned char*>(re.data())) != NULL;
|
||||
|
||||
if (!ok)
|
||||
{
|
||||
qWarning() << "Failed to hash public key data for digest";
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
return re;
|
||||
}
|
||||
|
||||
QByteArray CryptoKey::encodedPublicKey(KeyFormat format) const
|
||||
{
|
||||
if (!isLoaded())
|
||||
return QByteArray();
|
||||
|
||||
if (format == PEM) {
|
||||
BIO *b = BIO_new(BIO_s_mem());
|
||||
|
||||
if (!PEM_write_bio_RSAPublicKey(b, d->key)) {
|
||||
BUG() << "Failed to encode public key in PEM format";
|
||||
BIO_free(b);
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
BUF_MEM *buf;
|
||||
BIO_get_mem_ptr(b, &buf);
|
||||
|
||||
/* Close BIO, but don't free buf. */
|
||||
(void)BIO_set_close(b, BIO_NOCLOSE);
|
||||
BIO_free(b);
|
||||
|
||||
QByteArray re((const char *)buf->data, (int)buf->length);
|
||||
BUF_MEM_free(buf);
|
||||
return re;
|
||||
} else if (format == DER) {
|
||||
uchar *buf = NULL;
|
||||
int len = i2d_RSAPublicKey(d->key, &buf);
|
||||
if (len <= 0 || !buf) {
|
||||
BUG() << "Failed to encode public key in DER format";
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
QByteArray re((const char*)buf, len);
|
||||
OPENSSL_free(buf);
|
||||
return re;
|
||||
} else {
|
||||
Q_UNREACHABLE();
|
||||
}
|
||||
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
QByteArray CryptoKey::encodedPrivateKey(KeyFormat format) const
|
||||
{
|
||||
if (!isLoaded() || !isPrivate())
|
||||
return QByteArray();
|
||||
|
||||
if (format == PEM) {
|
||||
BIO *b = BIO_new(BIO_s_mem());
|
||||
|
||||
if (!PEM_write_bio_RSAPrivateKey(b, d->key, NULL, NULL, 0, NULL, NULL)) {
|
||||
BUG() << "Failed to encode private key in PEM format";
|
||||
BIO_free(b);
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
BUF_MEM *buf;
|
||||
BIO_get_mem_ptr(b, &buf);
|
||||
|
||||
/* Close BIO, but don't free buf. */
|
||||
(void)BIO_set_close(b, BIO_NOCLOSE);
|
||||
BIO_free(b);
|
||||
|
||||
QByteArray re((const char *)buf->data, (int)buf->length);
|
||||
BUF_MEM_free(buf);
|
||||
return re;
|
||||
} else if (format == DER) {
|
||||
uchar *buf = NULL;
|
||||
int len = i2d_RSAPrivateKey(d->key, &buf);
|
||||
if (len <= 0 || !buf) {
|
||||
BUG() << "Failed to encode private key in DER format";
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
QByteArray re((const char*)buf, len);
|
||||
OPENSSL_free(buf);
|
||||
return re;
|
||||
} else {
|
||||
Q_UNREACHABLE();
|
||||
}
|
||||
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
QString CryptoKey::torServiceID() const
|
||||
{
|
||||
if (!isLoaded())
|
||||
return QString();
|
||||
|
||||
QByteArray digest = publicKeyDigest();
|
||||
if (digest.isNull())
|
||||
return QString();
|
||||
|
||||
static const int hostnameDigestSize = 10;
|
||||
static const int hostnameEncodedSize = 16;
|
||||
|
||||
QByteArray re(hostnameEncodedSize+1, 0);
|
||||
base32_encode(re.data(), re.size(), digest.constData(), hostnameDigestSize);
|
||||
|
||||
// Chop extra null byte
|
||||
re.chop(1);
|
||||
|
||||
return QString::fromLatin1(re);
|
||||
}
|
||||
|
||||
QByteArray CryptoKey::signData(const QByteArray &data) const
|
||||
{
|
||||
QByteArray digest(32, 0);
|
||||
bool ok = SHA256(reinterpret_cast<const unsigned char*>(data.constData()), data.size(),
|
||||
reinterpret_cast<unsigned char*>(digest.data())) != NULL;
|
||||
if (!ok) {
|
||||
qWarning() << "Digest for RSA signature failed";
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
return signSHA256(digest);
|
||||
}
|
||||
|
||||
QByteArray CryptoKey::signSHA256(const QByteArray &digest) const
|
||||
{
|
||||
if (!isPrivate())
|
||||
return QByteArray();
|
||||
|
||||
QByteArray re(RSA_size(d->key), 0);
|
||||
unsigned sigsize = 0;
|
||||
int r = RSA_sign(NID_sha256, reinterpret_cast<const unsigned char*>(digest.constData()), digest.size(),
|
||||
reinterpret_cast<unsigned char*>(re.data()), &sigsize, d->key);
|
||||
|
||||
if (r != 1) {
|
||||
qWarning() << "RSA encryption failed when generating signature";
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
re.truncate(sigsize);
|
||||
return re;
|
||||
}
|
||||
|
||||
bool CryptoKey::verifyData(const QByteArray &data, QByteArray signature) const
|
||||
{
|
||||
QByteArray digest(32, 0);
|
||||
bool ok = SHA256(reinterpret_cast<const unsigned char*>(data.constData()), data.size(),
|
||||
reinterpret_cast<unsigned char*>(digest.data())) != NULL;
|
||||
|
||||
if (!ok) {
|
||||
qWarning() << "Digest for RSA verify failed";
|
||||
return false;
|
||||
}
|
||||
|
||||
return verifySHA256(digest, signature);
|
||||
}
|
||||
|
||||
bool CryptoKey::verifySHA256(const QByteArray &digest, QByteArray signature) const
|
||||
{
|
||||
if (!isLoaded())
|
||||
return false;
|
||||
|
||||
int r = RSA_verify(NID_sha256, reinterpret_cast<const uchar*>(digest.constData()), digest.size(),
|
||||
reinterpret_cast<uchar*>(signature.data()), signature.size(), d->key);
|
||||
if (r != 1)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Copyright (c) 2001-2004, Roger Dingledine
|
||||
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson
|
||||
* Copyright (c) 2007-2010, The Tor Project, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* Neither the names of the copyright owners nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#define BASE32_CHARS "abcdefghijklmnopqrstuvwxyz234567"
|
||||
|
||||
/* Implements base32 encoding as in rfc3548. Requires that srclen*8 is a multiple of 5. */
|
||||
void base32_encode(char *dest, unsigned destlen, const char *src, unsigned srclen)
|
||||
{
|
||||
unsigned i, bit, v, u;
|
||||
unsigned nbits = srclen * 8;
|
||||
|
||||
/* We need an even multiple of 5 bits, and enough space */
|
||||
if ((nbits%5) != 0 || destlen > (nbits/5)+1) {
|
||||
Q_ASSERT(false);
|
||||
memset(dest, 0, destlen);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0, bit = 0; bit < nbits; ++i, bit += 5)
|
||||
{
|
||||
/* set v to the 16-bit value starting at src[bits/8], 0-padded. */
|
||||
v = ((quint8) src[bit / 8]) << 8;
|
||||
if (bit + 5 < nbits)
|
||||
v += (quint8) src[(bit/8)+1];
|
||||
|
||||
/* set u to the 5-bit value at the bit'th bit of src. */
|
||||
u = (v >> (11 - (bit % 8))) & 0x1F;
|
||||
dest[i] = BASE32_CHARS[u];
|
||||
}
|
||||
|
||||
dest[i] = '\0';
|
||||
}
|
||||
|
||||
/* Implements base32 decoding as in rfc3548. Requires that srclen*5 is a multiple of 8. */
|
||||
bool base32_decode(char *dest, unsigned destlen, const char *src, unsigned srclen)
|
||||
{
|
||||
unsigned int i, j, bit;
|
||||
unsigned nbits = srclen * 5;
|
||||
|
||||
/* We need an even multiple of 8 bits, and enough space */
|
||||
if ((nbits%8) != 0 || (nbits/8)+1 > destlen) {
|
||||
Q_ASSERT(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
char *tmp = new char[srclen];
|
||||
|
||||
/* Convert base32 encoded chars to the 5-bit values that they represent. */
|
||||
for (j = 0; j < srclen; ++j)
|
||||
{
|
||||
if (src[j] > 0x60 && src[j] < 0x7B)
|
||||
tmp[j] = src[j] - 0x61;
|
||||
else if (src[j] > 0x31 && src[j] < 0x38)
|
||||
tmp[j] = src[j] - 0x18;
|
||||
else if (src[j] > 0x40 && src[j] < 0x5B)
|
||||
tmp[j] = src[j] - 0x41;
|
||||
else
|
||||
{
|
||||
delete[] tmp;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* Assemble result byte-wise by applying five possible cases. */
|
||||
for (i = 0, bit = 0; bit < nbits; ++i, bit += 8)
|
||||
{
|
||||
switch (bit % 40)
|
||||
{
|
||||
case 0:
|
||||
dest[i] = (((quint8)tmp[(bit/5)]) << 3) + (((quint8)tmp[(bit/5)+1]) >> 2);
|
||||
break;
|
||||
case 8:
|
||||
dest[i] = (((quint8)tmp[(bit/5)]) << 6) + (((quint8)tmp[(bit/5)+1]) << 1)
|
||||
+ (((quint8)tmp[(bit/5)+2]) >> 4);
|
||||
break;
|
||||
case 16:
|
||||
dest[i] = (((quint8)tmp[(bit/5)]) << 4) + (((quint8)tmp[(bit/5)+1]) >> 1);
|
||||
break;
|
||||
case 24:
|
||||
dest[i] = (((quint8)tmp[(bit/5)]) << 7) + (((quint8)tmp[(bit/5)+1]) << 2)
|
||||
+ (((quint8)tmp[(bit/5)+2]) >> 3);
|
||||
break;
|
||||
case 32:
|
||||
dest[i] = (((quint8)tmp[(bit/5)]) << 5) + ((quint8)tmp[(bit/5)+1]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
delete[] tmp;
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -37,6 +37,8 @@
|
||||
#include <QSharedData>
|
||||
#include <QExplicitlySharedDataPointer>
|
||||
|
||||
#include "bytearray.h"
|
||||
|
||||
class CryptoKey
|
||||
{
|
||||
public:
|
||||
@ -53,54 +55,17 @@ public:
|
||||
CryptoKey();
|
||||
~CryptoKey();
|
||||
|
||||
#ifdef TO_REMOVE
|
||||
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);
|
||||
const ByteArray bytes() const { return key_data; }
|
||||
bool loadFromTorMessage(const ByteArray& b);
|
||||
bool isLoaded() const { return !key_data.isNull(); }
|
||||
#ifdef TO_REMOVE
|
||||
bool isPrivate() const;
|
||||
|
||||
QByteArray publicKeyDigest() const;
|
||||
QByteArray encodedPublicKey(KeyFormat format) const;
|
||||
QByteArray encodedPrivateKey(KeyFormat format) const;
|
||||
QString torServiceID() const;
|
||||
int bits() const;
|
||||
|
||||
// Calculate and sign SHA-256 digest of data using this key and PKCS #1 v2.0 padding
|
||||
QByteArray signData(const QByteArray &data) const;
|
||||
// Verify a signature as per signData
|
||||
bool verifyData(const QByteArray &data, QByteArray signature) const;
|
||||
|
||||
// Sign the input SHA-256 digest using this key and PKCS #1 v2.0 padding
|
||||
QByteArray signSHA256(const QByteArray &digest) const;
|
||||
// Verify a signature as per signSHA256
|
||||
bool verifySHA256(const QByteArray &digest, QByteArray signature) const;
|
||||
#endif
|
||||
|
||||
private:
|
||||
#ifdef TO_REMOVE
|
||||
struct Data : public QSharedData
|
||||
{
|
||||
typedef struct rsa_st RSA;
|
||||
RSA *key;
|
||||
|
||||
Data(RSA *k = 0) : key(k) { }
|
||||
~Data();
|
||||
};
|
||||
#endif
|
||||
|
||||
QByteArray key_data;
|
||||
#ifdef TO_REMOVE
|
||||
QExplicitlySharedDataPointer<Data> d;
|
||||
#endif
|
||||
ByteArray key_data;
|
||||
};
|
||||
|
||||
QByteArray torControlHashedPassword(const QByteArray &password);
|
||||
ByteArray torControlHashedPassword(const ByteArray &password);
|
||||
|
||||
#endif // CRYPTOKEY_H
|
||||
|
@ -41,14 +41,14 @@ GetConfCommand::GetConfCommand(Type t)
|
||||
{
|
||||
}
|
||||
|
||||
QByteArray GetConfCommand::build(const QByteArray &key)
|
||||
ByteArray GetConfCommand::build(const ByteArray &key)
|
||||
{
|
||||
return build(QList<QByteArray>() << key);
|
||||
return build(QList<ByteArray>() << key);
|
||||
}
|
||||
|
||||
QByteArray GetConfCommand::build(const QList<QByteArray> &keys)
|
||||
ByteArray GetConfCommand::build(const QList<ByteArray> &keys)
|
||||
{
|
||||
QByteArray out;
|
||||
ByteArray out;
|
||||
if (type == GetConf) {
|
||||
out = "GETCONF";
|
||||
} else if (type == GetInfo) {
|
||||
@ -58,7 +58,7 @@ QByteArray GetConfCommand::build(const QList<QByteArray> &keys)
|
||||
return out;
|
||||
}
|
||||
|
||||
foreach (const QByteArray &key, keys) {
|
||||
foreach (const ByteArray &key, keys) {
|
||||
out.append(' ');
|
||||
out.append(key);
|
||||
}
|
||||
@ -67,49 +67,29 @@ QByteArray GetConfCommand::build(const QList<QByteArray> &keys)
|
||||
return out;
|
||||
}
|
||||
|
||||
void GetConfCommand::onReply(int statusCode, const QByteArray &data)
|
||||
void GetConfCommand::onReply(int statusCode, const ByteArray &data)
|
||||
{
|
||||
TorControlCommand::onReply(statusCode, data);
|
||||
if (statusCode != 250)
|
||||
return;
|
||||
|
||||
int kep = data.indexOf('=');
|
||||
QString key = QString::fromLatin1(data.mid(0, kep));
|
||||
QVariant value;
|
||||
std::string key = data.mid(0, kep).toString();
|
||||
std::string value;
|
||||
if (kep >= 0)
|
||||
value = QString::fromLatin1(unquotedString(data.mid(kep + 1)));
|
||||
value = unquotedString(data.mid(kep + 1)).toString();
|
||||
|
||||
m_lastKey = key;
|
||||
QVariantMap::iterator it = m_results.find(key);
|
||||
if (it != m_results.end()) {
|
||||
// Make a list of values
|
||||
QVariantList results = it->toList();
|
||||
if (results.isEmpty())
|
||||
results.append(*it);
|
||||
results.append(value);
|
||||
*it = QVariant(results);
|
||||
} else {
|
||||
m_results.insert(key, value);
|
||||
}
|
||||
m_results[key].push_back(value);
|
||||
}
|
||||
|
||||
void GetConfCommand::onDataLine(const QByteArray &data)
|
||||
void GetConfCommand::onDataLine(const ByteArray &data)
|
||||
{
|
||||
if (m_lastKey.isEmpty()) {
|
||||
if (m_lastKey.empty()) {
|
||||
qWarning() << "torctrl: Unexpected data line in GetConf command";
|
||||
return;
|
||||
}
|
||||
|
||||
QVariantMap::iterator it = m_results.find(m_lastKey);
|
||||
if (it != m_results.end()) {
|
||||
QVariantList results = it->toList();
|
||||
if (results.isEmpty() && !it->toByteArray().isEmpty())
|
||||
results.append(*it);
|
||||
results.append(data);
|
||||
*it = QVariant(results);
|
||||
} else {
|
||||
m_results.insert(m_lastKey, QVariantList() << data);
|
||||
}
|
||||
m_results[m_lastKey].push_back(data.toString());
|
||||
}
|
||||
|
||||
void GetConfCommand::onDataFinished()
|
||||
@ -117,8 +97,13 @@ void GetConfCommand::onDataFinished()
|
||||
m_lastKey.clear();
|
||||
}
|
||||
|
||||
QVariant GetConfCommand::get(const QByteArray &key) const
|
||||
std::list<std::string> GetConfCommand::get(const ByteArray& key) const
|
||||
{
|
||||
return m_results.value(QString::fromLatin1(key));
|
||||
auto it = m_results.find(key.toString());
|
||||
|
||||
if(it != m_results.end())
|
||||
return it->second;
|
||||
else
|
||||
return std::list<std::string>();
|
||||
}
|
||||
|
||||
|
@ -56,20 +56,20 @@ public:
|
||||
|
||||
GetConfCommand(Type type);
|
||||
|
||||
QByteArray build(const QByteArray &key);
|
||||
QByteArray build(const QList<QByteArray> &keys);
|
||||
ByteArray build(const ByteArray &key);
|
||||
ByteArray build(const QList<ByteArray> &keys);
|
||||
|
||||
const QVariantMap &results() const { return m_results; }
|
||||
QVariant get(const QByteArray &key) const;
|
||||
const std::map<std::string,std::list<std::string> > &results() const { return m_results; }
|
||||
std::list<std::string> get(const ByteArray &key) const;
|
||||
|
||||
protected:
|
||||
virtual void onReply(int statusCode, const QByteArray &data);
|
||||
virtual void onDataLine(const QByteArray &data);
|
||||
virtual void onReply(int statusCode, const ByteArray &data);
|
||||
virtual void onDataLine(const ByteArray &data);
|
||||
virtual void onDataFinished();
|
||||
|
||||
private:
|
||||
QVariantMap m_results;
|
||||
QString m_lastKey;
|
||||
std::map<std::string,std::list<std::string> > m_results;
|
||||
std::string m_lastKey;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -32,11 +32,9 @@
|
||||
|
||||
#include "HiddenService.h"
|
||||
#include "TorControl.h"
|
||||
#include "TorSocket.h"
|
||||
#include "CryptoKey.h"
|
||||
#include "Useful.h"
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QTimer>
|
||||
#include <QDebug>
|
||||
|
||||
@ -47,7 +45,7 @@ HiddenService::HiddenService(HiddenServiceClient *client)
|
||||
{
|
||||
}
|
||||
|
||||
HiddenService::HiddenService(HiddenServiceClient *client,const QString &path)
|
||||
HiddenService::HiddenService(HiddenServiceClient *client,const std::string& path)
|
||||
: m_dataPath(path), m_status(NotCreated), m_client(client)
|
||||
{
|
||||
/* Set the initial status and, if possible, load the hostname */
|
||||
@ -58,7 +56,7 @@ HiddenService::HiddenService(HiddenServiceClient *client,const QString &path)
|
||||
}
|
||||
}
|
||||
|
||||
HiddenService::HiddenService(HiddenServiceClient *client,const CryptoKey &privateKey, const QString &path)
|
||||
HiddenService::HiddenService(HiddenServiceClient *client,const CryptoKey &privateKey, const std::string &path)
|
||||
: m_dataPath(path), m_status(NotCreated), m_client(client)
|
||||
{
|
||||
setPrivateKey(privateKey);
|
||||
@ -92,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 ByteArray& sid)
|
||||
{
|
||||
m_service_id = sid;
|
||||
m_hostname = sid + ".onion";
|
||||
|
@ -38,11 +38,11 @@
|
||||
#include <QList>
|
||||
#include "CryptoKey.h"
|
||||
|
||||
#include "bytearray.h"
|
||||
|
||||
namespace Tor
|
||||
{
|
||||
|
||||
class TorSocket;
|
||||
|
||||
// This class is used to receive synchroneous notifications from the hidden service.
|
||||
// Each client should implement its own notification handling.
|
||||
|
||||
@ -77,20 +77,20 @@ public:
|
||||
};
|
||||
|
||||
HiddenService(HiddenServiceClient *client);
|
||||
HiddenService(HiddenServiceClient *client,const QString &dataPath);
|
||||
HiddenService(HiddenServiceClient *client,const CryptoKey &privateKey, const QString &dataPath = QString());
|
||||
HiddenService(HiddenServiceClient *client, const std::string &dataPath);
|
||||
HiddenService(HiddenServiceClient *client, const CryptoKey &privateKey, const std::string &dataPath = QString());
|
||||
|
||||
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 m_service_id.toString(); }
|
||||
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 ByteArray &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);
|
||||
|
||||
@ -98,12 +98,12 @@ private slots:
|
||||
void servicePublished();
|
||||
|
||||
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;
|
||||
ByteArray m_service_id;
|
||||
|
||||
void loadPrivateKey();
|
||||
void setStatus(Status newStatus);
|
||||
|
@ -42,12 +42,12 @@ ProtocolInfoCommand::ProtocolInfoCommand(TorControl *m)
|
||||
{
|
||||
}
|
||||
|
||||
QByteArray ProtocolInfoCommand::build()
|
||||
ByteArray ProtocolInfoCommand::build()
|
||||
{
|
||||
return QByteArray("PROTOCOLINFO 1\r\n");
|
||||
return ByteArray("PROTOCOLINFO 1\r\n");
|
||||
}
|
||||
|
||||
void ProtocolInfoCommand::onReply(int statusCode, const QByteArray &data)
|
||||
void ProtocolInfoCommand::onReply(int statusCode, const ByteArray &data)
|
||||
{
|
||||
TorControlCommand::onReply(statusCode, data);
|
||||
if (statusCode != 250)
|
||||
@ -55,14 +55,14 @@ void ProtocolInfoCommand::onReply(int statusCode, const QByteArray &data)
|
||||
|
||||
if (data.startsWith("AUTH "))
|
||||
{
|
||||
QList<QByteArray> tokens = splitQuotedStrings(data.mid(5), ' ');
|
||||
QList<ByteArray> tokens = splitQuotedStrings(data.mid(5), ' ');
|
||||
|
||||
foreach (QByteArray token, tokens)
|
||||
foreach (ByteArray token, tokens)
|
||||
{
|
||||
if (token.startsWith("METHODS="))
|
||||
{
|
||||
QList<QByteArray> textMethods = unquotedString(token.mid(8)).split(',');
|
||||
for (QList<QByteArray>::Iterator it = textMethods.begin(); it != textMethods.end(); ++it)
|
||||
QList<ByteArray> textMethods = unquotedString(token.mid(8)).split(',');
|
||||
for (QList<ByteArray>::Iterator it = textMethods.begin(); it != textMethods.end(); ++it)
|
||||
{
|
||||
if (*it == "NULL")
|
||||
m_authMethods |= AuthNull;
|
||||
@ -80,6 +80,6 @@ void ProtocolInfoCommand::onReply(int statusCode, const QByteArray &data)
|
||||
}
|
||||
else if (data.startsWith("VERSION Tor="))
|
||||
{
|
||||
m_torVersion = QString::fromLatin1(unquotedString(data.mid(12, data.indexOf(' ', 12))));
|
||||
m_torVersion = std::string(unquotedString(data.mid(12, data.indexOf(' ', 12))));
|
||||
}
|
||||
}
|
||||
|
@ -57,14 +57,14 @@ public:
|
||||
Q_DECLARE_FLAGS(AuthMethods, AuthMethod)
|
||||
|
||||
ProtocolInfoCommand(TorControl *manager);
|
||||
QByteArray build();
|
||||
ByteArray build();
|
||||
|
||||
AuthMethods authMethods() const { return m_authMethods; }
|
||||
QString torVersion() const { return m_torVersion; }
|
||||
QString cookieFile() const { return m_cookieFile; }
|
||||
|
||||
protected:
|
||||
virtual void onReply(int statusCode, const QByteArray &data);
|
||||
virtual void onReply(int statusCode, const ByteArray &data);
|
||||
|
||||
private:
|
||||
TorControl *manager;
|
||||
|
@ -50,49 +50,55 @@ bool SetConfCommand::isSuccessful() const
|
||||
return statusCode() == 250;
|
||||
}
|
||||
|
||||
QByteArray SetConfCommand::build(const QByteArray &key, const QByteArray &value)
|
||||
ByteArray SetConfCommand::build(const ByteArray &key, const ByteArray &value)
|
||||
{
|
||||
return build(QList<QPair<QByteArray, QByteArray> >() << qMakePair(key, value));
|
||||
return build(std::list<std::pair<ByteArray, ByteArray> > { std::make_pair(key, value) } );
|
||||
}
|
||||
|
||||
QByteArray SetConfCommand::build(const QVariantMap &data)
|
||||
// ByteArray SetConfCommand::build(const std::list<std::pair<ByteArray,ByteArray> > &data)
|
||||
// {
|
||||
// QList<QPair<QByteArray, QByteArray> > out;
|
||||
//
|
||||
// for (QVariantMap::ConstIterator it = data.begin(); it != data.end(); it++) {
|
||||
// QByteArray key = it.key().toLatin1();
|
||||
//
|
||||
// if (static_cast<QMetaType::Type>(it.value().type()) == QMetaType::QVariantList) {
|
||||
// QVariantList values = it.value().value<QVariantList>();
|
||||
// foreach (const QVariant &value, values)
|
||||
// out.append(qMakePair(key, value.toString().toLatin1()));
|
||||
// } else {
|
||||
// out.append(qMakePair(key, it.value().toString().toLatin1()));
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// return build(out);
|
||||
// }
|
||||
|
||||
ByteArray SetConfCommand::build(const std::list<std::pair<ByteArray, ByteArray> >& data)
|
||||
{
|
||||
QList<QPair<QByteArray, QByteArray> > out;
|
||||
ByteArray out(m_resetMode ? "RESETCONF" : "SETCONF");
|
||||
|
||||
for (QVariantMap::ConstIterator it = data.begin(); it != data.end(); it++) {
|
||||
QByteArray key = it.key().toLatin1();
|
||||
for (auto& p:data)
|
||||
{
|
||||
out += " " ;
|
||||
out += p.first;
|
||||
|
||||
if (static_cast<QMetaType::Type>(it.value().type()) == QMetaType::QVariantList) {
|
||||
QVariantList values = it.value().value<QVariantList>();
|
||||
foreach (const QVariant &value, values)
|
||||
out.append(qMakePair(key, value.toString().toLatin1()));
|
||||
} else {
|
||||
out.append(qMakePair(key, it.value().toString().toLatin1()));
|
||||
if (!p.second.empty())
|
||||
{
|
||||
out += "=" ;
|
||||
out += quotedString(p.second);
|
||||
}
|
||||
}
|
||||
|
||||
return build(out);
|
||||
}
|
||||
|
||||
QByteArray SetConfCommand::build(const QList<QPair<QByteArray, QByteArray> > &data)
|
||||
{
|
||||
QByteArray out(m_resetMode ? "RESETCONF" : "SETCONF");
|
||||
|
||||
for (int i = 0; i < data.size(); i++) {
|
||||
out += " " + data[i].first;
|
||||
if (!data[i].second.isEmpty())
|
||||
out += "=" + quotedString(data[i].second);
|
||||
}
|
||||
|
||||
out.append("\r\n");
|
||||
return out;
|
||||
}
|
||||
|
||||
void SetConfCommand::onReply(int statusCode, const QByteArray &data)
|
||||
void SetConfCommand::onReply(int statusCode, const ByteArray &data)
|
||||
{
|
||||
TorControlCommand::onReply(statusCode, data);
|
||||
if (statusCode != 250)
|
||||
m_errorMessage = QString::fromLatin1(data);
|
||||
m_errorMessage = data.toString();
|
||||
}
|
||||
|
||||
void SetConfCommand::onFinished(int statusCode)
|
||||
|
@ -54,11 +54,10 @@ public:
|
||||
|
||||
void setResetMode(bool resetMode);
|
||||
|
||||
QByteArray build(const QByteArray &key, const QByteArray &value);
|
||||
QByteArray build(const QVariantMap &data);
|
||||
QByteArray build(const QList<QPair<QByteArray, QByteArray> > &data);
|
||||
ByteArray build(const ByteArray &key, const ByteArray &value);
|
||||
ByteArray build(const std::list<std::pair<ByteArray, ByteArray> > &data);
|
||||
|
||||
QString errorMessage() const { return m_errorMessage; }
|
||||
std::string errorMessage() const { return m_errorMessage; }
|
||||
bool isSuccessful() const;
|
||||
|
||||
signals:
|
||||
@ -66,10 +65,10 @@ signals:
|
||||
void setConfFailed(int code);
|
||||
|
||||
protected:
|
||||
QString m_errorMessage;
|
||||
std::string m_errorMessage;
|
||||
bool m_resetMode;
|
||||
|
||||
virtual void onReply(int statusCode, const QByteArray &data);
|
||||
virtual void onReply(int statusCode, const ByteArray &data);
|
||||
virtual void onFinished(int statusCode);
|
||||
};
|
||||
|
||||
|
@ -48,8 +48,8 @@ class SettingsFilePrivate : public QObject
|
||||
|
||||
public:
|
||||
SettingsFile *q;
|
||||
QString filePath;
|
||||
QString errorMessage;
|
||||
std::string filePath;
|
||||
std::string errorMessage;
|
||||
QTimer syncTimer;
|
||||
QJsonObject jsonRoot;
|
||||
SettingsObject *rootObject;
|
||||
@ -58,17 +58,17 @@ public:
|
||||
virtual ~SettingsFilePrivate();
|
||||
|
||||
void reset();
|
||||
void setError(const QString &message);
|
||||
bool checkDirPermissions(const QString &path);
|
||||
void setError(const std::string &message);
|
||||
bool checkDirPermissions(const std::string &path);
|
||||
bool readFile();
|
||||
bool writeFile();
|
||||
|
||||
static QStringList splitPath(const QString &input, bool &ok);
|
||||
QJsonValue read(const QJsonObject &base, const QStringList &path);
|
||||
bool write(const QStringList &path, const QJsonValue &value);
|
||||
static std::list<std::string> splitPath(const std::string& input, bool &ok);
|
||||
QJsonValue read(const QJsonObject &base, const std::list<std::string> &path);
|
||||
bool write(const std::list<std::string> &path, const QJsonValue &value);
|
||||
|
||||
signals:
|
||||
void modified(const QStringList &path, const QJsonValue &value);
|
||||
void modified(const std::list<std::string> &path, const QJsonValue &value);
|
||||
|
||||
private slots:
|
||||
void sync();
|
||||
|
@ -37,7 +37,6 @@
|
||||
#include <QJsonValue>
|
||||
#include <QJsonObject>
|
||||
#include <QJsonArray>
|
||||
#include <QStringList>
|
||||
#include <QDateTime>
|
||||
|
||||
class SettingsObject;
|
||||
|
@ -32,14 +32,14 @@
|
||||
|
||||
#include "StrUtil.h"
|
||||
|
||||
QByteArray quotedString(const QByteArray &string)
|
||||
ByteArray quotedString(const ByteArray &string)
|
||||
{
|
||||
QByteArray out;
|
||||
ByteArray out;
|
||||
out.reserve(string.size() * 2);
|
||||
|
||||
out.append('"');
|
||||
|
||||
for (int i = 0; i < string.size(); ++i)
|
||||
for (uint i = 0; i < string.size(); ++i)
|
||||
{
|
||||
switch (string[i])
|
||||
{
|
||||
@ -59,15 +59,15 @@ QByteArray quotedString(const QByteArray &string)
|
||||
return out;
|
||||
}
|
||||
|
||||
QByteArray unquotedString(const QByteArray &string)
|
||||
ByteArray unquotedString(const ByteArray &string)
|
||||
{
|
||||
if (string.size() < 2 || string[0] != '"')
|
||||
return string;
|
||||
|
||||
QByteArray out;
|
||||
ByteArray out;
|
||||
out.reserve(string.size() - 2);
|
||||
|
||||
for (int i = 1; i < string.size(); ++i)
|
||||
for (uint i = 1; i < string.size(); ++i)
|
||||
{
|
||||
switch (string[i])
|
||||
{
|
||||
@ -85,13 +85,13 @@ QByteArray unquotedString(const QByteArray &string)
|
||||
return out;
|
||||
}
|
||||
|
||||
QList<QByteArray> splitQuotedStrings(const QByteArray &input, char separator)
|
||||
std::list<ByteArray> splitQuotedStrings(const ByteArray &input, char separator)
|
||||
{
|
||||
QList<QByteArray> out;
|
||||
std::list<ByteArray> out;
|
||||
bool inquote = false;
|
||||
int start = 0;
|
||||
uint start = 0;
|
||||
|
||||
for (int i = 0; i < input.size(); ++i)
|
||||
for (uint i = 0; i < input.size(); ++i)
|
||||
{
|
||||
switch (input[i])
|
||||
{
|
||||
@ -106,13 +106,13 @@ QList<QByteArray> splitQuotedStrings(const QByteArray &input, char separator)
|
||||
|
||||
if (!inquote && input[i] == separator)
|
||||
{
|
||||
out.append(input.mid(start, i - start));
|
||||
out.push_back(input.mid(start, i - start));
|
||||
start = i+1;
|
||||
}
|
||||
}
|
||||
|
||||
if (start < input.size())
|
||||
out.append(input.mid(start));
|
||||
out.push_back(input.mid(start));
|
||||
|
||||
return out;
|
||||
}
|
||||
|
@ -33,14 +33,15 @@
|
||||
#ifndef STRINGUTIL_H
|
||||
#define STRINGUTIL_H
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QList>
|
||||
#include <list>
|
||||
|
||||
QByteArray quotedString(const QByteArray &string);
|
||||
#include "bytearray.h"
|
||||
|
||||
ByteArray quotedString(const ByteArray &string);
|
||||
|
||||
/* Return the unquoted contents of a string, either until an end quote or an unescaped separator character. */
|
||||
QByteArray unquotedString(const QByteArray &string);
|
||||
ByteArray unquotedString(const ByteArray &string);
|
||||
|
||||
QList<QByteArray> splitQuotedStrings(const QByteArray &input, char separator);
|
||||
std::list<ByteArray> splitQuotedStrings(const ByteArray& input, char separator);
|
||||
|
||||
#endif // STRINGUTIL_H
|
||||
|
@ -85,7 +85,7 @@ public:
|
||||
QHostAddress torAddress;
|
||||
QString errorMessage;
|
||||
QString torVersion;
|
||||
QByteArray authPassword;
|
||||
ByteArray authPassword;
|
||||
QHostAddress socksAddress;
|
||||
QList<HiddenService*> services;
|
||||
quint16 controlPort, socksPort;
|
||||
@ -112,8 +112,8 @@ public slots:
|
||||
void getTorInfoReply();
|
||||
void setError(const QString &message);
|
||||
|
||||
void statusEvent(int code, const QByteArray &data);
|
||||
void updateBootstrap(const QList<QByteArray> &data);
|
||||
void statusEvent(int code, const ByteArray &data);
|
||||
void updateBootstrap(const QList<ByteArray> &data);
|
||||
};
|
||||
|
||||
}
|
||||
@ -276,7 +276,7 @@ QVariantMap TorControl::bootstrapStatus() const
|
||||
return d->bootstrapStatus;
|
||||
}
|
||||
|
||||
void TorControl::setAuthPassword(const QByteArray &password)
|
||||
void TorControl::setAuthPassword(const ByteArray &password)
|
||||
{
|
||||
d->authPassword = password;
|
||||
}
|
||||
@ -385,7 +385,7 @@ void TorControlPrivate::protocolInfoReply()
|
||||
AuthenticateCommand *auth = new AuthenticateCommand;
|
||||
connect(auth, &TorControlCommand::finished, this, &TorControlPrivate::authenticateReply);
|
||||
|
||||
QByteArray data;
|
||||
ByteArray data;
|
||||
ProtocolInfoCommand::AuthMethods methods = info->authMethods();
|
||||
|
||||
if (methods.testFlag(ProtocolInfoCommand::AuthNull))
|
||||
@ -402,7 +402,7 @@ void TorControlPrivate::protocolInfoReply()
|
||||
QFile file(cookieFile);
|
||||
if (file.open(QIODevice::ReadOnly))
|
||||
{
|
||||
QByteArray cookie = file.readAll();
|
||||
ByteArray cookie = file.readAll();
|
||||
file.close();
|
||||
|
||||
/* Simple test to avoid a vulnerability where any process listening on what we think is
|
||||
@ -458,8 +458,8 @@ void TorControlPrivate::getTorInfo()
|
||||
GetConfCommand *command = new GetConfCommand(GetConfCommand::GetInfo);
|
||||
connect(command, &TorControlCommand::finished, this, &TorControlPrivate::getTorInfoReply);
|
||||
|
||||
QList<QByteArray> keys;
|
||||
keys << QByteArray("status/circuit-established") << QByteArray("status/bootstrap-phase");
|
||||
QList<ByteArray> keys;
|
||||
keys << ByteArray("status/circuit-established") << ByteArray("status/bootstrap-phase");
|
||||
|
||||
/* If these are set in the config, they override the automatic behavior. */
|
||||
SettingsObject settings(QStringLiteral("tor"));
|
||||
@ -479,7 +479,7 @@ void TorControlPrivate::getTorInfo()
|
||||
rsEvents->sendEvent(ev);
|
||||
}
|
||||
} else
|
||||
keys << QByteArray("net/listeners/socks");
|
||||
keys << ByteArray("net/listeners/socks");
|
||||
|
||||
socket->sendCommand(command, command->build(keys));
|
||||
}
|
||||
@ -490,9 +490,9 @@ void TorControlPrivate::getTorInfoReply()
|
||||
if (!command || !q->isConnected())
|
||||
return;
|
||||
|
||||
QList<QByteArray> listenAddresses = splitQuotedStrings(command->get(QByteArray("net/listeners/socks")).toString().toLatin1(), ' ');
|
||||
for (QList<QByteArray>::Iterator it = listenAddresses.begin(); it != listenAddresses.end(); ++it) {
|
||||
QByteArray value = unquotedString(*it);
|
||||
QList<ByteArray> listenAddresses = splitQuotedStrings(command->get(ByteArray("net/listeners/socks")).toString().toLatin1(), ' ');
|
||||
for (QList<ByteArray>::Iterator it = listenAddresses.begin(); it != listenAddresses.end(); ++it) {
|
||||
ByteArray value = unquotedString(*it);
|
||||
int sepp = value.indexOf(':');
|
||||
QHostAddress address(QString::fromLatin1(value.mid(0, sepp)));
|
||||
quint16 port = (quint16)value.mid(sepp+1).toUInt();
|
||||
@ -523,14 +523,14 @@ void TorControlPrivate::getTorInfoReply()
|
||||
}
|
||||
}
|
||||
|
||||
if (command->get(QByteArray("status/circuit-established")).toInt() == 1) {
|
||||
if (command->get(ByteArray("status/circuit-established")).toInt() == 1) {
|
||||
torCtrlDebug() << "torctrl: Tor indicates that circuits have been established; state is TorReady" << std::endl;
|
||||
setTorStatus(TorControl::TorReady);
|
||||
} else {
|
||||
setTorStatus(TorControl::TorOffline);
|
||||
}
|
||||
|
||||
QByteArray bootstrap = command->get(QByteArray("status/bootstrap-phase")).toString().toLatin1();
|
||||
ByteArray bootstrap = command->get(ByteArray("status/bootstrap-phase")).toString().toLatin1();
|
||||
if (!bootstrap.isEmpty())
|
||||
updateBootstrap(splitQuotedStrings(bootstrap, ' '));
|
||||
}
|
||||
@ -580,7 +580,7 @@ void TorControlPrivate::publishServices()
|
||||
} else {
|
||||
torCtrlDebug() << "torctrl: Using legacy SETCONF hidden service configuration for tor" << torVersion.toStdString() << std::endl;
|
||||
SetConfCommand *command = new SetConfCommand;
|
||||
QList<QPair<QByteArray,QByteArray> > torConfig;
|
||||
QList<QPair<ByteArray,ByteArray> > torConfig;
|
||||
|
||||
foreach (HiddenService *service, services)
|
||||
{
|
||||
@ -596,7 +596,7 @@ void TorControlPrivate::publishServices()
|
||||
torCtrlDebug() << "torctrl: Configuring hidden service at" << service->dataPath().toStdString() << std::endl;
|
||||
|
||||
QDir dir(service->dataPath());
|
||||
torConfig.append(qMakePair(QByteArray("HiddenServiceDir"), dir.absolutePath().toLocal8Bit()));
|
||||
torConfig.append(qMakePair(ByteArray("HiddenServiceDir"), dir.absolutePath().toLocal8Bit()));
|
||||
|
||||
const QList<HiddenService::Target> &targets = service->targets();
|
||||
for (QList<HiddenService::Target>::ConstIterator tit = targets.begin(); tit != targets.end(); ++tit)
|
||||
@ -604,7 +604,7 @@ void TorControlPrivate::publishServices()
|
||||
QString target = QString::fromLatin1("%1 %2:%3").arg(tit->servicePort)
|
||||
.arg(tit->targetAddress.toString())
|
||||
.arg(tit->targetPort);
|
||||
torConfig.append(qMakePair(QByteArray("HiddenServicePort"), target.toLatin1()));
|
||||
torConfig.append(qMakePair(ByteArray("HiddenServicePort"), target.toLatin1()));
|
||||
}
|
||||
|
||||
QObject::connect(command, &SetConfCommand::setConfSucceeded, service, &HiddenService::servicePublished);
|
||||
@ -640,11 +640,11 @@ void TorControl::shutdownSync()
|
||||
}
|
||||
}
|
||||
|
||||
void TorControlPrivate::statusEvent(int code, const QByteArray &data)
|
||||
void TorControlPrivate::statusEvent(int code, const ByteArray &data)
|
||||
{
|
||||
Q_UNUSED(code);
|
||||
|
||||
QList<QByteArray> tokens = splitQuotedStrings(data.trimmed(), ' ');
|
||||
QList<ByteArray> tokens = splitQuotedStrings(data.trimmed(), ' ');
|
||||
if (tokens.size() < 3)
|
||||
return;
|
||||
|
||||
@ -660,7 +660,7 @@ void TorControlPrivate::statusEvent(int code, const QByteArray &data)
|
||||
}
|
||||
}
|
||||
|
||||
void TorControlPrivate::updateBootstrap(const QList<QByteArray> &data)
|
||||
void TorControlPrivate::updateBootstrap(const QList<ByteArray> &data)
|
||||
{
|
||||
bootstrapStatus.clear();
|
||||
// WARN or NOTICE
|
||||
@ -721,7 +721,7 @@ public:
|
||||
Q_ASSERT(!command);
|
||||
command = new GetConfCommand(GetConfCommand::GetInfo);
|
||||
QObject::connect(command, &TorControlCommand::finished, this, &SaveConfigOperation::configTextReply);
|
||||
socket->sendCommand(command, command->build(QList<QByteArray>() << "config-text" << "config-file"));
|
||||
socket->sendCommand(command, command->build(QList<ByteArray>() << "config-text" << "config-file"));
|
||||
}
|
||||
|
||||
private slots:
|
||||
@ -763,7 +763,7 @@ private slots:
|
||||
|
||||
QVariantList configText = command->get("config-text").toList();
|
||||
foreach (const QVariant &value, configText) {
|
||||
QByteArray line = value.toByteArray();
|
||||
ByteArray line = value.toByteArray();
|
||||
|
||||
bool skip = false;
|
||||
for (const char **key = bannedKeys; *key; key++) {
|
||||
|
@ -40,7 +40,7 @@ TorControlCommand::TorControlCommand()
|
||||
{
|
||||
}
|
||||
|
||||
void TorControlCommand::onReply(int statusCode, const QByteArray &data)
|
||||
void TorControlCommand::onReply(int statusCode, const ByteArray &data)
|
||||
{
|
||||
emit replyLine(statusCode, data);
|
||||
}
|
||||
@ -51,7 +51,7 @@ void TorControlCommand::onFinished(int statusCode)
|
||||
emit finished();
|
||||
}
|
||||
|
||||
void TorControlCommand::onDataLine(const QByteArray &data)
|
||||
void TorControlCommand::onDataLine(const ByteArray &data)
|
||||
{
|
||||
Q_UNUSED(data);
|
||||
}
|
||||
|
@ -34,7 +34,8 @@
|
||||
#define TORCONTROLCOMMAND_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QByteArray>
|
||||
|
||||
#include "bytearray.h"
|
||||
|
||||
namespace Tor
|
||||
{
|
||||
@ -52,13 +53,13 @@ public:
|
||||
int statusCode() const { return m_finalStatus; }
|
||||
|
||||
signals:
|
||||
void replyLine(int statusCode, const QByteArray &data);
|
||||
void replyLine(int statusCode, const ByteArray &data);
|
||||
void finished();
|
||||
|
||||
protected:
|
||||
virtual void onReply(int statusCode, const QByteArray &data);
|
||||
virtual void onReply(int statusCode, const ByteArray &data);
|
||||
virtual void onFinished(int statusCode);
|
||||
virtual void onDataLine(const QByteArray &data);
|
||||
virtual void onDataLine(const ByteArray &data);
|
||||
virtual void onDataFinished();
|
||||
|
||||
private:
|
||||
|
@ -34,12 +34,11 @@
|
||||
|
||||
#include "TorControlSocket.h"
|
||||
#include "TorControlCommand.h"
|
||||
#include <QDebug>
|
||||
|
||||
using namespace Tor;
|
||||
|
||||
TorControlSocket::TorControlSocket(QObject *parent)
|
||||
: QTcpSocket(parent), currentCommand(0), inDataReply(false)
|
||||
TorControlSocket::TorControlSocket()
|
||||
: currentCommand(0), inDataReply(false)
|
||||
{
|
||||
connect(this, SIGNAL(readyRead()), this, SLOT(process()));
|
||||
connect(this, SIGNAL(disconnected()), this, SLOT(clear()));
|
||||
@ -54,7 +53,7 @@ void TorControlSocket::sendCommand(TorControlCommand *command, const QByteArray
|
||||
{
|
||||
Q_ASSERT(data.endsWith("\r\n"));
|
||||
|
||||
commandQueue.append(command);
|
||||
commandQueue.push_back(command);
|
||||
write(data);
|
||||
|
||||
std::cerr << "[TOR CTRL] Sent: \"" << QString(data.trimmed()).toStdString() << "\"" << std::endl;
|
||||
@ -84,7 +83,7 @@ void TorControlSocket::clear()
|
||||
currentCommand = 0;
|
||||
}
|
||||
|
||||
void TorControlSocket::setError(const QString &message)
|
||||
void TorControlSocket::setError(const std::string &message)
|
||||
{
|
||||
m_errorMessage = message;
|
||||
emit error(message);
|
||||
|
@ -30,29 +30,26 @@
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef TORCONTROLSOCKET_H
|
||||
#define TORCONTROLSOCKET_H
|
||||
#pragma once
|
||||
|
||||
#include <QTcpSocket>
|
||||
#include <QQueue>
|
||||
#include "pqi/rstcpsocket.h"
|
||||
|
||||
namespace Tor
|
||||
{
|
||||
|
||||
class TorControlCommand;
|
||||
|
||||
class TorControlSocket : public QTcpSocket
|
||||
class TorControlSocket : public RsTcpSocket
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit TorControlSocket(QObject *parent = 0);
|
||||
explicit TorControlSocket();
|
||||
virtual ~TorControlSocket();
|
||||
|
||||
QString errorMessage() const { return m_errorMessage; }
|
||||
std::string errorMessage() const { return m_errorMessage; }
|
||||
|
||||
void registerEvent(const QByteArray &event, TorControlCommand *handler);
|
||||
|
||||
void sendCommand(const QByteArray &data) { sendCommand(0, data); }
|
||||
void sendCommand(const std::string& data) { sendCommand(0, data); }
|
||||
void sendCommand(TorControlCommand *command, const QByteArray &data);
|
||||
|
||||
signals:
|
||||
@ -63,13 +60,13 @@ private slots:
|
||||
void clear();
|
||||
|
||||
private:
|
||||
QQueue<TorControlCommand*> commandQueue;
|
||||
std::list<TorControlCommand*> commandQueue;
|
||||
QHash<QByteArray,TorControlCommand*> eventCommands;
|
||||
QString m_errorMessage;
|
||||
std::string m_errorMessage;
|
||||
TorControlCommand *currentCommand;
|
||||
bool inDataReply;
|
||||
|
||||
void setError(const QString &message);
|
||||
void setError(const std::string& message);
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -1,155 +0,0 @@
|
||||
/* Ricochet - https://ricochet.im/
|
||||
* Copyright (C) 2014, John Brooks <john.brooks@dereferenced.net>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* * Neither the names of the copyright owners nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "TorSocket.h"
|
||||
#include "TorControl.h"
|
||||
#include <QNetworkProxy>
|
||||
|
||||
using namespace Tor;
|
||||
|
||||
TorSocket::TorSocket(QObject *parent)
|
||||
: QTcpSocket(parent)
|
||||
, m_port(0)
|
||||
, m_reconnectEnabled(true)
|
||||
, m_maxInterval(900)
|
||||
, m_connectAttempts(0)
|
||||
{
|
||||
connect(torControl, SIGNAL(connectivityChanged()), SLOT(connectivityChanged()));
|
||||
connect(&m_connectTimer, SIGNAL(timeout()), SLOT(reconnect()));
|
||||
connect(this, SIGNAL(disconnected()), SLOT(onFailed()));
|
||||
connect(this, SIGNAL(error(QAbstractSocket::SocketError)), SLOT(onFailed()));
|
||||
|
||||
m_connectTimer.setSingleShot(true);
|
||||
connectivityChanged();
|
||||
}
|
||||
|
||||
TorSocket::~TorSocket()
|
||||
{
|
||||
}
|
||||
|
||||
void TorSocket::setReconnectEnabled(bool enabled)
|
||||
{
|
||||
if (enabled == m_reconnectEnabled)
|
||||
return;
|
||||
|
||||
m_reconnectEnabled = enabled;
|
||||
if (m_reconnectEnabled) {
|
||||
m_connectAttempts = 0;
|
||||
reconnect();
|
||||
} else {
|
||||
m_connectTimer.stop();
|
||||
}
|
||||
}
|
||||
|
||||
void TorSocket::setMaxAttemptInterval(int interval)
|
||||
{
|
||||
m_maxInterval = interval;
|
||||
}
|
||||
|
||||
void TorSocket::resetAttempts()
|
||||
{
|
||||
m_connectAttempts = 0;
|
||||
if (m_connectTimer.isActive()) {
|
||||
m_connectTimer.stop();
|
||||
m_connectTimer.start(reconnectInterval() * 1000);
|
||||
}
|
||||
}
|
||||
|
||||
int TorSocket::reconnectInterval()
|
||||
{
|
||||
int delay = 0;
|
||||
if (m_connectAttempts <= 4)
|
||||
delay = 30;
|
||||
else if (m_connectAttempts <= 6)
|
||||
delay = 120;
|
||||
else
|
||||
delay = m_maxInterval;
|
||||
|
||||
return qMin(delay, m_maxInterval);
|
||||
}
|
||||
|
||||
void TorSocket::reconnect()
|
||||
{
|
||||
if (!torControl->hasConnectivity() || !reconnectEnabled())
|
||||
return;
|
||||
|
||||
m_connectTimer.stop();
|
||||
if (!m_host.isEmpty() && m_port) {
|
||||
std::cerr << "Attempting reconnection of socket to" << m_host.toStdString() << ":" << m_port << std::endl;
|
||||
connectToHost(m_host, m_port);
|
||||
}
|
||||
}
|
||||
|
||||
void TorSocket::connectivityChanged()
|
||||
{
|
||||
if (torControl->hasConnectivity()) {
|
||||
setProxy(torControl->connectionProxy());
|
||||
if (state() == QAbstractSocket::UnconnectedState)
|
||||
reconnect();
|
||||
} else {
|
||||
m_connectTimer.stop();
|
||||
m_connectAttempts = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void TorSocket::connectToHost(const QString &hostName, quint16 port, OpenMode openMode,
|
||||
NetworkLayerProtocol protocol)
|
||||
{
|
||||
m_host = hostName;
|
||||
m_port = port;
|
||||
|
||||
if (!torControl->hasConnectivity())
|
||||
return;
|
||||
|
||||
if (proxy() != torControl->connectionProxy())
|
||||
setProxy(torControl->connectionProxy());
|
||||
|
||||
QAbstractSocket::connectToHost(hostName, port, openMode, protocol);
|
||||
}
|
||||
|
||||
void TorSocket::connectToHost(const QHostAddress &address, quint16 port, OpenMode openMode)
|
||||
{
|
||||
TorSocket::connectToHost(address.toString(), port, openMode);
|
||||
}
|
||||
|
||||
void TorSocket::onFailed()
|
||||
{
|
||||
// Make sure the internal connection to the SOCKS proxy is closed
|
||||
// Otherwise reconnect attempts will fail (#295)
|
||||
close();
|
||||
|
||||
if (reconnectEnabled() && !m_connectTimer.isActive()) {
|
||||
m_connectAttempts++;
|
||||
m_connectTimer.start(reconnectInterval() * 1000);
|
||||
std::cerr << "Reconnecting socket to" << m_host.toStdString() << ":" << m_port << "in" << m_connectTimer.interval() / 1000 << "seconds" << std::endl;
|
||||
}
|
||||
}
|
@ -1,97 +0,0 @@
|
||||
/* Ricochet - https://ricochet.im/
|
||||
* Copyright (C) 2014, John Brooks <john.brooks@dereferenced.net>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* * Neither the names of the copyright owners nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef TORSOCKET_H
|
||||
#define TORSOCKET_H
|
||||
|
||||
#include <QTcpSocket>
|
||||
#include <QTimer>
|
||||
|
||||
namespace Tor {
|
||||
|
||||
/* Specialized QTcpSocket which makes connections over the SOCKS proxy
|
||||
* from a TorControl instance, automatically attempts reconnections, and
|
||||
* reacts to Tor's connectivity state.
|
||||
*
|
||||
* Use normal QTcpSocket/QAbstractSocket API. When a connection fails, it
|
||||
* will be retried automatically after the correct interval and when
|
||||
* connectivity is available.
|
||||
*
|
||||
* To fully disconnect, destroy the object, or call
|
||||
* setReconnectEnabled(false) and disconnect the socket with
|
||||
* disconnectFromHost or abort.
|
||||
*
|
||||
* The caller is responsible for resetting the attempt counter if a
|
||||
* connection was successful and reconnection will be used again.
|
||||
*/
|
||||
class TorSocket : public QTcpSocket
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit TorSocket(QObject *parent = 0);
|
||||
virtual ~TorSocket();
|
||||
|
||||
bool reconnectEnabled() const { return m_reconnectEnabled; }
|
||||
void setReconnectEnabled(bool enabled);
|
||||
int maxAttemptInterval() { return m_maxInterval; }
|
||||
void setMaxAttemptInterval(int interval);
|
||||
void resetAttempts();
|
||||
|
||||
virtual void connectToHost(const QString &hostName, quint16 port, OpenMode openMode = ReadWrite, NetworkLayerProtocol protocol = AnyIPProtocol);
|
||||
virtual void connectToHost(const QHostAddress &address, quint16 port, OpenMode openMode = ReadWrite);
|
||||
|
||||
QString hostName() const { return m_host; }
|
||||
quint16 port() const { return m_port; }
|
||||
|
||||
protected:
|
||||
virtual int reconnectInterval();
|
||||
|
||||
private slots:
|
||||
void reconnect();
|
||||
void connectivityChanged();
|
||||
void onFailed();
|
||||
|
||||
private:
|
||||
QString m_host;
|
||||
quint16 m_port;
|
||||
QTimer m_connectTimer;
|
||||
bool m_reconnectEnabled;
|
||||
int m_maxInterval;
|
||||
int m_connectAttempts;
|
||||
|
||||
using QAbstractSocket::connectToHost;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
91
libretroshare/src/tor/bytearray.h
Normal file
91
libretroshare/src/tor/bytearray.h
Normal file
@ -0,0 +1,91 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "util/rsprint.h"
|
||||
#include "util/rsdebug.h"
|
||||
|
||||
class ByteArray: public std::vector<unsigned char>
|
||||
{
|
||||
public:
|
||||
ByteArray() =default;
|
||||
ByteArray(int n) : std::vector<unsigned char>(n) {}
|
||||
ByteArray(const unsigned char *d,int n) : std::vector<unsigned char>(n) { memcpy(data(),d,n); }
|
||||
virtual ~ByteArray() =default;
|
||||
|
||||
ByteArray(const std::string& c) { resize(c.size()); memcpy(data(),c.c_str(),c.size()); }
|
||||
const ByteArray& operator=(const std::string& c) { resize(c.size()); memcpy(data(),c.c_str(),c.size()); return *this; }
|
||||
|
||||
bool isNull() const { return empty(); }
|
||||
ByteArray toHex() const { return ByteArray(RsUtil::BinToHex(data(),size(),0)); }
|
||||
std::string toString() const { std::string res; for(auto c:*this) res += c; return res; }
|
||||
|
||||
ByteArray operator+(const ByteArray& b) const { auto res(*this); for(unsigned char c:b) res.push_back(c); return res; }
|
||||
ByteArray operator+(const std::string& b) const { return operator+(ByteArray(b)); }
|
||||
|
||||
void append(const ByteArray& b) { for(auto c:b) push_back(c); }
|
||||
void append(const char *b) { for(uint32_t n=0;b[n]!=0;++n) push_back(b[n]); }
|
||||
|
||||
ByteArray& operator+=(const ByteArray& b) { for(auto c:b) push_back(c); return *this; }
|
||||
ByteArray& operator+=(const char *b) { for(uint32_t n=0;b[n]!=0;++n) push_back(b[n]); return *this;}
|
||||
|
||||
ByteArray left(uint32_t l) const { auto res = *this; res.resize(std::min((uint32_t)size(),l)); return res; }
|
||||
ByteArray toUpper() const { auto res = *this; for(uint32_t i=0;i<size();++i) if( res[i]<='z' && res[i]>='a') res[i] += 'A'-'a'; return res; }
|
||||
|
||||
bool startsWith(const char *b) const
|
||||
{
|
||||
for(uint32_t n=0;b[n]!=0;++n)
|
||||
if(n >= size() || b[n]!=(*this)[n])
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool operator==(const char *b) const
|
||||
{
|
||||
uint32_t n;
|
||||
for(n=0;b[n]!=0;++n)
|
||||
if(n >= size() || b[n]!=(*this)[n])
|
||||
return false;
|
||||
|
||||
return n==size();
|
||||
}
|
||||
|
||||
ByteArray mid(uint32_t n,int s=-1) const
|
||||
{
|
||||
ByteArray res((s>=0)?s:(size()-n));
|
||||
memcpy(res.data(),&data()[n],res.size());
|
||||
return res;
|
||||
}
|
||||
|
||||
int indexOf(unsigned char c,int from=0) const
|
||||
{
|
||||
for(uint32_t i=from;i<size();++i)
|
||||
if((*this)[i]==c)
|
||||
return (int)i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
ByteArray replace(const ByteArray& b1,const ByteArray& b2)
|
||||
{
|
||||
if(b1.empty())
|
||||
{
|
||||
RsErr() << "Attempting to replace an empty string!";
|
||||
return *this;
|
||||
}
|
||||
ByteArray res ;
|
||||
|
||||
for(uint32_t i=0;i+b1.size()<=size();)
|
||||
if(!memcmp(&(*this)[i],b1.data(),b1.size()))
|
||||
{
|
||||
res.append(b2);
|
||||
i += b1.size();
|
||||
}
|
||||
else
|
||||
res.push_back((*this)[i++]);
|
||||
|
||||
return res;
|
||||
}
|
||||
};
|
Loading…
Reference in New Issue
Block a user