Remove Shibboleth support

Issue #6451
This commit is contained in:
Olivier Goffart 2018-11-27 12:24:06 +01:00
parent ba24ef3fe3
commit 697b6b9e81
23 changed files with 19 additions and 1236 deletions

View File

@ -126,14 +126,6 @@ if(OWNCLOUD_5XX_NO_BLACKLIST)
add_definitions(-DOWNCLOUD_5XX_NO_BLACKLIST=1)
endif()
# Disable shibboleth.
# So the client can be built without QtWebKit
option(NO_SHIBBOLETH "Build without Shibboleth support. Allow to build the client without QtWebKit" OFF)
if(NO_SHIBBOLETH)
message("Compiling without shibboleth")
add_definitions(-DNO_SHIBBOLETH=1)
endif()
if(APPLE)
set( SOCKETAPI_TEAM_IDENTIFIER_PREFIX "" CACHE STRING "SocketApi prefix (including a following dot) that must match the codesign key's TeamIdentifier/Organizational Unit" )
endif()

View File

@ -68,7 +68,7 @@ Linux with system dependencies
------------------------------
1. Build sources from e.g. a github checkout with dependencies provided by your linux distribution. While this allows more freedom for development, it does not exactly represent what we ship as packages. See above for how to recreate packages from source.
* Debian/Ubuntu: ``apt install qtdeclarative5-dev libinotifytools-dev qt5keychain-dev libqt5webkit5-dev python-sphinx libsqlite3-dev``
* Debian/Ubuntu: ``apt install qtdeclarative5-dev libinotifytools-dev qt5keychain-dev python-sphinx libsqlite3-dev``
2. Follow the :ref:`generic-build-instructions`, starting with step 1.
@ -167,7 +167,7 @@ follow `Windows Installer Build (Cross-Compile)`_ instead.
7. Build the client::
cmake -G "MinGW Makefiles" -DNO_SHIBBOLETH=1 ../client
cmake -G "MinGW Makefiles" ../client
mingw32-make
.. note:: You can try using ninja to build in parallel using
@ -253,7 +253,7 @@ To build the most up-to-date version of the client:
3. Configure the client build::
cmake -DCMAKE_PREFIX_PATH=/opt/ownCloud/qt-5.10.1 -DCMAKE_INSTALL_PREFIX=/Users/path/to/client/../install/ -DNO_SHIBBOLETH=1 ..
cmake -DCMAKE_PREFIX_PATH=/opt/ownCloud/qt-5.10.1 -DCMAKE_INSTALL_PREFIX=/Users/path/to/client/../install/ ..
.. note:: For Linux builds (using QT5 libraries via build-dep) a typical setting is ``-DCMAKE_PREFIX_PATH=/opt/ownCloud/qt-5.10.1/`` - version number may vary. For Linux builds using system dependencies -DCMAKE_PREFIX_PATH is not needed.

View File

