From 73758abf97a61c970749d48d1b6a17e6db73208b Mon Sep 17 00:00:00 2001 From: Aaron Seigo Date: Thu, 26 May 2011 16:02:56 +0200 Subject: [PATCH] start of package verification --- remote/signing.cpp | 57 ++++++++++++++++++---- remote/signing.h | 17 ++++++- remote/signing_p.h | 1 + tests/signed.plasmoid | Bin 0 -> 1540 bytes tests/signed.plasmoid.sig | Bin 0 -> 72 bytes tests/signedPackage/contents/code/main.js | 45 +++++++++++++++++ tests/signedPackage/metadata.desktop | 21 ++++++++ tests/signingtest.cpp | 3 +- 8 files changed, 132 insertions(+), 12 deletions(-) create mode 100644 tests/signed.plasmoid create mode 100644 tests/signed.plasmoid.sig create mode 100644 tests/signedPackage/contents/code/main.js create mode 100644 tests/signedPackage/metadata.desktop diff --git a/remote/signing.cpp b/remote/signing.cpp index d424ec4f7..7207d4b6b 100644 --- a/remote/signing.cpp +++ b/remote/signing.cpp @@ -42,6 +42,7 @@ #include #include +#include "plasma/package.h" #include // FILE @@ -493,6 +494,39 @@ TrustLevel Signing::trustLevelOf(const QString &keyID) const return d->addKeyToCache(keyID.toAscii()); } +QString Signing::signerOf(const Package &package) const +{ + const QString contents = package.path() + "CONTENTS"; + kDebug() << "gonna go in for" << package.path(); + kDebug() << "hash is" << package.contentsHash(); + + if (!QFile::exists(contents)) { + kDebug() << "not contents hash for package at" << package.path(); + return QString(); + } + + QFile file(contents); + + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { + kDebug() << "could not open hash file for reading" << contents; + return QString(); + } + + char hash[10 * 1024]; + qint64 read = file.read(hash, 10 * 1024 - 1); + if (read < 1) { + kDebug() << "failed to read the CONTENTS file at" << contents; + } + + hash[read + 1] = '\0'; + const QString actualHash = package.contentsHash(); + if (actualHash != hash) { + kDebug() << "CONTENTS does not match contents of package" << package.path(); + } + + return "Success!"; +} + QString Signing::signerOf(const KUrl &package, const KUrl &signature) const { kDebug() << "Checking existence of " << package.pathOrUrl(); @@ -503,25 +537,28 @@ QString Signing::signerOf(const KUrl &package, const KUrl &signature) const return QString(); } - const QString packagePath = package.path(); - if (!QFile::exists(packagePath)) { - kDebug() << "Package" << packagePath << "does not exist: signature verification aborted."; + return d->verifySignature(package.path(), signature.path()); +} + +QString SigningPrivate::verifySignature(const QString &filePath, const QString &signature) +{ + if (!QFile::exists(filePath)) { + kDebug() << "Package" << filePath << "does not exist: signature verification aborted."; return QString(); } - const QString signaturePath = signature.isEmpty() ? packagePath + (".sig") - : signature.path(); + const QString signaturePath = signature.isEmpty() ? filePath + (".sig") : signature; if (!QFile::exists(signaturePath)) { kDebug() << "Signature" << signaturePath << "does not exist: signature verification aborted."; return QString(); } - //kDebug() << "Cheking if " << packagePath << " and " << signaturePath << " matches"; + //kDebug() << "Cheking if " << filePath << " and " << signaturePath << " matches"; - FILE *pFile = fopen(packagePath.toLocal8Bit().data(), "r"); + FILE *pFile = fopen(filePath.toLocal8Bit().data(), "r"); if (!pFile) { - kDebug() << "failed to open package file" << packagePath; + kDebug() << "failed to open file" << filePath; return QString(); } @@ -535,7 +572,7 @@ QString Signing::signerOf(const KUrl &package, const KUrl &signature) const GpgME::Data file(pFile); GpgME::Data sig(pSig); - GpgME::VerificationResult vRes = d->m_gpgContext->verifyDetachedSignature(sig, file); + GpgME::VerificationResult vRes = m_gpgContext->verifyDetachedSignature(sig, file); QString rv; if (!vRes.error()) { @@ -547,7 +584,7 @@ QString Signing::signerOf(const KUrl &package, const KUrl &signature) const } } - //kDebug() << "message " << packagePath << " and signature " << signaturePath << "matched! The fingerprint of the signer is: " << rv; + //kDebug() << "message " << filePath << " and signature " << signaturePath << "matched! The fingerprint of the signer is: " << rv; } fclose(pFile); diff --git a/remote/signing.h b/remote/signing.h index 4925c2674..b9f968de0 100644 --- a/remote/signing.h +++ b/remote/signing.h @@ -38,6 +38,7 @@ class QString; namespace Plasma { +class Package; class SigningPrivate; /** @@ -116,6 +117,20 @@ public: */ TrustLevel trustLevelOf(const QString &keyID) const; + /** + * Tests for a successful match between the object and signature files, referenced by their + * absolute path. The signature path is optional and, if not specified, the function will + * automatically try to retrieve it by appending the string ".sig" to the package path. + * + * @param package a Plasma::Package object representing the package to be tested + * + * @return The signer's unique key id, or an empty string if a signer was not found. + * Failure can be due to the signature not matching or the signature file missing. + * On success, this information can then be used with trustLevelOf and/or + * descriptiveString to get more information on the key. + */ + QString signerOf(const Package &package) const; + /** * Tests for a successful match between the object and signature files, referenced by their * absolute path. The signature path is optional and, if not specified, the function will @@ -128,7 +143,7 @@ public: * * @return The signer's unique key id, or an empty string if a signer was not found. * Failure can be due to the signature not matching or the signature file missing. - * On success, this informatoin can then be used with trustLevelOf and/or + * On success, this information can then be used with trustLevelOf and/or * descriptiveString to get more information on the key. */ QString signerOf(const KUrl &package, const KUrl &signature = KUrl()) const ; diff --git a/remote/signing_p.h b/remote/signing_p.h index 4ef3c4cde..4410c1e40 100644 --- a/remote/signing_p.h +++ b/remote/signing_p.h @@ -54,6 +54,7 @@ public: Plasma::TrustLevel addKeyToCache(const QByteArray &fingerprint); void dumpKeysToDebug(); QStringList keysID(const bool returnPrivate) const; + QString verifySignature(const QString &packagePath, const QString &signaturePath); void processKeystore(const QString &path); void keyAdded(const QString &path); diff --git a/tests/signed.plasmoid b/tests/signed.plasmoid new file mode 100644 index 0000000000000000000000000000000000000000..68ca4b70accd1e8d70bbaca2f8253674d3d8b54b GIT binary patch literal 1540 zcmWIWW@h1H0D;oTN;@zEN^mmBFeK;am89mC6zhkEa56B*X7%_!u)pV9TEWf0$nt`j zfq^9js5k&_L|SPliV=LsMkME_q(aPz4_ScA91);-9AKyLt44;qF)=V~Wno|t#V{u~ zF*8pus~GMqH3tl5%?&x2ciVtx?{DoJZvvz}a^HlNaI`UMZxEB6miuzUYNd-CgLtj0NN!;-%N2zy=OngYFJpC!X35?CLd;Xc zaZ!kb*^{UhTMuTg%09y9=+UW|63Y6->QDR8B)%Um8O>$e(l0VTb8A_9c~we=Q~mx| zN{?P~|LeH5c$e+8mPqF-d>i`DDQl=d7SrYQ>IsSnJD;^U^umJUvl(Zf%3IYHVCF5j z;f{vR-1yMMy&NzPkJ8-PL^2$Y)ARFP=H@NKP#0 zWmu-vqNVN&?IJ&)$^0a^`AkQ8xs&||hSvHQPR?yhUrcV7tXY=-!qYpkuX5oP*@tHD zr9~n)Etwp9Z&J6M4L=w2#=`sjmQ}+4b}rq^5wp?FbA`h3qR^(KnSbXooqAzvYpgWk zx=|*V>#djfZhA|Zalb80*IuH@!p`>6s39jH&q~s!Pit<_+-)MxR*clm@I@z_oI z6XSw5_}Qj8Z%>-yv;OO?AUn&r!dd!{)sISQY%Fm$%?Q7;=ZQ!D4z`QiGD7*)zI%Kv zjhj;}yXkX$`dOlsWf*Yf0@W`3ajtNFp(8HsCl zg$I?DE!{kAy^cS(=CPZ~r#UAwxt6J=O2~gae)Ri-`1sp3m+qGR-_FFf)~)oQ72i#L zP~t`;%Fw!;8UscK23=sn6aXg5+|-i9l*E!my_D4A?2`NfeCaVaFxv01fxw^dnl+5e z3mCjZd>fn=PK;s{dX((BZRPDBito31<@a9>5z(x9cjirn&F`7YZ*Q_kTJ$Z~|Hviw zRaho5)Kxg*-fXd_MhPrt_a@G$%)Yqs+{I-Rg?m&Mu9|RShugIS3jJ(P9#_SBJ$`c4 z>x}k$ljP&8f_bfamI)=*a;*rL=wIgaapAnrPO;18DaLMd5L3G>5S21fgn7ZTr!ns* zne*P;|ASk?e9v<2_{T?B$wqhk8og@$?W%;J3c_k0cXSFBPG&ycdeCX%`Ls)KFy z_VtFJH%hKPH&<2dwdlh+%F4;jHzn3wHC=kkh`m+z#+R8J&q}*_$-bWbrp#yGV{=J2 z+qAToEWQ2eu{_62rah6kaP`aiPfDV1IlemY{1N=l=*#i8Z7(b~{=Hi&ANvPbtS~ak zG2<$mB%q~~0K;2H5EH4SVuh4c7^M`#ILvYi**Irp literal 0 HcmV?d00001 diff --git a/tests/signedPackage/contents/code/main.js b/tests/signedPackage/contents/code/main.js new file mode 100644 index 000000000..50a8f62c9 --- /dev/null +++ b/tests/signedPackage/contents/code/main.js @@ -0,0 +1,45 @@ +// because we put the following line in the metadata.desktop file, we have access +// to the HTTP extension in this Plasmoid. +// +// X-Plasma-RequiredExtensions=http +// +// More documentation can be found here: +// +// http://techbase.kde.org/Development/Tutorials/Plasma/JavaScript/API#Extensions + +output = new TextEdit +output.readOnly = true + +layout = new LinearLayout +layout.orientation = QtVertical +layout.addItem(output) + +// in case our request for HTTP urls in the metadata.desktop was rejected (e.g. due +// to security restrictions) we won't have a plasmoid.get, so let's check for it +// before using it! +if (plasmoid.getUrl) { + var getJob = plasmoid.getUrl("http://dot.kde.org/rss.xml"); + function recv(job, data) + { + if (job == getJob) { + print("we have our job") + if (data.length) { + output.append(data.toUtf8()) + } + } + } + + function fini(job) + { + if (job == getJob) { + print("our job is finished") + } else { + print("some other job is finished?") + } + } + + getJob.data.connect(recv) + getJob.finished.connect(fini) +} else { + output.text = i18n("HTTP access denied!") +} diff --git a/tests/signedPackage/metadata.desktop b/tests/signedPackage/metadata.desktop new file mode 100644 index 000000000..9d6cf9582 --- /dev/null +++ b/tests/signedPackage/metadata.desktop @@ -0,0 +1,21 @@ +[Desktop Entry] +Name=JavaScript File Operations +Comment=Demonstrates accessing data via HTTP in JavaScript +Icon=text-x-generic + +Type=Service +X-KDE-ServiceTypes=Plasma/Applet + +X-Plasma-API=javascript +X-Plasma-MainScript=code/main.js + +X-KDE-PluginInfo-Author=Aaron Seigo +X-KDE-PluginInfo-Email=aseigo@kde.org +X-KDE-PluginInfo-Name=org.kde.plasma.simpified-javascript-http-example +X-KDE-PluginInfo-Version=0.1 +X-KDE-PluginInfo-Website= +X-KDE-PluginInfo-Category=Examples +X-KDE-PluginInfo-Depends= +X-KDE-PluginInfo-License=GPL + +X-Plasma-OptionalExtensions=http diff --git a/tests/signingtest.cpp b/tests/signingtest.cpp index 40231b4fd..a247fdac9 100644 --- a/tests/signingtest.cpp +++ b/tests/signingtest.cpp @@ -33,7 +33,7 @@ SigningTest::SigningTest(QObject *parent) { const QString prefix = QString::fromLatin1(KDESRCDIR); m_path = prefix + "signed.plasmoid"; - m_sig = prefix + "signed.plasmoid.asc"; + m_sig = prefix + "signed.plasmoid.sig"; m_invalidSig = prefix + "signed.plasmoid.invalid.sig"; } @@ -77,6 +77,7 @@ void SigningTest::validSignatureWithoutDefinedSigFile() void SigningTest::validPackage() { + QVERIFY(!m_signing->signerOf(m_package).isEmpty()); } void SigningTest::confirmDtorPerformance()