mirror of
https://github.com/nextcloud/desktop.git
synced 2025-10-26 11:17:43 +00:00
Merge remote-tracking branch 'origin/ssl_client_cert'
Conflicts: CMakeLists.txt csync/src/CMakeLists.txt csync/src/csync_owncloud.c
This commit is contained in:
commit
d70e146c1f
@ -142,6 +142,7 @@ endif()
|
||||
if (USE_NEON)
|
||||
find_package(Neon REQUIRED)
|
||||
endif(USE_NEON)
|
||||
find_package(OpenSSL)
|
||||
|
||||
if(NOT TOKEN_AUTH_ONLY)
|
||||
if (Qt5Core_DIR)
|
||||
|
||||
@ -68,6 +68,7 @@ if(USE_NEON)
|
||||
)
|
||||
list(APPEND CSYNC_LINK_LIBRARIES
|
||||
${NEON_LIBRARIES}
|
||||
${CRYPTO_LIBRARY}
|
||||
)
|
||||
add_definitions(-DUSE_NEON)
|
||||
endif(USE_NEON)
|
||||
@ -93,6 +94,8 @@ include_directories(
|
||||
${CSYNC_PRIVATE_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
FIND_LIBRARY(CRYPTO_LIBRARY NAMES crypto)
|
||||
|
||||
add_library(${CSYNC_LIBRARY} SHARED ${csync_SRCS})
|
||||
#add_library(${CSYNC_LIBRARY}_static STATIC ${csync_SRCS})
|
||||
|
||||
|
||||
@ -46,6 +46,11 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct csync_client_certs_s {
|
||||
char *certificatePath;
|
||||
char *certificatePasswd;
|
||||
};
|
||||
|
||||
/**
|
||||
* Instruction enum. In the file traversal structure, it describes
|
||||
* the csync state of a file.
|
||||
|
||||
@ -385,6 +385,7 @@ int dav_connect(CSYNC *csyncCtx, const char *base_url) {
|
||||
unsigned int port = 0;
|
||||
int proxystate = -1;
|
||||
csync_owncloud_ctx_t *ctx = csyncCtx->owncloud_context;
|
||||
struct csync_client_certs_s* clientCerts = csyncCtx->clientCerts;
|
||||
|
||||
if (ctx->_connected) {
|
||||
return 0;
|
||||
@ -448,6 +449,29 @@ int dav_connect(CSYNC *csyncCtx, const char *base_url) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
if(clientCerts != NULL) {
|
||||
ne_ssl_client_cert *clicert;
|
||||
|
||||
DEBUG_WEBDAV("dav_connect: certificatePath and certificatePasswd are set, so we use it" );
|
||||
DEBUG_WEBDAV(" with certificatePath: %s", clientCerts->certificatePath );
|
||||
DEBUG_WEBDAV(" with certificatePasswd: %s", clientCerts->certificatePasswd );
|
||||
clicert = ne_ssl_clicert_read ( clientCerts->certificatePath );
|
||||
if ( clicert == NULL ) {
|
||||
DEBUG_WEBDAV ( "Error read certificate : %s", ne_get_error ( ctx->dav_session.ctx ) );
|
||||
} else {
|
||||
if ( ne_ssl_clicert_encrypted ( clicert ) ) {
|
||||
int rtn = ne_ssl_clicert_decrypt ( clicert, clientCerts->certificatePasswd );
|
||||
if ( !rtn ) {
|
||||
DEBUG_WEBDAV ( "Certificate was deciphered successfully." );
|
||||
ne_ssl_set_clicert ( ctx->dav_session.ctx, clicert );
|
||||
} else {
|
||||
DEBUG_WEBDAV ( "Errors while deciphering certificate: %s", ne_get_error ( ctx->dav_session.ctx ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
DEBUG_WEBDAV("dav_connect: error with csync_client_certs_s* clientCerts");
|
||||
}
|
||||
ne_ssl_trust_default_ca( ctx->dav_session.ctx );
|
||||
ne_ssl_set_verify( ctx->dav_session.ctx, ssl_callback_by_neon, ctx);
|
||||
}
|
||||
@ -478,6 +502,7 @@ out:
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
char *owncloud_error_string(CSYNC* ctx)
|
||||
{
|
||||
return ctx->owncloud_context->dav_session.error_string;
|
||||
@ -505,7 +530,6 @@ int owncloud_commit(CSYNC* ctx) {
|
||||
SAFE_FREE( ctx->owncloud_context->dav_session.pwd );
|
||||
SAFE_FREE( ctx->owncloud_context->dav_session.session_key);
|
||||
SAFE_FREE( ctx->owncloud_context->dav_session.error_string );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -513,6 +537,12 @@ void owncloud_destroy(CSYNC* ctx)
|
||||
{
|
||||
owncloud_commit(ctx);
|
||||
SAFE_FREE(ctx->owncloud_context);
|
||||
|
||||
SAFE_FREE(ctx->clientCerts->certificatePasswd);
|
||||
SAFE_FREE(ctx->clientCerts->certificatePath);
|
||||
SAFE_FREE(ctx->clientCerts);
|
||||
ctx->clientCerts = NULL;
|
||||
|
||||
ctx->owncloud_context = 0;
|
||||
ne_sock_exit();
|
||||
}
|
||||
@ -547,12 +577,28 @@ int owncloud_set_property(CSYNC* ctx, const char *key, void *data) {
|
||||
if( c_streq(key, "redirect_callback")) {
|
||||
if (data) {
|
||||
csync_owncloud_redirect_callback_t* cb_wrapper = data;
|
||||
|
||||
ctx->owncloud_context->dav_session.redir_callback = *cb_wrapper;
|
||||
} else {
|
||||
ctx->owncloud_context->dav_session.redir_callback = NULL;
|
||||
}
|
||||
}
|
||||
if( c_streq(key, "SSLClientCerts")) {
|
||||
if(ctx->clientCerts != NULL) {
|
||||
SAFE_FREE(ctx->clientCerts->certificatePasswd);
|
||||
SAFE_FREE(ctx->clientCerts->certificatePath);
|
||||
SAFE_FREE(ctx->clientCerts);
|
||||
ctx->clientCerts = NULL;
|
||||
}
|
||||
if (data) {
|
||||
struct csync_client_certs_s* clientCerts = (struct csync_client_certs_s*) data;
|
||||
struct csync_client_certs_s* newCerts = c_malloc(sizeof(struct csync_client_certs_s));
|
||||
newCerts->certificatePath = c_strdup(clientCerts->certificatePath);
|
||||
newCerts->certificatePasswd = c_strdup(clientCerts->certificatePasswd);
|
||||
ctx->clientCerts = newCerts;
|
||||
} else {
|
||||
DEBUG_WEBDAV("error: in owncloud_set_property for 'SSLClientCerts'" );
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
@ -567,3 +613,4 @@ void owncloud_init(CSYNC* ctx) {
|
||||
}
|
||||
|
||||
/* vim: set ts=4 sw=4 et cindent: */
|
||||
|
||||
|
||||
@ -96,6 +96,7 @@ struct csync_owncloud_ctx_s {
|
||||
int _connected; /* flag to indicate if a connection exists, ie.
|
||||
the dav_session is valid */
|
||||
};
|
||||
|
||||
typedef struct csync_owncloud_ctx_s csync_owncloud_ctx_t;
|
||||
//typedef csync_owncloud_ctx_t* csync_owncloud_ctx_p;
|
||||
|
||||
|
||||
@ -79,6 +79,7 @@ typedef struct csync_file_stat_s csync_file_stat_t;
|
||||
|
||||
struct csync_owncloud_ctx_s; // csync_owncloud.c
|
||||
|
||||
|
||||
/**
|
||||
* @brief csync public structure
|
||||
*/
|
||||
@ -96,6 +97,9 @@ struct csync_s {
|
||||
} callbacks;
|
||||
c_strlist_t *excludes;
|
||||
|
||||
// needed for SSL client certificate support
|
||||
struct csync_client_certs_s *clientCerts;
|
||||
|
||||
struct {
|
||||
char *file;
|
||||
sqlite3 *db;
|
||||
|
||||
114
src/3rdparty/certificates/p12topem.cpp
vendored
Normal file
114
src/3rdparty/certificates/p12topem.cpp
vendored
Normal file
@ -0,0 +1,114 @@
|
||||
/*
|
||||
* 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) {
|
||||
int len = 0;
|
||||
BUF_MEM *bptr;
|
||||
void* data;
|
||||
string ret = "";
|
||||
|
||||
BIO_get_mem_ptr(o, &bptr);
|
||||
len = bptr->length;
|
||||
data = calloc(len+10, sizeof(char));
|
||||
BIO_read(o, data, len);
|
||||
ret = strdup((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;
|
||||
}
|
||||
62
src/3rdparty/certificates/p12topem.h
vendored
Normal file
62
src/3rdparty/certificates/p12topem.h
vendored
Normal file
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* 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 */
|
||||
|
||||
@ -110,7 +110,7 @@ QString queryPassword(const QString &user)
|
||||
class HttpCredentialsText : public HttpCredentials {
|
||||
public:
|
||||
HttpCredentialsText(const QString& user, const QString& password)
|
||||
: HttpCredentials(user, password),
|
||||
: HttpCredentials(user, password, "", "", ""), // FIXME: not working with client certs yet (qknight)
|
||||
_sslTrusted(false)
|
||||
{}
|
||||
|
||||
|
||||
@ -24,6 +24,8 @@ set(client_UI
|
||||
settingsdialog.ui
|
||||
sharedialog.ui
|
||||
sslerrordialog.ui
|
||||
owncloudsetuppage.ui
|
||||
addcertificatedialog.ui
|
||||
wizard/owncloudadvancedsetuppage.ui
|
||||
wizard/owncloudhttpcredspage.ui
|
||||
wizard/owncloudsetupnocredspage.ui
|
||||
@ -59,6 +61,7 @@ set(client_SRCS
|
||||
accountmigrator.cpp
|
||||
quotainfo.cpp
|
||||
accountstate.cpp
|
||||
addcertificatedialog.cpp
|
||||
wizard/abstractcredswizardpage.cpp
|
||||
wizard/owncloudadvancedsetuppage.cpp
|
||||
wizard/owncloudhttpcredspage.cpp
|
||||
@ -106,6 +109,7 @@ set(3rdparty_SRC
|
||||
../3rdparty/qtsingleapplication/qtlocalpeer.cpp
|
||||
../3rdparty/qtsingleapplication/qtsingleapplication.cpp
|
||||
../3rdparty/qtsingleapplication/qtsinglecoreapplication.cpp
|
||||
../3rdparty/certificates/p12topem.cpp
|
||||
)
|
||||
|
||||
if (APPLE)
|
||||
@ -251,6 +255,7 @@ install(TARGETS ${APPLICATION_EXECUTABLE}
|
||||
BUNDLE DESTINATION "."
|
||||
)
|
||||
|
||||
|
||||
# FIXME: The following lines are dup in src/gui and src/cmd because it needs to be done after both are installed
|
||||
#FIXME: find a nice solution to make the second if(BUILD_OWNCLOUD_OSX_BUNDLE) unnecessary
|
||||
# currently it needs to be done because the code right above needs to be executed no matter
|
||||
|
||||
49
src/gui/addcertificatedialog.cpp
Normal file
49
src/gui/addcertificatedialog.cpp
Normal file
@ -0,0 +1,49 @@
|
||||
#include "ui_addcertificatedialog.h"
|
||||
#include "addcertificatedialog.h"
|
||||
#include <QFileDialog>
|
||||
#include <QLineEdit>
|
||||
|
||||
|
||||
namespace OCC {
|
||||
AddCertificateDialog::AddCertificateDialog(QWidget *parent) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::AddCertificateDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
ui->labelErrorCertif->setText("");
|
||||
}
|
||||
|
||||
AddCertificateDialog::~AddCertificateDialog()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void AddCertificateDialog::on_pushButtonBrowseCertificate_clicked()
|
||||
{
|
||||
QString fileName = QFileDialog::getOpenFileName(this, tr("Select a certificate"), "", tr("Certificate files (*.p12 *.pfx)"));
|
||||
ui->lineEditCertificatePath->setText(fileName);
|
||||
}
|
||||
|
||||
QString AddCertificateDialog::getCertificatePath()
|
||||
{
|
||||
return ui->lineEditCertificatePath->text();
|
||||
}
|
||||
|
||||
QString AddCertificateDialog::getCertificatePasswd()
|
||||
{
|
||||
return ui->lineEditPWDCertificate->text();
|
||||
}
|
||||
|
||||
void AddCertificateDialog::showErrorMessage(const QString message)
|
||||
{
|
||||
ui->labelErrorCertif->setText(message);
|
||||
}
|
||||
|
||||
void AddCertificateDialog::Reinit()
|
||||
{
|
||||
ui->labelErrorCertif->setText("");
|
||||
ui->lineEditCertificatePath->setText("");
|
||||
ui->lineEditPWDCertificate->setText("");
|
||||
}
|
||||
|
||||
}
|
||||
35
src/gui/addcertificatedialog.h
Normal file
35
src/gui/addcertificatedialog.h
Normal file
@ -0,0 +1,35 @@
|
||||
#ifndef ADDCERTIFICATEDIALOG_H
|
||||
#define ADDCERTIFICATEDIALOG_H
|
||||
|
||||
#include <QDialog>
|
||||
#include <QString>
|
||||
|
||||
namespace OCC {
|
||||
|
||||
namespace Ui {
|
||||
class AddCertificateDialog;
|
||||
}
|
||||
|
||||
class AddCertificateDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit AddCertificateDialog(QWidget *parent = 0);
|
||||
~AddCertificateDialog();
|
||||
QString getCertificatePath();
|
||||
QString getCertificatePasswd();
|
||||
void showErrorMessage(const QString message);
|
||||
void Reinit();
|
||||
|
||||
private slots:
|
||||
void on_pushButtonBrowseCertificate_clicked();
|
||||
|
||||
private:
|
||||
Ui::AddCertificateDialog *ui;
|
||||
|
||||
};
|
||||
|
||||
}//End namespace OCC
|
||||
|
||||
#endif // ADDCERTIFICATEDIALOG_H
|
||||
220
src/gui/addcertificatedialog.ui
Normal file
220
src/gui/addcertificatedialog.ui
Normal file
@ -0,0 +1,220 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>OCC::AddCertificateDialog</class>
|
||||
<widget class="QDialog" name="OCC::AddCertificateDialog">
|
||||
<property name="windowModality">
|
||||
<enum>Qt::ApplicationModal</enum>
|
||||
</property>
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>400</width>
|
||||
<height>350</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>400</width>
|
||||
<height>350</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>400</width>
|
||||
<height>350</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>SSL client certificate authentication</string>
|
||||
</property>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>30</x>
|
||||
<y>280</y>
|
||||
<width>341</width>
|
||||
<height>32</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="labelCertificateFile">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>20</x>
|
||||
<y>100</y>
|
||||
<width>141</width>
|
||||
<height>16</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Certificate :</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLineEdit" name="lineEditCertificatePath">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>20</x>
|
||||
<y>120</y>
|
||||
<width>291</width>
|
||||
<height>21</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QPushButton" name="pushButtonBrowseCertificate">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>320</x>
|
||||
<y>120</y>
|
||||
<width>71</width>
|
||||
<height>21</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Browse...</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="labelPWDCertificate">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>20</x>
|
||||
<y>160</y>
|
||||
<width>181</width>
|
||||
<height>16</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Certificate password :</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLineEdit" name="lineEditPWDCertificate">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>20</x>
|
||||
<y>180</y>
|
||||
<width>291</width>
|
||||
<height>21</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="echoMode">
|
||||
<enum>QLineEdit::Password</enum>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="labelErrorMessage">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>20</x>
|
||||
<y>30</y>
|
||||
<width>341</width>
|
||||
<height>41</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>This server probably requires a SSL client certificate.</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="labelErrorCertif">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>20</x>
|
||||
<y>220</y>
|
||||
<width>361</width>
|
||||
<height>51</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="palette">
|
||||
<palette>
|
||||
<active>
|
||||
<colorrole role="Text">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>231</red>
|
||||
<green>23</green>
|
||||
<blue>12</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
</active>
|
||||
<inactive>
|
||||
<colorrole role="Text">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>231</red>
|
||||
<green>23</green>
|
||||
<blue>12</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
</inactive>
|
||||
<disabled>
|
||||
<colorrole role="Text">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>127</red>
|
||||
<green>127</green>
|
||||
<blue>127</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
</disabled>
|
||||
</palette>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>OCC::AddCertificateDialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>OCC::AddCertificateDialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
@ -301,6 +301,7 @@ void Folder::slotRunEtagJob()
|
||||
_requestEtagJob = new RequestEtagJob(account, remotePath(), this);
|
||||
// check if the etag is different
|
||||
QObject::connect(_requestEtagJob, SIGNAL(etagRetreived(QString)), this, SLOT(etagRetreived(QString)));
|
||||
QObject::connect(_requestEtagJob, SIGNAL(networkError(QNetworkReply*)), this, SLOT(slotNetworkUnavailable()));
|
||||
FolderMan::instance()->slotScheduleETagJob(alias(), _requestEtagJob);
|
||||
// The _requestEtagJob is auto deleting itself on finish. Our guard pointer _requestEtagJob will then be null.
|
||||
}
|
||||
|
||||
@ -26,7 +26,7 @@
|
||||
namespace OCC
|
||||
{
|
||||
|
||||
OwncloudHttpCredsPage::OwncloudHttpCredsPage()
|
||||
OwncloudHttpCredsPage::OwncloudHttpCredsPage(QWidget* parent)
|
||||
: AbstractCredentialsWizardPage(),
|
||||
_ui(),
|
||||
_connected(false),
|
||||
@ -36,6 +36,10 @@ OwncloudHttpCredsPage::OwncloudHttpCredsPage()
|
||||
{
|
||||
_ui.setupUi(this);
|
||||
|
||||
if(parent){
|
||||
_ocWizard = qobject_cast<OwncloudWizard *>(parent);
|
||||
}
|
||||
|
||||
registerField( QLatin1String("OCUser*"), _ui.leUsername);
|
||||
registerField( QLatin1String("OCPasswd*"), _ui.lePassword);
|
||||
|
||||
@ -148,7 +152,8 @@ void OwncloudHttpCredsPage::setErrorString(const QString& err)
|
||||
|
||||
AbstractCredentials* OwncloudHttpCredsPage::getCredentials() const
|
||||
{
|
||||
return new HttpCredentialsGui(_ui.leUsername->text(), _ui.lePassword->text());
|
||||
QDateTime now = QDateTime::currentDateTime();
|
||||
return new HttpCredentialsGui(_ui.leUsername->text(), _ui.lePassword->text(), _ocWizard->ownCloudCertificatePath, now.toString(QLatin1String("yyyy-MM-dd")), _ocWizard->ownCloudCertificatePasswd);
|
||||
}
|
||||
|
||||
void OwncloudHttpCredsPage::setConfigExists(bool config)
|
||||
|
||||
@ -17,6 +17,7 @@
|
||||
#define MIRALL_OWNCLOUD_HTTP_CREDS_PAGE_H
|
||||
|
||||
#include "wizard/abstractcredswizardpage.h"
|
||||
#include "wizard/owncloudwizard.h"
|
||||
|
||||
#include "ui_owncloudhttpcredspage.h"
|
||||
|
||||
@ -28,7 +29,7 @@ class OwncloudHttpCredsPage : public AbstractCredentialsWizardPage
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
OwncloudHttpCredsPage();
|
||||
OwncloudHttpCredsPage(QWidget* parent);
|
||||
|
||||
AbstractCredentials* getCredentials() const Q_DECL_OVERRIDE;
|
||||
|
||||
@ -53,6 +54,7 @@ private:
|
||||
bool _checking;
|
||||
bool _configExists;
|
||||
QProgressIndicator* _progressIndi;
|
||||
OwncloudWizard* _ocWizard;
|
||||
};
|
||||
|
||||
} // namespace OCC
|
||||
|
||||
@ -19,17 +19,21 @@
|
||||
#include <QTimer>
|
||||
#include <QPushButton>
|
||||
#include <QMessageBox>
|
||||
#include <QSsl>
|
||||
#include <QSslCertificate>
|
||||
|
||||
#include "QProgressIndicator.h"
|
||||
|
||||
#include "wizard/owncloudwizardcommon.h"
|
||||
#include "wizard/owncloudsetuppage.h"
|
||||
#include "../3rdparty/certificates/p12topem.h"
|
||||
#include "theme.h"
|
||||
#include "account.h"
|
||||
|
||||
namespace OCC
|
||||
{
|
||||
|
||||
OwncloudSetupPage::OwncloudSetupPage()
|
||||
OwncloudSetupPage::OwncloudSetupPage(QWidget *parent)
|
||||
: QWizardPage(),
|
||||
_ui(),
|
||||
_oCUrl(),
|
||||
@ -58,6 +62,10 @@ OwncloudSetupPage::OwncloudSetupPage()
|
||||
|
||||
connect(_ui.leUrl, SIGNAL(textChanged(QString)), SLOT(slotUrlChanged(QString)));
|
||||
connect(_ui.leUrl, SIGNAL(editingFinished()), SLOT(slotUrlEditFinished()));
|
||||
|
||||
addCertDial = new AddCertificateDialog(this);
|
||||
_ocWizard = qobject_cast<OwncloudWizard *>(parent);
|
||||
connect(_ocWizard,SIGNAL(needCertificate()),this,SLOT(slotAskSSLClientCertificate()));
|
||||
}
|
||||
|
||||
void OwncloudSetupPage::setServerUrl( const QString& newUrl )
|
||||
@ -228,14 +236,18 @@ void OwncloudSetupPage::setErrorString( const QString& err, bool retryHTTPonly )
|
||||
_ui.errorLabel->setVisible(false);
|
||||
} else {
|
||||
if (retryHTTPonly) {
|
||||
QString msg = tr("<p>Could not connect securely:</p><p>%1</p><p>Do you want to connect unencrypted instead (not recommended)?</p>").arg(err);
|
||||
QString title = tr("Connection failed");
|
||||
if (QMessageBox::question(this, title, msg, QMessageBox::Yes, QMessageBox::No) == QMessageBox::Yes) {
|
||||
QUrl url(_ui.leUrl->text());
|
||||
url.setScheme("http");
|
||||
_ui.leUrl->setText(url.toString());
|
||||
// skip ahead to next page, since the user would expect us to retry automatically
|
||||
wizard()->next();
|
||||
if (err.contains("SSL handshake failed", Qt::CaseInsensitive)) {
|
||||
slotAskSSLClientCertificate();
|
||||
} else {
|
||||
QString msg = tr("<p>Could not connect securely:</p><p>%1</p><p>Do you want to connect unencrypted instead (not recommended)?</p>").arg(err);
|
||||
QString title = tr("Connection failed");
|
||||
if (QMessageBox::question(this, title, msg, QMessageBox::Yes, QMessageBox::No) == QMessageBox::Yes) {
|
||||
QUrl url(_ui.leUrl->text());
|
||||
url.setScheme("http");
|
||||
_ui.leUrl->setText(url.toString());
|
||||
// skip ahead to next page, since the user would expect us to retry automatically
|
||||
wizard()->next();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -269,4 +281,76 @@ void OwncloudSetupPage::setConfigExists( bool config )
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void OwncloudSetupPage::slotAskSSLClientCertificate()
|
||||
{
|
||||
addCertDial->show();
|
||||
connect(addCertDial, SIGNAL(accepted()),this,SLOT(slotCertificateAccepted()));
|
||||
}
|
||||
|
||||
//called during the validation of the client certificate.
|
||||
void OwncloudSetupPage::slotCertificateAccepted()
|
||||
{
|
||||
QSslCertificate sslCertificate;
|
||||
|
||||
resultP12ToPem certif = p12ToPem(addCertDial->getCertificatePath().toStdString() , addCertDial->getCertificatePasswd().toStdString());
|
||||
if(certif.ReturnCode){
|
||||
QString s = QString::fromStdString(certif.Certificate);
|
||||
QByteArray ba = s.toLocal8Bit();
|
||||
|
||||
QList<QSslCertificate> sslCertificateList = QSslCertificate::fromData(ba, QSsl::Pem);
|
||||
sslCertificate = sslCertificateList.takeAt(0);
|
||||
|
||||
this->_ocWizard->ownCloudCertificate = ba;
|
||||
this->_ocWizard->ownCloudPrivateKey = certif.PrivateKey.c_str();
|
||||
this->_ocWizard->ownCloudCertificatePath = addCertDial->getCertificatePath();
|
||||
this->_ocWizard->ownCloudCertificatePasswd = addCertDial->getCertificatePasswd();
|
||||
|
||||
//FIXME qknight: hacky code ahead
|
||||
AccountPtr acc = this->_ocWizard->account();
|
||||
acc->setCertificate(_ocWizard->ownCloudCertificate, _ocWizard->ownCloudPrivateKey);
|
||||
|
||||
QList<QByteArray> qba = sslCertificate.subjectInfoAttributes();
|
||||
QString _DN = "";
|
||||
QString _C,_ST, _L, _O, _OU, _CN, _emailAddress;
|
||||
foreach(QByteArray qa, qba)
|
||||
{
|
||||
if(strcmp(qa.data(),"C")==0){
|
||||
_C="/"+QString(qa)+"="+sslCertificate.subjectInfo(qa).join('/');
|
||||
}
|
||||
else if(strcmp(qa.data(),"ST")==0){
|
||||
_ST="/"+QString(qa)+"="+sslCertificate.subjectInfo(qa).join('/');
|
||||
}
|
||||
else if(strcmp(qa.data(),"L")==0){
|
||||
_L="/"+QString(qa)+"="+sslCertificate.subjectInfo(qa).join('/');
|
||||
}
|
||||
else if(strcmp(qa.data(),"O")==0){
|
||||
_O="/"+QString(qa)+"="+sslCertificate.subjectInfo(qa).join('/');
|
||||
}
|
||||
else if(strcmp(qa.data(),"OU")==0){
|
||||
_OU="/"+QString(qa)+"="+sslCertificate.subjectInfo(qa).join('/');
|
||||
}
|
||||
else if(strcmp(qa.data(),"CN")==0){
|
||||
_CN="/"+QString(qa)+"="+sslCertificate.subjectInfo(qa).join('/');
|
||||
}
|
||||
else if(strcmp(qa.data(),"emailAddress")==0){
|
||||
_emailAddress="/"+QString(qa)+"="+sslCertificate.subjectInfo(qa).join('/');
|
||||
}
|
||||
}
|
||||
_DN += _C+_ST+_L+_O+_OU+_CN+_emailAddress;
|
||||
addCertDial->Reinit();
|
||||
validatePage();
|
||||
} else {
|
||||
QString message;
|
||||
message = certif.Comment.c_str();
|
||||
addCertDial->showErrorMessage(message);
|
||||
addCertDial->show();
|
||||
}
|
||||
}
|
||||
|
||||
OwncloudSetupPage::~OwncloudSetupPage()
|
||||
{
|
||||
delete addCertDial;
|
||||
}
|
||||
|
||||
} // namespace OCC
|
||||
|
||||
@ -19,6 +19,10 @@
|
||||
#include <QWizard>
|
||||
|
||||
#include "wizard/owncloudwizardcommon.h"
|
||||
#include "wizard/owncloudwizard.h"
|
||||
|
||||
#include "../addcertificatedialog.h"
|
||||
|
||||
#include "ui_owncloudsetupnocredspage.h"
|
||||
|
||||
class QLabel;
|
||||
@ -31,7 +35,8 @@ class OwncloudSetupPage: public QWizardPage
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
OwncloudSetupPage();
|
||||
OwncloudSetupPage(QWidget *parent=0);
|
||||
~OwncloudSetupPage();
|
||||
|
||||
virtual bool isComplete() const Q_DECL_OVERRIDE;
|
||||
virtual void initializePage() Q_DECL_OVERRIDE;
|
||||
@ -50,6 +55,8 @@ public slots:
|
||||
void setConfigExists( bool );
|
||||
void startSpinner();
|
||||
void stopSpinner();
|
||||
void slotAskSSLClientCertificate();
|
||||
void slotCertificateAccepted();
|
||||
|
||||
protected slots:
|
||||
void slotUrlChanged(const QString&);
|
||||
@ -64,14 +71,20 @@ private:
|
||||
bool urlHasChanged();
|
||||
|
||||
Ui_OwncloudSetupPage _ui;
|
||||
|
||||
QString _oCUrl;
|
||||
QString _ocUser;
|
||||
bool _authTypeKnown;
|
||||
bool _checking;
|
||||
bool _configExists;
|
||||
bool _multipleFoldersExist;
|
||||
WizardCommon::AuthType _authType;
|
||||
|
||||
QProgressIndicator* _progressIndi;
|
||||
QButtonGroup* _selectiveSyncButtons;
|
||||
QString _remoteFolder;
|
||||
AddCertificateDialog* addCertDial;
|
||||
OwncloudWizard* _ocWizard;
|
||||
};
|
||||
|
||||
} // namespace OCC
|
||||
|
||||
@ -37,8 +37,8 @@ namespace OCC
|
||||
OwncloudWizard::OwncloudWizard(QWidget *parent)
|
||||
: QWizard(parent),
|
||||
_account(0),
|
||||
_setupPage(new OwncloudSetupPage),
|
||||
_httpCredsPage(new OwncloudHttpCredsPage),
|
||||
_setupPage(new OwncloudSetupPage(this)),
|
||||
_httpCredsPage(new OwncloudHttpCredsPage(this)),
|
||||
_shibbolethCredsPage(new OwncloudShibbolethCredsPage),
|
||||
_advancedSetupPage(new OwncloudAdvancedSetupPage),
|
||||
_resultPage(new OwncloudWizardResultPage),
|
||||
@ -238,5 +238,11 @@ AbstractCredentials* OwncloudWizard::getCredentials() const
|
||||
return 0;
|
||||
}
|
||||
|
||||
// outputs the signal needed to authenticate a certificate
|
||||
void OwncloudWizard::raiseCertificatePopup()
|
||||
{
|
||||
emit needCertificate();
|
||||
}
|
||||
|
||||
|
||||
} // end namespace
|
||||
|
||||
@ -61,6 +61,12 @@ public:
|
||||
void successfulStep();
|
||||
AbstractCredentials* getCredentials() const;
|
||||
|
||||
void raiseCertificatePopup();
|
||||
QByteArray ownCloudCertificate;
|
||||
QString ownCloudPrivateKey;
|
||||
QString ownCloudCertificatePath;
|
||||
QString ownCloudCertificatePasswd;
|
||||
|
||||
public slots:
|
||||
void setAuthType(WizardCommon::AuthType type);
|
||||
void setRemoteFolder( const QString& );
|
||||
@ -75,6 +81,7 @@ signals:
|
||||
// make sure to connect to this, rather than finished(int)!!
|
||||
void basicSetupFinished( int );
|
||||
void skipFolderConfiguration();
|
||||
void needCertificate();
|
||||
|
||||
private:
|
||||
AccountPtr _account;
|
||||
|
||||
@ -66,6 +66,7 @@ set(libsync_SRCS
|
||||
creds/http/httpconfigfile.cpp
|
||||
creds/credentialscommon.cpp
|
||||
../3rdparty/qjson/json.cpp
|
||||
../3rdparty/certificates/p12topem.cpp
|
||||
)
|
||||
if(TOKEN_AUTH_ONLY)
|
||||
set (libsync_SRCS
|
||||
@ -122,6 +123,7 @@ list(APPEND libsync_LINK_TARGETS
|
||||
${QT_LIBRARIES}
|
||||
ocsync
|
||||
${OS_SPECIFIC_LINK_LIBRARIES}
|
||||
${OPENSSL_LIBRARIES}
|
||||
)
|
||||
|
||||
if(QTKEYCHAIN_FOUND OR QT5KEYCHAIN_FOUND)
|
||||
|
||||
@ -20,6 +20,7 @@
|
||||
#include "owncloudtheme.h"
|
||||
#include "creds/abstractcredentials.h"
|
||||
#include "creds/credentialsfactory.h"
|
||||
#include "../3rdparty/certificates/p12topem.h"
|
||||
|
||||
#include <QSettings>
|
||||
#include <QMutex>
|
||||
@ -29,8 +30,8 @@
|
||||
#include <QNetworkCookieJar>
|
||||
#include <QFileInfo>
|
||||
#include <QDir>
|
||||
|
||||
#include <QDebug>
|
||||
#include <QSslKey>
|
||||
|
||||
namespace OCC {
|
||||
|
||||
@ -294,6 +295,7 @@ QNetworkReply *Account::getRequest(const QString &relPath)
|
||||
QNetworkReply *Account::getRequest(const QUrl &url)
|
||||
{
|
||||
QNetworkRequest request(url);
|
||||
request.setSslConfiguration(this->createSslConfig());
|
||||
return _am->get(request);
|
||||
}
|
||||
|
||||
@ -305,14 +307,61 @@ QNetworkReply *Account::davRequest(const QByteArray &verb, const QString &relPat
|
||||
QNetworkReply *Account::davRequest(const QByteArray &verb, const QUrl &url, QNetworkRequest req, QIODevice *data)
|
||||
{
|
||||
req.setUrl(url);
|
||||
req.setSslConfiguration(this->createSslConfig());
|
||||
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;
|
||||
}
|
||||
|
||||
QSslConfiguration Account::createSslConfig()
|
||||
{
|
||||
// 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"
|
||||
|
||||
// maybe this code must not have to be reevaluated every request?
|
||||
QSslConfiguration sslConfig;
|
||||
QSslCertificate sslClientCertificate;
|
||||
|
||||
// maybe move this code from createSslConfig to the Account constructor
|
||||
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.defaultConfiguration();
|
||||
sslConfig.setCaCertificates(QSslSocket::systemCaCertificates());
|
||||
QList<QSslCertificate> caCertifs = sslConfig.caCertificates();
|
||||
sslConfig.setLocalCertificate(sslClientCertificate);
|
||||
sslConfig.setPrivateKey(privateKey);
|
||||
qDebug() << "Added SSL client certificate to the query";
|
||||
} else {
|
||||
qDebug() << "Failed to add the SSL client certificate to the query!";
|
||||
}
|
||||
|
||||
return sslConfig;
|
||||
}
|
||||
|
||||
void Account::setApprovedCerts(const QList<QSslCertificate> certs)
|
||||
{
|
||||
_approvedCerts = certs;
|
||||
@ -387,32 +436,34 @@ void Account::setCredentialSetting(const QString &key, const QVariant &value)
|
||||
void Account::slotHandleErrors(QNetworkReply *reply , QList<QSslError> errors)
|
||||
{
|
||||
NetworkJobTimeoutPauser pauser(reply);
|
||||
qDebug() << "SSL-Errors happened for url " << reply->url().toString();
|
||||
QString out;
|
||||
QDebug(&out) << "SSL-Errors happened for url " << reply->url().toString();
|
||||
foreach(const QSslError &error, errors) {
|
||||
qDebug() << "\tError in " << error.certificate() << ":"
|
||||
<< error.errorString() << "("<< error.error()<< ")";
|
||||
QDebug(&out) << "\tError in " << error.certificate() << ":"
|
||||
<< error.errorString() << "("<< error.error() << ")" << "\n";
|
||||
}
|
||||
|
||||
if( _treatSslErrorsAsFailure ) {
|
||||
// User decided once not to trust. Honor this decision.
|
||||
qDebug() << "Certs not trusted by user decision, returning.";
|
||||
qDebug() << out << "Certs not trusted by user decision, returning.";
|
||||
return;
|
||||
}
|
||||
|
||||
QList<QSslCertificate> approvedCerts;
|
||||
if (_sslErrorHandler.isNull() ) {
|
||||
qDebug() << Q_FUNC_INFO << "called without valid SSL error handler for account" << url();
|
||||
qDebug() << out << Q_FUNC_INFO << "called without valid SSL error handler for account" << url();
|
||||
return;
|
||||
}
|
||||
|
||||
if (_sslErrorHandler->handleErrors(errors, &approvedCerts, sharedFromThis())) {
|
||||
QSslSocket::addDefaultCaCertificates(approvedCerts);
|
||||
addApprovedCerts(approvedCerts);
|
||||
// all ssl certs are known and accepted. We can ignore the problems right away.
|
||||
// qDebug() << out << "Certs are known and trusted! This is not an actual error.";
|
||||
reply->ignoreSslErrors();
|
||||
} else {
|
||||
if (_sslErrorHandler->handleErrors(errors, &approvedCerts, sharedFromThis())) {
|
||||
QSslSocket::addDefaultCaCertificates(approvedCerts);
|
||||
addApprovedCerts(approvedCerts);
|
||||
// all ssl certs are known and accepted. We can ignore the problems right away.
|
||||
qDebug() << "Certs are already known and trusted, Errors are not valid.";
|
||||
reply->ignoreSslErrors();
|
||||
} else {
|
||||
_treatSslErrorsAsFailure = true;
|
||||
return;
|
||||
}
|
||||
_treatSslErrorsAsFailure = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -19,6 +19,7 @@
|
||||
#include <QUrl>
|
||||
#include <QNetworkCookie>
|
||||
#include <QNetworkRequest>
|
||||
#include <QSslSocket>
|
||||
#include <QSslCertificate>
|
||||
#include <QSslConfiguration>
|
||||
#include <QSslError>
|
||||
@ -123,6 +124,7 @@ public:
|
||||
QNetworkReply* davRequest(const QByteArray &verb, const QUrl &url, QNetworkRequest req, QIODevice *data = 0);
|
||||
|
||||
/** The ssl configuration during the first connection */
|
||||
QSslConfiguration createSslConfig();
|
||||
QSslConfiguration sslConfiguration() const { return _sslConfiguration; }
|
||||
void setSslConfiguration(const QSslConfiguration &config);
|
||||
/** The certificates of the account */
|
||||
@ -144,6 +146,8 @@ public:
|
||||
QVariant credentialSetting(const QString& key) const;
|
||||
void setCredentialSetting(const QString& key, const QVariant &value);
|
||||
|
||||
void setCertificate(const QByteArray certficate = QByteArray(), const QString privateKey = QString());
|
||||
|
||||
void clearCookieJar();
|
||||
|
||||
QNetworkAccessManager* networkAccessManager();
|
||||
@ -169,10 +173,14 @@ private:
|
||||
QList<QSslCertificate> _approvedCerts;
|
||||
QSslConfiguration _sslConfiguration;
|
||||
QScopedPointer<AbstractSslErrorHandler> _sslErrorHandler;
|
||||
QuotaInfo *_quotaInfo;
|
||||
QNetworkAccessManager *_am;
|
||||
AbstractCredentials* _credentials;
|
||||
bool _treatSslErrorsAsFailure;
|
||||
int _state;
|
||||
static QString _configFileName;
|
||||
QByteArray _pemCertificate;
|
||||
QString _pemPrivateKey;
|
||||
QString _davPath; // default "remote.php/webdav/";
|
||||
bool _wasMigrated;
|
||||
};
|
||||
|
||||
@ -64,6 +64,9 @@ static const char downloadLimitC[] = "BWLimit/downloadLimit";
|
||||
|
||||
static const char maxLogLinesC[] = "Logging/maxLogLines";
|
||||
|
||||
const char certPath[] = "http_certificatePath";
|
||||
const char certDate[] = "http_certificateDate";
|
||||
const char certPasswd[] = "http_certificatePasswd";
|
||||
QString ConfigFile::_confDir = QString::null;
|
||||
bool ConfigFile::_askedUser = false;
|
||||
|
||||
@ -213,6 +216,7 @@ QString ConfigFile::excludeFile(Scope scope) const
|
||||
// prefer sync-exclude.lst, but if it does not exist, check for
|
||||
// exclude.lst for compatibility reasons in the user writeable
|
||||
// directories.
|
||||
QFileInfo fi;
|
||||
|
||||
if (scope != SystemScope) {
|
||||
QFileInfo fi;
|
||||
@ -255,6 +259,7 @@ QString ConfigFile::excludeFileFromSystem()
|
||||
fi.setFile( QCoreApplication::applicationDirPath(),
|
||||
QLatin1String("../Resources/") + exclFile );
|
||||
#endif
|
||||
|
||||
return fi.absoluteFilePath();
|
||||
}
|
||||
|
||||
@ -567,4 +572,40 @@ void ConfigFile::setCrashReporter(bool enabled)
|
||||
settings.setValue(QLatin1String(crashReporterC), enabled);
|
||||
}
|
||||
|
||||
QString ConfigFile::certificatePath() const
|
||||
{
|
||||
return retrieveData(QString(), QLatin1String(certPath)).toString();
|
||||
}
|
||||
|
||||
void ConfigFile::setCertificatePath(const QString& cPath)
|
||||
{
|
||||
QSettings settings(configFile(), QSettings::IniFormat);
|
||||
settings.setValue( QLatin1String(certPath), cPath);
|
||||
settings.sync();
|
||||
}
|
||||
|
||||
QString ConfigFile::certificateDate() const
|
||||
{
|
||||
return retrieveData(QString(), QLatin1String(certDate)).toString();
|
||||
}
|
||||
|
||||
void ConfigFile::setCertificateDate(const QString& cDate)
|
||||
{
|
||||
QSettings settings(configFile(), QSettings::IniFormat);
|
||||
settings.setValue( QLatin1String(certDate), cDate);
|
||||
settings.sync();
|
||||
}
|
||||
|
||||
QString ConfigFile::certificatePasswd() const
|
||||
{
|
||||
return retrieveData(QString(), QLatin1String(certPasswd)).toString();
|
||||
}
|
||||
|
||||
void ConfigFile::setCertificatePasswd(const QString& cPasswd)
|
||||
{
|
||||
QSettings settings(configFile(), QSettings::IniFormat);
|
||||
settings.setValue( QLatin1String(certPasswd), cPasswd);
|
||||
settings.sync();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -12,8 +12,8 @@
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#ifndef MIRALLCONFIGFILE_H
|
||||
#define MIRALLCONFIGFILE_H
|
||||
#ifndef CONFIGFILE_H
|
||||
#define CONFIGFILE_H
|
||||
|
||||
#include "owncloudlib.h"
|
||||
#include <QSharedPointer>
|
||||
@ -116,6 +116,13 @@ public:
|
||||
void saveGeometryHeader(QHeaderView *header);
|
||||
void restoreGeometryHeader(QHeaderView *header);
|
||||
|
||||
QString certificatePath() const;
|
||||
void setCertificatePath(const QString& cPath);
|
||||
QString certificateDate() const;
|
||||
void setCertificateDate(const QString& cDate);
|
||||
QString certificatePasswd() const;
|
||||
void setCertificatePasswd(const QString& cPasswd);
|
||||
|
||||
protected:
|
||||
QVariant getPolicySetting(const QString& policy, const QVariant& defaultValue = QVariant()) const;
|
||||
void storeData(const QString& group, const QString& key, const QVariant& value);
|
||||
@ -137,4 +144,4 @@ private:
|
||||
};
|
||||
|
||||
}
|
||||
#endif // MIRALLCONFIGFILE_H
|
||||
#endif // CONFIGFILE_H
|
||||
|
||||
@ -30,6 +30,12 @@ public:
|
||||
bool passwordExists() const;
|
||||
void removePassword();
|
||||
void fixupOldPassword();
|
||||
QString certificatePath() const;
|
||||
void setCertificatePath(const QString& cPath);
|
||||
QString certificateDate() const;
|
||||
void setCertificateDate(const QString& cDate);
|
||||
QString certificatePasswd() const;
|
||||
void setCertificatePasswd(const QString& cPasswd);
|
||||
|
||||
private:
|
||||
void removeOldPassword();
|
||||
|
||||
@ -59,6 +59,9 @@ int getauth(const char *prompt,
|
||||
QString qPrompt = QString::fromLatin1( prompt ).trimmed();
|
||||
QString user = http_credentials->user();
|
||||
QString pwd = http_credentials->password();
|
||||
QString certificatePath = http_credentials->certificatePath();
|
||||
QString certificateDate = http_credentials->certificateDate();
|
||||
QString certificatePasswd = http_credentials->certificatePasswd();
|
||||
|
||||
if( qPrompt == QLatin1String("Enter your username:") ) {
|
||||
// qDebug() << "OOO Username requested!";
|
||||
@ -79,6 +82,9 @@ int getauth(const char *prompt,
|
||||
namespace
|
||||
{
|
||||
const char userC[] = "user";
|
||||
const char certifPathC[] = "certificatePath";
|
||||
const char certifPasswdC[] = "certificatePasswd";
|
||||
const char certifDateC[] = "certificateDate";
|
||||
const char authenticationFailedC[] = "owncloud-authentication-failed";
|
||||
} // ns
|
||||
|
||||
@ -101,15 +107,21 @@ private:
|
||||
HttpCredentials::HttpCredentials()
|
||||
: _user(),
|
||||
_password(),
|
||||
_certificatePath(),
|
||||
_certificateDate(),
|
||||
_certificatePasswd(),
|
||||
_ready(false),
|
||||
_fetchJobInProgress(false),
|
||||
_readPwdFromDeprecatedPlace(false)
|
||||
{
|
||||
}
|
||||
|
||||
HttpCredentials::HttpCredentials(const QString& user, const QString& password)
|
||||
HttpCredentials::HttpCredentials(const QString& user, const QString& password, const QString& certificatePath, const QString& certificateDate, const QString& certificatePasswd)
|
||||
: _user(user),
|
||||
_password(password),
|
||||
_certificatePath(certificatePath),
|
||||
_certificateDate(certificateDate),
|
||||
_certificatePasswd(certificatePasswd),
|
||||
_ready(true),
|
||||
_fetchJobInProgress(false)
|
||||
{
|
||||
@ -118,6 +130,13 @@ HttpCredentials::HttpCredentials(const QString& user, const QString& password)
|
||||
void HttpCredentials::syncContextPreInit (CSYNC* ctx)
|
||||
{
|
||||
csync_set_auth_callback (ctx, getauth);
|
||||
// create a SSL client certificate configuration in CSYNC* ctx
|
||||
struct csync_client_certs_s clientCerts;
|
||||
clientCerts.certificatePath = strdup(_certificatePath.toStdString().c_str());
|
||||
clientCerts.certificatePasswd = strdup(_certificatePasswd.toStdString().c_str());
|
||||
csync_set_module_property(ctx, "SSLClientCerts", &clientCerts);
|
||||
free(clientCerts.certificatePath);
|
||||
free(clientCerts.certificatePasswd);
|
||||
}
|
||||
|
||||
void HttpCredentials::syncContextPreStart (CSYNC* ctx)
|
||||
@ -167,6 +186,21 @@ QString HttpCredentials::password() const
|
||||
return _password;
|
||||
}
|
||||
|
||||
QString HttpCredentials::certificatePath() const
|
||||
{
|
||||
return _certificatePath;
|
||||
}
|
||||
|
||||
QString HttpCredentials::certificateDate() const
|
||||
{
|
||||
return _certificateDate;
|
||||
}
|
||||
|
||||
QString HttpCredentials::certificatePasswd() const
|
||||
{
|
||||
return _certificatePasswd;
|
||||
}
|
||||
|
||||
QNetworkAccessManager* HttpCredentials::getQNAM() const
|
||||
{
|
||||
AccessManager* qnam = new HttpCredentialsAccessManager(this);
|
||||
@ -196,6 +230,9 @@ void HttpCredentials::fetch()
|
||||
|
||||
// User must be fetched from config file
|
||||
fetchUser();
|
||||
_certificatePath = _account->credentialSetting(QLatin1String(certifPathC)).toString();
|
||||
_certificatePasswd = _account->credentialSetting(QLatin1String(certifPasswdC)).toString();
|
||||
_certificateDate = _account->credentialSetting(QLatin1String(certifDateC)).toString();
|
||||
|
||||
QSettings *settings = _account->settingsWithGroup(Theme::instance()->appName());
|
||||
const QString kck = keychainKey(_account->url().toString(), _user );
|
||||
@ -322,6 +359,9 @@ void HttpCredentials::persist()
|
||||
return;
|
||||
}
|
||||
_account->setCredentialSetting(QLatin1String(userC), _user);
|
||||
_account->setCredentialSetting(QLatin1String(certifPathC), _certificatePath);
|
||||
_account->setCredentialSetting(QLatin1String(certifPasswdC), _certificatePasswd);
|
||||
_account->setCredentialSetting(QLatin1String(certifDateC), _certificateDate);
|
||||
WritePasswordJob *job = new WritePasswordJob(Theme::instance()->appName());
|
||||
QSettings *settings = _account->settingsWithGroup(Theme::instance()->appName());
|
||||
settings->setParent(job); // make the job parent to make setting deleted properly
|
||||
|
||||
@ -36,7 +36,7 @@ class OWNCLOUDSYNC_EXPORT HttpCredentials : public AbstractCredentials
|
||||
|
||||
public:
|
||||
explicit HttpCredentials();
|
||||
HttpCredentials(const QString& user, const QString& password);
|
||||
HttpCredentials(const QString& user, const QString& password, const QString& certificatePath, const QString& certificateDate, const QString& certificatePasswd);
|
||||
|
||||
void syncContextPreInit(CSYNC* ctx) Q_DECL_OVERRIDE;
|
||||
void syncContextPreStart(CSYNC* ctx) Q_DECL_OVERRIDE;
|
||||
@ -53,6 +53,9 @@ public:
|
||||
void invalidateToken() Q_DECL_OVERRIDE;
|
||||
QString fetchUser();
|
||||
virtual bool sslIsTrusted() { return false; }
|
||||
QString certificatePath() const;
|
||||
QString certificateDate() const;
|
||||
QString certificatePasswd() const;
|
||||
|
||||
private Q_SLOTS:
|
||||
void slotAuthentication(QNetworkReply*, QAuthenticator*);
|
||||
@ -64,6 +67,9 @@ protected:
|
||||
QString _password;
|
||||
|
||||
private:
|
||||
QString _certificatePath;
|
||||
QString _certificateDate;
|
||||
QString _certificatePasswd;
|
||||
bool _ready;
|
||||
bool _fetchJobInProgress; //True if the keychain job is in progress or the input dialog visible
|
||||
bool _readPwdFromDeprecatedPlace;
|
||||
@ -72,7 +78,7 @@ private:
|
||||
class OWNCLOUDSYNC_EXPORT HttpCredentialsGui : public HttpCredentials {
|
||||
public:
|
||||
explicit HttpCredentialsGui() : HttpCredentials() {}
|
||||
HttpCredentialsGui(const QString& user, const QString& password) : HttpCredentials(user, password) {}
|
||||
HttpCredentialsGui(const QString& user, const QString& password, const QString& certificatePath, const QString& certificateDate, const QString& certificatePasswd) : HttpCredentials(user, password, certificatePath, certificateDate, certificatePasswd) {}
|
||||
QString queryPassword(bool *ok) Q_DECL_OVERRIDE;
|
||||
};
|
||||
|
||||
|
||||
@ -154,6 +154,10 @@ void AbstractNetworkJob::slotFinished()
|
||||
{
|
||||
_timer.stop();
|
||||
|
||||
if( _reply->error() == QNetworkReply::SslHandshakeFailedError ) {
|
||||
qDebug() << "SslHandshakeFailedError: " << reply()->errorString() << " : can be caused by a webserver wanting SSL client certificates";
|
||||
}
|
||||
|
||||
if( _reply->error() != QNetworkReply::NoError ) {
|
||||
qDebug() << Q_FUNC_INFO << _reply->error() << _reply->errorString();
|
||||
if (_reply->error() == QNetworkReply::ProxyAuthenticationRequiredError) {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user