@ -99,7 +99,6 @@ set(client_SRCS
servernotificationhandler.cpp
guiutility.cpp
elidedlabel.cpp
creds/credentialsfactory.cpp
creds/httpcredentialsgui.cpp
creds/oauth.cpp
wizard/postfixlineedit.cpp
@ -114,15 +113,6 @@ set(client_SRCS
wizard/owncloudwizardresultpage.cpp
)
IF(NOT NO_SHIBBOLETH)
list(APPEND client_SRCS
creds/shibbolethcredentials.cpp
creds/shibboleth/shibbolethwebview.cpp
creds/shibboleth/shibbolethuserjob.cpp
wizard/owncloudshibbolethcredspage.cpp
)
endif()
set(updater_SRCS
updater/ocupdater.cpp
updater/updateinfo.cpp
@ -307,11 +297,6 @@ if (APPLE)
target_link_libraries( ${APPLICATION_EXECUTABLE} Qt5::MacExtras)
endif()
if (NOT NO_SHIBBOLETH)
find_package(Qt5 COMPONENTS WebKitWidgets)
target_link_libraries( ${APPLICATION_EXECUTABLE} Qt5::WebKitWidgets)
endif()
if(WITH_CRASHREPORTER)
target_link_libraries(${APPLICATION_EXECUTABLE} crashreporter-handler)

View File

@ -17,8 +17,7 @@
#include "sslerrordialog.h"
#include "proxyauthhandler.h"
#include <theme.h>
#include <creds/credentialsfactory.h>
#include <creds/abstractcredentials.h>
#include <creds/httpcredentialsgui.h>
#include <cookiejar.h>
#include <QSettings>
#include <QDir>
@ -26,7 +25,6 @@
namespace {
static const char urlC[] = "url";
static const char authTypeC[] = "authType";
static const char userC[] = "user";
static const char httpUserC[] = "http_user";
static const char davUserC[] = "dav_user";
@ -226,7 +224,6 @@ void AccountManager::saveAccountHelper(Account *acc, QSettings &settings, bool s
Q_FOREACH (QString key, acc->_settingsMap.keys()) {
settings.setValue(key, acc->_settingsMap.value(key));
}
settings.setValue(QLatin1String(authTypeC), acc->_credentials->authType());
// HACK: Save http_user also as user
if (acc->_settingsMap.contains(httpUserC))
@ -266,44 +263,29 @@ AccountPtr AccountManager::loadAccountHelper(QSettings &settings)
auto acc = createAccount();
QString authType = settings.value(QLatin1String(authTypeC)).toString();
// There was an account-type saving bug when 'skip folder config' was used
// See #5408. This attempts to fix up the "dummy" authType
if (authType == QLatin1String("dummy")) {
if (settings.contains(QLatin1String("http_user"))) {
authType = "http";
} else if (settings.contains(QLatin1String("shibboleth_shib_user"))) {
authType = "shibboleth";
}
}
QString overrideUrl = Theme::instance()->overrideServerUrl();
QString forceAuth = Theme::instance()->forceConfigAuthType();
if (!forceAuth.isEmpty() && !overrideUrl.isEmpty()) {
// If forceAuth is set, this might also mean the overrideURL has changed.
// See enterprise issues #1126
acc->setUrl(overrideUrl);
authType = forceAuth;
} else {
acc->setUrl(urlConfig.toUrl());
}
qCInfo(lcAccountManager) << "Account for" << acc->url() << "using auth type" << authType;
acc->_serverVersion = settings.value(QLatin1String(serverVersionC)).toString();
acc->_davUser = settings.value(QLatin1String(davUserC)).toString();
// We want to only restore settings for that auth type and the user value
acc->_settingsMap.insert(QLatin1String(userC), settings.value(userC));
QString authTypePrefix = authType + "_";
QString authTypePrefix = "http_";
Q_FOREACH (QString key, settings.childKeys()) {
if (!key.startsWith(authTypePrefix))
continue;
acc->_settingsMap.insert(key, settings.value(key));
}
acc->setCredentials(CredentialsFactory::create(authType));
acc->setCredentials(new HttpCredentialsGui);
// now the server cert, it is in the general group
settings.beginGroup(QLatin1String("General"));

View File

@ -1,50 +0,0 @@
/*
* Copyright (C) by Krzesimir Nowak <krzesimir@endocode.com>
*
* 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; either version 2 of the License, or
* (at your option) any later version.
*
* 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.
*/
#include <QLoggingCategory>
#include <QString>
#include "creds/credentialsfactory.h"
#include "creds/httpcredentialsgui.h"
#include "creds/dummycredentials.h"
#ifndef NO_SHIBBOLETH
#include "creds/shibbolethcredentials.h"
#endif
namespace OCC {
Q_LOGGING_CATEGORY(lcGuiCredentials, "gui.credentials", QtInfoMsg)
namespace CredentialsFactory {
AbstractCredentials *create(const QString &type)
{
// empty string might happen for old version of configuration
if (type == "http" || type == "") {
return new HttpCredentialsGui;
} else if (type == "dummy") {
return new DummyCredentials;
#ifndef NO_SHIBBOLETH
} else if (type == "shibboleth") {
return new ShibbolethCredentials;
#endif
} else {
qCWarning(lcGuiCredentials, "Unknown credentials type: %s", qPrintable(type));
return new DummyCredentials;
}
}
} // ns CredentialsFactory
} // namespace OCC

View File

@ -1,38 +0,0 @@
/*
* Copyright (C) by Krzesimir Nowak <krzesimir@endocode.com>
*
* 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; either version 2 of the License, or
* (at your option) any later version.
*
* 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 MIRALL_CREDS_CREDENTIALS_FACTORY_H
#define MIRALL_CREDS_CREDENTIALS_FACTORY_H
#include "owncloudlib.h"
class QString;
namespace OCC {
class AbstractCredentials;
/**
* @brief The HttpCredentialsGui namespace
* @ingroup gui
*/
namespace CredentialsFactory {
AbstractCredentials *create(const QString &type);
} // ns CredentialsFactory
} // namespace OCC
#endif

View File

@ -1,41 +0,0 @@
/*
* Copyright (C) by Olivier Goffart <ogoffart@owncloud.com>
*
* 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; either version 2 of the License, or
* (at your option) any later version.
*
* 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.
*/
#include "shibbolethuserjob.h"
#include <account.h>
#include <QJsonDocument>
#include <QJsonObject>
#include <QLoggingCategory>
namespace OCC {
Q_DECLARE_LOGGING_CATEGORY(lcShibboleth)
ShibbolethUserJob::ShibbolethUserJob(AccountPtr account, QObject *parent)
: JsonApiJob(account, QLatin1String("ocs/v1.php/cloud/user"), parent)
{
setIgnoreCredentialFailure(true);
connect(this, &JsonApiJob::jsonReceived, this, &ShibbolethUserJob::slotJsonReceived);
}
void ShibbolethUserJob::slotJsonReceived(const QJsonDocument &json, int statusCode)
{
if (statusCode != 100) {
qCWarning(lcShibboleth) << "JSON Api call resulted in status code != 100";
}
QString user = json.object().value("ocs").toObject().value("data").toObject().value("id").toString();
emit userFetched(user);
}
}

View File

@ -1,42 +0,0 @@
/*
* Copyright (C) by Olivier Goffart <ogoffart@owncloud.com>
*
* 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; either version 2 of the License, or
* (at your option) any later version.
*
* 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.
*/
#pragma once
#include <networkjobs.h>
class QJsonDocument;
namespace OCC {
/**
* @brief Fetch the user name of the shibboleth connection
* @ingroup gui
*/
class ShibbolethUserJob : public JsonApiJob
{
Q_OBJECT
public:
explicit ShibbolethUserJob(AccountPtr account, QObject *parent = 0);
signals:
// is always emitted when the job is finished. user is empty in case of error.
void userFetched(const QString &user);
private slots:
void slotJsonReceived(const QJsonDocument &, int statusCode);
};
} // namespace OCC

View File

@ -1,169 +0,0 @@
/*
* Copyright (C) by Krzesimir Nowak <krzesimir@endocode.com>
*
* 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; either version 2 of the License, or
* (at your option) any later version.
*
* 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.
*/
#include <QApplication>
#include <QNetworkCookie>
#include <QNetworkCookieJar>
#include <QWebFrame>
#include <QWebPage>
#include <QMessageBox>
#include <QNetworkReply>
#include <QSettings>
#include <QMainWindow>
#include "creds/shibboleth/shibbolethwebview.h"
#include "creds/shibbolethcredentials.h"
#include "account.h"
#include "logger.h"
#include "accessmanager.h"
#include "theme.h"
#include "configfile.h"
#include "cookiejar.h"
namespace {
const char ShibbolethWebViewGeometryC[] = "ShibbolethWebView/Geometry";
}
namespace OCC {
class UserAgentWebPage : public QWebPage
{
public:
UserAgentWebPage(QObject *parent)
: QWebPage(parent)
{
if (!qEnvironmentVariableIsEmpty("OWNCLOUD_SHIBBOLETH_DEBUG")) {
settings()->setAttribute(QWebSettings::DeveloperExtrasEnabled, true);
}
}
QString userAgentForUrl(const QUrl &url) const
{
return QWebPage::userAgentForUrl(url) + " " + Utility::userAgentString();
}
};
ShibbolethWebView::ShibbolethWebView(AccountPtr account, QWidget *parent)
: QWebView(parent)
, _account(account)
, _accepted(false)
, _cursorOverriden(false)
{
// no minimize
setWindowFlags(Qt::Dialog);
setAttribute(Qt::WA_DeleteOnClose);
QWebPage *page = new UserAgentWebPage(this);
connect(page, &QWebPage::loadStarted,
this, &ShibbolethWebView::slotLoadStarted);
connect(page, &QWebPage::loadFinished,
this, &ShibbolethWebView::slotLoadFinished);
// Make sure to accept the same SSL certificate issues as the regular QNAM we use for syncing
QObject::connect(page->networkAccessManager(), &QNetworkAccessManager::sslErrors,
_account.data(), &Account::slotHandleSslErrors);
// The Account keeps ownership of the cookie jar, it must outlive this webview.
account->lendCookieJarTo(page->networkAccessManager());
connect(static_cast<CookieJar *>(page->networkAccessManager()->cookieJar()), &CookieJar::newCookiesForUrl,
this, &ShibbolethWebView::onNewCookiesForUrl);
page->mainFrame()->load(account->url());
this->setPage(page);
setWindowTitle(tr("%1 - Authenticate").arg(Theme::instance()->appNameGUI()));
// Debug view to display the cipher suite
if (!qEnvironmentVariableIsEmpty("OWNCLOUD_SHIBBOLETH_DEBUG")) {
// open an additional window to display some cipher debug info
QWebPage *debugPage = new UserAgentWebPage(this);
debugPage->mainFrame()->load(QUrl("https://cc.dcsec.uni-hannover.de/"));
QWebView *debugView = new QWebView(this);
debugView->setPage(debugPage);
QMainWindow *window = new QMainWindow(this);
window->setWindowTitle(tr("SSL Chipher Debug View"));
window->setCentralWidget(debugView);
window->show();
}
// If we have a valid cookie, it's most likely expired. We can use this as
// as a criteria to tell the user why the browser window pops up
QNetworkCookie shibCookie = ShibbolethCredentials::findShibCookie(_account.data(), ShibbolethCredentials::accountCookies(_account.data()));
if (shibCookie != QNetworkCookie()) {
Logger::instance()->postOptionalGuiLog(tr("Reauthentication required"), tr("Your session has expired. You need to re-login to continue to use the client."));
}
ConfigFile config;
QSettings settings(config.configFile());
resize(900, 700); // only effective the first time, later overridden by restoreGeometry
restoreGeometry(settings.value(ShibbolethWebViewGeometryC).toByteArray());
}
ShibbolethWebView::~ShibbolethWebView()
{
ConfigFile config;
QSettings settings(config.configFile());
settings.setValue(ShibbolethWebViewGeometryC, saveGeometry());
}
void ShibbolethWebView::onNewCookiesForUrl(const QList<QNetworkCookie> &cookieList, const QUrl &url)
{
if (url.host() == _account->url().host()) {
QNetworkCookie shibCookie = ShibbolethCredentials::findShibCookie(_account.data(), cookieList);
if (shibCookie != QNetworkCookie()) {
Q_EMIT shibbolethCookieReceived(shibCookie);
accept();
close();
}
}
}
void ShibbolethWebView::closeEvent(QCloseEvent *event)
{
if (_cursorOverriden) {
QApplication::restoreOverrideCursor();
}
if (!_accepted) {
Q_EMIT rejected();
}
QWebView::closeEvent(event);
}
void ShibbolethWebView::slotLoadStarted()
{
if (!_cursorOverriden) {
QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
_cursorOverriden = true;
}
}
void ShibbolethWebView::slotLoadFinished(bool success)
{
if (_cursorOverriden) {
QApplication::restoreOverrideCursor();
}
if (!title().isNull()) {
setWindowTitle(QString::fromLatin1("%1 - %2 (%3)").arg(Theme::instance()->appNameGUI(), title(), url().host()));
}
if (!success) {
qCWarning(lcShibboleth) << "Could not load Shibboleth login page to log you in.";
}
}
void ShibbolethWebView::accept()
{
_accepted = true;
}
} // namespace OCC

View File

@ -1,67 +0,0 @@
/*
* Copyright (C) by Krzesimir Nowak <krzesimir@endocode.com>
*
* 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; either version 2 of the License, or
* (at your option) any later version.
*
* 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 MIRALL_WIZARD_SHIBBOLETH_WEB_VIEW_H
#define MIRALL_WIZARD_SHIBBOLETH_WEB_VIEW_H
#include "owncloudlib.h"
#include <QList>
#include <QPointer>
#include <QWebView>
#include "accountfwd.h"
class QNetworkCookie;
class QUrl;
namespace OCC {
class ShibbolethCookieJar;
/**
* @brief The ShibbolethWebView class
* @ingroup gui
*/
class ShibbolethWebView : public QWebView
{
Q_OBJECT
public:
ShibbolethWebView(AccountPtr account, QWidget *parent = 0);
ShibbolethWebView(AccountPtr account, ShibbolethCookieJar *jar, QWidget *parent = 0);
~ShibbolethWebView();
void closeEvent(QCloseEvent *event) Q_DECL_OVERRIDE;
Q_SIGNALS:
void shibbolethCookieReceived(const QNetworkCookie &cookie);
void rejected();
private Q_SLOTS:
void onNewCookiesForUrl(const QList<QNetworkCookie> &cookieList, const QUrl &url);
void slotLoadStarted();
void slotLoadFinished(bool success);
protected:
void accept();
private:
void setup(AccountPtr account, ShibbolethCookieJar *jar);
AccountPtr _account;
bool _accepted;
bool _cursorOverriden;
};
} // namespace OCC
#endif

View File

@ -1,396 +0,0 @@
/*
* Copyright (C) by Krzesimir Nowak <krzesimir@endocode.com>
* Copyright (C) by Klaas Freitag <freitag@owncloud.com>
*
* 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; either version 2 of the License, or
* (at your option) any later version.
*
* 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.
*/
#include <QSettings>
#include <QNetworkReply>
#include <QMessageBox>
#include <QAuthenticator>
#include "creds/shibbolethcredentials.h"
#include "creds/shibboleth/shibbolethwebview.h"
#include "creds/shibbolethcredentials.h"
#include "shibboleth/shibbolethuserjob.h"
#include "creds/credentialscommon.h"
#include "creds/httpcredentialsgui.h"
#include "accessmanager.h"
#include "account.h"
#include "configfile.h"
#include "theme.h"
#include "cookiejar.h"
#include "owncloudgui.h"
#include "syncengine.h"
#include <keychain.h>
using namespace QKeychain;
namespace OCC {
Q_LOGGING_CATEGORY(lcShibboleth, "gui.credentials.shibboleth", QtInfoMsg)
namespace {
// Not "user" because it has a special meaning for http
const char userC[] = "shib_user";
const char shibCookieNameC[] = "_shibsession_";
} // ns
ShibbolethCredentials::ShibbolethCredentials()
: AbstractCredentials()
, _url()
, _ready(false)
, _stillValid(false)
, _browser(0)
, _keychainMigration(false)
{
}
ShibbolethCredentials::ShibbolethCredentials(const QNetworkCookie &cookie)
: _ready(true)
, _stillValid(true)
, _browser(0)
, _shibCookie(cookie)
, _keychainMigration(false)
{
}
void ShibbolethCredentials::setAccount(Account *account)
{
AbstractCredentials::setAccount(account);
// This is for existing saved accounts.
if (_user.isEmpty()) {
_user = _account->credentialSetting(QLatin1String(userC)).toString();
}
// When constructed with a cookie (by the wizard), we usually don't know the
// user name yet. Request it now from the server.
if (_ready && _user.isEmpty()) {
QTimer::singleShot(1234, this, &ShibbolethCredentials::slotFetchUser);
}
}
QString ShibbolethCredentials::authType() const
{
return QString::fromLatin1("shibboleth");
}
QString ShibbolethCredentials::user() const
{
return _user;
}
QNetworkAccessManager *ShibbolethCredentials::createQNAM() const
{
QNetworkAccessManager *qnam(new AccessManager);
connect(qnam, &QNetworkAccessManager::finished,
this, &ShibbolethCredentials::slotReplyFinished);
return qnam;
}
void ShibbolethCredentials::slotReplyFinished(QNetworkReply *r)
{
if (!_browser.isNull()) {
return;
}
QVariant target = r->attribute(QNetworkRequest::RedirectionTargetAttribute);
if (target.isValid()) {
_stillValid = false;
// The Login window will be opened in NetworkJob's finished signal
qCWarning(lcShibboleth) << "detected redirect, will open Login Window";
} else {
//_stillValid = true; // gets set when reading from keychain or getting it from browser
}
}
bool ShibbolethCredentials::ready() const
{
return _ready;
}
void ShibbolethCredentials::fetchFromKeychain()
{
_wasFetched = true;
if (_user.isEmpty()) {
_user = _account->credentialSetting(QLatin1String(userC)).toString();
}
if (_ready) {
Q_EMIT fetched();
} else {
_url = _account->url();
_keychainMigration = false;
fetchFromKeychainHelper();
}
}
void ShibbolethCredentials::fetchFromKeychainHelper()
{
ReadPasswordJob *job = new ReadPasswordJob(Theme::instance()->appName());
job->setSettings(ConfigFile::settingsWithGroup(Theme::instance()->appName(), job).release());
job->setInsecureFallback(false);
job->setKey(keychainKey(_url.toString(), user(),
_keychainMigration ? QString() : _account->id()));
connect(job, &Job::finished, this, &ShibbolethCredentials::slotReadJobDone);
job->start();
}
void ShibbolethCredentials::askFromUser()
{
// First, we do a DetermineAuthTypeJob to make sure that the server is still using shibboleth and did not upgrade to oauth
DetermineAuthTypeJob *job = new DetermineAuthTypeJob(_account->sharedFromThis(), this);
connect(job, &DetermineAuthTypeJob::authType, [this, job](DetermineAuthTypeJob::AuthType type) {
if (type == DetermineAuthTypeJob::Shibboleth) {
// Normal case, still shibboleth
showLoginWindow();
} else if (type == DetermineAuthTypeJob::OAuth) {
// Hack: upgrade to oauth
auto newCred = new HttpCredentialsGui;
job->setParent(0);
job->deleteLater();
auto account = this->_account;
auto user = this->_user;
account->setCredentials(newCred); // delete this
account->setCredentialSetting(QLatin1String("user"), user);
newCred->fetchUser();
newCred->askFromUser();
} else {
// Basic auth or unkown. Since it may be unkown it might be a temporary failure, don't replace the credentials here
// Still show the login window in that case not to break the flow.
showLoginWindow();
}
});
job->start();
}
bool ShibbolethCredentials::stillValid(QNetworkReply *reply)
{
Q_UNUSED(reply)
return _stillValid;
}
void ShibbolethCredentials::persist()
{
storeShibCookie(_shibCookie);
if (!_user.isEmpty()) {
_account->setCredentialSetting(QLatin1String(userC), _user);
}
}
void ShibbolethCredentials::invalidateToken()
{
_ready = false;
CookieJar *jar = static_cast<CookieJar *>(_account->networkAccessManager()->cookieJar());
// Remove the _shibCookie
auto cookies = jar->allCookies();
for (auto it = cookies.begin(); it != cookies.end();) {
if (it->name() == _shibCookie.name()) {
it = cookies.erase(it);
} else {
++it;
}
}
jar->setAllCookies(cookies);
// Clear all other temporary cookies
jar->clearSessionCookies();
removeShibCookie();
_shibCookie = QNetworkCookie();
}
void ShibbolethCredentials::forgetSensitiveData()
{
invalidateToken();
}
void ShibbolethCredentials::onShibbolethCookieReceived(const QNetworkCookie &shibCookie)
{
storeShibCookie(shibCookie);
_shibCookie = shibCookie;
addToCookieJar(shibCookie);
slotFetchUser();
}
void ShibbolethCredentials::slotFetchUser()
{
// We must first do a request to webdav so the session is enabled.
// (because for some reason we can't access the API without that.. a bug in the server maybe?)
EntityExistsJob *job = new EntityExistsJob(_account->sharedFromThis(), _account->davPath(), this);
connect(job, &EntityExistsJob::exists, this, &ShibbolethCredentials::slotFetchUserHelper);
job->setIgnoreCredentialFailure(true);
job->start();
}
void ShibbolethCredentials::slotFetchUserHelper()
{
ShibbolethUserJob *job = new ShibbolethUserJob(_account->sharedFromThis(), this);
connect(job, &ShibbolethUserJob::userFetched, this, &ShibbolethCredentials::slotUserFetched);
job->start();
}
void ShibbolethCredentials::slotUserFetched(const QString &user)
{
if (_user.isEmpty()) {
if (user.isEmpty()) {
qCWarning(lcShibboleth) << "Failed to fetch the shibboleth user";
}
_user = user;
} else if (user != _user) {
qCWarning(lcShibboleth) << "Wrong user: " << user << "!=" << _user;
QMessageBox::warning(_browser, tr("Login Error"), tr("You must sign in as user %1").arg(_user));
invalidateToken();
showLoginWindow();
return;
}
_stillValid = true;
_ready = true;
Q_EMIT asked();
}
void ShibbolethCredentials::slotBrowserRejected()
{
_ready = false;
Q_EMIT asked();
}
void ShibbolethCredentials::slotReadJobDone(QKeychain::Job *job)
{
// If we can't find the credentials at the keys that include the account id,
// try to read them from the legacy locations that don't have a account id.
if (!_keychainMigration && job->error() == QKeychain::EntryNotFound) {
qCWarning(lcShibboleth)
<< "Could not find keychain entry, attempting to read from legacy location";
_keychainMigration = true;
fetchFromKeychainHelper();
return;
}
if (job->error() == QKeychain::NoError) {
ReadPasswordJob *readJob = static_cast<ReadPasswordJob *>(job);
delete readJob->settings();
QList<QNetworkCookie> cookies = QNetworkCookie::parseCookies(readJob->textData().toUtf8());
if (cookies.count() > 0) {
_shibCookie = cookies.first();
addToCookieJar(_shibCookie);
}
// access
job->setSettings(ConfigFile::settingsWithGroup(Theme::instance()->appName(), job).release());
_ready = true;
_stillValid = true;
Q_EMIT fetched();
} else {
_ready = false;
Q_EMIT fetched();
}
// If keychain data was read from legacy location, wipe these entries and store new ones
if (_keychainMigration && _ready) {
persist();
DeletePasswordJob *job = new DeletePasswordJob(Theme::instance()->appName());
job->setSettings(ConfigFile::settingsWithGroup(Theme::instance()->appName(), job).release());
job->setKey(keychainKey(_account->url().toString(), user(), QString()));
job->start();
qCWarning(lcShibboleth) << "Migrated old keychain entries";
}
}
void ShibbolethCredentials::showLoginWindow()
{
if (!_browser.isNull()) {
ownCloudGui::raiseDialog(_browser);
return;
}
CookieJar *jar = static_cast<CookieJar *>(_account->networkAccessManager()->cookieJar());
// When opening a new window clear all the session cookie that might keep the user from logging in
// (or the session may already be open in the server, and there will not be redirect asking for the
// real long term cookie we want to store)
jar->clearSessionCookies();
_browser = new ShibbolethWebView(_account->sharedFromThis());
connect(_browser.data(), &ShibbolethWebView::shibbolethCookieReceived,
this, &ShibbolethCredentials::onShibbolethCookieReceived, Qt::QueuedConnection);
connect(_browser.data(), &ShibbolethWebView::rejected, this, &ShibbolethCredentials::slotBrowserRejected);
ownCloudGui::raiseDialog(_browser);
}
QList<QNetworkCookie> ShibbolethCredentials::accountCookies(Account *account)
{
return account->networkAccessManager()->cookieJar()->cookiesForUrl(account->davUrl());
}
QNetworkCookie ShibbolethCredentials::findShibCookie(Account *account, QList<QNetworkCookie> cookies)
{
if (cookies.isEmpty()) {
cookies = accountCookies(account);
}
Q_FOREACH (QNetworkCookie cookie, cookies) {
if (cookie.name().startsWith(shibCookieNameC)) {
return cookie;
}
}
return QNetworkCookie();
}
QByteArray ShibbolethCredentials::shibCookieName()
{
return QByteArray(shibCookieNameC);
}
void ShibbolethCredentials::storeShibCookie(const QNetworkCookie &cookie)
{
WritePasswordJob *job = new WritePasswordJob(Theme::instance()->appName());
job->setSettings(ConfigFile::settingsWithGroup(Theme::instance()->appName(), job).release());
// we don't really care if it works...
//connect(job, SIGNAL(finished(QKeychain::Job*)), SLOT(slotWriteJobDone(QKeychain::Job*)));
job->setKey(keychainKey(_account->url().toString(), user(), _account->id()));
job->setTextData(QString::fromUtf8(cookie.toRawForm()));
job->start();
}
void ShibbolethCredentials::removeShibCookie()
{
DeletePasswordJob *job = new DeletePasswordJob(Theme::instance()->appName());
job->setSettings(ConfigFile::settingsWithGroup(Theme::instance()->appName(), job).release());
job->setKey(keychainKey(_account->url().toString(), user(), _account->id()));
job->start();
}
void ShibbolethCredentials::addToCookieJar(const QNetworkCookie &cookie)
{
QList<QNetworkCookie> cookies;
cookies << cookie;
QNetworkCookieJar *jar = _account->networkAccessManager()->cookieJar();
jar->blockSignals(true); // otherwise we'd call ourselves
jar->setCookiesFromUrl(cookies, _account->url());
jar->blockSignals(false);
}
} // namespace OCC

View File

@ -1,104 +0,0 @@
/*
* Copyright (C) by Krzesimir Nowak <krzesimir@endocode.com>
*
* 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; either version 2 of the License, or
* (at your option) any later version.
*
* 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 MIRALL_CREDS_SHIBBOLETH_CREDENTIALS_H
#define MIRALL_CREDS_SHIBBOLETH_CREDENTIALS_H
#include <QList>
#include <QLoggingCategory>
#include <QMap>
#include <QNetworkCookie>
#include <QUrl>
#include <QPointer>
#include "creds/abstractcredentials.h"
namespace QKeychain {
class Job;
}
class QAuthenticator;
namespace OCC {
Q_DECLARE_LOGGING_CATEGORY(lcShibboleth)
class ShibbolethWebView;
/**
* @brief The ShibbolethCredentials class
* @ingroup gui
*/
class ShibbolethCredentials : public AbstractCredentials
{
Q_OBJECT
public:
ShibbolethCredentials();
/* create credentials for an already connected account */
ShibbolethCredentials(const QNetworkCookie &cookie);
void setAccount(Account *account) Q_DECL_OVERRIDE;
QString authType() const Q_DECL_OVERRIDE;
QString user() const Q_DECL_OVERRIDE;
QNetworkAccessManager *createQNAM() const Q_DECL_OVERRIDE;
bool ready() const Q_DECL_OVERRIDE;
void fetchFromKeychain() Q_DECL_OVERRIDE;
void askFromUser() Q_DECL_OVERRIDE;
bool stillValid(QNetworkReply *reply) Q_DECL_OVERRIDE;
void persist() Q_DECL_OVERRIDE;
void invalidateToken() Q_DECL_OVERRIDE;
void forgetSensitiveData() Q_DECL_OVERRIDE;
void showLoginWindow();
static QList<QNetworkCookie> accountCookies(Account *);
static QNetworkCookie findShibCookie(Account *, QList<QNetworkCookie> cookies = QList<QNetworkCookie>());
static QByteArray shibCookieName();
private Q_SLOTS:
void onShibbolethCookieReceived(const QNetworkCookie &);
void slotBrowserRejected();
void slotReadJobDone(QKeychain::Job *);
void slotReplyFinished(QNetworkReply *);
void slotUserFetched(const QString &user);
void slotFetchUser();
void slotFetchUserHelper();
Q_SIGNALS:
void newCookie(const QNetworkCookie &cookie);
private:
void storeShibCookie(const QNetworkCookie &cookie);
void removeShibCookie();
void addToCookieJar(const QNetworkCookie &cookie);
/// Reads data from keychain, progressing to slotReadJobDone
void fetchFromKeychainHelper();
QUrl _url;
QByteArray prepareCookieData() const;
bool _ready;
bool _stillValid;
QPointer<ShibbolethWebView> _browser;
QNetworkCookie _shibCookie;
QString _user;
bool _keychainMigration;
};
} // namespace OCC
#endif

View File

@ -34,8 +34,6 @@
#include "filesystem.h"
#include "owncloudgui.h"
#include "creds/credentialsfactory.h"
#include "creds/abstractcredentials.h"
#include "creds/dummycredentials.h"
namespace OCC {
@ -85,17 +83,6 @@ bool OwncloudSetupWizard::bringWizardToFrontIfVisible()
return false;
}
if (wiz->_ocWizard->currentId() == WizardCommon::Page_ShibbolethCreds) {
// Try to find if there is a browser open and raise that instead (Issue #6105)
const auto allWindow = qApp->topLevelWidgets();
auto it = std::find_if(allWindow.cbegin(), allWindow.cend(), [](QWidget *w)
{ return QLatin1String(w->metaObject()->className()) == QLatin1String("OCC::ShibbolethWebView"); });
if (it != allWindow.cend()) {
ownCloudGui::raiseDialog(*it);
return true;
}
}
ownCloudGui::raiseDialog(wiz->_ocWizard);
return true;
}
@ -103,7 +90,7 @@ bool OwncloudSetupWizard::bringWizardToFrontIfVisible()
void OwncloudSetupWizard::startWizard()
{
AccountPtr account = AccountManager::createAccount();
account->setCredentials(CredentialsFactory::create("dummy"));
account->setCredentials(new DummyCredentials);
account->setUrl(Theme::instance()->overrideServerUrl());
_ocWizard->setAccount(account);
_ocWizard->setOCUrl(account->url().toString());
@ -186,7 +173,7 @@ void OwncloudSetupWizard::slotFindServer()
AccountPtr account = _ocWizard->account();
// Set fake credentials before we check what credential it actually is.
account->setCredentials(CredentialsFactory::create("dummy"));
account->setCredentials(new DummyCredentials);
// Determining the actual server URL can be a multi-stage process
// 1. Check url/status.php with CheckServerJob
@ -409,7 +396,7 @@ void OwncloudSetupWizard::slotAuthError()
}
_ocWizard->show();
if (_ocWizard->currentId() == WizardCommon::Page_ShibbolethCreds || _ocWizard->currentId() == WizardCommon::Page_OAuthCreds) {
if (_ocWizard->currentId() == WizardCommon::Page_OAuthCreds) {
_ocWizard->back();
}
_ocWizard->displayError(errorMsg, _ocWizard->currentId() == WizardCommon::Page_ServerSetup && checkDowngradeAdvised(reply));

View File

@ -13,7 +13,7 @@
*/
#include "creds/abstractcredentials.h"
#include "creds/credentialsfactory.h"
#include "creds/dummycredentials.h"
#include "account.h"
#include "wizard/owncloudwizard.h"
@ -28,10 +28,8 @@ void AbstractCredentialsWizardPage::cleanupPage()
AccountPtr account = static_cast<OwncloudWizard *>(wizard())->account();
AbstractCredentials *creds = account->credentials();
if (creds) {
if (!creds->inherits("DummyCredentials")) {
account->setCredentials(CredentialsFactory::create("dummy"));
}
if (creds && !qobject_cast<DummyCredentials *>(creds)) {
account->setCredentials(new DummyCredentials);
}
}
}

