diff options
author | Robert Griebl <robert.griebl@pelagicore.com> | 2018-08-02 17:45:42 +0200 |
---|---|---|
committer | Robert Griebl <robert.griebl@pelagicore.com> | 2018-08-03 12:37:35 +0000 |
commit | d16409c723495cef98ab691de5e03b87a7596038 (patch) | |
tree | 7d15a06b63919e1ef4e07ae3703ce56680823d33 | |
parent | 580e5eac4dadfd96b591b81e4af3bf072bcb461a (diff) |
Fix store-signed packages
There were multiple bugs in the way store signatures were created and
verified. This patch should fix all issues, plus it adds auto-tests to
catch regressions going forward.
Change-Id: I903bcc7d2dc485b5ed4ee7448d1f1e1ac8242c29
Reviewed-by: Bernd Weimer <bernd.weimer@pelagicore.com>
-rw-r--r-- | doc/configuration.qdoc | 5 | ||||
-rw-r--r-- | doc/installer.qdoc | 2 | ||||
-rw-r--r-- | doc/packager.qdoc | 4 | ||||
-rw-r--r-- | src/installer-lib/applicationinstaller.cpp | 16 | ||||
-rw-r--r-- | src/installer-lib/applicationinstaller.h | 5 | ||||
-rw-r--r-- | src/installer-lib/applicationinstaller_p.h | 1 | ||||
-rw-r--r-- | src/installer-lib/installationtask.cpp | 15 | ||||
-rw-r--r-- | src/main-lib/defaultconfiguration.cpp | 6 | ||||
-rw-r--r-- | src/main-lib/defaultconfiguration.h | 1 | ||||
-rw-r--r-- | src/main-lib/main.cpp | 7 | ||||
-rw-r--r-- | src/main-lib/main.h | 1 | ||||
-rw-r--r-- | src/tools/packager/packager.cpp | 2 | ||||
-rw-r--r-- | src/tools/packager/packagingjob.cpp | 14 | ||||
-rw-r--r-- | tests/applicationinstaller/tst_applicationinstaller.cpp | 96 | ||||
-rwxr-xr-x | tests/data/certificates/create-test-certificates.sh | 2 | ||||
-rwxr-xr-x | tests/data/create-test-packages.sh | 6 | ||||
-rw-r--r-- | tests/packager-tool/tst_packager-tool.cpp | 2 |
17 files changed, 138 insertions, 47 deletions
diff --git a/doc/configuration.qdoc b/doc/configuration.qdoc index 841725b9..b2941c69 100644 --- a/doc/configuration.qdoc +++ b/doc/configuration.qdoc @@ -254,6 +254,11 @@ all your imports paths and file references relative to your main config file. \li bool \li Disables all security related checks. Use this in a development setup only! (default: false) \row + \li \b --development-mode + \br \e flags/developmentMode + \li bool + \li Allows the installation of packages that only come with a valid developer signature. (default: false) +\row \li \b --no-ui-watchdog \br \e flags/noUiWatchdog \li bool diff --git a/doc/installer.qdoc b/doc/installer.qdoc index d1474c6a..5094c2d1 100644 --- a/doc/installer.qdoc +++ b/doc/installer.qdoc @@ -85,7 +85,7 @@ If you want to make use of signed packages, you need to setup a public key infra support this. You need: \list - \li A \e {Developer CA} which is responsible for creating certicates that are distributed + \li A \e {Developer CA} which is responsible for creating certificates that are distributed to developers in P12 format. The developers use these certificates to developer-sign their packages (using the Packager tool), before submitting to an app-store. \li An \e {App-Store CA} which is responsible for creating certificates that are used diff --git a/doc/packager.qdoc b/doc/packager.qdoc index 2f71cbbd..853df484 100644 --- a/doc/packager.qdoc +++ b/doc/packager.qdoc @@ -116,10 +116,10 @@ developer only (development mode), and packages that are signed by a trusted app \c{<password>} - \c{[device-id]} + \c{<device-id>} \li Takes the input \c package, adds a store signature and writes the output to \c signed-package. You need to supply a \c certificate in P12 format together with a \c password matching the - certificate. If you specify the optional \c device-id, the resulting package can only be + certificate. If you don't leave the \c device-id empty, the resulting package can only be installed on this specific device. The following options are supported: \c{--verbose}: Dump the package's meta-data header and footer information to stdout. diff --git a/src/installer-lib/applicationinstaller.cpp b/src/installer-lib/applicationinstaller.cpp index 94190a41..a8b24281 100644 --- a/src/installer-lib/applicationinstaller.cpp +++ b/src/installer-lib/applicationinstaller.cpp @@ -167,7 +167,7 @@ for this \a taskId, to either cancel the installation or try to complete it. The ApplicationInstaller has two convenience functions to help the System-UI with verifying the - meta-data: versionCompare() and, in case you are using reverse-DNS notation for application-ids, + meta-data: compareVersions() and, in case you are using reverse-DNS notation for application-ids, validateDnsName(). \sa taskStateChanged(), startPackageInstallation() @@ -197,13 +197,14 @@ ApplicationInstaller *ApplicationInstaller::s_instance = nullptr; ApplicationInstaller::ApplicationInstaller(const QVector<InstallationLocation> &installationLocations, const QDir &manifestDir, const QDir &imageMountDir, - QObject *parent) + const QString &hardwareId, QObject *parent) : QObject(parent) , d(new ApplicationInstallerPrivate()) { d->installationLocations = installationLocations; d->manifestDir = manifestDir; d->imageMountDir = imageMountDir; + d->hardwareId = hardwareId; } ApplicationInstaller::~ApplicationInstaller() @@ -213,7 +214,8 @@ ApplicationInstaller::~ApplicationInstaller() } ApplicationInstaller *ApplicationInstaller::createInstance(const QVector<InstallationLocation> &installationLocations, - const QDir &manifestDir, const QDir &imageMountDir, QString *error) + const QDir &manifestDir, const QDir &imageMountDir, + const QString &hardwareId, QString *error) { if (Q_UNLIKELY(s_instance)) qFatal("ApplicationInstaller::createInstance() was called a second time."); @@ -235,7 +237,8 @@ ApplicationInstaller *ApplicationInstaller::createInstance(const QVector<Install qmlRegisterSingletonType<ApplicationInstaller>("QtApplicationManager", 1, 0, "ApplicationInstaller", &ApplicationInstaller::instanceForQml); - return s_instance = new ApplicationInstaller(installationLocations, manifestDir, imageMountDir, QCoreApplication::instance()); + return s_instance = new ApplicationInstaller(installationLocations, manifestDir, imageMountDir, + hardwareId, QCoreApplication::instance()); } ApplicationInstaller *ApplicationInstaller::instance() @@ -271,6 +274,11 @@ void ApplicationInstaller::setAllowInstallationOfUnsignedPackages(bool b) d->allowInstallationOfUnsignedPackages = b; } +QString ApplicationInstaller::hardwareId() const +{ + return d->hardwareId; +} + bool ApplicationInstaller::isApplicationUserIdSeparationEnabled() const { return d->userIdSeparation; diff --git a/src/installer-lib/applicationinstaller.h b/src/installer-lib/applicationinstaller.h index 1a3e54ba..c82c30af 100644 --- a/src/installer-lib/applicationinstaller.h +++ b/src/installer-lib/applicationinstaller.h @@ -79,7 +79,7 @@ public: ~ApplicationInstaller(); static ApplicationInstaller *createInstance(const QVector<InstallationLocation> &installationLocations, - const QDir &manifestDir, const QDir &imageMountDir, + const QDir &manifestDir, const QDir &imageMountDir, const QString &hardwareId, QString *error); static ApplicationInstaller *instance(); static QObject *instanceForQml(QQmlEngine *qmlEngine, QJSEngine *); @@ -88,6 +88,7 @@ public: void setDevelopmentMode(bool b); bool allowInstallationOfUnsignedPackages() const; void setAllowInstallationOfUnsignedPackages(bool b); + QString hardwareId() const; bool isApplicationUserIdSeparationEnabled() const; uint commonApplicationGroupId() const; @@ -170,7 +171,7 @@ private: private: ApplicationInstaller(const QVector<InstallationLocation> &installationLocations, const QDir &manifestDir, - const QDir &imageMountDir, QObject *parent); + const QDir &imageMountDir, const QString &hardwareId, QObject *parent); ApplicationInstaller(const ApplicationInstaller &); static ApplicationInstaller *s_instance; diff --git a/src/installer-lib/applicationinstaller_p.h b/src/installer-lib/applicationinstaller_p.h index 7db32049..88f51b74 100644 --- a/src/installer-lib/applicationinstaller_p.h +++ b/src/installer-lib/applicationinstaller_p.h @@ -71,6 +71,7 @@ public: QString error; + QString hardwareId; QList<QByteArray> chainOfTrust; QQueue<AsynchronousTask *> taskQueue; diff --git a/src/installer-lib/installationtask.cpp b/src/installer-lib/installationtask.cpp index 5ab9bfd5..29f68929 100644 --- a/src/installer-lib/installationtask.cpp +++ b/src/installer-lib/installationtask.cpp @@ -40,6 +40,7 @@ ****************************************************************************/ #include <QTemporaryDir> +#include <QMessageAuthenticationCode> #include "logging.h" #include "applicationinstaller_p.h" @@ -217,9 +218,19 @@ void InstallationTask::execute() if (ApplicationManager::instance()->securityChecksEnabled()) { if (!m_extractor->installationReport().storeSignature().isEmpty()) { // normal package from the store - if (!Signature(m_extractor->installationReport().digest()).verify(m_extractor->installationReport().storeSignature(), chainOfTrust)) + QByteArray sigDigest = m_extractor->installationReport().digest(); + bool sigOk = false; + + if (Signature(sigDigest).verify(m_extractor->installationReport().storeSignature(), chainOfTrust)) { + sigOk = true; + } else if (!m_ai->hardwareId().isEmpty()) { + // did not verify - if we have a hardware-id, try to verify with it + sigDigest = QMessageAuthenticationCode::hash(sigDigest, m_ai->hardwareId().toUtf8(), QCryptographicHash::Sha256); + if (Signature(sigDigest).verify(m_extractor->installationReport().storeSignature(), chainOfTrust)) + sigOk = true; + } + if (!sigOk) throw Exception(Error::Package, "could not verify the package's store signature"); - } else if (!m_extractor->installationReport().developerSignature().isEmpty()) { // developer package - needs a device in dev mode if (!m_ai->developmentMode()) diff --git a/src/main-lib/defaultconfiguration.cpp b/src/main-lib/defaultconfiguration.cpp index c6e3a1c9..28492d79 100644 --- a/src/main-lib/defaultconfiguration.cpp +++ b/src/main-lib/defaultconfiguration.cpp @@ -108,6 +108,7 @@ DefaultConfiguration::DefaultConfiguration(const QStringList &defaultConfigFileP m_clp.addOption({ qSL("slow-animations"), qSL("run all animations in slow motion.") }); m_clp.addOption({ qSL("load-dummydata"), qSL("loads QML dummy-data.") }); m_clp.addOption({ qSL("no-security"), qSL("disables all security related checks (dev only!)") }); + m_clp.addOption({ qSL("development-mode"), qSL("enable development mode, allowing installation of dev-signed packages.") }); m_clp.addOption({ qSL("no-ui-watchdog"), qSL("disables detecting hung UI applications (e.g. via Wayland's ping/pong).") }); m_clp.addOption({ qSL("no-dlt-logging"), qSL("disables logging using automotive DLT.") }); m_clp.addOption({ qSL("force-single-process"), qSL("forces single-process mode even on a wayland enabled build.") }); @@ -213,6 +214,11 @@ bool DefaultConfiguration::noSecurity() const return value<bool>("no-security", { "flags", "noSecurity" }); } +bool DefaultConfiguration::developmentMode() const +{ + return value<bool>("development-mode", { "flags", "developmentMode" }); +} + bool DefaultConfiguration::noUiWatchdog() const { return value<bool>("no-ui-watchdog", { "flags", "noUiWatchdog" }); diff --git a/src/main-lib/defaultconfiguration.h b/src/main-lib/defaultconfiguration.h index 884bc253..2b2f4bbe 100644 --- a/src/main-lib/defaultconfiguration.h +++ b/src/main-lib/defaultconfiguration.h @@ -75,6 +75,7 @@ public: bool slowAnimations() const; bool loadDummyData() const; bool noSecurity() const; + bool developmentMode() const; bool noUiWatchdog() const; bool noDltLogging() const; bool forceSingleProcess() const; diff --git a/src/main-lib/main.cpp b/src/main-lib/main.cpp index 3b4faa0e..37f3682d 100644 --- a/src/main-lib/main.cpp +++ b/src/main-lib/main.cpp @@ -189,6 +189,7 @@ void Main::setup(const DefaultConfiguration *cfg, const QStringList &deploymentW { // basics that are needed in multiple setup functions below m_noSecurity = cfg->noSecurity(); + m_developmentMode = cfg->developmentMode(); m_builtinAppsManifestDirs = cfg->builtinAppsManifestDirs(); m_installedAppsManifestDir = cfg->installedAppsManifestDir(); @@ -501,11 +502,15 @@ void Main::setupInstaller(const QString &appImageMountDir, const QStringList &ca m_applicationInstaller = ApplicationInstaller::createInstance(m_installationLocations, m_installedAppsManifestDir, appImageMountDir, + hardwareId(), &error); if (Q_UNLIKELY(!m_applicationInstaller)) throw Exception(Error::System, error); - if (m_noSecurity) { + + if (m_developmentMode) m_applicationInstaller->setDevelopmentMode(true); + + if (m_noSecurity) { m_applicationInstaller->setAllowInstallationOfUnsignedPackages(true); } else { QList<QByteArray> caCertificateList; diff --git a/src/main-lib/main.h b/src/main-lib/main.h index d07aa695..675ece9c 100644 --- a/src/main-lib/main.h +++ b/src/main-lib/main.h @@ -170,6 +170,7 @@ private: QVector<QVariantMap> m_systemProperties; bool m_noSecurity = false; + bool m_developmentMode = false; QStringList m_builtinAppsManifestDirs; QString m_installedAppsManifestDir; }; diff --git a/src/tools/packager/packager.cpp b/src/tools/packager/packager.cpp index b237cc99..d6b3a830 100644 --- a/src/tools/packager/packager.cpp +++ b/src/tools/packager/packager.cpp @@ -265,7 +265,7 @@ int main(int argc, char *argv[]) clp.showHelp(1); p = PackagingJob::storeVerify(clp.positionalArguments().at(1), - clp.positionalArguments().mid(2, clp.positionalArguments().size() - 2), + clp.positionalArguments().mid(2, clp.positionalArguments().size() - 3), *--clp.positionalArguments().cend()); break; } diff --git a/src/tools/packager/packagingjob.cpp b/src/tools/packager/packagingjob.cpp index 66ef4336..d0e1a8c8 100644 --- a/src/tools/packager/packagingjob.cpp +++ b/src/tools/packager/packagingjob.cpp @@ -261,8 +261,11 @@ void PackagingJob::execute() Q_DECL_NOEXCEPT_EXPR(false) m_output = qSL("no store signature"); m_resultCode = 1; } else { - QByteArray digestPlusId = QMessageAuthenticationCode::hash(report.digest(), m_hardwareId.toUtf8(), QCryptographicHash::Sha256); - Signature sig(digestPlusId); + QByteArray sigDigest = report.digest(); + if (!m_hardwareId.isEmpty()) + sigDigest = QMessageAuthenticationCode::hash(sigDigest, m_hardwareId.toUtf8(), QCryptographicHash::Sha256); + + Signature sig(sigDigest); if (!sig.verify(report.storeSignature(), certificates)) { m_output = qSL("invalid store signature (") + sig.errorString() + qSL(")"); m_resultCode = 2; @@ -295,8 +298,11 @@ void PackagingJob::execute() Q_DECL_NOEXCEPT_EXPR(false) throw Exception(Error::Package, "could not create signature: %1").arg(sig.errorString()); report.setDeveloperSignature(signature); } else if (m_mode == StoreSign) { - QByteArray digestPlusId = QMessageAuthenticationCode::hash(report.digest(), m_hardwareId.toUtf8(), QCryptographicHash::Sha256); - Signature sig(digestPlusId); + QByteArray sigDigest = report.digest(); + if (!m_hardwareId.isEmpty()) + sigDigest = QMessageAuthenticationCode::hash(sigDigest, m_hardwareId.toUtf8(), QCryptographicHash::Sha256); + + Signature sig(sigDigest); QByteArray signature = sig.create(certificates.first(), m_passphrase.toUtf8()); if (signature.isEmpty()) diff --git a/tests/applicationinstaller/tst_applicationinstaller.cpp b/tests/applicationinstaller/tst_applicationinstaller.cpp index b4f08dab..259a7575 100644 --- a/tests/applicationinstaller/tst_applicationinstaller.cpp +++ b/tests/applicationinstaller/tst_applicationinstaller.cpp @@ -59,20 +59,42 @@ static QString sudoServerError; static int spyTimeout = 5000; // shorthand for specifying QSignalSpy timeouts // RAII to reset the global attribute -class AllowUnsignedInstallation +class AllowInstallations { public: - AllowUnsignedInstallation(bool b = true) - : m_old(ApplicationInstaller::instance()->allowInstallationOfUnsignedPackages()) + enum Type { + AllowUnsinged, + RequireDevSigned, + RequireStoreSigned + }; + + AllowInstallations(Type t) + : m_oldUnsigned(ApplicationInstaller::instance()->allowInstallationOfUnsignedPackages()) + , m_oldDevMode(ApplicationInstaller::instance()->developmentMode()) { - ApplicationInstaller::instance()->setAllowInstallationOfUnsignedPackages(b); + switch (t) { + case AllowUnsinged: + ApplicationInstaller::instance()->setAllowInstallationOfUnsignedPackages(true); + ApplicationInstaller::instance()->setDevelopmentMode(false); + break; + case RequireDevSigned: + ApplicationInstaller::instance()->setAllowInstallationOfUnsignedPackages(false); + ApplicationInstaller::instance()->setDevelopmentMode(true); + break; + case RequireStoreSigned: + ApplicationInstaller::instance()->setAllowInstallationOfUnsignedPackages(false); + ApplicationInstaller::instance()->setDevelopmentMode(false); + break; + } } - ~AllowUnsignedInstallation() + ~AllowInstallations() { - ApplicationInstaller::instance()->setAllowInstallationOfUnsignedPackages(m_old); + ApplicationInstaller::instance()->setAllowInstallationOfUnsignedPackages(m_oldUnsigned); + ApplicationInstaller::instance()->setDevelopmentMode(m_oldDevMode); } private: - bool m_old; + bool m_oldUnsigned; + bool m_oldDevMode; }; class tst_ApplicationInstaller : public QObject @@ -359,7 +381,7 @@ void tst_ApplicationInstaller::initTestCase() // finally, instantiate the ApplicationInstaller and a bunch of signal-spies for its signals QString installerError; - m_ai = ApplicationInstaller::createInstance(m_installationLocations, pathTo(Manifests), pathTo(ImageMounts), &installerError); + m_ai = ApplicationInstaller::createInstance(m_installationLocations, pathTo(Manifests), pathTo(ImageMounts), m_hardwareId, &installerError); QVERIFY2(m_ai, qPrintable(installerError)); m_startedSpy = new QSignalSpy(m_ai, &ApplicationInstaller::taskStarted); @@ -374,9 +396,11 @@ void tst_ApplicationInstaller::initTestCase() // crypto stuff - we need to load the root CA and developer CA certificates QFile devcaFile(AM_TESTDATA_DIR "certificates/devca.crt"); + QFile storecaFile(AM_TESTDATA_DIR "certificates/store.crt"); QFile caFile(AM_TESTDATA_DIR "certificates/ca.crt"); QVERIFY2(devcaFile.open(QIODevice::ReadOnly), qPrintable(devcaFile.errorString())); - QVERIFY2(caFile.open(QIODevice::ReadOnly), qPrintable(devcaFile.errorString())); + QVERIFY2(storecaFile.open(QIODevice::ReadOnly), qPrintable(storecaFile.errorString())); + QVERIFY2(caFile.open(QIODevice::ReadOnly), qPrintable(caFile.errorString())); QList<QByteArray> chainOfTrust; chainOfTrust << devcaFile.readAll() << caFile.readAll(); @@ -547,6 +571,7 @@ void tst_ApplicationInstaller::packageInstallation_data() QTest::addColumn<QString>("updatePackageName"); QTest::addColumn<QString>("updateInstallationLocationId"); QTest::addColumn<bool>("devSigned"); + QTest::addColumn<bool>("storeSigned"); QTest::addColumn<bool>("expectedSuccess"); QTest::addColumn<bool>("updateExpectedSuccess"); QTest::addColumn<QVariantMap>("extraMetaData"); @@ -569,59 +594,71 @@ void tst_ApplicationInstaller::packageInstallation_data() QTest::newRow("normal") \ << "test.appkg" << "internal-0" << "test-update.appkg" << "internal-0" - << false << true << true << nomd<< ""; + << false << false << true << true << nomd<< ""; + QTest::newRow("no-dev-signed") \ + << "test.appkg" << "internal-0" << "" << "" + << true << false << false << false << nomd << "cannot install unsigned packages"; QTest::newRow("dev-signed") \ << "test-dev-signed.appkg" << "internal-0" << "test-update-dev-signed.appkg" << "internal-0" - << true << true << true << nomd << ""; + << true << false << true << true << nomd << ""; + QTest::newRow("no-store-signed") \ + << "test.appkg" << "internal-0" << "" << "" + << false << true << false << false << nomd << "cannot install unsigned packages"; + QTest::newRow("no-store-but-dev-signed") \ + << "test-dev-signed.appkg" << "internal-0" << "" << "" + << false << true << false << false << nomd << "cannot install development packages on consumer devices"; + QTest::newRow("store-signed") \ + << "test-store-signed.appkg" << "internal-0" << "" << "" + << false << true << true << false << nomd << ""; QTest::newRow("extra-metadata") \ << "test-extra.appkg" << "internal-0" << "" << "" - << false << true << false << extramd << ""; + << false << false << true << false << extramd << ""; QTest::newRow("extra-metadata-dev-signed") \ << "test-extra-dev-signed.appkg" << "internal-0" << "" << "" - << true << true << false << extramd << ""; + << true << false << true << false << extramd << ""; QTest::newRow("update-to-different-location") \ << "test.appkg" << "internal-0" << "test-update.appkg" << "internal-1" - << false << true << false << nomd << "the application com.pelagicore.test cannot be installed to internal-1, since it is already installed to internal-0"; + << false << false << true << false << nomd << "the application com.pelagicore.test cannot be installed to internal-1, since it is already installed to internal-0"; QTest::newRow("invalid-location") \ << "test.appkg" << "internal-42" << "" << "" - << false << false << false << nomd << "invalid installation location"; + << false << false << false << false << nomd << "invalid installation location"; QTest::newRow("invalid-file-order") \ << "test-invalid-file-order.appkg" << "internal-0" << "" << "" - << false << false << false << nomd << "could not find info.yaml and icon.png at the beginning of the package"; + << false << false << false << false << nomd << "could not find info.yaml and icon.png at the beginning of the package"; QTest::newRow("invalid-header-format") \ << "test-invalid-header-formatversion.appkg" << "internal-0" << "" << "" - << false << false << false << nomd << "metadata has an invalid format specification: wrong formatVersion header: expected 1, got 2"; + << false << false << false << false << nomd << "metadata has an invalid format specification: wrong formatVersion header: expected 1, got 2"; QTest::newRow("invalid-header-diskspaceused") \ << "test-invalid-header-diskspaceused.appkg" << "internal-0" << "" << "" - << false << false << false << nomd << "metadata has an invalid diskSpaceUsed field (0)"; + << false << false << false << false << nomd << "metadata has an invalid diskSpaceUsed field (0)"; QTest::newRow("invalid-header-id") \ << "test-invalid-header-id.appkg" << "internal-0" << "" << "" - << false << false << false << nomd << "metadata has an invalid applicationId field (:invalid)"; + << false << false << false << false << nomd << "metadata has an invalid applicationId field (:invalid)"; QTest::newRow("non-matching-header-id") \ << "test-non-matching-header-id.appkg" << "internal-0" << "" << "" - << false << false << false << nomd << "the application identifiers in --PACKAGE-HEADER--' and info.yaml do not match"; + << false << false << false << false << nomd << "the application identifiers in --PACKAGE-HEADER--' and info.yaml do not match"; QTest::newRow("tampered-extra-signed-header") \ << "test-tampered-extra-signed-header.appkg" << "internal-0" << "" << "" - << false << false << false << nomd << "~package digest mismatch.*"; + << false << false << false << false << nomd << "~package digest mismatch.*"; QTest::newRow("invalid-info.yaml") \ << "test-invalid-info.appkg" << "internal-0" << "" << "" - << false << false << false << nomd << "~.*YAML parse error at line \\d+, column \\d+: did not find expected key"; + << false << false << false << false << nomd << "~.*YAML parse error at line \\d+, column \\d+: did not find expected key"; QTest::newRow("invalid-info.yaml-id") \ << "test-invalid-info-id.appkg" << "internal-0" << "" << "" - << false << false << false << nomd << "~.*the identifier \\(:invalid\\) is not a valid application-id: must consist of printable ASCII characters only, except any of .*"; + << false << false << false << false << nomd << "~.*the identifier \\(:invalid\\) is not a valid application-id: must consist of printable ASCII characters only, except any of .*"; QTest::newRow("invalid-footer-signature") \ << "test-invalid-footer-signature.appkg" << "internal-0" << "" << "" - << false << false << false << nomd << "could not verify the package's developer signature"; + << true << false << false << false << nomd << "could not verify the package's developer signature"; #ifdef Q_OS_LINUX QTest::newRow("sdcard") \ << "test.appkg" << "removable-0" << "test-update.appkg" << "removable-0" - << false << true << true << nomd << ""; + << false << false << true << true << nomd << ""; QTest::newRow("sdcard-dev-signed") \ << "test-dev-signed.appkg" << "removable-0" << "test-update-dev-signed.appkg" << "removable-0" - << true << true << true << nomd << ""; + << true << false << true << true << nomd << ""; QTest::newRow("sdcard-no-space") \ << "bigtest-dev-signed.appkg" << "removable-0" << "" << "" - << true << false << false << nomd << "~not enough storage space left on removable-0: [0-9.]+ MB available, but [0-9.]+ MB needed"; + << true << false << false << false << nomd << "~not enough storage space left on removable-0: [0-9.]+ MB available, but [0-9.]+ MB needed"; #endif } @@ -635,6 +672,7 @@ void tst_ApplicationInstaller::packageInstallation() QFETCH(QString, updatePackageName); QFETCH(QString, updateInstallationLocationId); QFETCH(bool, devSigned); + QFETCH(bool, storeSigned); QFETCH(bool, expectedSuccess); QFETCH(bool, updateExpectedSuccess); QFETCH(QVariantMap, extraMetaData); @@ -645,7 +683,9 @@ void tst_ApplicationInstaller::packageInstallation() QSKIP("no removable installation locations on this platform"); #endif - AllowUnsignedInstallation allow(!devSigned); + AllowInstallations allow(storeSigned ? AllowInstallations::RequireStoreSigned + : (devSigned ? AllowInstallations::RequireDevSigned + : AllowInstallations::AllowUnsinged)); int lastPass = (updatePackageName.isEmpty() ? 1 : 2); // pass 1 is the installation / pass 2 is the update (if needed) diff --git a/tests/data/certificates/create-test-certificates.sh b/tests/data/certificates/create-test-certificates.sh index c7ab2b78..3bc69874 100755 --- a/tests/data/certificates/create-test-certificates.sh +++ b/tests/data/certificates/create-test-certificates.sh @@ -100,7 +100,7 @@ runSSL req -batch -subj '/C=DE/ST=Foo/L=Bar/CN=www.other.com' -newkey rsa:2048 - runSSL ca -batch -config openssl-other-ca.cnf -policy signing_policy -extensions signing_req -out other.crt -infiles other.csr runSSL pkcs12 -export -out other.p12 -password pass:password -inkey other-priv.key -nodes -certfile other-ca.crt -in other.crt -name "Other Certificate" -echo -e "$G All test certificated have been created successfully$W" +echo -e "$G All test certificates have been created successfully$W" echo exit 0 diff --git a/tests/data/create-test-packages.sh b/tests/data/create-test-packages.sh index 109defd9..5c4d16f5 100755 --- a/tests/data/create-test-packages.sh +++ b/tests/data/create-test-packages.sh @@ -101,6 +101,12 @@ packager create-package "$dst/test.appkg" "$src" info "Dev-sign package" packager dev-sign-package "$dst/test.appkg" "$dst/test-dev-signed.appkg" certificates/dev1.p12 password +info "Store-sign package" +packager store-sign-package "$dst/test.appkg" "$dst/test-store-signed.appkg" certificates/store.p12 password "foobar" + +info "Store-sign dev package" +packager store-sign-package "$dst/test-dev-signed.appkg" "$dst/test-store-dev-signed.appkg" certificates/store.p12 password "foobar" + info "Create package with extra meta-data" cat >"$tmp/exmd" <<EOT array: diff --git a/tests/packager-tool/tst_packager-tool.cpp b/tests/packager-tool/tst_packager-tool.cpp index 0546cffe..bed5c5d3 100644 --- a/tests/packager-tool/tst_packager-tool.cpp +++ b/tests/packager-tool/tst_packager-tool.cpp @@ -104,7 +104,7 @@ void tst_PackagerTool::initTestCase() QVector<InstallationLocation> locations = InstallationLocation::parseInstallationLocations({ internalLocation }, m_hardwareId); QString errorString; - m_ai = ApplicationInstaller::createInstance(locations, pathTo("manifests"), pathTo("image-mounts"), &errorString); + m_ai = ApplicationInstaller::createInstance(locations, pathTo("manifests"), pathTo("image-mounts"), m_hardwareId, &errorString); QVERIFY2(m_ai, qPrintable(errorString)); QVERIFY2(ApplicationManager::createInstance(nullptr, true, &errorString), qPrintable(errorString)); |