extern "C" {
#endif
-struct csync_client_certs_s {
- char *certificatePath;
- char *certificatePasswd;
-};
-
enum csync_status_codes_e {
CSYNC_STATUS_OK = 0,
} callbacks;
c_strlist_t *excludes;
-
- // needed for SSL client certificate support
- struct csync_client_certs_s *clientCerts;
struct {
char *file;
+++ /dev/null
-/*
- * Copyright (C) by Pierre MOREAU <p.moreau@agim.idshost.fr>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-/**
- * \file p12topem.cpp
- * \brief Static library to convert p12 to pem
- * \author Pierre MOREAU <p.moreau@agim.idshost.fr>
- * \version 1.0.0
- * \date 09 January 2014
- */
-
-#include "p12topem.h"
-
-/**
- * \fn string x509ToString (BIO)
- * \brief Return string from BIO SSL
- * \param BIO o PEM_write_BIO_...
- * \return string PEM
- */
-string x509ToString(BIO *o) {
- BUF_MEM *bptr;
- BIO_get_mem_ptr(o, &bptr);
- int len = bptr->length;
- void* data = calloc(len+10, sizeof(char));
- BIO_read(o, data, len);
- string ret = std::string(static_cast<char*>(data));
- free(data);
-
- return ret;
-}
-
-/**
- * \fn resultP12ToPem p12ToPem (string, string)
- * \brief Convert P12 to PEM
- * \param string p12File Path to P12 file
- * \param string p12Passwd Password to open P12 file
- * \return result (bool ReturnCode, Int ErrorCode, String Comment, String PrivateKey, String Certificate)
- */
-resultP12ToPem p12ToPem(string p12File, string p12Passwd) {
- FILE *fp;
- PKCS12 *p12 = NULL;
- EVP_PKEY *pkey = NULL;
- X509 *cert = NULL;
- STACK_OF(X509) *ca = NULL;
-
- BIO *o = BIO_new(BIO_s_mem());
-
- string privateKey = "";
- string certificate = "";
-
- resultP12ToPem ret;
- ret.ReturnCode = false;
- ret.ErrorCode = 0;
- ret.Comment = "";
- ret.PrivateKey = "";
- ret.Certificate = "";
-
- SSLeay_add_all_algorithms();
- ERR_load_crypto_strings();
- if(!(fp = fopen(p12File.c_str(), "rb"))) {
- ret.ErrorCode = 1;
- ret.Comment = strerror(errno);
- return ret;
- }
-
- p12 = d2i_PKCS12_fp(fp, &p12);
- fclose (fp);
-
- if (!p12) {
- ret.ErrorCode = 2;
- ret.Comment = "Unable to open PKCS#12 file";
- return ret;
- }
- if (!PKCS12_parse(p12, p12Passwd.c_str(), &pkey, &cert, &ca)) {
- ret.ErrorCode = 3;
- ret.Comment = "Unable to parse PKCS#12 file (wrong password ?)";
- return ret;
- }
- PKCS12_free(p12);
-
- if (!(pkey && cert)) {
- ret.ErrorCode = 4;
- ret.Comment = "Certificate and/or key file doesn't exists";
- } else {
- PEM_write_bio_PrivateKey(o, pkey, 0, 0, 0, NULL, 0);
- privateKey = x509ToString(o);
-
- PEM_write_bio_X509(o, cert);
- certificate = x509ToString(o);
-
- BIO_free(o);
-
- ret.ReturnCode = true;
- ret.ErrorCode = 0;
- ret.Comment = "All is fine";
- ret.PrivateKey = privateKey;
- ret.Certificate = certificate;
- }
- return ret;
-}
+++ /dev/null
-/*
- * Copyright (C) by Pierre MOREAU <p.moreau@agim.idshost.fr>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-#ifndef P12TOPEM_H
-#define P12TOPEM_H
-
-/**
- * \file p12topem.h
- * \brief Static library to convert p12 to pem
- * \author Pierre MOREAU <p.moreau@agim.idshost.fr>
- * \version 1.0.0
- * \date 09 January 2014
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <string>
-#include <openssl/pem.h>
-#include <openssl/err.h>
-#include <openssl/pkcs12.h>
-
-using namespace std;
-
-/**
- * \struct resultP12ToPem p12topem.h
- */
-struct resultP12ToPem {
- bool ReturnCode;
- int ErrorCode;
- string Comment;
- string PrivateKey;
- string Certificate;
-};
-
-/**
- * \brief Return string from BIO SSL
- * \param BIO o PEM_write_BIO_...
- * \return string PEM
- */
-string x509ToString(BIO *o);
-
-/**
- * \brief Convert P12 to PEM
- * \param string p12File Path to P12 file
- * \param string p12Passwd Password to open P12 file
- * \return result (bool ReturnCode, Int ErrorCode, String Comment, String PrivateKey, String Certificate)
- */
-resultP12ToPem p12ToPem(string p12File, string p12Passwd);
-
-#endif /* P12TOPEM_H */
-
class HttpCredentialsText : public HttpCredentials {
public:
HttpCredentialsText(const QString& user, const QString& password)
- : HttpCredentials(user, password, "", ""), // FIXME: not working with client certs yet (qknight)
+ : HttpCredentials(user, password), // FIXME: not working with client certs yet (qknight)
_sslTrusted(false)
{}
../3rdparty/qtsingleapplication/qtlocalpeer.cpp
../3rdparty/qtsingleapplication/qtsingleapplication.cpp
../3rdparty/qtsingleapplication/qtsinglecoreapplication.cpp
- ../3rdparty/certificates/p12topem.cpp
)
if (APPLE)
acc->setCredentials(CredentialsFactory::create(authType));
- // now the cert, it is in the general group
+ // now the server cert, it is in the general group
settings.beginGroup(QLatin1String("General"));
acc->setApprovedCerts(QSslCertificate::fromData(settings.value(caCertsKeyC).toByteArray()));
settings.endGroup();
<x>0</x>
<y>0</y>
<width>462</width>
- <height>186</height>
+ <height>188</height>
</rect>
</property>
<property name="windowTitle">
<item row="0" column="0">
<widget class="QLabel" name="labelCertificateFile">
<property name="text">
- <string>Certificate :</string>
+ <string>Certificate & Key (pkcs12) :</string>
</property>
</widget>
</item>
Q_OBJECT
public:
explicit HttpCredentialsGui() : HttpCredentials() {}
- HttpCredentialsGui(const QString& user, const QString& password, const QString& certificatePath, const QString& certificatePasswd) : HttpCredentials(user, password, certificatePath, certificatePasswd) {}
+ HttpCredentialsGui(const QString& user, const QString& password, const QSslCertificate& certificate, const QSslKey& key) : HttpCredentials(user, password, certificate, key) {}
void askFromUser() Q_DECL_OVERRIDE;
Q_INVOKABLE void askFromUserAsync();
connect(ui->btnClientSideTLS, SIGNAL(clicked(bool)), this, SLOT(returnClientSideTLS()));
connect(ui->btnBack, SIGNAL(clicked(bool)), this, SLOT(returnBack()));
- // DM: TLS Client Cert GUI support disabled for now
+
+#if QT_VERSION < QT_VERSION_CHECK(5, 4, 0)
+ // We support only from Qt 5.4.x because of https://doc.qt.io/qt-5/qsslcertificate.html#importPkcs12
ui->btnClientSideTLS->hide();
+#endif
}
void OwncloudConnectionMethodDialog::setUrl(const QUrl &url)
AbstractCredentials* OwncloudHttpCredsPage::getCredentials() const
{
- return new HttpCredentialsGui(_ui.leUsername->text(), _ui.lePassword->text(), _ocWizard->ownCloudCertificatePath, _ocWizard->ownCloudCertificatePasswd);
+ return new HttpCredentialsGui(_ui.leUsername->text(), _ui.lePassword->text(), _ocWizard->_clientSslCertificate, _ocWizard->_clientSslKey);
}
#include <QMessageBox>
#include <QSsl>
#include <QSslCertificate>
+#include <QNetworkAccessManager>
#include "QProgressIndicator.h"
#include "wizard/owncloudwizardcommon.h"
#include "wizard/owncloudsetuppage.h"
#include "wizard/owncloudconnectionmethoddialog.h"
-#include "../3rdparty/certificates/p12topem.h"
#include "theme.h"
#include "account.h"
connect(_ui.leUrl, SIGNAL(editingFinished()), SLOT(slotUrlEditFinished()));
addCertDial = new AddCertificateDialog(this);
- connect(_ocWizard,SIGNAL(needCertificate()),this,SLOT(slotAskSSLClientCertificate()));
}
void OwncloudSetupPage::setServerUrl( const QString& newUrl )
}
break;
case OwncloudConnectionMethodDialog::Client_Side_TLS:
- slotAskSSLClientCertificate();
+#if QT_VERSION >= QT_VERSION_CHECK(5, 4, 0)
+ addCertDial->show();
+ connect(addCertDial, SIGNAL(accepted()),this,SLOT(slotCertificateAccepted()));
+#endif
break;
case OwncloudConnectionMethodDialog::Closed:
case OwncloudConnectionMethodDialog::Back:
_progressIndi->stopAnimation();
}
-void OwncloudSetupPage::slotAskSSLClientCertificate()
-{
- addCertDial->show();
- connect(addCertDial, SIGNAL(accepted()),this,SLOT(slotCertificateAccepted()));
-}
-
QString subjectInfoHelper(const QSslCertificate& cert, const QByteArray &qa)
{
#if QT_VERSION < QT_VERSION_CHECK(5,0,0)
//called during the validation of the client certificate.
void OwncloudSetupPage::slotCertificateAccepted()
{
- QSslCertificate sslCertificate;
+#if QT_VERSION >= QT_VERSION_CHECK(5, 4, 0)
+ QList<QSslCertificate> clientCaCertificates;
+ QFile certFile(addCertDial->getCertificatePath());
+ certFile.open(QFile::ReadOnly);
+ if(QSslCertificate::importPkcs12(&certFile,
+ &_ocWizard->_clientSslKey, &_ocWizard->_clientSslCertificate,
+ &clientCaCertificates,
+ addCertDial->getCertificatePasswd().toLocal8Bit())){
+ AccountPtr acc = _ocWizard->account();
- resultP12ToPem certif = p12ToPem(addCertDial->getCertificatePath().toStdString() , addCertDial->getCertificatePasswd().toStdString());
- if(certif.ReturnCode){
- QString s = QString::fromStdString(certif.Certificate);
- QByteArray ba = s.toLocal8Bit();
+ // to re-create the session ticket because we added a key/cert
+ acc->setSslConfiguration(QSslConfiguration());
+ QSslConfiguration sslConfiguration = acc->getOrCreateSslConfig();
- QList<QSslCertificate> sslCertificateList = QSslCertificate::fromData(ba, QSsl::Pem);
- sslCertificate = sslCertificateList.takeAt(0);
+ // We're stuffing the certificate into the configuration form here. Later the
+ // cert will come via the HttpCredentials
+ sslConfiguration.setLocalCertificate(_ocWizard->_clientSslCertificate);
+ sslConfiguration.setPrivateKey(_ocWizard->_clientSslKey);
+ acc->setSslConfiguration(sslConfiguration);
- _ocWizard->ownCloudCertificate = ba;
- _ocWizard->ownCloudPrivateKey = certif.PrivateKey.c_str();
- _ocWizard->ownCloudCertificatePath = addCertDial->getCertificatePath();
- _ocWizard->ownCloudCertificatePasswd = addCertDial->getCertificatePasswd();
+ // Make sure TCP connections get re-established
+ acc->networkAccessManager()->clearAccessCache();
- AccountPtr acc = _ocWizard->account();
- acc->setCertificate(_ocWizard->ownCloudCertificate, _ocWizard->ownCloudPrivateKey);
- addCertDial->reinit();
+ addCertDial->reinit(); // FIXME: Why not just have this only created on use?
validatePage();
} else {
- QString message;
- message = certif.Comment.c_str();
- addCertDial->showErrorMessage(message);
+ addCertDial->showErrorMessage("Could not load certificate");
addCertDial->show();
}
+#endif
}
OwncloudSetupPage::~OwncloudSetupPage()
{
- delete addCertDial;
}
} // namespace OCC
void setErrorString( const QString&, bool retryHTTPonly );
void startSpinner();
void stopSpinner();
- void slotAskSSLClientCertificate();
void slotCertificateAccepted();
protected slots:
return 0;
}
-// outputs the signal needed to authenticate a certificate
-void OwncloudWizard::raiseCertificatePopup()
-{
- emit needCertificate();
-}
-
-
} // end namespace
#define MIRALL_OWNCLOUD_WIZARD_H
#include <QWizard>
+#include <QSslKey>
+#include <QSslCertificate>
#include "wizard/owncloudwizardcommon.h"
#include "accountfwd.h"
void displayError( const QString&, bool retryHTTPonly);
AbstractCredentials* getCredentials() const;
- void raiseCertificatePopup();
- QByteArray ownCloudCertificate;
- QString ownCloudPrivateKey;
- QString ownCloudCertificatePath;
- QString ownCloudCertificatePasswd;
+ // FIXME: Can those be local variables?
+ // Set from the OwncloudSetupPage, later used from OwncloudHttpCredsPage
+ QSslKey _clientSslKey;
+ QSslCertificate _clientSslCertificate;
public slots:
void setAuthType(WizardCommon::AuthType type);
creds/abstractcredentials.cpp
creds/credentialscommon.cpp
../3rdparty/qjson/json.cpp
- ../3rdparty/certificates/p12topem.cpp
)
if(TOKEN_AUTH_ONLY)
#include "configfile.h"
#include "accessmanager.h"
#include "creds/abstractcredentials.h"
-#include "../3rdparty/certificates/p12topem.h"
#include "capabilities.h"
#include "theme.h"
return _am->sendCustomRequest(req, verb, data);
}
-void Account::setCertificate(const QByteArray certficate, const QString privateKey)
-{
- _pemCertificate=certficate;
- _pemPrivateKey=privateKey;
-}
-
void Account::setSslConfiguration(const QSslConfiguration &config)
{
_sslConfiguration = config;
// if setting the client certificate fails, you will probably get an error similar to this:
// "An internal error number 1060 happened. SSL handshake failed, client certificate was requested: SSL error: sslv3 alert handshake failure"
QSslConfiguration sslConfig = QSslConfiguration::defaultConfiguration();
- QSslCertificate sslClientCertificate;
- ConfigFile cfgFile;
- if(!cfgFile.certificatePath().isEmpty() && !cfgFile.certificatePasswd().isEmpty()) {
- resultP12ToPem certif = p12ToPem(cfgFile.certificatePath().toStdString(), cfgFile.certificatePasswd().toStdString());
- QString s = QString::fromStdString(certif.Certificate);
- QByteArray ba = s.toLocal8Bit();
- this->setCertificate(ba, QString::fromStdString(certif.PrivateKey));
- }
- if((!_pemCertificate.isEmpty())&&(!_pemPrivateKey.isEmpty())) {
- // Read certificates
- QList<QSslCertificate> sslCertificateList = QSslCertificate::fromData(_pemCertificate, QSsl::Pem);
- if(sslCertificateList.length() != 0) {
- sslClientCertificate = sslCertificateList.takeAt(0);
- }
- // Read key from file
- QSslKey privateKey(_pemPrivateKey.toLocal8Bit(), QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey , "");
-
- // SSL configuration
- sslConfig.setCaCertificates(QSslSocket::systemCaCertificates());
- sslConfig.setLocalCertificate(sslClientCertificate);
- sslConfig.setPrivateKey(privateKey);
- qDebug() << "Added SSL client certificate to the query";
- }
-
#if QT_VERSION > QT_VERSION_CHECK(5, 2, 0)
// Try hard to re-use session for different requests
sslConfig.setSslOption(QSsl::SslOptionDisableSessionTickets, false);
QList<QSslCertificate> _rejectedCertificates;
static QString _configFileName;
- QByteArray _pemCertificate;
- QString _pemPrivateKey;
+
QString _davPath; // defaults to value from theme, might be overwritten in brandings
friend class AccountManager;
};
// status.php could not be loaded (network or server issue!).
void ConnectionValidator::slotNoStatusFound(QNetworkReply *reply)
{
- qDebug() << Q_FUNC_INFO << reply->error() << reply->errorString();
+ qDebug() << Q_FUNC_INFO << reply->error() << reply->errorString() << reply->peek(1024);
+ if (reply && !_account->credentials()->ready()) {
+ // This could be needed for SSL client certificates
+ // We need to load them from keychain and try
+ reportResult( CredentialsMissingOrWrong );
+ } else
if( reply && ! _account->credentials()->stillValid(reply)) {
_errors.append(tr("Authentication error: Either username or password are wrong."));
} else {
#include <QDebug>
#include <QNetworkReply>
#include <QSettings>
+#include <QSslKey>
#include <keychain.h>
namespace
{
const char userC[] = "user";
-const char certifPathC[] = "certificatePath";
-const char certifPasswdC[] = "certificatePasswd";
+const char clientCertificatePEMC[] = "_clientCertificatePEM";
+const char clientKeyPEMC[] = "_clientKeyPEM";
const char authenticationFailedC[] = "owncloud-authentication-failed";
} // ns
QByteArray credHash = QByteArray(_cred->user().toUtf8()+":"+_cred->password().toUtf8()).toBase64();
QNetworkRequest req(request);
req.setRawHeader(QByteArray("Authorization"), QByteArray("Basic ") + credHash);
- //qDebug() << "Request for " << req.url() << "with authorization" << QByteArray::fromBase64(credHash);
+ //qDebug() << "Request for " << req.url() << "with authorization"
+ // << QByteArray::fromBase64(credHash)
+ // << _cred->_clientSslKey << _cred->_clientSslCertificate
+ // << _cred->_clientSslKey.isNull() << _cred->_clientSslCertificate.isNull();
+
+ if (!_cred->_clientSslKey.isNull() && !_cred->_clientSslCertificate.isNull()) {
+ // SSL configuration
+ QSslConfiguration sslConfiguration = req.sslConfiguration();
+ sslConfiguration.setLocalCertificate(_cred->_clientSslCertificate);
+ sslConfiguration.setPrivateKey(_cred->_clientSslKey);
+ req.setSslConfiguration(sslConfiguration);
+ }
+
+
return AccessManager::createRequest(op, req, outgoingData);
}
private:
const HttpCredentials *_cred;
};
+
+static void addSettingsToJob(Account *account, QKeychain::Job *job)
+{
+ Q_UNUSED(account);
+ auto settings = Utility::settingsWithGroup(Theme::instance()->appName());
+ settings->setParent(job); // make the job parent to make setting deleted properly
+ job->setSettings(settings.release());
+}
+
HttpCredentials::HttpCredentials()
: _ready(false)
{
}
-HttpCredentials::HttpCredentials(const QString& user, const QString& password, const QString& certificatePath, const QString& certificatePasswd)
+// From wizard
+HttpCredentials::HttpCredentials(const QString& user, const QString& password, const QSslCertificate& certificate, const QSslKey& key)
: _user(user),
_password(password),
_ready(true),
- _certificatePath(certificatePath),
- _certificatePasswd(certificatePasswd)
+ _clientSslKey(key),
+ _clientSslCertificate(certificate)
{
}
return _password;
}
-QString HttpCredentials::certificatePath() const
-{
- return _certificatePath;
-}
-
-QString HttpCredentials::certificatePasswd() const
-{
- return _certificatePasswd;
-}
-
void HttpCredentials::setAccount(Account* account)
{
AbstractCredentials::setAccount(account);
{
// User must be fetched from config file
fetchUser();
- _certificatePath = _account->credentialSetting(QLatin1String(certifPathC)).toString();
- _certificatePasswd = _account->credentialSetting(QLatin1String(certifPasswdC)).toString();
- auto settings = Utility::settingsWithGroup(Theme::instance()->appName());
const QString kck = keychainKey(_account->url().toString(), _user );
- QString key = QString::fromLatin1( "%1/data" ).arg( kck );
- if( settings && settings->contains(key) ) {
- // Clean the password from the config file if it is in there.
- // we do not want a security problem.
- settings->remove(key);
- key = QString::fromLatin1( "%1/type" ).arg( kck );
- settings->remove(key);
- settings->sync();
- }
-
if (_ready) {
Q_EMIT fetched();
} else {
+ // Read client cert from keychain
+ const QString kck = keychainKey(_account->url().toString(), _user + clientCertificatePEMC);
ReadPasswordJob *job = new ReadPasswordJob(Theme::instance()->appName());
- settings->setParent(job); // make the job parent to make setting deleted properly
- job->setSettings(settings.release());
-
+ addSettingsToJob(_account, job);
job->setInsecureFallback(false);
job->setKey(kck);
- connect(job, SIGNAL(finished(QKeychain::Job*)), SLOT(slotReadJobDone(QKeychain::Job*)));
+ qDebug() << "-------- ----->" << _clientSslCertificate << _clientSslKey;
+
+ connect(job, SIGNAL(finished(QKeychain::Job*)), SLOT(slotReadClientCertPEMJobDone(QKeychain::Job*)));
job->start();
}
}
+
+void HttpCredentials::slotReadClientCertPEMJobDone(QKeychain::Job* incoming)
+{
+ // Store PEM in memory
+ ReadPasswordJob *readJob = static_cast<ReadPasswordJob*>(incoming);
+ if (readJob->error() == NoError && readJob->binaryData().length() > 0) {
+ QList<QSslCertificate> sslCertificateList = QSslCertificate::fromData(readJob->binaryData(), QSsl::Pem);
+ if(sslCertificateList.length() >= 1) {
+ _clientSslCertificate = sslCertificateList.at(0);
+ }
+ }
+
+ // Load key too
+ const QString kck = keychainKey(_account->url().toString(), _user + clientKeyPEMC);
+ ReadPasswordJob *job = new ReadPasswordJob(Theme::instance()->appName());
+ addSettingsToJob(_account, job);
+ job->setInsecureFallback(false);
+ job->setKey(kck);
+
+ connect(job, SIGNAL(finished(QKeychain::Job*)), SLOT(slotReadClientKeyPEMJobDone(QKeychain::Job*)));
+ job->start();
+}
+
+void HttpCredentials::slotReadClientKeyPEMJobDone(QKeychain::Job* incoming)
+{
+ // Store key in memory
+ ReadPasswordJob *readJob = static_cast<ReadPasswordJob*>(incoming);
+
+ if (readJob->error() == NoError && readJob->binaryData().length() > 0) {
+ QByteArray clientKeyPEM = readJob->binaryData();
+ // FIXME Unfortunately Qt has a bug and we can't just use QSsl::Opaque to let it
+ // load whatever we have. So we try until it works.
+ _clientSslKey = QSslKey(clientKeyPEM, QSsl::Rsa);
+ if (_clientSslKey.isNull()) {
+ _clientSslKey = QSslKey(clientKeyPEM, QSsl::Dsa);
+ }
+#if QT_VERSION >= QT_VERSION_CHECK(5, 5, 0)
+ // ec keys are Qt 5.5
+ if (_clientSslKey.isNull()) {
+ _clientSslKey = QSslKey(clientKeyPEM, QSsl::Ec);
+ }
+#endif
+ if (_clientSslKey.isNull()) {
+ qDebug() << "Warning: Could not load SSL key into Qt!";
+ }
+ }
+
+ // Now fetch the actual server password
+ const QString kck = keychainKey(_account->url().toString(), _user );
+ ReadPasswordJob *job = new ReadPasswordJob(Theme::instance()->appName());
+ addSettingsToJob(_account, job);
+ job->setInsecureFallback(false);
+ job->setKey(kck);
+
+ connect(job, SIGNAL(finished(QKeychain::Job*)), SLOT(slotReadJobDone(QKeychain::Job*)));
+ job->start();
+}
+
+
bool HttpCredentials::stillValid(QNetworkReply *reply)
{
return ((reply->error() != QNetworkReply::AuthenticationRequiredError)
|| !reply->property(authenticationFailedC).toBool()));
}
-void HttpCredentials::slotReadJobDone(QKeychain::Job *job)
+void HttpCredentials::slotReadJobDone(QKeychain::Job *incomingJob)
{
- ReadPasswordJob *readJob = static_cast<ReadPasswordJob*>(job);
- _password = readJob->textData();
+ QKeychain::ReadPasswordJob *job = static_cast<ReadPasswordJob*>(incomingJob);
+ _password = job->textData();
if( _user.isEmpty()) {
qDebug() << "Strange: User is empty!";
QKeychain::Error error = job->error();
if( !_password.isEmpty() && error == NoError ) {
-
// All cool, the keychain did not come back with error.
// Still, the password can be empty which indicates a problem and
// the password dialog has to be opened.
}
DeletePasswordJob *job = new DeletePasswordJob(Theme::instance()->appName());
- auto settings = Utility::settingsWithGroup(Theme::instance()->appName());
- settings->setParent(job); // make the job parent to make setting deleted properly
- job->setSettings(settings.release());
+ addSettingsToJob(_account, job);
job->setInsecureFallback(true);
job->setKey(kck);
job->start();
// We never connected or fetched the user, there is nothing to save.
return;
}
+
_account->setCredentialSetting(QLatin1String(userC), _user);
- _account->setCredentialSetting(QLatin1String(certifPathC), _certificatePath);
- _account->setCredentialSetting(QLatin1String(certifPasswdC), _certificatePasswd);
+
+ // write cert
WritePasswordJob *job = new WritePasswordJob(Theme::instance()->appName());
- auto settings = Utility::settingsWithGroup(Theme::instance()->appName());
- settings->setParent(job); // make the job parent to make setting deleted properly
- job->setSettings(settings.release());
+ addSettingsToJob(_account, job);
+ job->setInsecureFallback(false);
+ connect(job, SIGNAL(finished(QKeychain::Job*)), SLOT(slotWriteClientCertPEMJobDone(QKeychain::Job*)));
+ job->setKey(keychainKey(_account->url().toString(), _user + clientCertificatePEMC));
+ job->setBinaryData(_clientSslCertificate.toPem());
+ job->start();
+}
+void HttpCredentials::slotWriteClientCertPEMJobDone(Job *incomingJob)
+{
+ Q_UNUSED(incomingJob);
+ // write ssl key
+ WritePasswordJob* job = new WritePasswordJob(Theme::instance()->appName());
+ addSettingsToJob(_account, job);
+ job->setInsecureFallback(false);
+ connect(job, SIGNAL(finished(QKeychain::Job*)), SLOT(slotWriteClientKeyPEMJobDone(QKeychain::Job*)));
+ job->setKey(keychainKey(_account->url().toString(), _user + clientKeyPEMC));
+ job->setBinaryData(_clientSslKey.toPem());
+ job->start();
+}
+
+void HttpCredentials::slotWriteClientKeyPEMJobDone(Job *incomingJob)
+{
+ Q_UNUSED(incomingJob);
+ WritePasswordJob* job = new WritePasswordJob(Theme::instance()->appName());
+ addSettingsToJob(_account, job);
job->setInsecureFallback(false);
connect(job, SIGNAL(finished(QKeychain::Job*)), SLOT(slotWriteJobDone(QKeychain::Job*)));
job->setKey(keychainKey(_account->url().toString(), _user));
#define MIRALL_CREDS_HTTP_CREDENTIALS_H
#include <QMap>
-
+#include <QSslCertificate>
+#include <QSslKey>
#include "creds/abstractcredentials.h"
class QNetworkReply;
namespace QKeychain {
class Job;
+class WritePasswordJob;
+class ReadPasswordJob;
}
namespace OCC
class OWNCLOUDSYNC_EXPORT HttpCredentials : public AbstractCredentials
{
Q_OBJECT
-
+ friend class HttpCredentialsAccessManager;
public:
explicit HttpCredentials();
- HttpCredentials(const QString& user, const QString& password, const QString& certificatePath, const QString& certificatePasswd);
+ HttpCredentials(const QString& user, const QString& password, const QSslCertificate& certificate = QSslCertificate(), const QSslKey& key = QSslKey());
QString authType() const Q_DECL_OVERRIDE;
QNetworkAccessManager* getQNAM() const Q_DECL_OVERRIDE;
void forgetSensitiveData() Q_DECL_OVERRIDE;
QString fetchUser();
virtual bool sslIsTrusted() { return false; }
- QString certificatePath() const;
- QString certificatePasswd() const;
// To fetch the user name as early as possible
void setAccount(Account* account) Q_DECL_OVERRIDE;
private Q_SLOTS:
void slotAuthentication(QNetworkReply*, QAuthenticator*);
+
+ void slotReadClientCertPEMJobDone(QKeychain::Job*);
+ void slotReadClientKeyPEMJobDone(QKeychain::Job*);
void slotReadJobDone(QKeychain::Job*);
+
+ void slotWriteClientCertPEMJobDone(QKeychain::Job*);
+ void slotWriteClientKeyPEMJobDone(QKeychain::Job*);
void slotWriteJobDone(QKeychain::Job*);
void clearQNAMCache();
QString _user;
QString _password;
QString _previousPassword;
+
QString _fetchErrorString;
bool _ready;
-
-private:
- QString _certificatePath;
- QString _certificatePasswd;
+ QSslKey _clientSslKey;
+ QSslCertificate _clientSslCertificate;
};
} // namespace OCC
QVariantMap status = QtJson::parse(QString::fromUtf8(body), success).toMap();
// empty or invalid response
if (!success || status.isEmpty()) {
- qDebug() << "status.php from server is not valid JSON!";
+ qDebug() << "status.php from server is not valid JSON!" << body << reply()->request().url();
}
qDebug() << "status.php returns: " << status << " " << reply()->error() << " Reply: " << reply();