mirror of
https://github.com/overte-org/overte.git
synced 2025-08-10 00:36:30 +02:00
Make RSA key-pair class a Runnable that's owned by a threadpool
This commit is contained in:
parent
66d39667e1
commit
8fb5d1b92d
4 changed files with 61 additions and 101 deletions
|
@ -22,6 +22,7 @@
|
||||||
#include <QtCore/QStringList>
|
#include <QtCore/QStringList>
|
||||||
#include <QtCore/QStandardPaths>
|
#include <QtCore/QStandardPaths>
|
||||||
#include <QtCore/QUrlQuery>
|
#include <QtCore/QUrlQuery>
|
||||||
|
#include <QtCore/QThreadPool>
|
||||||
#include <QtNetwork/QHttpMultiPart>
|
#include <QtNetwork/QHttpMultiPart>
|
||||||
#include <QtNetwork/QNetworkRequest>
|
#include <QtNetwork/QNetworkRequest>
|
||||||
#include <qthread.h>
|
#include <qthread.h>
|
||||||
|
@ -94,10 +95,6 @@ const QString DOUBLE_SLASH_SUBSTITUTE = "slashslash";
|
||||||
const QString ACCOUNT_MANAGER_REQUESTED_SCOPE = "owner";
|
const QString ACCOUNT_MANAGER_REQUESTED_SCOPE = "owner";
|
||||||
|
|
||||||
AccountManager::~AccountManager() {
|
AccountManager::~AccountManager() {
|
||||||
QMutexLocker lock(&_rsaKeygenLock);
|
|
||||||
while (_rsaKeygenThread) {
|
|
||||||
_rsaKeygenWait.wait(&_rsaKeygenLock);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AccountManager::logout() {
|
void AccountManager::logout() {
|
||||||
|
@ -747,96 +744,75 @@ void AccountManager::generateNewKeypair(bool isUserKeypair, const QUuid& domainI
|
||||||
qCDebug(networking) << "Clearing current private key in DataServerAccountInfo";
|
qCDebug(networking) << "Clearing current private key in DataServerAccountInfo";
|
||||||
_accountInfo.setPrivateKey(QByteArray());
|
_accountInfo.setPrivateKey(QByteArray());
|
||||||
|
|
||||||
// setup a new QThread to generate the keypair on, in case it takes a while
|
// Create a runnable keypair generated to create an RSA pair and exit.
|
||||||
QThread* generateThread = new QThread(this);
|
|
||||||
generateThread->setObjectName("Account Manager Generator Thread");
|
|
||||||
|
|
||||||
// setup a keypair generator
|
|
||||||
RSAKeypairGenerator* keypairGenerator = new RSAKeypairGenerator;
|
RSAKeypairGenerator* keypairGenerator = new RSAKeypairGenerator;
|
||||||
|
|
||||||
if (!isUserKeypair) {
|
if (!isUserKeypair) {
|
||||||
keypairGenerator->setDomainID(domainID);
|
|
||||||
_accountInfo.setDomainID(domainID);
|
_accountInfo.setDomainID(domainID);
|
||||||
}
|
}
|
||||||
|
|
||||||
// start keypair generation when the thread starts
|
|
||||||
connect(generateThread, &QThread::started, keypairGenerator, &RSAKeypairGenerator::generateKeypair);
|
|
||||||
|
|
||||||
// handle success or failure of keypair generation
|
// handle success or failure of keypair generation
|
||||||
connect(keypairGenerator, &RSAKeypairGenerator::generatedKeypair, this, &AccountManager::processGeneratedKeypair);
|
connect(keypairGenerator, &RSAKeypairGenerator::generatedKeypair, this,
|
||||||
connect(keypairGenerator, &RSAKeypairGenerator::errorGeneratingKeypair,
|
&AccountManager::processGeneratedKeypair);
|
||||||
this, &AccountManager::handleKeypairGenerationError);
|
connect(keypairGenerator, &RSAKeypairGenerator::errorGeneratingKeypair, this,
|
||||||
|
&AccountManager::handleKeypairGenerationError);
|
||||||
connect(keypairGenerator, &QObject::destroyed, generateThread, &QThread::quit);
|
|
||||||
connect(generateThread, &QThread::finished, this, &AccountManager::rsaKeygenThreadFinished);
|
|
||||||
connect(generateThread, &QThread::finished, generateThread, &QThread::deleteLater);
|
|
||||||
_rsaKeygenThread = generateThread;
|
|
||||||
|
|
||||||
keypairGenerator->moveToThread(generateThread);
|
|
||||||
|
|
||||||
qCDebug(networking) << "Starting worker thread to generate 2048-bit RSA keypair.";
|
qCDebug(networking) << "Starting worker thread to generate 2048-bit RSA keypair.";
|
||||||
generateThread->start();
|
// Start on Qt's global thread pool.
|
||||||
|
QThreadPool::globalInstance()->start(keypairGenerator);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AccountManager::processGeneratedKeypair() {
|
void AccountManager::processGeneratedKeypair(QByteArray publicKey, QByteArray privateKey) {
|
||||||
|
|
||||||
qCDebug(networking) << "Generated 2048-bit RSA keypair. Uploading public key now.";
|
qCDebug(networking) << "Generated 2048-bit RSA keypair. Uploading public key now.";
|
||||||
|
|
||||||
RSAKeypairGenerator* keypairGenerator = qobject_cast<RSAKeypairGenerator*>(sender());
|
// hold the private key to later set our metaverse API account info if upload succeeds
|
||||||
|
_pendingPrivateKey = privateKey;
|
||||||
|
|
||||||
if (keypairGenerator) {
|
// upload the public key so data-web has an up-to-date key
|
||||||
// hold the private key to later set our metaverse API account info if upload succeeds
|
const QString USER_PUBLIC_KEY_UPDATE_PATH = "api/v1/user/public_key";
|
||||||
_pendingPrivateKey = keypairGenerator->getPrivateKey();
|
const QString DOMAIN_PUBLIC_KEY_UPDATE_PATH = "api/v1/domains/%1/public_key";
|
||||||
|
|
||||||
// upload the public key so data-web has an up-to-date key
|
QString uploadPath;
|
||||||
const QString USER_PUBLIC_KEY_UPDATE_PATH = "api/v1/user/public_key";
|
const auto& domainID = _accountInfo.getDomainID();
|
||||||
const QString DOMAIN_PUBLIC_KEY_UPDATE_PATH = "api/v1/domains/%1/public_key";
|
if (domainID.isNull()) {
|
||||||
|
uploadPath = USER_PUBLIC_KEY_UPDATE_PATH;
|
||||||
QString uploadPath;
|
|
||||||
const auto& domainID = keypairGenerator->getDomainID();
|
|
||||||
if (domainID.isNull()) {
|
|
||||||
uploadPath = USER_PUBLIC_KEY_UPDATE_PATH;
|
|
||||||
} else {
|
|
||||||
uploadPath = DOMAIN_PUBLIC_KEY_UPDATE_PATH.arg(uuidStringWithoutCurlyBraces(domainID));
|
|
||||||
}
|
|
||||||
|
|
||||||
// setup a multipart upload to send up the public key
|
|
||||||
QHttpMultiPart* requestMultiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType);
|
|
||||||
|
|
||||||
QHttpPart publicKeyPart;
|
|
||||||
publicKeyPart.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("application/octet-stream"));
|
|
||||||
|
|
||||||
publicKeyPart.setHeader(QNetworkRequest::ContentDispositionHeader,
|
|
||||||
QVariant("form-data; name=\"public_key\"; filename=\"public_key\""));
|
|
||||||
publicKeyPart.setBody(keypairGenerator->getPublicKey());
|
|
||||||
requestMultiPart->append(publicKeyPart);
|
|
||||||
|
|
||||||
if (!domainID.isNull()) {
|
|
||||||
const auto& key = getTemporaryDomainKey(domainID);
|
|
||||||
QHttpPart apiKeyPart;
|
|
||||||
publicKeyPart.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("application/octet-stream"));
|
|
||||||
apiKeyPart.setHeader(QNetworkRequest::ContentDispositionHeader,
|
|
||||||
QVariant("form-data; name=\"api_key\""));
|
|
||||||
apiKeyPart.setBody(key.toUtf8());
|
|
||||||
requestMultiPart->append(apiKeyPart);
|
|
||||||
}
|
|
||||||
|
|
||||||
// setup callback parameters so we know once the keypair upload has succeeded or failed
|
|
||||||
JSONCallbackParameters callbackParameters;
|
|
||||||
callbackParameters.jsonCallbackReceiver = this;
|
|
||||||
callbackParameters.jsonCallbackMethod = "publicKeyUploadSucceeded";
|
|
||||||
callbackParameters.errorCallbackReceiver = this;
|
|
||||||
callbackParameters.errorCallbackMethod = "publicKeyUploadFailed";
|
|
||||||
|
|
||||||
sendRequest(uploadPath, AccountManagerAuth::Optional, QNetworkAccessManager::PutOperation,
|
|
||||||
callbackParameters, QByteArray(), requestMultiPart);
|
|
||||||
|
|
||||||
keypairGenerator->deleteLater();
|
|
||||||
} else {
|
} else {
|
||||||
qCWarning(networking) << "Expected processGeneratedKeypair to be called by a live RSAKeypairGenerator"
|
uploadPath = DOMAIN_PUBLIC_KEY_UPDATE_PATH.arg(uuidStringWithoutCurlyBraces(domainID));
|
||||||
<< "but the casted sender is NULL. Will not process generated keypair.";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// setup a multipart upload to send up the public key
|
||||||
|
QHttpMultiPart* requestMultiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType);
|
||||||
|
|
||||||
|
QHttpPart publicKeyPart;
|
||||||
|
publicKeyPart.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("application/octet-stream"));
|
||||||
|
|
||||||
|
publicKeyPart.setHeader(QNetworkRequest::ContentDispositionHeader,
|
||||||
|
QVariant("form-data; name=\"public_key\"; filename=\"public_key\""));
|
||||||
|
publicKeyPart.setBody(publicKey);
|
||||||
|
requestMultiPart->append(publicKeyPart);
|
||||||
|
|
||||||
|
// Currently broken? We don't have the temporary domain key.
|
||||||
|
if (!domainID.isNull()) {
|
||||||
|
const auto& key = getTemporaryDomainKey(domainID);
|
||||||
|
QHttpPart apiKeyPart;
|
||||||
|
publicKeyPart.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("application/octet-stream"));
|
||||||
|
apiKeyPart.setHeader(QNetworkRequest::ContentDispositionHeader,
|
||||||
|
QVariant("form-data; name=\"api_key\""));
|
||||||
|
apiKeyPart.setBody(key.toUtf8());
|
||||||
|
requestMultiPart->append(apiKeyPart);
|
||||||
|
}
|
||||||
|
|
||||||
|
// setup callback parameters so we know once the keypair upload has succeeded or failed
|
||||||
|
JSONCallbackParameters callbackParameters;
|
||||||
|
callbackParameters.jsonCallbackReceiver = this;
|
||||||
|
callbackParameters.jsonCallbackMethod = "publicKeyUploadSucceeded";
|
||||||
|
callbackParameters.errorCallbackReceiver = this;
|
||||||
|
callbackParameters.errorCallbackMethod = "publicKeyUploadFailed";
|
||||||
|
|
||||||
|
sendRequest(uploadPath, AccountManagerAuth::Optional, QNetworkAccessManager::PutOperation,
|
||||||
|
callbackParameters, QByteArray(), requestMultiPart);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AccountManager::publicKeyUploadSucceeded(QNetworkReply& reply) {
|
void AccountManager::publicKeyUploadSucceeded(QNetworkReply& reply) {
|
||||||
|
@ -875,12 +851,4 @@ void AccountManager::handleKeypairGenerationError() {
|
||||||
|
|
||||||
// reset our waiting state for keypair response
|
// reset our waiting state for keypair response
|
||||||
_isWaitingForKeypairResponse = false;
|
_isWaitingForKeypairResponse = false;
|
||||||
|
|
||||||
sender()->deleteLater();
|
|
||||||
}
|
|
||||||
|
|
||||||
void AccountManager::rsaKeygenThreadFinished() {
|
|
||||||
QMutexLocker lock(&_rsaKeygenLock);
|
|
||||||
_rsaKeygenThread = nullptr;
|
|
||||||
_rsaKeygenWait.wakeAll();
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,8 +15,6 @@
|
||||||
#include <QtCore/QByteArray>
|
#include <QtCore/QByteArray>
|
||||||
#include <QtCore/QObject>
|
#include <QtCore/QObject>
|
||||||
#include <QtCore/QUrl>
|
#include <QtCore/QUrl>
|
||||||
#include <QtCore/QMutex>
|
|
||||||
#include <QtCore/QWaitCondition>
|
|
||||||
#include <QtNetwork/QNetworkReply>
|
#include <QtNetwork/QNetworkReply>
|
||||||
#include <QUrlQuery>
|
#include <QUrlQuery>
|
||||||
|
|
||||||
|
@ -130,11 +128,10 @@ signals:
|
||||||
private slots:
|
private slots:
|
||||||
void processReply();
|
void processReply();
|
||||||
void handleKeypairGenerationError();
|
void handleKeypairGenerationError();
|
||||||
void processGeneratedKeypair();
|
void processGeneratedKeypair(QByteArray publicKey, QByteArray privateKey);
|
||||||
void publicKeyUploadSucceeded(QNetworkReply& reply);
|
void publicKeyUploadSucceeded(QNetworkReply& reply);
|
||||||
void publicKeyUploadFailed(QNetworkReply& reply);
|
void publicKeyUploadFailed(QNetworkReply& reply);
|
||||||
void generateNewKeypair(bool isUserKeypair = true, const QUuid& domainID = QUuid());
|
void generateNewKeypair(bool isUserKeypair = true, const QUuid& domainID = QUuid());
|
||||||
void rsaKeygenThreadFinished();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
AccountManager(AccountManager const& other) = delete;
|
AccountManager(AccountManager const& other) = delete;
|
||||||
|
@ -160,9 +157,6 @@ private:
|
||||||
QByteArray _pendingPrivateKey;
|
QByteArray _pendingPrivateKey;
|
||||||
|
|
||||||
QUuid _sessionID { QUuid::createUuid() };
|
QUuid _sessionID { QUuid::createUuid() };
|
||||||
QMutex _rsaKeygenLock;
|
|
||||||
QWaitCondition _rsaKeygenWait;
|
|
||||||
QThread* _rsaKeygenThread { nullptr };
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_AccountManager_h
|
#endif // hifi_AccountManager_h
|
||||||
|
|
|
@ -25,7 +25,10 @@
|
||||||
RSAKeypairGenerator::RSAKeypairGenerator(QObject* parent) :
|
RSAKeypairGenerator::RSAKeypairGenerator(QObject* parent) :
|
||||||
QObject(parent)
|
QObject(parent)
|
||||||
{
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void RSAKeypairGenerator::run() {
|
||||||
|
generateKeypair();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RSAKeypairGenerator::generateKeypair() {
|
void RSAKeypairGenerator::generateKeypair() {
|
||||||
|
@ -92,5 +95,5 @@ void RSAKeypairGenerator::generateKeypair() {
|
||||||
OPENSSL_free(publicKeyDER);
|
OPENSSL_free(publicKeyDER);
|
||||||
OPENSSL_free(privateKeyDER);
|
OPENSSL_free(privateKeyDER);
|
||||||
|
|
||||||
emit generatedKeypair();
|
emit generatedKeypair(_publicKey, _privateKey);
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,25 +13,20 @@
|
||||||
#define hifi_RSAKeypairGenerator_h
|
#define hifi_RSAKeypairGenerator_h
|
||||||
|
|
||||||
#include <QtCore/QObject>
|
#include <QtCore/QObject>
|
||||||
|
#include <QtCore/QRunnable>
|
||||||
#include <QtCore/QUuid>
|
#include <QtCore/QUuid>
|
||||||
|
|
||||||
class RSAKeypairGenerator : public QObject {
|
class RSAKeypairGenerator : public QObject, public QRunnable {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
RSAKeypairGenerator(QObject* parent = 0);
|
RSAKeypairGenerator(QObject* parent = nullptr);
|
||||||
|
|
||||||
void setDomainID(const QUuid& domainID) { _domainID = domainID; }
|
virtual void run() override;
|
||||||
const QUuid& getDomainID() const { return _domainID; }
|
|
||||||
|
|
||||||
const QByteArray& getPublicKey() const { return _publicKey; }
|
|
||||||
const QByteArray& getPrivateKey() const { return _privateKey; }
|
|
||||||
|
|
||||||
public slots:
|
|
||||||
void generateKeypair();
|
void generateKeypair();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void errorGeneratingKeypair();
|
void errorGeneratingKeypair();
|
||||||
void generatedKeypair();
|
void generatedKeypair(QByteArray publicKey, QByteArray privateKey);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QUuid _domainID;
|
QUuid _domainID;
|
||||||
|
|
Loading…
Reference in a new issue