View File

@ -23,7 +23,6 @@
#include "wizard/owncloudwizardcommon.h"
#include "wizard/owncloudwizard.h"
#include "creds/httpcredentialsgui.h"
#include "creds/credentialsfactory.h"
namespace OCC {
@ -67,7 +66,7 @@ void OwncloudOAuthCredsPage::initializePage()
{
OwncloudWizard *ocWizard = qobject_cast<OwncloudWizard *>(wizard());
Q_ASSERT(ocWizard);
ocWizard->account()->setCredentials(CredentialsFactory::create("http"));
ocWizard->account()->setCredentials(new HttpCredentialsGui);
_asyncAuth.reset(new OAuth(ocWizard->account().data(), this));
connect(_asyncAuth.data(), &OAuth::result, this, &OwncloudOAuthCredsPage::asyncAuthResult, Qt::QueuedConnection);
_asyncAuth->start();

View File

@ -206,8 +206,6 @@ int OwncloudSetupPage::nextId() const
return WizardCommon::Page_HttpCreds;
case DetermineAuthTypeJob::OAuth:
return WizardCommon::Page_OAuthCreds;
case DetermineAuthTypeJob::Shibboleth:
return WizardCommon::Page_ShibbolethCreds;
}
return WizardCommon::Page_HttpCreds;
}

