diff options
author | Gatis Paeglis <gatis.paeglis@qt.io> | 2016-10-20 16:25:07 +0200 |
---|---|---|
committer | Gatis Paeglis <gatis.paeglis@qt.io> | 2016-11-01 10:16:04 +0000 |
commit | 2f96b99e969ea7d4a183d413712f16cc0fe0f979 (patch) | |
tree | 9189b267fa04569ee9f1750bed97042616078858 /src | |
parent | 833fd98107ae8d1761a41244be61c079a38d1461 (diff) |
Introduce QOtaRepositoryConfig class
for configuring access to remote ostree repositories.
Change-Id: Ic44e9457daf2c7e2975ab81823a59357791a6fab
Reviewed-by: Topi Reiniƶ <topi.reinio@qt.io>
Reviewed-by: Gatis Paeglis <gatis.paeglis@qt.io>
Diffstat (limited to 'src')
-rw-r--r-- | src/imports/pluginmain.cpp | 129 | ||||
-rw-r--r-- | src/lib/lib.pro | 7 | ||||
-rw-r--r-- | src/lib/qotaclient.cpp | 164 | ||||
-rw-r--r-- | src/lib/qotaclient.h | 10 | ||||
-rw-r--r-- | src/lib/qotaclient_p.h | 6 | ||||
-rw-r--r-- | src/lib/qotaclientasync.cpp | 10 | ||||
-rw-r--r-- | src/lib/qotaclientasync_p.h | 2 | ||||
-rw-r--r-- | src/lib/qotarepositoryconfig.cpp | 274 | ||||
-rw-r--r-- | src/lib/qotarepositoryconfig.h | 84 | ||||
-rw-r--r-- | src/lib/qotarepositoryconfig_p.h | 57 |
10 files changed, 698 insertions, 45 deletions
diff --git a/src/imports/pluginmain.cpp b/src/imports/pluginmain.cpp index d7dd28a..69f6ef5 100644 --- a/src/imports/pluginmain.cpp +++ b/src/imports/pluginmain.cpp @@ -27,6 +27,7 @@ ** ****************************************************************************/ #include <QtOTAUpdate/QOTAClient> +#include <QtOTAUpdate/QOtaRepositoryConfig> #include <QtQml> QT_BEGIN_NAMESPACE @@ -312,6 +313,133 @@ QT_BEGIN_NAMESPACE object is not ready for use until this signal is received. */ +/*! + \qmlmethod bool OTAClient::setRepositoryConfig(OtaRepositoryConfig config) + + \include qotaclient.cpp set-repository-config + + The \a config argument is documented in OtaRepositoryConfig. + + \sa repositoryConfigChanged +*/ + +/*! + \qmlmethod OtaRepositoryConfig OTAClient::repositoryConfig() + + Returns a configuration object for the repository or \c null if the + configuration file does not exist or could not be read. + + \sa setRepositoryConfig(), removeRepositoryConfig() +*/ + +/*! + \qmlmethod bool OTAClient::removeRepositoryConfig() + + \include qotaclient.cpp remove-repository-config + + \sa repositoryConfigChanged +*/ + +/*! + \qmlsignal OTAClient::repositoryConfigChanged(OtaRepositoryConfig config) + + This signal is emitted when the configuration file was successfully updated + (\a repository holds the new configuration) or removed (\a repository + holds the \c null value). +*/ + +/*! + \inqmlmodule QtOTAUpdate + \qmltype OtaRepositoryConfig + \instantiates QOtaRepositoryConfig + \brief Used to configure the OSTree repository. + + OtaRepositoryConfig + \include qotarepositoryconfig.cpp repository-config-description +*/ + +/*! + \qmlsignal OtaRepositoryConfig::urlChanged() + + This signal is emitted when the value of url changes. +*/ + +/*! + \qmlsignal OtaRepositoryConfig::gpgVerifyChanged() + + This signal is emitted when the value of gpgVerify changes. +*/ + +/*! + \qmlsignal OtaRepositoryConfig::tlsClientCertPathChanged() + + This signal is emitted when the value of tlsClientCertPath changes. +*/ + +/*! + \qmlsignal OtaRepositoryConfig::tlsClientKeyPathChanged() + + This signal is emitted when the value of tlsClientKeyPath changes. +*/ + +/*! + \qmlsignal OtaRepositoryConfig::tlsPermissiveChanged() + + This signal is emitted when the value of tlsPermissive changes. +*/ + +/*! + \qmlsignal OtaRepositoryConfig::tlsCaPathChanged() + + This signal is emitted when the value of tlsCaPath changes. +*/ + +/*! + \qmlproperty bool OtaRepositoryConfig::gpgVerify + + Holds a bool indicating whether or not OSTree will require commits + to be signed by a known GPG key. + + Default is \c false. +*/ + +/*! + \qmlproperty bool OtaRepositoryConfig::tlsPermissive + + Holds a bool indicating whether to check the server's TLS certificates + against the system's certificate store. + + Default is \c false. +*/ + +/*! + \qmlproperty string OtaRepositoryConfig::url + + This property holds a URL for accessing remote OSTree repository. + The supported schemes at the moment are \c http and \c https. +*/ + +/*! + \qmlproperty string OtaRepositoryConfig::tlsClientCertPath + + This property holds a path to a file for the client-side certificate, + to present when making requests to the remote repository. +*/ + +/*! + \qmlproperty string OtaRepositoryConfig::tlsClientKeyPath + + This property holds a path to a file containing the client-side certificate key, + to present when making requests to the remote repository. +*/ + +/*! + \qmlproperty string OtaRepositoryConfig::tlsCaPath + + This property holds a path to a file containing trusted anchors instead of + the system's CA database. +*/ + static QObject *otaClientSingleton(QQmlEngine *qmlEngine, QJSEngine *jsEngine) { Q_UNUSED(qmlEngine); @@ -329,6 +457,7 @@ public: Q_ASSERT(QLatin1String(uri) == QLatin1String("QtOTAUpdate")); qmlRegisterSingletonType<QOTAClient>(uri, 1, 0, "OTAClient", otaClientSingleton); + qmlRegisterType<QOtaRepositoryConfig>(uri, 1, 0, "OtaRepositoryConfig"); } }; diff --git a/src/lib/lib.pro b/src/lib/lib.pro index 9ded106..c4f67c4 100644 --- a/src/lib/lib.pro +++ b/src/lib/lib.pro @@ -16,8 +16,11 @@ LIBS += -lostree-1 -lgio-2.0 -lglib-2.0 -lgobject-2.0 HEADERS += \ qotaclient.h \ qotaclientasync_p.h \ - qotaclient_p.h + qotaclient_p.h \ + qotarepositoryconfig.h \ + qotarepositoryconfig_p.h SOURCES += \ qotaclient.cpp \ - qotaclientasync.cpp + qotaclientasync.cpp \ + qotarepositoryconfig.cpp diff --git a/src/lib/qotaclient.cpp b/src/lib/qotaclient.cpp index 7654cc3..b28237f 100644 --- a/src/lib/qotaclient.cpp +++ b/src/lib/qotaclient.cpp @@ -28,13 +28,19 @@ ****************************************************************************/ #include "qotaclientasync_p.h" #include "qotaclient_p.h" +#include "qotarepositoryconfig_p.h" +#include "qotarepositoryconfig.h" #include "qotaclient.h" #include <QtCore/QFile> #include <QtCore/QJsonObject> +#include <QtCore/QDir> +#include <QtCore/QThread> Q_LOGGING_CATEGORY(qota, "b2qt.ota") +const QString repoConfigPath(QStringLiteral("/etc/ostree/remotes.d/qt-os.conf")); + QT_BEGIN_NAMESPACE QOTAClientPrivate::QOTAClientPrivate(QOTAClient *client) : @@ -264,41 +270,15 @@ QString QOTAClientPrivate::revision(QueryTarget target) const QOTAClient //! [client-description] provides an API to execute Over-the-Air update tasks. Offline - operations include querying the booted and rollback system version details, + operations include querying the booted and rollback system version details, and atomically performing rollbacks. Online operations include fetching a new system version from a remote server, and atomically performing system - updates. - - Using this API is safe and won't leave the system in an inconsistent state, - even if the power fails half-way through. - - \b {Remote Configuration} + updates. Using this API is safe and won't leave the system in an inconsistent + state, even if the power fails half-way through. A remote needs to be configured for a device to be able to locate a server - that is hosting an OTA update. A Tech Preview release does not provide Qt - API to configure remotes. To configure a remote, it is necessary to use the - ostree command line tool. Examples for remote configurations: - - No Security: - \badcode - ostree remote add --no-gpg-verify qt-os http://${SERVER_ADDRESS}:${PORT}/ostree-repo linux/qt - \endcode - - Using GPG Signing: - \badcode - ostree remote add --set=gpg-verify=true qt-os http://${SERVER_ADDRESS}:${PORT}/ostree-repo linux/qt - \endcode - - Using TLS Authentication: - \badcode - ostree remote add \ - --tls-client-cert-path /path/client.crt \ - --tls-client-key-path /path/client.key \ - --tls-ca-path /trusted/server.crt qt-os https://${SERVER_ADDRESS}:${PORT}/ostree-repo linux/qt - \endcode - - Above, \c ${SERVER_ADDRESS} is the server where you have exported the - OSTree repository, and \c ${PORT} is the port number. + that is hosting an OTA update, see setRepositoryConfig(). + //! [client-description] */ @@ -384,7 +364,16 @@ QString QOTAClientPrivate::revision(QueryTarget target) const object is not ready for use until this signal is received. */ -QOTAClient::QOTAClient(QObject *parent) : QObject(parent), +/*! + \fn void QOTAClient::repositoryConfigChanged(QOtaRepositoryConfig *repository) + + This signal is emitted when the configuration file was updated (\a repository + holds a pointer to the new configuration) or removed (\a repository holds the + \c nullptr value). +*/ + +QOTAClient::QOTAClient(QObject *parent) : + QObject(parent), d_ptr(new QOTAClientPrivate(this)) { Q_D(QOTAClient); @@ -468,6 +457,117 @@ bool QOTAClient::rollback() const } /*! +//! [remove-repository-config] + Remove a configuration file for the repository. + + The repository configuration is stored on a file system in \c {/etc/ostree/remotes.d/\*.conf} + + If the configuration file does not exist, this function returns \c true. + If the configuration file exists, this function returns \c true if the file + is removed successfully; otherwise returns \c false. +//! [remove-repository-config] + + \sa setRepositoryConfig(), repositoryConfigChanged +*/ +bool QOTAClient::removeRepositoryConfig() +{ + Q_D(QOTAClient); + if (!otaEnabled() || !QDir().exists(repoConfigPath)) + return true; + + bool removed = QDir().remove(repoConfigPath); + if (removed) + emit repositoryConfigChanged(nullptr); + else + d->errorOccurred(QStringLiteral("Failed to remove repository configuration")); + + return removed; +} + +/*! +//! [set-repository-config] + Change the configuration for the repository. The repository configuration + is stored on a file system in \c {/etc/ostree/remotes.d/\*.conf} + + Returns \c true if the configuration file is changed successfully; + otherwise returns \c false. +//! [set-repository-config] + + The \a config argument is documented in QOtaRepositoryConfig. + + \sa removeRepositoryConfig(), repositoryConfigChanged +*/ +bool QOTAClient::setRepositoryConfig(QOtaRepositoryConfig *config) +{ + Q_D(QOTAClient); + if (!d->isReady()) + return false; + + if (QDir().exists(repoConfigPath)) { + d->errorOccurred(QStringLiteral("Repository configuration already exists")); + return false; + } + // URL + if (config->url().isEmpty()) { + d->errorOccurred(QStringLiteral("Repository URL can not be empty")); + return false; + } + // TLS client certs + int tlsClientArgs = 0; + if (!config->tlsClientCertPath().isEmpty()) + ++tlsClientArgs; + if (!config->tlsClientKeyPath().isEmpty()) + ++tlsClientArgs; + if (tlsClientArgs == 1) { + d->errorOccurred(QStringLiteral("Both tlsClientCertPath and tlsClientKeyPath are required" + " for TLS client authentication functionality")); + return false; + } + + // FORMAT: ostree remote add [OPTION...] NAME URL [BRANCH...] + QString cmd(QStringLiteral("ostree remote add")); + // GPG + cmd.append(QStringLiteral(" --set=gpg-verify=")); + config->gpgVerify() ? cmd.append(QStringLiteral("true")) : cmd.append(QStringLiteral("false")); + // TLS client authentication + if (!config->tlsClientCertPath().isEmpty()) { + cmd.append(QStringLiteral(" --set=tls-client-cert-path=")); + cmd.append(config->tlsClientCertPath()); + cmd.append(QStringLiteral(" --set=tls-client-key-path=")); + cmd.append(config->tlsClientKeyPath()); + } + // TLS server authentication + cmd.append(QStringLiteral(" --set=tls-permissive=")); + config->tlsPermissive() ? cmd.append(QStringLiteral("true")) : cmd.append(QStringLiteral("false")); + if (!config->tlsCaPath().isEmpty()) { + cmd.append(QStringLiteral(" --set=tls-ca-path=")); + cmd.append(config->tlsCaPath()); + } + // NAME URL [BRANCH...] + cmd.append(QString(QStringLiteral(" qt-os %1 linux/qt")).arg(config->url())); + + bool ok = true; + d->m_otaAsync->ostree(cmd, &ok); + if (ok) + emit repositoryConfigChanged(config); + + return ok; +} + +/*! + Returns a configuration object for the repository or \c nullptr if the + configuration file does not exist or could not be read. + + \sa setRepositoryConfig(), removeRepositoryConfig() +*/ +QOtaRepositoryConfig *QOTAClient::repositoryConfig() const +{ + if (!otaEnabled()) + return nullptr; + return QOtaRepositoryConfig().d_func()->repositoryConfigFromFile(repoConfigPath); +} + +/*! \property QOTAClient::otaEnabled \brief whether a device supports OTA updates. */ diff --git a/src/lib/qotaclient.h b/src/lib/qotaclient.h index cc413e3..7944561 100644 --- a/src/lib/qotaclient.h +++ b/src/lib/qotaclient.h @@ -36,6 +36,7 @@ QT_BEGIN_NAMESPACE class QOTAClientPrivate; +class QOtaRepositoryConfig; class Q_DECL_EXPORT QOTAClient : public QObject { @@ -60,8 +61,8 @@ class Q_DECL_EXPORT QOTAClient : public QObject Q_PROPERTY(QString rollbackRevision READ rollbackRevision NOTIFY rollbackInfoChanged) Q_PROPERTY(QByteArray rollbackInfo READ rollbackInfo NOTIFY rollbackInfoChanged) public: - explicit QOTAClient(QObject *parent = Q_NULLPTR); - ~QOTAClient(); + explicit QOTAClient(QObject *parent = nullptr); + virtual ~QOTAClient(); bool updateAvailable() const; bool rollbackAvailable() const; @@ -75,6 +76,10 @@ public: Q_INVOKABLE bool update() const; Q_INVOKABLE bool rollback() const; + Q_INVOKABLE bool setRepositoryConfig(QOtaRepositoryConfig *config); + Q_INVOKABLE QOtaRepositoryConfig *repositoryConfig() const; + Q_INVOKABLE bool removeRepositoryConfig(); + QString bootedVersion() const; QString bootedDescription() const; QString bootedRevision() const; @@ -98,6 +103,7 @@ Q_SIGNALS: void restartRequiredChanged(bool required); void statusStringChanged(const QString &status); void errorOccurred(const QString &error); + void repositoryConfigChanged(QOtaRepositoryConfig *config); void initializationFinished(); void fetchRemoteInfoFinished(bool success); diff --git a/src/lib/qotaclient_p.h b/src/lib/qotaclient_p.h index 064ea5b..61670bf 100644 --- a/src/lib/qotaclient_p.h +++ b/src/lib/qotaclient_p.h @@ -29,18 +29,18 @@ #ifndef QOTACLIENT_P_H #define QOTACLIENT_P_H -#include "qotaclient.h" - #include <QtCore/QObject> #include <QtCore/QLoggingCategory> #include <QtCore/QByteArray> -#include <QtCore/QThread> #include <QtCore/QScopedPointer> #include <QtCore/QJsonDocument> Q_DECLARE_LOGGING_CATEGORY(qota) +class QThread; class QOTAClientAsync; +class QOtaRepositoryConfig; +class QOTAClient; class QOTAClientPrivate : public QObject { diff --git a/src/lib/qotaclientasync.cpp b/src/lib/qotaclientasync.cpp index ee7ddc8..f638e19 100644 --- a/src/lib/qotaclientasync.cpp +++ b/src/lib/qotaclientasync.cpp @@ -57,7 +57,7 @@ static void parseErrorString(QString *error) error->remove(0, qstrlen("error: ")); if (error->startsWith(QLatin1String("Remote")) && error->endsWith(QLatin1String("not found"))) - *error = QLatin1String("Remote configuration not found."); + *error = QLatin1String("Repository configuration not found"); } QString QOTAClientAsync::ostree(const QString &command, bool *ok, bool updateStatus) @@ -142,7 +142,7 @@ QJsonDocument QOTAClientAsync::info(QOTAClientPrivate::QueryTarget target, bool bool QOTAClientAsync::multiprocessLock(const QString &method) { qCDebug(qota) << QTime::currentTime().toString() << method << "- waiting for lock..."; - GError *error = Q_NULLPTR; + GError *error = nullptr; ostree_sysroot_lock (m_sysroot, &error); if (emitGError(error)) return false; @@ -167,7 +167,7 @@ void QOTAClientAsync::_initialize() { if (!multiprocessLock(QStringLiteral("_initialize"))) return; - GError *error = Q_NULLPTR; + GError *error = nullptr; ostree_sysroot_load (m_sysroot, 0, &error); if (emitGError(error)) return; @@ -208,7 +208,7 @@ void QOTAClientAsync::_update(const QString &updateToRev) bool ok = true; QString defaultRev; QString kernelArgs; - GError *error = Q_NULLPTR; + GError *error = nullptr; emit statusStringChanged(QStringLiteral("Checking for missing objects...")); ostree(QString(QStringLiteral("ostree pull qt-os:%1")).arg(updateToRev), &ok, true); multiprocessUnlock(); @@ -278,7 +278,7 @@ void QOTAClientAsync::_rollback() { if (!multiprocessLock(QStringLiteral("_rollback"))) return; - GError *error = Q_NULLPTR; + GError *error = nullptr; ostree_sysroot_load (m_sysroot, 0, &error); if (emitGError(error)) return; diff --git a/src/lib/qotaclientasync_p.h b/src/lib/qotaclientasync_p.h index d21b085..c91a7fa 100644 --- a/src/lib/qotaclientasync_p.h +++ b/src/lib/qotaclientasync_p.h @@ -48,6 +48,7 @@ class QOTAClientAsync : public QObject public: QOTAClientAsync(); virtual ~QOTAClientAsync(); + QString ostree(const QString &command, bool *ok, bool updateStatus = false); signals: void initialize(); @@ -65,7 +66,6 @@ signals: void statusStringChanged(const QString &status); protected: - QString ostree(const QString &command, bool *ok, bool updateStatus = false); QJsonDocument info(QOTAClientPrivate::QueryTarget target, bool *ok, const QString &rev = QString()); bool multiprocessLock(const QString &method); void multiprocessUnlock(); diff --git a/src/lib/qotarepositoryconfig.cpp b/src/lib/qotarepositoryconfig.cpp new file mode 100644 index 0000000..b557326 --- /dev/null +++ b/src/lib/qotarepositoryconfig.cpp @@ -0,0 +1,274 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt OTA Update module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include "qotarepositoryconfig_p.h" +#include "qotarepositoryconfig.h" + +#include <QtCore/QFile> +#include <QtCore/QDir> +#include <QtCore/QTextStream> + +const QString url(QStringLiteral("url=")); +const QString clientCert(QStringLiteral("tls-client-cert-path=")); +const QString clientKey(QStringLiteral("tls-client-key-path=")); +const QString ca(QStringLiteral("tls-ca-path=")); +// these 'bool' values by default are 'false' in QOtaRepositoryConfig +const QString gpg(QStringLiteral("gpg-verify=true")); +const QString tls(QStringLiteral("tls-permissive=true")); + +QOtaRepositoryConfigPrivate::QOtaRepositoryConfigPrivate(QOtaRepositoryConfig *repo) : + q_ptr(repo), + m_gpgVerify(false), + m_tlsPermissive(false) +{ +} + +QOtaRepositoryConfigPrivate::~QOtaRepositoryConfigPrivate() +{ +} + +QOtaRepositoryConfig *QOtaRepositoryConfigPrivate::repositoryConfigFromFile(const QString &configPath) const +{ + if (!QDir().exists(configPath)) + return nullptr; + + QFile config(configPath); + if (!config.open(QFile::ReadOnly)) + return nullptr; + + QOtaRepositoryConfig *conf = new QOtaRepositoryConfig(); + QTextStream in(&config); + while (!in.atEnd()) { + QString line = in.readLine().trimmed(); + // string(s) + if (line.startsWith(url)) + conf->setUrl(line.mid(url.length())); + else if (line.startsWith(clientCert)) + conf->setTlsClientCertPath(line.mid(clientCert.length())); + else if (line.startsWith(clientKey)) + conf->setTlsClientKeyPath(line.mid(clientKey.length())); + else if (line.startsWith(ca)) + conf->setTlsCaPath(line.mid(ca.length())); + // bool(s) + else if (line.startsWith(gpg)) + conf->setGpgVerify(true); + else if (line.startsWith(tls)) + conf->setTlsPermissive(true); + } + + return conf; +} + +/*! + \class QOtaRepositoryConfig + \inmodule qtotaupdate + \brief Used to configure the OSTree repository. + + QOtaRepositoryConfig +//! [repository-config-description] + provides an API to configure an OSTree repository. The repository + on client devices is located in \c {/ostree/repo}. The update process involves client + devices replicating an OSTree repository from a remote sever. Use this class to describe + the remote repository location and enable/disable security features. +//! [repository-config-description] +*/ + +/*! + \fn void QOtaRepositoryConfig::urlChanged() + + This signal is emitted when the value of url changes. +*/ + +/*! + \fn void QOtaRepositoryConfig::gpgVerifyChanged() + + This signal is emitted when the value of gpgVerify changes. +*/ + +/*! + \fn void QOtaRepositoryConfig::tlsClientCertPathChanged() + + This signal is emitted when the value of tlsClientCertPath changes. +*/ + +/*! + \fn void QOtaRepositoryConfig::tlsClientKeyPathChanged() + + This signal is emitted when the value of tlsClientKeyPath changes. +*/ + +/*! + \fn void QOtaRepositoryConfig::tlsPermissiveChanged() + + This signal is emitted when the value of tlsPermissive changes. +*/ + +/*! + \fn void QOtaRepositoryConfig::tlsCaPathChanged() + + This signal is emitted when the value of tlsCaPath changes. +*/ + +QOtaRepositoryConfig::QOtaRepositoryConfig(QObject *parent) : + QObject(parent), + d_ptr(new QOtaRepositoryConfigPrivate(this)) +{ +} + +QOtaRepositoryConfig::~QOtaRepositoryConfig() +{ + delete d_ptr; +} + +void QOtaRepositoryConfig::setUrl(const QString &url) +{ + Q_D(QOtaRepositoryConfig); + if (url.trimmed() == d->m_url) + return; + + d->m_url = url.trimmed(); + emit urlChanged(); +} + +/*! + \property QOtaRepositoryConfig::url + \brief a URL for accessing remote OSTree repository. + + The supported schemes at the moment are \c http and \c https. +*/ +QString QOtaRepositoryConfig::url() const +{ + return d_func()->m_url; +} + +void QOtaRepositoryConfig::setGpgVerify(bool verify) +{ + Q_D(QOtaRepositoryConfig); + if (verify == d->m_gpgVerify) + return; + + d->m_gpgVerify = verify; + emit gpgVerifyChanged(); +} + +/*! + \property QOtaRepositoryConfig::gpgVerify + \brief whether or not OSTree will require commits to be signed by a known GPG key. + + Default is \c false. +*/ +bool QOtaRepositoryConfig::gpgVerify() const +{ + return d_func()->m_gpgVerify; +} + +void QOtaRepositoryConfig::setTlsClientCertPath(const QString &certPath) +{ + Q_D(QOtaRepositoryConfig); + if (certPath.trimmed() == d->m_clientCertPath) + return; + + d->m_clientCertPath = certPath.trimmed(); + emit tlsClientCertPathChanged(); +} + +/*! + \property QOtaRepositoryConfig::tlsClientCertPath + \brief a path to a file for the client-side certificate. + + A path to a file for the client-side certificate, to present when making requests + to the remote repository. +*/ +QString QOtaRepositoryConfig::tlsClientCertPath() const +{ + return d_func()->m_clientCertPath; +} + +void QOtaRepositoryConfig::setTlsClientKeyPath(const QString &keyPath) +{ + Q_D(QOtaRepositoryConfig); + if (keyPath.trimmed() == d->m_clientKeyPath) + return; + + d->m_clientKeyPath = keyPath.trimmed(); + emit tlsClientKeyPathChanged(); +} + +/*! + \property QOtaRepositoryConfig::tlsClientKeyPath + \brief a path to a file containing the client-side certificate key. + + A path to a file containing the client-side certificate key, to present when making + requests to the remote repository. +*/ +QString QOtaRepositoryConfig::tlsClientKeyPath() const +{ + return d_func()->m_clientKeyPath; +} + +void QOtaRepositoryConfig::setTlsPermissive(bool permissive) +{ + Q_D(QOtaRepositoryConfig); + if (permissive == d->m_tlsPermissive) + return; + + d->m_tlsPermissive = permissive; + emit tlsPermissiveChanged(); +} + +/*! + \property QOtaRepositoryConfig::tlsPermissive + \brief whether to check the server's TLS certificates against the system's certificate store. + + If this variable is set to \c true, any certificate will be accepted. + + Default is \c false. +*/ +bool QOtaRepositoryConfig::tlsPermissive() const +{ + return d_func()->m_tlsPermissive; +} + +void QOtaRepositoryConfig::setTlsCaPath(const QString &caPath) +{ + Q_D(QOtaRepositoryConfig); + if (caPath.trimmed() == d->m_tlsCaPath) + return; + + d->m_tlsCaPath = caPath.trimmed(); + emit tlsCaPathChanged(); +} + +/*! + \property QOtaRepositoryConfig::tlsCaPath + \brief a path to a file containing trusted anchors instead of the system's CA database. +*/ +QString QOtaRepositoryConfig::tlsCaPath() const +{ + return d_func()->m_tlsCaPath; +} diff --git a/src/lib/qotarepositoryconfig.h b/src/lib/qotarepositoryconfig.h new file mode 100644 index 0000000..11e7400 --- /dev/null +++ b/src/lib/qotarepositoryconfig.h @@ -0,0 +1,84 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt OTA Update module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef QOTAREPOSITORYCONFIG_H +#define QOTAREPOSITORYCONFIG_H + +#include <QtCore/QObject> +#include <QtCore/QString> + +class QOTAClient; +class QOtaRepositoryConfigPrivate; + +class Q_DECL_EXPORT QOtaRepositoryConfig : public QObject +{ + Q_OBJECT + Q_PROPERTY(QString url READ url WRITE setUrl NOTIFY urlChanged) + Q_PROPERTY(bool gpgVerify READ gpgVerify WRITE setGpgVerify NOTIFY gpgVerifyChanged) + Q_PROPERTY(QString tlsClientCertPath READ tlsClientCertPath WRITE setTlsClientCertPath NOTIFY tlsClientCertPathChanged) + Q_PROPERTY(QString tlsClientKeyPath READ tlsClientKeyPath WRITE setTlsClientKeyPath NOTIFY tlsClientKeyPathChanged) + Q_PROPERTY(bool tlsPermissive READ tlsPermissive WRITE setTlsPermissive NOTIFY tlsPermissiveChanged) + Q_PROPERTY(QString tlsCaPath READ tlsCaPath WRITE setTlsCaPath NOTIFY tlsCaPathChanged) +public: + explicit QOtaRepositoryConfig(QObject *parent = nullptr); + virtual ~QOtaRepositoryConfig(); + + void setUrl(const QString &url); + QString url() const; + + void setGpgVerify(bool verify); + bool gpgVerify() const; + + void setTlsClientCertPath(const QString &certPath); + QString tlsClientCertPath() const; + + void setTlsClientKeyPath(const QString &keyPath); + QString tlsClientKeyPath() const; + + void setTlsPermissive(bool permissive); + bool tlsPermissive() const; + + void setTlsCaPath(const QString &caPath); + QString tlsCaPath() const; + +Q_SIGNALS: + void urlChanged(); + void gpgVerifyChanged(); + void tlsClientCertPathChanged(); + void tlsClientKeyPathChanged(); + void tlsPermissiveChanged(); + void tlsCaPathChanged(); + +private: + Q_DISABLE_COPY(QOtaRepositoryConfig) + Q_DECLARE_PRIVATE(QOtaRepositoryConfig) + QOtaRepositoryConfigPrivate *const d_ptr; + friend class QOTAClient; +}; + +#endif // QOTAREPOSITORYCONFIG_H diff --git a/src/lib/qotarepositoryconfig_p.h b/src/lib/qotarepositoryconfig_p.h new file mode 100644 index 0000000..9f7caf1 --- /dev/null +++ b/src/lib/qotarepositoryconfig_p.h @@ -0,0 +1,57 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt OTA Update module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef QOTAREPOSITORYCONFIG_P_H +#define QOTAREPOSITORYCONFIG_P_H + +#endif // QOTAREPOSITORYCONFIG_P_H + +#include <QtCore/QObject> +#include <QtCore/QString> + +class QOtaRepositoryConfig; + +class QOtaRepositoryConfigPrivate : public QObject +{ + Q_OBJECT + Q_DECLARE_PUBLIC(QOtaRepositoryConfig) +public: + QOtaRepositoryConfigPrivate(QOtaRepositoryConfig *repo); + virtual ~QOtaRepositoryConfigPrivate(); + + QOtaRepositoryConfig *repositoryConfigFromFile(const QString &configPath) const; + + // members + QOtaRepositoryConfig *const q_ptr; + QString m_url; + bool m_gpgVerify; + QString m_clientCertPath; + QString m_clientKeyPath; + bool m_tlsPermissive; + QString m_tlsCaPath; +}; |