diff --git a/libraries/networking/src/AccountManager.cpp b/libraries/networking/src/AccountManager.cpp index e70e3e26d0..05f0ec12b5 100644 --- a/libraries/networking/src/AccountManager.cpp +++ b/libraries/networking/src/AccountManager.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -743,6 +744,9 @@ void AccountManager::generateNewKeypair(bool isUserKeypair, const QUuid& domainI return; } + // Ensure openssl/Qt config is set up. + QSslConfiguration::defaultConfiguration(); + // make sure we don't already have an outbound keypair generation request if (!_isWaitingForKeypairResponse) { _isWaitingForKeypairResponse = true; @@ -751,94 +755,75 @@ void AccountManager::generateNewKeypair(bool isUserKeypair, const QUuid& domainI qCDebug(networking) << "Clearing current private key in DataServerAccountInfo"; _accountInfo.setPrivateKey(QByteArray()); - // setup a new QThread to generate the keypair on, in case it takes a while - QThread* generateThread = new QThread(this); - generateThread->setObjectName("Account Manager Generator Thread"); - - // setup a keypair generator + // Create a runnable keypair generated to create an RSA pair and exit. RSAKeypairGenerator* keypairGenerator = new RSAKeypairGenerator; if (!isUserKeypair) { - keypairGenerator->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 - connect(keypairGenerator, &RSAKeypairGenerator::generatedKeypair, this, &AccountManager::processGeneratedKeypair); - connect(keypairGenerator, &RSAKeypairGenerator::errorGeneratingKeypair, - this, &AccountManager::handleKeypairGenerationError); - - connect(keypairGenerator, &QObject::destroyed, generateThread, &QThread::quit); - connect(generateThread, &QThread::finished, generateThread, &QThread::deleteLater); - - keypairGenerator->moveToThread(generateThread); + connect(keypairGenerator, &RSAKeypairGenerator::generatedKeypair, this, + &AccountManager::processGeneratedKeypair); + connect(keypairGenerator, &RSAKeypairGenerator::errorGeneratingKeypair, this, + &AccountManager::handleKeypairGenerationError); 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."; - RSAKeypairGenerator* keypairGenerator = qobject_cast(sender()); + // hold the private key to later set our metaverse API account info if upload succeeds + _pendingPrivateKey = privateKey; - if (keypairGenerator) { - // hold the private key to later set our metaverse API account info if upload succeeds - _pendingPrivateKey = keypairGenerator->getPrivateKey(); + // upload the public key so data-web has an up-to-date key + const QString USER_PUBLIC_KEY_UPDATE_PATH = "api/v1/user/public_key"; + 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 - const QString USER_PUBLIC_KEY_UPDATE_PATH = "api/v1/user/public_key"; - const QString DOMAIN_PUBLIC_KEY_UPDATE_PATH = "api/v1/domains/%1/public_key"; - - 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(); + QString uploadPath; + const auto& domainID = _accountInfo.getDomainID(); + if (domainID.isNull()) { + uploadPath = USER_PUBLIC_KEY_UPDATE_PATH; } else { - qCWarning(networking) << "Expected processGeneratedKeypair to be called by a live RSAKeypairGenerator" - << "but the casted sender is NULL. Will not process generated keypair."; + 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(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) { @@ -877,6 +862,4 @@ void AccountManager::handleKeypairGenerationError() { // reset our waiting state for keypair response _isWaitingForKeypairResponse = false; - - sender()->deleteLater(); } diff --git a/libraries/networking/src/AccountManager.h b/libraries/networking/src/AccountManager.h index 88ebaf5656..9068966512 100644 --- a/libraries/networking/src/AccountManager.h +++ b/libraries/networking/src/AccountManager.h @@ -128,7 +128,7 @@ signals: private slots: void processReply(); void handleKeypairGenerationError(); - void processGeneratedKeypair(); + void processGeneratedKeypair(QByteArray publicKey, QByteArray privateKey); void publicKeyUploadSucceeded(QNetworkReply& reply); void publicKeyUploadFailed(QNetworkReply& reply); void generateNewKeypair(bool isUserKeypair = true, const QUuid& domainID = QUuid()); diff --git a/libraries/networking/src/RSAKeypairGenerator.cpp b/libraries/networking/src/RSAKeypairGenerator.cpp index 8ca8b81ea3..e83615e3df 100644 --- a/libraries/networking/src/RSAKeypairGenerator.cpp +++ b/libraries/networking/src/RSAKeypairGenerator.cpp @@ -25,7 +25,10 @@ RSAKeypairGenerator::RSAKeypairGenerator(QObject* parent) : QObject(parent) { - +} + +void RSAKeypairGenerator::run() { + generateKeypair(); } void RSAKeypairGenerator::generateKeypair() { @@ -92,5 +95,5 @@ void RSAKeypairGenerator::generateKeypair() { OPENSSL_free(publicKeyDER); OPENSSL_free(privateKeyDER); - emit generatedKeypair(); + emit generatedKeypair(_publicKey, _privateKey); } diff --git a/libraries/networking/src/RSAKeypairGenerator.h b/libraries/networking/src/RSAKeypairGenerator.h index 36f4a9550b..552f12395b 100644 --- a/libraries/networking/src/RSAKeypairGenerator.h +++ b/libraries/networking/src/RSAKeypairGenerator.h @@ -13,25 +13,20 @@ #define hifi_RSAKeypairGenerator_h #include +#include #include -class RSAKeypairGenerator : public QObject { +class RSAKeypairGenerator : public QObject, public QRunnable { Q_OBJECT public: - RSAKeypairGenerator(QObject* parent = 0); + RSAKeypairGenerator(QObject* parent = nullptr); - void setDomainID(const QUuid& domainID) { _domainID = domainID; } - const QUuid& getDomainID() const { return _domainID; } - - const QByteArray& getPublicKey() const { return _publicKey; } - const QByteArray& getPrivateKey() const { return _privateKey; } - -public slots: + virtual void run() override; void generateKeypair(); signals: void errorGeneratingKeypair(); - void generatedKeypair(); + void generatedKeypair(QByteArray publicKey, QByteArray privateKey); private: QUuid _domainID;