View File

@ -1,112 +0,0 @@
/*
* Copyright (C) by Krzesimir Nowak <krzesimir@endocode.com>
*
* 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; either version 2 of the License, or
* (at your option) any later version.
*
* 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.
*/
#include <QVariant>
#include "wizard/owncloudshibbolethcredspage.h"
#include "theme.h"
#include "account.h"
#include "cookiejar.h"
#include "wizard/owncloudwizardcommon.h"
#include "wizard/owncloudwizard.h"
#include "creds/shibbolethcredentials.h"
#include "creds/shibboleth/shibbolethwebview.h"
namespace OCC {
OwncloudShibbolethCredsPage::OwncloudShibbolethCredsPage()
: AbstractCredentialsWizardPage()
, _browser(0)
, _afterInitialSetup(false)
{
}
void OwncloudShibbolethCredsPage::setupBrowser()
{
if (!_browser.isNull()) {
return;
}
OwncloudWizard *ocWizard = qobject_cast<OwncloudWizard *>(wizard());
AccountPtr account = ocWizard->account();
// we need to reset the cookie jar to drop temporary cookies (like the shib cookie)
// i.e. if someone presses "back"
QNetworkAccessManager *qnam = account->networkAccessManager();
CookieJar *jar = new CookieJar;
jar->restore(account->cookieJarPath());
// Implicitly deletes the old cookie jar, and reparents the jar
qnam->setCookieJar(jar);
_browser = new ShibbolethWebView(account);
connect(_browser.data(), &ShibbolethWebView::shibbolethCookieReceived,
this, &OwncloudShibbolethCredsPage::slotShibbolethCookieReceived, Qt::QueuedConnection);
connect(_browser.data(), &ShibbolethWebView::rejected,
this, &OwncloudShibbolethCredsPage::slotBrowserRejected);
_browser->move(ocWizard->x(), ocWizard->y());
_browser->show();
_browser->setFocus();
}
void OwncloudShibbolethCredsPage::setVisible(bool visible)
{
if (!_afterInitialSetup) {
QWizardPage::setVisible(visible);
return;
}
if (isVisible() == visible) {
return;
}
if (visible) {
setupBrowser();
wizard()->hide();
} else {
wizard()->show();
}
}
void OwncloudShibbolethCredsPage::initializePage()
{
_afterInitialSetup = true;
}
int OwncloudShibbolethCredsPage::nextId() const
{
return WizardCommon::Page_AdvancedSetup;
}
void OwncloudShibbolethCredsPage::setConnected()
{
wizard()->show();
}
AbstractCredentials *OwncloudShibbolethCredsPage::getCredentials() const
{
return new ShibbolethCredentials(_cookie);
}
void OwncloudShibbolethCredsPage::slotShibbolethCookieReceived(const QNetworkCookie &cookie)
{
_cookie = cookie;
emit connectToOCUrl(field("OCUrl").toString().simplified());
}
void OwncloudShibbolethCredsPage::slotBrowserRejected()
{
wizard()->back();
wizard()->show();
}
} // namespace OCC

View File

@ -1,67 +0,0 @@
/*
* Copyright (C) by Krzesimir Nowak <krzesimir@endocode.com>
*
* 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; either version 2 of the License, or
* (at your option) any later version.
*
* 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 MIRALL_OWNCLOUD_SHIBBOLETH_CREDS_PAGE_H
#define MIRALL_OWNCLOUD_SHIBBOLETH_CREDS_PAGE_H
#include <QList>
#include <QMap>
#include <QNetworkCookie>
#include <QUrl>
#include <QPointer>
#include "wizard/abstractcredswizardpage.h"
#include "accountfwd.h"
namespace OCC {
class ShibbolethWebView;
/**
* @brief The OwncloudShibbolethCredsPage class
* @ingroup gui
*/
class OwncloudShibbolethCredsPage : public AbstractCredentialsWizardPage
{
Q_OBJECT
public:
OwncloudShibbolethCredsPage();
AbstractCredentials *getCredentials() const Q_DECL_OVERRIDE;
void initializePage() Q_DECL_OVERRIDE;
int nextId() const Q_DECL_OVERRIDE;
void setConnected();
Q_SIGNALS:
void connectToOCUrl(const QString &);
public Q_SLOTS:
void setVisible(bool visible) Q_DECL_OVERRIDE;
private Q_SLOTS:
void slotShibbolethCookieReceived(const QNetworkCookie &);
void slotBrowserRejected();
private:
void setupBrowser();
QPointer<ShibbolethWebView> _browser;
bool _afterInitialSetup;
QNetworkCookie _cookie;
};
} // namespace OCC
#endif

View File

@ -22,9 +22,6 @@
#include "wizard/owncloudsetuppage.h"
#include "wizard/owncloudhttpcredspage.h"
#include "wizard/owncloudoauthcredspage.h"
#ifndef NO_SHIBBOLETH
#include "wizard/owncloudshibbolethcredspage.h"
#endif
#include "wizard/owncloudadvancedsetuppage.h"
#include "wizard/owncloudwizardresultpage.h"
@ -46,9 +43,6 @@ OwncloudWizard::OwncloudWizard(QWidget *parent)
, _setupPage(new OwncloudSetupPage(this))
, _httpCredsPage(new OwncloudHttpCredsPage(this))
, _browserCredsPage(new OwncloudOAuthCredsPage)
#ifndef NO_SHIBBOLETH
, _shibbolethCredsPage(new OwncloudShibbolethCredsPage)
#endif
, _advancedSetupPage(new OwncloudAdvancedSetupPage)
, _resultPage(new OwncloudWizardResultPage)
, _credentialsPage(0)
@ -58,9 +52,6 @@ OwncloudWizard::OwncloudWizard(QWidget *parent)
setPage(WizardCommon::Page_ServerSetup, _setupPage);
setPage(WizardCommon::Page_HttpCreds, _httpCredsPage);
setPage(WizardCommon::Page_OAuthCreds, _browserCredsPage);
#ifndef NO_SHIBBOLETH
setPage(WizardCommon::Page_ShibbolethCreds, _shibbolethCredsPage);
#endif
setPage(WizardCommon::Page_AdvancedSetup, _advancedSetupPage);
setPage(WizardCommon::Page_Result, _resultPage);
@ -74,9 +65,6 @@ OwncloudWizard::OwncloudWizard(QWidget *parent)
connect(_setupPage, &OwncloudSetupPage::determineAuthType, this, &OwncloudWizard::determineAuthType);
connect(_httpCredsPage, &OwncloudHttpCredsPage::connectToOCUrl, this, &OwncloudWizard::connectToOCUrl);
connect(_browserCredsPage, &OwncloudOAuthCredsPage::connectToOCUrl, this, &OwncloudWizard::connectToOCUrl);
#ifndef NO_SHIBBOLETH
connect(_shibbolethCredsPage, &OwncloudShibbolethCredsPage::connectToOCUrl, this, &OwncloudWizard::connectToOCUrl);
#endif
connect(_advancedSetupPage, &OwncloudAdvancedSetupPage::createLocalAndRemoteFolders,
this, &OwncloudWizard::createLocalAndRemoteFolders);
@ -158,12 +146,6 @@ void OwncloudWizard::successfulStep()
_browserCredsPage->setConnected();
break;
#ifndef NO_SHIBBOLETH
case WizardCommon::Page_ShibbolethCreds:
_shibbolethCredsPage->setConnected();
break;
#endif
case WizardCommon::Page_AdvancedSetup:
_advancedSetupPage->directoriesCreated();
break;
@ -180,12 +162,7 @@ void OwncloudWizard::successfulStep()
void OwncloudWizard::setAuthType(DetermineAuthTypeJob::AuthType type)
{
_setupPage->setAuthType(type);
#ifndef NO_SHIBBOLETH
if (type == DetermineAuthTypeJob::Shibboleth) {
_credentialsPage = _shibbolethCredsPage;
} else
#endif
if (type == DetermineAuthTypeJob::OAuth) {
if (type == DetermineAuthTypeJob::OAuth) {
_credentialsPage = _browserCredsPage;
} else { // try Basic auth even for "Unknown"
_credentialsPage = _httpCredsPage;

View File

@ -32,9 +32,6 @@ Q_DECLARE_LOGGING_CATEGORY(lcWizard)
class OwncloudSetupPage;
class OwncloudHttpCredsPage;
class OwncloudOAuthCredsPage;
#ifndef NO_SHIBBOLETH
class OwncloudShibbolethCredsPage;
#endif
class OwncloudAdvancedSetupPage;
class OwncloudWizardResultPage;
class AbstractCredentials;
@ -105,9 +102,6 @@ private:
OwncloudSetupPage *_setupPage;
OwncloudHttpCredsPage *_httpCredsPage;
OwncloudOAuthCredsPage *_browserCredsPage;
#ifndef NO_SHIBBOLETH
OwncloudShibbolethCredsPage *_shibbolethCredsPage;
#endif
OwncloudAdvancedSetupPage *_advancedSetupPage;
OwncloudWizardResultPage *_resultPage;
AbstractCredentialsWizardPage *_credentialsPage;

View File

@ -36,7 +36,6 @@ namespace WizardCommon {
enum Pages {
Page_ServerSetup,
Page_HttpCreds,
Page_ShibbolethCreds,
Page_OAuthCreds,
Page_AdvancedSetup,
Page_Result

View File

@ -852,58 +852,23 @@ void DetermineAuthTypeJob::start()
// Don't send cookies, we can't determine the auth type if we're logged in
req.setAttribute(QNetworkRequest::CookieLoadControlAttribute, QNetworkRequest::Manual);
// Start two parallel requests, one determines whether it's a shib server
// and the other checks the HTTP auth method.
auto get = _account->sendRequest("GET", _account->davUrl(), req);
auto propfind = _account->sendRequest("PROPFIND", _account->davUrl(), req);
get->setTimeout(30 * 1000);
propfind->setTimeout(30 * 1000);
get->setIgnoreCredentialFailure(true);
propfind->setIgnoreCredentialFailure(true);
connect(get, &AbstractNetworkJob::redirected, this, [this, get](QNetworkReply *, const QUrl &target, int) {
#ifndef NO_SHIBBOLETH
QRegExp shibbolethyWords("SAML|wayf");
shibbolethyWords.setCaseSensitivity(Qt::CaseInsensitive);
if (target.toString().contains(shibbolethyWords)) {
_resultGet = Shibboleth;
get->setFollowRedirects(false);
}
#else
Q_UNUSED(this)
Q_UNUSED(get)
Q_UNUSED(target)
#endif
});
connect(get, &SimpleNetworkJob::finishedSignal, this, [this]() {
_getDone = true;
checkBothDone();
});
connect(propfind, &SimpleNetworkJob::finishedSignal, this, [this](QNetworkReply *reply) {
auto authChallenge = reply->rawHeader("WWW-Authenticate").toLower();
auto result = Basic;
if (authChallenge.contains("bearer ")) {
_resultPropfind = OAuth;
result = OAuth;
} else if (authChallenge.isEmpty()) {
qCWarning(lcDetermineAuthTypeJob) << "Did not receive WWW-Authenticate reply to auth-test PROPFIND";
}
_propfindDone = true;
checkBothDone();
qCInfo(lcDetermineAuthTypeJob) << "Auth type for" << _account->davUrl() << "is" << result;
emit this->authType(result);
this->deleteLater();
});
}
void DetermineAuthTypeJob::checkBothDone()
{
if (!_getDone || !_propfindDone)
return;
auto result = _resultPropfind;
// OAuth > Shib > Basic
if (_resultGet == Shibboleth && result != OAuth)
result = Shibboleth;
qCInfo(lcDetermineAuthTypeJob) << "Auth type for" << _account->davUrl() << "is" << result;
emit authType(result);
deleteLater();
}
SimpleNetworkJob::SimpleNetworkJob(AccountPtr account, QObject *parent)
: AbstractNetworkJob(account, QString(), parent)
{

View File

@ -373,7 +373,6 @@ public:
enum AuthType {
Basic, // also the catch-all fallback for backwards compatibility reasons
OAuth,
Shibboleth
};
explicit DetermineAuthTypeJob(AccountPtr account, QObject *parent = 0);
@ -382,13 +381,7 @@ signals:
void authType(AuthType);
private:
void checkBothDone();
AccountPtr _account;
AuthType _resultGet = Basic;
AuthType _resultPropfind = Basic;
bool _getDone = false;
bool _propfindDone = false;
};
/**