| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450 |
- /*
- * Copyright (C) by Daniel Molkentin <danimo@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.
- */
- #ifndef SERVERCONNECTION_H
- #define SERVERCONNECTION_H
- #include <QByteArray>
- #include <QUrl>
- #include <QNetworkCookie>
- #include <QNetworkRequest>
- #include <QSslSocket>
- #include <QSslCertificate>
- #include <QSslConfiguration>
- #include <QSslCipher>
- #include <QSslError>
- #include <QSharedPointer>
- #ifndef TOKEN_AUTH_ONLY
- #include <QPixmap>
- #endif
- #include "common/utility.h"
- #include <memory>
- #include "capabilities.h"
- #include "clientsideencryption.h"
- #include "syncfileitem.h"
- class QSettings;
- class QNetworkReply;
- class QUrl;
- class QNetworkAccessManager;
- namespace QKeychain {
- class Job;
- class WritePasswordJob;
- class ReadPasswordJob;
- }
- namespace OCC {
- class AbstractCredentials;
- class Account;
- using AccountPtr = QSharedPointer<Account>;
- class AccessManager;
- class SimpleNetworkJob;
- class PushNotifications;
- class UserStatusConnector;
- class SyncJournalDb;
- /**
- * @brief Reimplement this to handle SSL errors from libsync
- * @ingroup libsync
- */
- class AbstractSslErrorHandler
- {
- public:
- virtual ~AbstractSslErrorHandler() = default;
- virtual bool handleErrors(QList<QSslError>, const QSslConfiguration &conf, QList<QSslCertificate> *, AccountPtr) = 0;
- };
- /**
- * @brief The Account class represents an account on an ownCloud Server
- * @ingroup libsync
- *
- * The Account has a name and url. It also has information about credentials,
- * SSL errors and certificates.
- */
- class OWNCLOUDSYNC_EXPORT Account : public QObject
- {
- Q_OBJECT
- Q_PROPERTY(QString id MEMBER _id)
- Q_PROPERTY(QString davUser MEMBER _davUser)
- Q_PROPERTY(QString displayName MEMBER _displayName)
- Q_PROPERTY(QString prettyName READ prettyName NOTIFY prettyNameChanged)
- Q_PROPERTY(QUrl url MEMBER _url)
- Q_PROPERTY(bool e2eEncryptionKeysGenerationAllowed MEMBER _e2eEncryptionKeysGenerationAllowed)
- Q_PROPERTY(bool askUserForMnemonic READ askUserForMnemonic WRITE setAskUserForMnemonic NOTIFY askUserForMnemonicChanged)
- public:
- static AccountPtr create();
- ~Account() override;
- AccountPtr sharedFromThis();
- [[nodiscard]] AccountPtr sharedFromThis() const;
- /**
- * The user that can be used in dav url.
- *
- * This can very well be different frome the login user that's
- * stored in credentials()->user().
- */
- [[nodiscard]] QString davUser() const;
- void setDavUser(const QString &newDavUser);
- [[nodiscard]] QString davDisplayName() const;
- void setDavDisplayName(const QString &newDisplayName);
- #ifndef TOKEN_AUTH_ONLY
- [[nodiscard]] QImage avatar() const;
- void setAvatar(const QImage &img);
- #endif
- /// The name of the account as shown in the toolbar
- [[nodiscard]] QString displayName() const;
- /// User id in a form 'user@example.de, optionally port is added (if it is not 80 or 443)
- [[nodiscard]] QString userIdAtHostWithPort() const;
- /// The name of the account that is displayed as nicely as possible,
- /// e.g. the actual name of the user (John Doe). If this cannot be
- /// provided, defaults to davUser (e.g. johndoe)
- [[nodiscard]] QString prettyName() const;
- [[nodiscard]] QColor accentColor() const;
- [[nodiscard]] QColor headerColor() const;
- [[nodiscard]] QColor headerTextColor() const;
- /// The internal id of the account.
- [[nodiscard]] QString id() const;
- /** Server url of the account */
- void setUrl(const QUrl &url);
- [[nodiscard]] QUrl url() const { return _url; }
- /// Adjusts _userVisibleUrl once the host to use is discovered.
- void setUserVisibleHost(const QString &host);
- /**
- * @brief The possibly themed dav path for the account. It has
- * a trailing slash.
- * @returns the (themeable) dav path for the account.
- */
- [[nodiscard]] QString davPath() const;
- /**
- * @brief The possibly themed dav path root for the account. It has
- * no trailing slash.
- * @returns the (themeable) dav path for the account.
- */
- [[nodiscard]] QString davPathRoot() const;
- /** Returns webdav entry URL, based on url() */
- [[nodiscard]] QUrl davUrl() const;
- /** Returns the legacy permalink url for a file.
- *
- * This uses the old way of manually building the url. New code should
- * use the "privatelink" property accessible via PROPFIND.
- */
- [[nodiscard]] QUrl deprecatedPrivateLinkUrl(const QByteArray &numericFileId) const;
- /** Holds the accounts credentials */
- [[nodiscard]] AbstractCredentials *credentials() const;
- void setCredentials(AbstractCredentials *cred);
- /** Create a network request on the account's QNAM.
- *
- * Network requests in AbstractNetworkJobs are created through
- * this function. Other places should prefer to use jobs or
- * sendRequest().
- */
- QNetworkReply *sendRawRequest(const QByteArray &verb,
- const QUrl &url,
- QNetworkRequest req = QNetworkRequest(),
- QIODevice *data = nullptr);
- QNetworkReply *sendRawRequest(const QByteArray &verb,
- const QUrl &url, QNetworkRequest req, const QByteArray &data);
- QNetworkReply *sendRawRequest(const QByteArray &verb,
- const QUrl &url, QNetworkRequest req, QHttpMultiPart *data);
- /** Create and start network job for a simple one-off request.
- *
- * More complicated requests typically create their own job types.
- */
- SimpleNetworkJob *sendRequest(const QByteArray &verb,
- const QUrl &url,
- QNetworkRequest req = QNetworkRequest(),
- QIODevice *data = nullptr);
- /** The ssl configuration during the first connection */
- QSslConfiguration getOrCreateSslConfig();
- [[nodiscard]] QSslConfiguration sslConfiguration() const { return _sslConfiguration; }
- void setSslConfiguration(const QSslConfiguration &config);
- // Because of bugs in Qt, we use this to store info needed for the SSL Button
- QSslCipher _sessionCipher;
- QByteArray _sessionTicket;
- QList<QSslCertificate> _peerCertificateChain;
- /** The certificates of the account */
- [[nodiscard]] QList<QSslCertificate> approvedCerts() const { return _approvedCerts; }
- void setApprovedCerts(const QList<QSslCertificate> certs);
- void addApprovedCerts(const QList<QSslCertificate> certs);
- // Usually when a user explicitly rejects a certificate we don't
- // ask again. After this call, a dialog will again be shown when
- // the next unknown certificate is encountered.
- void resetRejectedCertificates();
- // pluggable handler
- void setSslErrorHandler(AbstractSslErrorHandler *handler);
- // To be called by credentials only, for storing username and the like
- [[nodiscard]] QVariant credentialSetting(const QString &key) const;
- void setCredentialSetting(const QString &key, const QVariant &value);
- /** Assign a client certificate */
- void setCertificate(const QByteArray certficate = QByteArray(), const QString privateKey = QString());
- /** Access the server capabilities */
- [[nodiscard]] const Capabilities &capabilities() const;
- void setCapabilities(const QVariantMap &caps);
- /** Access the server version
- *
- * For servers >= 10.0.0, this can be the empty string until capabilities
- * have been received.
- */
- [[nodiscard]] QString serverVersion() const;
- /** Server version for easy comparison.
- *
- * Example: serverVersionInt() >= makeServerVersion(11, 2, 3)
- *
- * Will be 0 if the version is not available yet.
- */
- [[nodiscard]] int serverVersionInt() const;
- static constexpr int makeServerVersion(const int majorVersion, const int minorVersion, const int patchVersion) {
- return (majorVersion << 16) + (minorVersion << 8) + patchVersion;
- };
- void setServerVersion(const QString &version);
- /** Whether the server is too old.
- *
- * Not supporting server versions is a gradual process. There's a hard
- * compatibility limit (see ConnectionValidator) that forbids connecting
- * to extremely old servers. And there's a weak "untested, not
- * recommended, potentially dangerous" limit, that users might want
- * to go beyond.
- *
- * This function returns true if the server is beyond the weak limit.
- */
- [[nodiscard]] bool serverVersionUnsupported() const;
- [[nodiscard]] bool secureFileDropSupported() const;
- [[nodiscard]] bool isUsernamePrefillSupported() const;
- [[nodiscard]] bool isChecksumRecalculateRequestSupported() const;
- [[nodiscard]] int checksumRecalculateServerVersionMinSupportedMajor() const;
- /** True when the server connection is using HTTP2 */
- bool isHttp2Supported() { return _http2Supported; }
- void setHttp2Supported(bool value) { _http2Supported = value; }
- void clearCookieJar();
- void lendCookieJarTo(QNetworkAccessManager *guest);
- QString cookieJarPath();
- void resetNetworkAccessManager();
- QNetworkAccessManager *networkAccessManager();
- QSharedPointer<QNetworkAccessManager> sharedNetworkAccessManager();
- /// Called by network jobs on credential errors, emits invalidCredentials()
- void handleInvalidCredentials();
- ClientSideEncryption* e2e();
- /// Used in RemoteWipe
- void retrieveAppPassword();
- void writeAppPasswordOnce(QString appPassword);
- void deleteAppPassword();
- void deleteAppToken();
- /// Direct Editing
- // Check for the directEditing capability
- void fetchDirectEditors(const QUrl &directEditingURL, const QString &directEditingETag);
- void setupUserStatusConnector();
- void trySetupPushNotifications();
- [[nodiscard]] PushNotifications *pushNotifications() const;
- void setPushNotificationsReconnectInterval(int interval);
- [[nodiscard]] std::shared_ptr<UserStatusConnector> userStatusConnector() const;
- void setLockFileState(const QString &serverRelativePath,
- SyncJournalDb * const journal,
- const SyncFileItem::LockStatus lockStatus);
- SyncFileItem::LockStatus fileLockStatus(SyncJournalDb * const journal,
- const QString &folderRelativePath) const;
- bool fileCanBeUnlocked(SyncJournalDb * const journal, const QString &folderRelativePath) const;
- void setTrustCertificates(bool trustCertificates);
- [[nodiscard]] bool trustCertificates() const;
- void setE2eEncryptionKeysGenerationAllowed(bool allowed);
- [[nodiscard]] bool e2eEncryptionKeysGenerationAllowed() const;
- [[nodiscard]] bool askUserForMnemonic() const;
- public slots:
- /// Used when forgetting credentials
- void clearQNAMCache();
- void slotHandleSslErrors(QNetworkReply *, QList<QSslError>);
- void setAskUserForMnemonic(const bool ask);
- signals:
- /// Emitted whenever there's network activity
- void propagatorNetworkActivity();
- /// Triggered by handleInvalidCredentials()
- void invalidCredentials();
- void credentialsFetched(OCC::AbstractCredentials *credentials);
- void credentialsAsked(OCC::AbstractCredentials *credentials);
- /// Forwards from QNetworkAccessManager::proxyAuthenticationRequired().
- void proxyAuthenticationRequired(const QNetworkProxy &, QAuthenticator *);
- // e.g. when the approved SSL certificates changed
- void wantsAccountSaved(OCC::Account *acc);
- void serverVersionChanged(OCC::Account *account, const QString &newVersion, const QString &oldVersion);
- void accountChangedAvatar();
- void accountChangedDisplayName();
- void prettyNameChanged();
- void askUserForMnemonicChanged();
- /// Used in RemoteWipe
- void appPasswordRetrieved(QString);
- void pushNotificationsReady(OCC::Account *account);
- void pushNotificationsDisabled(OCC::Account *account);
- void userStatusChanged();
- void serverUserStatusChanged();
- void capabilitiesChanged();
- void lockFileSuccess();
- void lockFileError(const QString&);
- protected Q_SLOTS:
- void slotCredentialsFetched();
- void slotCredentialsAsked();
- void slotDirectEditingRecieved(const QJsonDocument &json);
- private:
- Account(QObject *parent = nullptr);
- void setSharedThis(AccountPtr sharedThis);
- static QString davPathBase();
- bool _trustCertificates = false;
- bool _e2eEncryptionKeysGenerationAllowed = false;
- bool _e2eAskUserForMnemonic = false;
- QWeakPointer<Account> _sharedThis;
- QString _id;
- QString _davUser;
- QString _displayName;
- QTimer _pushNotificationsReconnectTimer;
- #ifndef TOKEN_AUTH_ONLY
- QImage _avatarImg;
- #endif
- QMap<QString, QVariant> _settingsMap;
- QUrl _url;
- /** If url to use for any user-visible urls.
- *
- * If the server configures overwritehost this can be different from
- * the connection url in _url. We retrieve the visible host through
- * the ocs/v1.php/config endpoint in ConnectionValidator.
- */
- QUrl _userVisibleUrl;
- QList<QSslCertificate> _approvedCerts;
- QSslConfiguration _sslConfiguration;
- Capabilities _capabilities;
- QString _serverVersion;
- QScopedPointer<AbstractSslErrorHandler> _sslErrorHandler;
- QSharedPointer<QNetworkAccessManager> _am;
- QScopedPointer<AbstractCredentials> _credentials;
- bool _http2Supported = false;
- /// Certificates that were explicitly rejected by the user
- QList<QSslCertificate> _rejectedCertificates;
- static QString _configFileName;
- ClientSideEncryption _e2e;
- /// Used in RemoteWipe
- bool _wroteAppPassword = false;
- friend class AccountManager;
- // Direct Editing
- QString _lastDirectEditingETag;
- PushNotifications *_pushNotifications = nullptr;
- std::shared_ptr<UserStatusConnector> _userStatusConnector;
- /* IMPORTANT - remove later - FIXME MS@2019-12-07 -->
- * TODO: For "Log out" & "Remove account": Remove client CA certs and KEY!
- *
- * Disabled as long as selecting another cert is not supported by the UI.
- *
- * Being able to specify a new certificate is important anyway: expiry etc.
- *
- * We introduce this dirty hack here, to allow deleting them upon Remote Wipe.
- */
- public:
- void setRemoteWipeRequested_HACK() { _isRemoteWipeRequested_HACK = true; }
- bool isRemoteWipeRequested_HACK() { return _isRemoteWipeRequested_HACK; }
- private:
- bool _isRemoteWipeRequested_HACK = false;
- // <-- FIXME MS@2019-12-07
- };
- }
- Q_DECLARE_METATYPE(OCC::AccountPtr)
- Q_DECLARE_METATYPE(OCC::Account *)
- #endif //SERVERCONNECTION_H
|