mirror of
https://github.com/qbittorrent/qBittorrent
synced 2025-07-06 05:01:25 -07:00
Add support for SSL torrents
The 'SSL torrent' feature is not standardized. I.e. there are no BEP (BitTorrent Enhancement Proposals) associated with it, so we do not greatly encourage its usage as it will only work with libtorrent clients and derivatives. It will not work with other torrent clients that do not support the libtorrent specific implementation. This PR aims to provide minimal support for those who need SSL torrents. Furthermore, it is intended that there will be no UI support (nor indication) of adding/creating SSL torrents. * Prerequisites: I omit the instructions of creating those files as the intended audience (experts & advanced users) should have no problem with it. All files are as follow: 1. Root (torrent publisher) certificate 2. Root private key 3. A .torrent file created with root certificate 5. Peer certificate (signed by the root certificate) 6. Peer private key 7. Diffie-Hellman parameters file All files are stored in .pem format. * Enable SSL torrent protocol in qbt There are 2 hidden keys to put in qbt config file, under `[BitTorrent]` section: 1. `Session\SSL\Enabled`: set it to `true`. 2. `Session\SSL\Port`: set it to some unused port or omit the key entirely to let qbt pick one for you. * Add an SSL torrent to qbt The only way of adding an SSL torrent is via WebAPI. The `/api/v2/torrents/add` endpoint will support 3 additional parameters. You must provide them for an SSL torrent. 1. `ssl_certificate`: Contents of the peer certificate file (in PEM format). 2. `ssl_private_key`: Contents of the peer private key file. 3. `ssl_dh_params`: Contents of the Diffie-Hellman parameters file. * Change the SSL parameters to a torrent In case you provided wrong SSL parameters when adding a torrent, there is a new endpoint `/api/v2/torrents/setSSLParameters` that you can update the SSL parameters. The parameters (`ssl_*`) are the same as `/api/v2/torrents/add` endpoint. * Query the SSL parameters of a torrent There is a new endpoint `/api/v2/torrents/SSLParameters` that you can query the SSL parameters of a torrent. References: * https://www.libtorrent.org/manual-ref.html#ssl-torrents * https://blog.libtorrent.org/2012/01/bittorrent-over-ssl/ PR #20338. --------- Co-authored-by: Radu Carpa <radu.carpa@cern.ch>
This commit is contained in:
parent
c6ee0ff017
commit
cffd74b62a
24 changed files with 482 additions and 101 deletions
|
@ -45,6 +45,7 @@
|
|||
#include "base/bittorrent/peeraddress.h"
|
||||
#include "base/bittorrent/peerinfo.h"
|
||||
#include "base/bittorrent/session.h"
|
||||
#include "base/bittorrent/sslparameters.h"
|
||||
#include "base/bittorrent/torrent.h"
|
||||
#include "base/bittorrent/torrentdescriptor.h"
|
||||
#include "base/bittorrent/trackerentry.h"
|
||||
|
@ -55,6 +56,7 @@
|
|||
#include "base/torrentfilter.h"
|
||||
#include "base/utils/datetime.h"
|
||||
#include "base/utils/fs.h"
|
||||
#include "base/utils/sslkey.h"
|
||||
#include "base/utils/string.h"
|
||||
#include "apierror.h"
|
||||
#include "serialize/serialize_torrent.h"
|
||||
|
@ -108,6 +110,9 @@ const QString KEY_PROP_SAVE_PATH = u"save_path"_s;
|
|||
const QString KEY_PROP_DOWNLOAD_PATH = u"download_path"_s;
|
||||
const QString KEY_PROP_COMMENT = u"comment"_s;
|
||||
const QString KEY_PROP_ISPRIVATE = u"is_private"_s;
|
||||
const QString KEY_PROP_SSL_CERTIFICATE = u"ssl_certificate"_s;
|
||||
const QString KEY_PROP_SSL_PRIVATEKEY = u"ssl_private_key"_s;
|
||||
const QString KEY_PROP_SSL_DHPARAMS = u"ssl_dh_params"_s;
|
||||
|
||||
// File keys
|
||||
const QString KEY_FILE_INDEX = u"index"_s;
|
||||
|
@ -721,27 +726,38 @@ void TorrentsController::addAction()
|
|||
}
|
||||
}
|
||||
|
||||
BitTorrent::AddTorrentParams addTorrentParams;
|
||||
// TODO: Check if destination actually exists
|
||||
addTorrentParams.skipChecking = skipChecking;
|
||||
addTorrentParams.sequential = seqDownload;
|
||||
addTorrentParams.firstLastPiecePriority = firstLastPiece;
|
||||
addTorrentParams.addToQueueTop = addToQueueTop;
|
||||
addTorrentParams.addPaused = addPaused;
|
||||
addTorrentParams.stopCondition = stopCondition;
|
||||
addTorrentParams.contentLayout = contentLayout;
|
||||
addTorrentParams.savePath = Path(savepath);
|
||||
addTorrentParams.downloadPath = Path(downloadPath);
|
||||
addTorrentParams.useDownloadPath = useDownloadPath;
|
||||
addTorrentParams.category = category;
|
||||
addTorrentParams.tags.insert(tags.cbegin(), tags.cend());
|
||||
addTorrentParams.name = torrentName;
|
||||
addTorrentParams.uploadLimit = upLimit;
|
||||
addTorrentParams.downloadLimit = dlLimit;
|
||||
addTorrentParams.seedingTimeLimit = seedingTimeLimit;
|
||||
addTorrentParams.inactiveSeedingTimeLimit = inactiveSeedingTimeLimit;
|
||||
addTorrentParams.ratioLimit = ratioLimit;
|
||||
addTorrentParams.useAutoTMM = autoTMM;
|
||||
const BitTorrent::AddTorrentParams addTorrentParams
|
||||
{
|
||||
// TODO: Check if destination actually exists
|
||||
.name = torrentName,
|
||||
.category = category,
|
||||
.tags = {tags.cbegin(), tags.cend()},
|
||||
.savePath = Path(savepath),
|
||||
.useDownloadPath = useDownloadPath,
|
||||
.downloadPath = Path(downloadPath),
|
||||
.sequential = seqDownload,
|
||||
.firstLastPiecePriority = firstLastPiece,
|
||||
.addForced = false,
|
||||
.addToQueueTop = addToQueueTop,
|
||||
.addPaused = addPaused,
|
||||
.stopCondition = stopCondition,
|
||||
.filePaths = {},
|
||||
.filePriorities = {},
|
||||
.skipChecking = skipChecking,
|
||||
.contentLayout = contentLayout,
|
||||
.useAutoTMM = autoTMM,
|
||||
.uploadLimit = upLimit,
|
||||
.downloadLimit = dlLimit,
|
||||
.seedingTimeLimit = seedingTimeLimit,
|
||||
.inactiveSeedingTimeLimit = inactiveSeedingTimeLimit,
|
||||
.ratioLimit = ratioLimit,
|
||||
.sslParameters =
|
||||
{
|
||||
.certificate = QSslCertificate(params()[KEY_PROP_SSL_CERTIFICATE].toLatin1()),
|
||||
.privateKey = Utils::SSLKey::load(params()[KEY_PROP_SSL_PRIVATEKEY].toLatin1()),
|
||||
.dhParams = params()[KEY_PROP_SSL_DHPARAMS].toLatin1()
|
||||
}
|
||||
};
|
||||
|
||||
bool partialSuccess = false;
|
||||
for (QString url : asConst(urls.split(u'\n')))
|
||||
|
@ -1444,3 +1460,43 @@ void TorrentsController::exportAction()
|
|||
|
||||
setResult(result.value(), u"application/x-bittorrent"_s, (id.toString() + u".torrent"));
|
||||
}
|
||||
|
||||
void TorrentsController::SSLParametersAction()
|
||||
{
|
||||
requireParams({u"hash"_s});
|
||||
|
||||
const auto id = BitTorrent::TorrentID::fromString(params()[u"hash"_s]);
|
||||
const BitTorrent::Torrent *torrent = BitTorrent::Session::instance()->getTorrent(id);
|
||||
if (!torrent)
|
||||
throw APIError(APIErrorType::NotFound);
|
||||
|
||||
const BitTorrent::SSLParameters sslParams = torrent->getSSLParameters();
|
||||
const QJsonObject ret
|
||||
{
|
||||
{KEY_PROP_SSL_CERTIFICATE, QString::fromLatin1(sslParams.certificate.toPem())},
|
||||
{KEY_PROP_SSL_PRIVATEKEY, QString::fromLatin1(sslParams.privateKey.toPem())},
|
||||
{KEY_PROP_SSL_DHPARAMS, QString::fromLatin1(sslParams.dhParams)}
|
||||
};
|
||||
setResult(ret);
|
||||
}
|
||||
|
||||
void TorrentsController::setSSLParametersAction()
|
||||
{
|
||||
requireParams({u"hash"_s, KEY_PROP_SSL_CERTIFICATE, KEY_PROP_SSL_PRIVATEKEY, KEY_PROP_SSL_DHPARAMS});
|
||||
|
||||
const auto id = BitTorrent::TorrentID::fromString(params()[u"hash"_s]);
|
||||
BitTorrent::Torrent *const torrent = BitTorrent::Session::instance()->getTorrent(id);
|
||||
if (!torrent)
|
||||
throw APIError(APIErrorType::NotFound);
|
||||
|
||||
const BitTorrent::SSLParameters sslParams
|
||||
{
|
||||
.certificate = QSslCertificate(params()[KEY_PROP_SSL_CERTIFICATE].toLatin1()),
|
||||
.privateKey = Utils::SSLKey::load(params()[KEY_PROP_SSL_PRIVATEKEY].toLatin1()),
|
||||
.dhParams = params()[KEY_PROP_SSL_DHPARAMS].toLatin1()
|
||||
};
|
||||
if (!sslParams.isValid())
|
||||
throw APIError(APIErrorType::BadData);
|
||||
|
||||
torrent->setSSLParameters(sslParams);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue