consolidate remoting files, add signing gsoc

This commit is contained in:
Aaron Seigo 2011-04-29 15:18:35 +02:00
parent 365cdef434
commit 9cdbf422ff
24 changed files with 954 additions and 28 deletions

View File

@ -47,6 +47,11 @@ if(QCA2_FOUND)
endif(QCA2_FOUND)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config-plasma.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-plasma.h)
#FIXME: gpgme++ is in kdepimlibs, must move somewhere else!
macro_optional_find_package(KdepimLibs 4.5.60)
macro_log_feature(KDEPIMLIBS_FOUND "kdepimlibs" "KDE PIM libraries" "http://www.kde.org" FALSE "" "Needed for building several Plasma DataEngines")
include_directories(${KDEPIMLIBS_INCLUDE_DIRS})
add_subdirectory(tests)
add_definitions(-DKDE_DEFAULT_DEBUG_AREA=1209)
@ -109,7 +114,6 @@ set(plasma_LIB_SRCS
private/datacontainer_p.cpp
private/dataengineconsumer.cpp
private/dataengineservice.cpp
private/denyallauthorization.cpp
private/effectwatcher.cpp
private/extenderapplet.cpp
private/extenderitemmimedata.cpp
@ -117,8 +121,6 @@ set(plasma_LIB_SRCS
private/getsource.cpp
private/nativetabbar.cpp
private/packages.cpp
private/pinpairingauthorization.cpp
private/pinpairingdialog.cpp
private/plasmoidservice.cpp
private/remotedataengine.cpp
private/remoteservice.cpp
@ -127,7 +129,6 @@ set(plasma_LIB_SRCS
private/serviceprovider.cpp
private/storage.cpp
private/style.cpp
private/trustedonlyauthorization.cpp
private/tooltip.cpp
private/wallpaperrenderthread.cpp
private/windowpreview.cpp
@ -143,7 +144,12 @@ set(plasma_LIB_SRCS
remote/authorizationrule.cpp
remote/clientpinrequest.cpp
remote/credentials.cpp
remote/denyallauthorization.cpp
remote/pinpairingauthorization.cpp
remote/pinpairingdialog.cpp
remote/serviceaccessjob.cpp
remote/signing.cpp
remote/trustedonlyauthorization.cpp
runnercontext.cpp
runnermanager.cpp
runnersyntax.cpp
@ -216,7 +222,7 @@ endif(NOT KDE_NO_DEPRECATED)
kde4_add_kcfg_files(plasma_LIB_SRCS data/kconfigxt/libplasma-theme-global.kcfgc)
kde4_add_ui_files(plasma_LIB_SRCS
private/pinpairing.ui
remote/pinpairing.ui
private/publish.ui)
#NEPOMUK_GENERATE_FROM_ONTOLOGY(
# nwc.nrl
@ -246,6 +252,8 @@ kde4_add_library(plasma ${LIBRARY_TYPE} ${plasma_LIB_SRCS})
target_link_libraries(plasma ${QT_QTUITOOLS_LIBRARY} ${QT_QTWEBKIT_LIBRARY}
${QT_QTSCRIPT_LIBRARY} ${QT_QTNETWORK_LIBRARY} ${QT_QTXML_LIBRARY} ${QT_QTSQL_LIBRARY} ${QT_QTDECLARATIVE_LIBRARY}
${KDE4_KDEUI_LIBS} kdnssd threadweaver kdeclarative ${PLASMA_EXTRA_LIBS})
#FIXME gpgme++ is in kdepimlibs, neeeds to be elsewhere
target_link_libraries(plasma ${KDEPIMLIBS_GPGMEPP_LIBS})
if(QCA2_FOUND)
target_link_libraries(plasma ${QCA2_LIBRARIES})

View File

@ -70,7 +70,6 @@
#endif
#include "abstracttoolbox.h"
#include "authorizationmanager.h"
#include "authorizationrule.h"
#include "configloader.h"
#include "containment.h"
@ -88,6 +87,8 @@
#include "private/applethandle_p.h"
#include "private/extenderitem_p.h"
#include "private/framesvg_p.h"
#include "remote/authorizationmanager.h"
#include "remote/authorizationmanager_p.h"
#include "theme.h"
#include "view.h"
#include "widgets/iconwidget.h"
@ -101,7 +102,6 @@
#include "pluginloader.h"
#include "private/associatedapplicationmanager_p.h"
#include "private/authorizationmanager_p.h"
#include "private/containment_p.h"
#include "private/extenderapplet_p.h"
#include "private/package_p.h"

View File

@ -32,13 +32,13 @@
#include <kservice.h>
#include <kstandarddirs.h>
#include "authorizationmanager.h"
#include "datacontainer.h"
#include "package.h"
#include "remote/authorizationmanager.h"
#include "remote/authorizationmanager_p.h"
#include "service.h"
#include "scripting/dataenginescript.h"
#include "private/authorizationmanager_p.h"
#include "private/dataengineservice_p.h"
#include "private/remotedataengine_p.h"
#include "private/service_p.h"

View File

@ -48,12 +48,12 @@
#include <kzip.h>
#include <kdebug.h>
#include "authorizationmanager.h"
#include "packagemetadata.h"
#include "private/authorizationmanager_p.h"
#include "private/package_p.h"
#include "private/plasmoidservice_p.h"
#include "private/service_p.h"
#include "remote/authorizationmanager.h"
#include "remote/authorizationmanager_p.h"
namespace Plasma
{

View File

@ -274,14 +274,17 @@ enum AnnouncementMethod {
Q_DECLARE_FLAGS(AnnouncementMethods, AnnouncementMethod)
enum TrustLevel {
InvalidCredentials = 0, /**< The credentials are invalid **/
UnknownCredentials = 1, /**< The credentials are unknown **/
ValidCredentials = 2, /**< The credentials are valid **/
TrustedCredentials = 3, /**< The credentials are trusted **/
UltimateCredentials = 4 /**< The ultimate trust level applies to the credentials **/
UnverifiableTrust = 0, /**< The plasmoid is shipped without any signature file*/
CompletelyUntrusted, /**< The plasmoid has been signed with a broken/expired/false signature*/
UnknownTrusted, /**< The plasmoid has been signed with an unknown key*/
UserTrusted, /**< The plasmoid has been signed with a key signed by the user himself*/
SelfTrusted, /**< The plasmoid has been signed with a user key*/
FullyTrused, /**< The plasmoid has been signed with a key signed by a KDE key*/
UltimatelyTrusted /**< The plasmoid has been signed with a KDE key*/
};
Q_ENUMS(TrustLevel)
/**
* @return the scaling factor (0..1) for a ZoomLevel
**/

View File

@ -21,9 +21,9 @@
#include "private/accessmanager_p.h"
#include "authorizationmanager.h"
#include "authorizationmanager_p.h"
#include "service.h"
#include "serviceaccessjob.h"
#include "private/authorizationmanager_p.h"
#include "config-plasma.h"

View File

@ -18,19 +18,19 @@
*/
#include "authorizationmanager.h"
#include "private/authorizationmanager_p.h"
#include "authorizationmanager_p.h"
#include "authorizationinterface.h"
#include "authorizationrule.h"
#include "authorizationrule_p.h"
#include "denyallauthorization_p.h"
#include "credentials.h"
#include "pinpairingauthorization_p.h"
#include "service.h"
#include "servicejob.h"
#include "trustedonlyauthorization_p.h"
#include "private/authorizationrule_p.h"
#include "private/denyallauthorization_p.h"
#include "private/joliemessagehelper_p.h"
#include "private/pinpairingauthorization_p.h"
#include "private/trustedonlyauthorization_p.h"
#include <QtCore/QBuffer>
#include <QtCore/QMap>

View File

@ -20,9 +20,9 @@
#include "authorizationrule.h"
#include "authorizationmanager.h"
#include "authorizationmanager_p.h"
#include "authorizationrule_p.h"
#include "credentials.h"
#include "private/authorizationmanager_p.h"
#include "private/authorizationrule_p.h"
#include <QtCore/QObject>
#include <QtCore/QTimer>

View File

@ -132,7 +132,7 @@ TrustLevel Credentials::trustLevel() const
}
*/
//Trust no one ;)
return ValidCredentials;
return UnknownTrusted;
}
bool Credentials::isValid() const

View File

@ -49,7 +49,7 @@ void PinPairingAuthorization::clientPinRequest(ClientPinRequest &request)
void PinPairingAuthorization::authorizationRequest(AuthorizationRule &rule)
{
kDebug();
if (rule.credentials().trustLevel() > TrustedCredentials) {
if (rule.credentials().trustLevel() > UnknownTrusted) {
rule.setPolicy(AuthorizationRule::Allow);
rule.setTargets(AuthorizationRule::AllServices);
} else {

657
remote/signing.cpp Normal file
View File

@ -0,0 +1,657 @@
/*
* Copyright (C) 2010 by Diego '[Po]lentino' Casella <polentino911@gmail.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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
*/
#include "signing.h"
#include "signing_p.h"
#define _FILE_OFFSET_BITS 64
#include <gpgme.h>
#include <gpgme++/gpgmefw.h>
#include <gpgme++/global.h>
#include <gpgme++/context.h>
#include <gpgme++/error.h>
#include <gpgme++/engineinfo.h>
#include <gpgme++/key.h>
#include <gpgme++/keylistresult.h>
#include <gpgme++/keygenerationresult.h>
#include <gpgme++/importresult.h>
#include <gpgme++/data.h>
#include <QtCore/QDir>
#include <QtCore/QStringList>
#include <kdirwatch.h>
#include <kdebug.h>
#include <kstandarddirs.h>
#include <kprocess.h>
#include <kuser.h>
#include <cstdio> // FILE
namespace Plasma
{
SigningPrivate::SigningPrivate(Signing *auth, const QString &keystorePath = 0)
: q(auth)
{
GpgME::initializeLibrary();
GpgME::Error error = GpgME::checkEngine(GpgME::OpenPGP);
if (error) {
kDebug() << "OpenPGP engine not found: authentication will not work.";
return;
}
m_gpgContext = GpgME::Context::createForProtocol(GpgME::OpenPGP);
m_gpgContext->setKeyListMode(GPGME_KEYLIST_MODE_LOCAL | GPGME_KEYLIST_MODE_SIGS);
m_keystorePath = keystorePath;
if (m_keystorePath.isEmpty() || m_keystorePath.isNull()) {
// From the gpgme doc: if the homeDirectory() is null, it means we are using the standard dir,
// that is "/home/$USER/.gnupg/ ; so let's retrieve it.
KUser user;
m_keystorePath.append(user.homeDir()).append("/.gnupg/");
} else {
error = m_gpgContext->setEngineHomeDirectory(m_keystorePath.toAscii().data());
if (error) {
kDebug() << "Failed setting custom gpg keystore directory: using default.";
}
}
m_keystoreDir = new KDirWatch();
m_keystoreDir->addDir(m_keystorePath);
m_keystoreDir->startScan(true);
m_KdeKeysDir = new KDirWatch();
m_KdeKeysDir->addDir(KStandardDirs::locate("appdata", "plasmakeys/"));
m_KdeKeysDir->startScan(true);
// Start watching the keystore and the dir with the kde keys, and notify for changed
q->connect(m_keystoreDir, SIGNAL(created(const QString &)), q, SLOT(slotProcessKeystore()));
// q->connect(m_keystoreDir, SIGNAL(dirty(const QString &)), q, SLOT(slotKDEKeyRemoved(const QString &)));
q->connect(m_keystoreDir, SIGNAL(deleted(const QString &)), q, SLOT(slotKDEKeyRemoved(const QString &)));
q->connect(m_KdeKeysDir, SIGNAL(created(const QString &)), q, SLOT(slotKDEKeyAdded(const QString &)));
q->connect(m_KdeKeysDir, SIGNAL(dirty(const QString &)), q, SLOT(slotKDEKeyAdded(const QString &)));
q->connect(m_KdeKeysDir, SIGNAL(deleted(const QString &)), q, SLOT(slotKDEKeyRemoved(const QString &)));
}
void SigningPrivate::importKdeKeysToKeystore()
{
QList< QByteArray > tmp;
if (!m_gpgContext) {
kDebug() << "GPGME context not valid: please re-initialize the library.";
keys.insert(UltimatelyTrusted, tmp);
return;
}
QString path(KStandardDirs::locate("appdata", "plasmakeys/"));
QDir dir(path);
if (!dir.exists() || path.isEmpty() || path.isNull()) {
kDebug() << "Directory with KDE keys not found: aborting";
keys[UltimatelyTrusted] = tmp;
return;
}
QStringList keyFiles = dir.entryList(QDir::Files); // QDir::Files is rendundant in this stage
// Foreach file found, open it and import the key into the gpg keyring.
// First avoid firing multiple entryWritten() signals
m_keystoreDir->stopScan();
m_KdeKeysDir->stopScan();
foreach(QString keyFile, keyFiles) {
FILE *fp;
fp = fopen(keyFile.toAscii().data(), "r");
GpgME::Data data(fp);
GpgME::ImportResult iRes = m_gpgContext->importKeys(data);
if (iRes.error()) {
kDebug() << "Error while importing the key located at: " << keyFile;
kDebug() << " The error is:" << iRes.error().asString() << "; Skipping.";
continue;
}
// The first fingerprint listed is the one we need to save
tmp.append(iRes.import(0).fingerprint());
}
keys[UltimatelyTrusted] = tmp;
// Restore scanning folders
m_keystoreDir->startScan(true, true);
m_KdeKeysDir->startScan(true, true);
}
void SigningPrivate::splitKeysByTrustLevel()
{
if (!m_gpgContext) {
kDebug() << "GPGME context not valid: please re-initialize the library.";
return;
}
QList<QByteArray> temp = keys[UltimatelyTrusted];
keys.clear();
keys[UltimatelyTrusted] = temp;
// Splitting the keys by their trust level is a boring task, since we have to distinguish
// `which key has been signed with an other given key` :P
//
// Loop 1: import and load the KDE keys, already done in importKdeKeysToKeystore()
//
// Loop 2: load the user keyring (private keys only), and loop for:
// - a: a key not yet expired;
// - b: a key not already present in the keys[UltimatelyTrusted];
//
// Loop 3: load the user keyring, and loop for:
// - a: a key not yet expired;
// - b: a key not already present in the keys[UltimatelyTrusted];
// - c: a key not yet in keys[SelfTrusted]
//
// After Loop 3, the tmp object contains the remaining keys not yet processed.
//
// Loop 4: foreach key not yet classified, inspect their signatures and:
// - a: if contains a key from keys[UltimatelyTrusted], save it in keys[FullyTrused];
// - b: if contains a key from keys[SelfTrusted], save it in keys[UserTrusted];
// - c: if the signature is unknown, let's save it in keys[UnknownTrusted].
QList< QByteArray > tmp;
GpgME::Error error = m_gpgContext->startKeyListing("", true);
while (!error) { // Loop 2
GpgME::Key key = m_gpgContext->nextKey(error);
if (error)
break;
QByteArray data(key.subkey(0).fingerprint());
// If the key is disabled, expired, invalid or revoked, put it in the untrusted list
if (key.isDisabled() || key.isExpired() || key.isInvalid() || key.isRevoked()) {
keys[CompletelyUntrusted].append(data);
continue;
}
// Ensure we are not processing twice the trusted KDE keys
if (keys[UltimatelyTrusted].contains(data)) {
continue;
}
// The keys is new, valid and private: save it !
keys[SelfTrusted].append(data);
}
GpgME::KeyListResult lRes = m_gpgContext->endKeyListing();
error = m_gpgContext->startKeyListing("");
while (!error) { // Loop 3
GpgME::Key key = m_gpgContext->nextKey(error);
if (error)
break;
QByteArray data(key.subkey(0).fingerprint());
if (keys[UltimatelyTrusted].contains(data) ||
keys[SelfTrusted].contains(data)) {
continue;
}
// If the key is disabled, expired, invalid or revoked, put it in the untrusted list
if (key.isDisabled() || key.isExpired() || key.isInvalid() || key.isRevoked()) {
keys[CompletelyUntrusted].append(data);
continue;
}
// The keys is new, valid and public: save it !
tmp.append(data);
}
lRes = m_gpgContext->endKeyListing();
if (lRes.error()) {
kDebug() << "Error while ending the keyListing operation: " << lRes.error().asString();
}
//Loop 4 - looking for keys signed by kde or by the user, tmp contains the valid public keys remaining
QString kdeKeys;
foreach(QByteArray s, keys[UltimatelyTrusted]) {
kdeKeys.append(s).append(' ');
}
QString selfKeys;
foreach(QByteArray s, keys[SelfTrusted]) {
selfKeys.append(s).append(' ');
}
foreach(QByteArray unknowTmpKey, tmp) {
QStringList signers = signersOf(QString(unknowTmpKey));
bool stored = false;
foreach(QString signer, signers) {
if (kdeKeys.contains(signer)) {
// if the unknown key has a signer that is a kde key, let's trust it
keys[FullyTrused].append(unknowTmpKey);
stored = true;
break;
} else if (selfKeys.contains(unknowTmpKey)) {
// if the unknown key has a signer that is a user key, let's trust it
keys[UserTrusted].append(unknowTmpKey);
stored = true;
break;
}
}
if (!stored) {
// We didn't stored the unknown key in the previous loop, which means that we
// don't know the hey al all.
keys[UnknownTrusted].append(unknowTmpKey);
}
}
// Lets print out all the keys found till now.
temp = keys[UltimatelyTrusted];
QStringList list;
foreach(QByteArray ba, temp) {
list.append(ba);
}
kDebug() << "UltimatelyTrusted = " << list;
list.clear();
temp = keys[FullyTrused];
foreach(QByteArray ba, temp) {
list.append(ba);
}
kDebug() << "FullyTrused = " << list;
list.clear();
temp = keys[SelfTrusted];
foreach(QByteArray ba, temp) {
list.append(ba);
}
kDebug() << "SelfTrusted = " << list;
list.clear();
temp = keys[UserTrusted];
foreach(QByteArray ba, temp) {
list.append(ba);
}
kDebug() << "UserTrusted = " << list;
list.clear();
temp = keys[UnknownTrusted];
foreach(QByteArray ba, temp) {
list.append(ba);
}
kDebug() << "UnknownTrusted = " << list;
list.clear();
temp = keys[CompletelyUntrusted];
foreach(QByteArray ba, temp) {
list.append(ba);
}
kDebug() << "CompletelyUntrusted = " << list;
kDebug() << "ALL = " << keys;
}
QStringList SigningPrivate::keysID(const bool returnPrivate) const
{
QStringList result;
if (!m_gpgContext) {
kDebug() << "GPGME context not valid: please re-initialize the library.";
return result;
}
GpgME::Error error = m_gpgContext->startKeyListing("", returnPrivate);
while (!error) {
GpgME::Key k = m_gpgContext->nextKey(error);
if (error)
break;
result.append(k.subkey(0).fingerprint());
}
GpgME::KeyListResult lRes = m_gpgContext->endKeyListing();
if (lRes.error()) {
kDebug() << "Error while ending the keyListing operation: " << lRes.error().asString();
}
return result;
}
QString SigningPrivate::signerOf(const QString &messagePath, const QString &signaturePath) const
{
FILE *pFile;
FILE *pSig;
pFile = fopen(messagePath.toAscii().data(), "r");
pSig = fopen(signaturePath.toAscii().data(), "r");
GpgME::Data file(pFile);
GpgME::Data sig(pSig);
GpgME::VerificationResult vRes = m_gpgContext->verifyDetachedSignature(sig, file);
if (!vRes.error()) {
kDebug() << "message " << messagePath << " and signature " << signaturePath << "matched! The fingerprint of the signer is: " << vRes.signature(0).fingerprint();
return QString(vRes.signature(0).fingerprint());
}
return QString();
}
QString SigningPrivate::descriptiveString(const QString &keyID) const
{
QString result;
if (!m_gpgContext) {
kDebug() << "GPGME context not valid: please re-initialize the library.";
return result;
}
GpgME::Error error = m_gpgContext->startKeyListing("");
while (!error) {
GpgME::Key k = m_gpgContext->nextKey(error);
if (error)
break;
QString fullID(k.subkey(0).fingerprint());
if (fullID.contains(keyID)) {
result.append(k.userID(0).id());
break;
}
}
GpgME::KeyListResult lRes = m_gpgContext->endKeyListing();
if (lRes.error()) {
kDebug() << "Error while ending the keyListing operation: " << lRes.error().asString();
}
return result;
}
QString SigningPrivate::keystorePath() const
{
return m_keystorePath;
}
void SigningPrivate::slotProcessKeystore()
{
QMap<TrustLevel, QList<QByteArray> > tmpMap = keys;
splitKeysByTrustLevel();
QList<QByteArray> oldValues;
oldValues << tmpMap[UnverifiableTrust]
<< tmpMap[CompletelyUntrusted]
<< tmpMap[UnknownTrusted]
<< tmpMap[SelfTrusted]
<< tmpMap[FullyTrused]
<< tmpMap[UltimatelyTrusted];
QList<QByteArray> newValues;
newValues << keys[UnverifiableTrust]
<< keys[CompletelyUntrusted]
<< keys[UnknownTrusted]
<< keys[SelfTrusted]
<< keys[FullyTrused]
<< keys[UltimatelyTrusted];
QString result;
bool keystoreIncreased = (newValues.size() >= oldValues.size());
if (keystoreIncreased) {
foreach(QByteArray value, newValues) {
if (!oldValues.contains(value)) {
// Found the key added
result.append(value);
break;
}
}
emit(q->keyAdded(result));
} else {
foreach(QByteArray value, oldValues) {
if (!newValues.contains(value)) {
// Found the removed key
result.append(value);
break;
}
}
emit(q->keyRemoved(result));
}
}
void SigningPrivate::slotKDEKeyAdded(const QString path)
{
// Avoid firing multiple signals by kdirwatch instances
m_KdeKeysDir->stopScan();
m_keystoreDir->stopScan();
FILE *fp;
fp = fopen(path.toAscii().data(), "r");
GpgME::Data data(fp);
GpgME::ImportResult iRes = m_gpgContext->importKeys(data);
bool alreadyInMap = false;
// Ensure we don't already have the key
foreach(QByteArray sec, keys[UltimatelyTrusted]) {
if (strcmp(sec.data(), iRes.import(0).fingerprint())) {
alreadyInMap = true;
break;
}
}
if (!alreadyInMap) {
keys[UltimatelyTrusted] << QByteArray(iRes.import(0).fingerprint());
splitKeysByTrustLevel();
}
// Restore scanning folders
m_KdeKeysDir->startScan(true, true);
m_keystoreDir->startScan(true, true);
QString result(iRes.import(0).fingerprint());
emit(q->keyAdded(result));
}
void SigningPrivate::slotKDEKeyRemoved(const QString path)
{
Q_UNUSED(path)
// Avoid firing multiple signals by kdirwatch instances
m_KdeKeysDir->stopScan();
m_keystoreDir->stopScan();
QList<QByteArray> oldKeys = keys[UltimatelyTrusted];
importKdeKeysToKeystore();
QList<QByteArray> newkeys = keys[UltimatelyTrusted];
QString result;
foreach(QByteArray key, oldKeys) {
if (!newkeys.contains(key)) {
// We found the missing key :)
result.append(key);
break;
}
}
GpgME::Error error = m_gpgContext->startKeyListing("");
while (!error) {
GpgME::Key k = m_gpgContext->nextKey(error);
if (error)
break;
if (result.contains(k.subkey(0).fingerprint())) {
error = m_gpgContext->startKeyDeletion(k, true); // GG
if (error) {
kDebug() << "Can't delete key with fingerprint: " << result;
m_gpgContext->endKeyListing();
return;
}
break;
}
}
GpgME::KeyListResult lRes = m_gpgContext->endKeyListing();
if (lRes.error()) {
kDebug() << "Error while ending the keyListing operation: " << lRes.error().asString();
}
splitKeysByTrustLevel();
// Restore scanning folders
m_KdeKeysDir->startScan(true, true);
m_keystoreDir->startScan(true, true);
emit(q->keyRemoved(result));
}
QStringList SigningPrivate::signersOf(const QString id) const
{
QStringList result;
GpgME::Error error = m_gpgContext->startKeyListing("");
while (!error) {
GpgME::Key k = m_gpgContext->nextKey(error);
if (error)
break;
for (unsigned int i = 0; i < k.numUserIDs(); ++i) {
for (unsigned int j = 0; j < k.userID(i).numSignatures(); ++j) {
QString sig(k.userID(i).signature(j).signerKeyID());
if (!result.contains(sig)) {
if(!id.contains(sig))
result.append(sig);
}
}
}
}
GpgME::KeyListResult lRes = m_gpgContext->endKeyListing();
if (lRes.error()) {
kDebug() << "Error while ending the keyListing operation: " << lRes.error().asString();
}
kDebug() << "Hey, the key " << id << " has been signed with " << result;
return result;
}
Signing::Signing(const QString &keystorePath)
: QObject(),
d(new SigningPrivate(this, keystorePath))
{
d->importKdeKeysToKeystore();
d->splitKeysByTrustLevel();
}
Signing::~Signing()
{
delete d;
}
QStringList Signing::keysByTrustLevel(TrustLevel trustLevel) const
{
if (trustLevel == UnverifiableTrust) {
return QStringList();
}
QList< QByteArray > s = d->keys[trustLevel];
QStringList tmp;
foreach(QByteArray sa, s) {
tmp.append(sa);
}
return tmp;
}
TrustLevel Signing::trustLevelOf(const QString &keyID) const
{
if (keyID.isEmpty() || keyID.isNull())
return Plasma::UnverifiableTrust;
for (int i = (int)Plasma::UnverifiableTrust; i <= (int)Plasma::UltimatelyTrusted; ++i) {
QList< QByteArray > tmp = d->keys[(Plasma::TrustLevel)i];
foreach(QByteArray key, tmp) {
if (key.contains(keyID.toAscii().data()))
return (Plasma::TrustLevel)i;
}
}
return Plasma::UnverifiableTrust;
}
QStringList Signing::privateKeys() const
{
return d->keysID(true);
}
QStringList Signing::publicKeys() const
{
return d->keysID(false);
}
QString Signing::signerOf(const KUrl &plasmoidPath, const KUrl &plasmoidSignaturePath) const
{
kDebug() << "Checking existence of " << plasmoidPath.pathOrUrl();
kDebug() << "Checking existence of " << plasmoidSignaturePath.pathOrUrl();
// Original file and signature to verify against
QFile fileHanlder(plasmoidPath.path());
QFile signatureHandler(plasmoidSignaturePath.isEmpty() ?
plasmoidPath.path().append(".asc") :
plasmoidSignaturePath.path());
fileHanlder.open(QIODevice::ReadOnly);
signatureHandler.open(QIODevice::ReadOnly);
if (!fileHanlder.exists()) {
kDebug() << "Plasmoid package doesn't exists: signature verification aborted.";
return QString();
}
if (!signatureHandler.exists()) {
kDebug() << "Plasmoid signature doesn't exists: signature verification aborted.";
return QString();
}
kDebug() << "Cheking if " << plasmoidPath.pathOrUrl() << " and " << plasmoidSignaturePath.pathOrUrl() << " matches";
return d->signerOf(plasmoidPath.pathOrUrl(), plasmoidSignaturePath.pathOrUrl());
}
QString Signing::keyStorePath() const
{
return d->keystorePath();
}
QString Signing::descriptiveString(const QString &keyID) const
{
if (keyID.isNull() || keyID.isEmpty())
return QString();
return d->descriptiveString(keyID);
}
}
#include "moc_signing.cpp"

187
remote/signing.h Normal file
View File

@ -0,0 +1,187 @@
/*
* Copyright (C) 2010 by Diego '[Po]lentino' Casella <polentino911@gmail.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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
*/
#ifndef AUTHENTICATION_H
#define AUTHENTICATION_H
#include <plasma/plasma_export.h>
#include <QtCore/QObject>
#include <QtCore/QDateTime>
#include <kurl.h>
#include <plasma.h>
class QStringList;
class QString;
/**
* Global namespace for Signing library
*/
namespace Plasma
{
class SigningPrivate;
/**
* A class to manage plasmoids authentication
*
* The Signing class is used to get the trust level of a scripted plasmoid by performing a check
* between the signature shipped with it, and the PGP keys found in the user keystore. If the keystore
* is empty, this class will take charge of populating it with the pre-shipped keys. To accomplish
* that, it relies upon the Gpgme++ libray; however the developer won't notice this, since the keys
* are accessed by their QString ID.
* It also performs handy operations, such as populating the local keystore with the keys shipped
* by default with KDE/linux distro, and notify the application which is using it about changes on the
* local keystore or in the keys folder.
*
* Example of usage:
* @code
*
* Plasma::Signing *m_auth = new Plasma::Signing(); // the constructor takes care of loading and spltting the keys
* // loaded by the default keystore.
*
* // If you want to specify a different keystore, simply put its relative path as argument:
* Plasma::Signing *m_auth = new Plasma::Signing(keystoreFullPath);
*
* // Now, supposed to previously saved in plasmoidPath and signaturePath the paths of the plasmoid and signature to check; then
* QString signer = m_auth->signerOf(plasmoidPath, signaturePath); // Returns the the hash of the signer key, if the file and
* // the signature have been successfully verified
*
* // If the signature is in the same folder of the file, you can also omit its path; the library will automatically load the
* // signature named plasmoidPath plus the ".asc" file extension.
* QString signer = m_auth->signerOf(plasmoidPath);
*
* // If you need to know the authentication level associated with a specific signer, simply call:
* Plasma::TrustLevel level = m_auth->trustLevelOf(signer)
*
* // If you need more details about a key with a given keyID, you have to call:
* QString info = m_auth->descriptiveString(keyID);
*
* @endcode
*
* @since 4.6
* @author Diego '[Po]lentino' Casella <polentino911@gmail.com>
*/
class PLASMA_EXPORT Signing : public QObject
{
Q_OBJECT
public:
/**
* Default constructor.
* It takes charge of loading the KDE keys, splitting the keys found in the default keystore (or in the one
* specified by @param keystorePath).
*
* @param keystorePath a default QString that denotes the full path of the keystore being used for the authentication
* process. Note that once selected, you can't change it.
*
*/
Signing(const QString &keystorePath = 0);
~Signing();
/**
* Returns a QStringList object containing all the key ID that matches the TrustLevel passed
* as parameter to the function
*
* @param trustLevel the TrustLevel we want to
*
* @return the QStringList with all the ID of the matching keys, or an empty one otherwise
*/
QStringList keysByTrustLevel(TrustLevel trustLevel) const;
/**
* Return the TrustLevel associated with the key passed as parameter to the function
*
* @param keyID the key we want to retrieve its trust level
*
* @return the TrustLevel value
*/
TrustLevel trustLevelOf(const QString &keyID) const;
/**
* @return a QStringList object containing the ID of all the private keys found in the keyring.
*/
QStringList privateKeys() const;
/**
* @return a QStringList object containing the ID of all the public keys found in the keyring.
* @note Private/Public key pairs are not returned: @see privateKeys() for that.
*/
QStringList publicKeys() const;
/**
* Tests for a successful match between the plasmoid 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 ".asc" to the plasmoid path.
*
* @arg plasmoidPath the full path of the plasmoid package we want to test
* @arg plasmoidSignaturePath optional path for the signature file
*
* @return a Qstring with the signer's unique key id, or an empty one if a signer was not found.
*/
QString signerOf(const KUrl &plasmoidPath, const KUrl &plasmoidSignaturePath = KUrl()) const ;
/**
* @return the QString path of the keystore being used.
*/
QString keyStorePath() const;
/**
* Method used to retrieve additional informations about the key passed as parameter to the function.
*
* @arg keyID the string containing the hash of the key we want to retrive the informations.
*
* @return a QString object containing the name, the email and the comment (if any) referenced by the
* id passed as argument to the function.
*/
QString descriptiveString(const QString &keyID) const;
Q_SIGNALS:
/**
* Emitted when a new key is added from the trusted keys folder. Applications should connect
* to this signal in order to update the trust level of the associated plasmoids.
*
* @param keyId the key added
*/
void keyAdded(const QString &keyId);
/*
* Emitted when a new key is removed from the trusted keys folder. Applications should connect
* to this signal in order to update the trust level of the associated plasmoids.
*
* @param keyID the key removed
*/
void keyRemoved(const QString &keyId);
private:
Q_PRIVATE_SLOT(d, void slotProcessKeystore());
Q_PRIVATE_SLOT(d, void slotKDEKeyAdded(QString path));
Q_PRIVATE_SLOT(d, void slotKDEKeyRemoved(QString path));
SigningPrivate * const d;
friend class SigningPrivate;
};
} // end Plasma namespace
#endif // AUTHENTICATION_H

71
remote/signing_p.h Normal file
View File

@ -0,0 +1,71 @@
/*
* Copyright (C) 2010 by Diego '[Po]lentino' Casella <polentino911@gmail.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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
*/
#ifndef SIGNING_P_H
#define SIGNING_P_H
#include <QtCore/QObject>
#include <QtCore/QStringList>
#include <KDE/KDirWatch>
namespace GpgME {
class Context;
}
namespace Plasma
{
/**
* @brief Encapsulates all the nasty GpgME stuff and shows a more friendly a simple implementation
* for our goal.
*/
class SigningPrivate
{
public:
SigningPrivate(Signing *auth, const QString &keystorePath);
Signing *q;
// Save all the keys in a single object, splitted by their SigningLevel
// Note: keys[CompletelyUntrusted] refers to an empty list
QMap<TrustLevel, QList<QByteArray> > keys;
void importKdeKeysToKeystore();
void splitKeysByTrustLevel();
QStringList keysID(const bool returnPrivate) const;
QString signerOf(const QString &messagePath, const QString &signaturePath) const;
QString descriptiveString(const QString &keyID) const;
QString keystorePath() const;
void slotProcessKeystore();
void slotKDEKeyAdded(const QString path);
void slotKDEKeyRemoved(const QString path);
QStringList signersOf(const QString id) const;
KDirWatch *m_KdeKeysDir; // used to be notified for changes in the folder with KDE keys
KDirWatch *m_keystoreDir; // used to be notified for changes in the gnupg folder
GpgME::Context *m_gpgContext;
QString m_keystorePath;
};
}
#endif // SIGNING_P_H

View File

@ -45,7 +45,7 @@ void TrustedOnlyAuthorization::clientPinRequest(ClientPinRequest &request)
void TrustedOnlyAuthorization::authorizationRequest(AuthorizationRule &rule)
{
if (rule.credentials().trustLevel() > TrustedCredentials) {
if (rule.credentials().trustLevel() > UnknownTrusted) {
rule.setPolicy(AuthorizationRule::Allow);
rule.setTargets(AuthorizationRule::AllServices);
}

View File

@ -18,7 +18,6 @@
*/
#include "service.h"
#include "private/authorizationmanager_p.h"
#include "private/service_p.h"
#include "private/serviceprovider_p.h"
@ -41,6 +40,7 @@
#include "private/remoteservice_p.h"
#include "private/remoteservicejob_p.h"
#include "pluginloader.h"
#include "remote/authorizationmanager_p.h"
namespace Plasma
{