diff --git a/autotests/expirycheckertest.cpp b/autotests/expirycheckertest.cpp index de247c46c..a6e682365 100644 --- a/autotests/expirycheckertest.cpp +++ b/autotests/expirycheckertest.cpp @@ -1,298 +1,299 @@ /* This file is part of libkleopatra's test suite. SPDX-FileCopyrightText: 2022 Sandro Knauß SPDX-FileCopyrightText: 2023 g10 Code GmbH SPDX-FileContributor: Ingo Klöcker SPDX-License-Identifier: LGPL-2.0-or-later */ #include #include +#include #include #include #include #include #include #include #include using namespace Kleo; using namespace GpgME; using days = Kleo::chrono::days; class FakeTimeProvider : public Kleo::TimeProvider { public: explicit FakeTimeProvider(const QDate &date) : mTime{date.startOfDay(Qt::UTC).toSecsSinceEpoch()} { } time_t getTime() const override { return mTime; } private: time_t mTime; }; class ExpiryCheckerTest : public QObject { Q_OBJECT private Q_SLOTS: void initTestCase() { qRegisterMetaType(); mGnupgHome = QTest::qExtractTestData(QStringLiteral("/fixtures/expirycheckertest")); qputenv("GNUPGHOME", mGnupgHome->path().toLocal8Bit()); // hold a reference to the key cache to avoid rebuilding while the test is running mKeyCache = KeyCache::instance(); // make sure that the key cache has been populated (void)mKeyCache->keys(); } void cleanupTestCase() { // verify that nobody else holds a reference to the key cache QVERIFY(mKeyCache.use_count() == 1); mKeyCache.reset(); (void)QProcess::execute(QStringLiteral("gpgconf"), {"--kill", "all"}); mGnupgHome.reset(); qunsetenv("GNUPGHOME"); } void valid_data() { QTest::addColumn("key"); QTest::addColumn("fakedate"); // use dates between creation date and expiration date (if there is one) of the test keys/certificates QTest::newRow("neverExpire") << testKey("test@kolab.org", GpgME::OpenPGP) << QDate{2012, 1, 1}; QTest::newRow("openpgp") << testKey("alice@autocrypt.example", GpgME::OpenPGP) << QDate{2020, 1, 1}; QTest::newRow("smime") << testKey("test@example.com", GpgME::CMS) << QDate{2012, 1, 1}; } void valid() { QFETCH(GpgME::Key, key); QFETCH(QDate, fakedate); - ExpiryChecker checker(days{1}, days{1}, days{1}, days{1}); + ExpiryChecker checker(ExpiryCheckerSettings{days{1}, days{1}, days{1}, days{1}}); checker.setTimeProviderForTest(std::make_shared(fakedate)); QSignalSpy spy(&checker, &ExpiryChecker::expiryMessage); checker.checkKey(key); QCOMPARE(spy.count(), 0); } void expired_data() { QTest::addColumn("key"); QTest::addColumn("fakedate"); QTest::addColumn("msg"); QTest::addColumn("msgOwnKey"); QTest::addColumn("msgOwnSigningKey"); // use the day after the expiration date of the test keys/certificates as fake date QTest::newRow("openpgp") << testKey("alice@autocrypt.example", GpgME::OpenPGP) // << QDate{2021, 1, 22} << QStringLiteral( "

The OpenPGP key for

alice@autocrypt.example (KeyID 0xF231550C4F47E38E)

expired less than a day ago.

") << QStringLiteral( "

Your OpenPGP encryption key

alice@autocrypt.example (KeyID 0xF231550C4F47E38E)

expired less than a day " "ago.

") << QStringLiteral( "

Your OpenPGP signing key

alice@autocrypt.example (KeyID 0xF231550C4F47E38E)

expired less than a day " "ago.

"); QTest::newRow("smime") << testKey("test@example.com", GpgME::CMS) // << QDate{2013, 3, 26} << QStringLiteral( "

The S/MIME certificate for

CN=unittest cert,EMAIL=test@example.com,O=KDAB,C=US (serial " "number 00D345203A186385C9)

expired less than a day ago.

") << QStringLiteral( "

Your S/MIME encryption certificate

CN=unittest cert,EMAIL=test@example.com,O=KDAB,C=US " "(serial number 00D345203A186385C9)

expired less than a day ago.

") << QStringLiteral( "

Your S/MIME signing certificate

CN=unittest cert,EMAIL=test@example.com,O=KDAB,C=US " "(serial number 00D345203A186385C9)

expired less than a day ago.

"); } void expired() { QFETCH(GpgME::Key, key); QFETCH(QDate, fakedate); QFETCH(QString, msg); QFETCH(QString, msgOwnKey); QFETCH(QString, msgOwnSigningKey); { - ExpiryChecker checker(days{1}, days{1}, days{1}, days{1}); + ExpiryChecker checker(ExpiryCheckerSettings{days{1}, days{1}, days{1}, days{1}}); checker.setTimeProviderForTest(std::make_shared(fakedate)); QSignalSpy spy(&checker, &ExpiryChecker::expiryMessage); checker.checkKey(key); QCOMPARE(spy.count(), 1); QList arguments = spy.takeFirst(); QCOMPARE(arguments.at(0).value().keyID(), key.keyID()); QCOMPARE(arguments.at(1).toString(), msg); QCOMPARE(arguments.at(2).value(), ExpiryChecker::OtherKeyExpired); } { - ExpiryChecker checker(days{1}, days{1}, days{1}, days{1}); + ExpiryChecker checker(ExpiryCheckerSettings{days{1}, days{1}, days{1}, days{1}}); checker.setTimeProviderForTest(std::make_shared(fakedate)); QSignalSpy spy(&checker, &ExpiryChecker::expiryMessage); checker.checkOwnKey(key); QCOMPARE(spy.count(), 1); QList arguments = spy.takeFirst(); QCOMPARE(arguments.at(0).value().keyID(), key.keyID()); QCOMPARE(arguments.at(1).toString(), msgOwnKey); QCOMPARE(arguments.at(2).value(), ExpiryChecker::OwnKeyExpired); } { - ExpiryChecker checker(days{1}, days{1}, days{1}, days{1}); + ExpiryChecker checker(ExpiryCheckerSettings{days{1}, days{1}, days{1}, days{1}}); checker.setTimeProviderForTest(std::make_shared(fakedate)); QSignalSpy spy(&checker, &ExpiryChecker::expiryMessage); checker.checkOwnSigningKey(key); QCOMPARE(spy.count(), 1); QList arguments = spy.takeFirst(); QCOMPARE(arguments.at(0).value().keyID(), key.keyID()); QCOMPARE(arguments.at(1).toString(), msgOwnSigningKey); QCOMPARE(arguments.at(2).value(), ExpiryChecker::OwnKeyExpired); } } void nearexpiry_data() { QTest::addColumn("key"); QTest::addColumn("fakedate"); QTest::addColumn("msg"); QTest::addColumn("msgOwnKey"); QTest::addColumn("msgOwnSigningKey"); // use the day 5 days before the expiration date of the test keys/certificates as fake date QTest::newRow("openpgp") << testKey("alice@autocrypt.example", GpgME::OpenPGP) // << QDate{2021, 1, 16} << QStringLiteral( "

The OpenPGP key for

alice@autocrypt.example (KeyID 0xF231550C4F47E38E)

expires in less than 6 days.

") << QStringLiteral( "

Your OpenPGP encryption key

alice@autocrypt.example (KeyID 0xF231550C4F47E38E)

expires in less than 6 " "days.

") << QStringLiteral( "

Your OpenPGP signing key

alice@autocrypt.example (KeyID 0xF231550C4F47E38E)

expires in less than 6 " "days.

"); QTest::newRow("smime") << testKey("test@example.com", GpgME::CMS) // << QDate{2013, 3, 20} << QStringLiteral( "

The S/MIME certificate for

CN=unittest cert,EMAIL=test@example.com,O=KDAB,C=US (serial " "number 00D345203A186385C9);

expires in less than 6 days.

") << QStringLiteral( "

Your S/MIME encryption certificate

CN=unittest cert,EMAIL=test@example.com,O=KDAB,C=US " "(serial number 00D345203A186385C9);

expires in less than 6 days.

") << QStringLiteral( "

Your S/MIME signing certificate

CN=unittest cert,EMAIL=test@example.com,O=KDAB,C=US " "(serial number 00D345203A186385C9);

expires in less than 6 days.

"); } void nearexpiry() { QFETCH(GpgME::Key, key); QFETCH(QDate, fakedate); QFETCH(QString, msg); QFETCH(QString, msgOwnKey); QFETCH(QString, msgOwnSigningKey); { - ExpiryChecker checker(days{1}, days{10}, days{1}, days{1}); + ExpiryChecker checker(ExpiryCheckerSettings{days{1}, days{10}, days{1}, days{1}}); checker.setTimeProviderForTest(std::make_shared(fakedate)); QSignalSpy spy(&checker, &ExpiryChecker::expiryMessage); // Test if the correct treshold is taken checker.checkKey(key); checker.checkOwnKey(key); checker.checkOwnSigningKey(key); QCOMPARE(spy.count(), 1); QList arguments = spy.takeFirst(); QCOMPARE(arguments.at(0).value().keyID(), key.keyID()); QCOMPARE(arguments.at(1).toString(), msg); QCOMPARE(arguments.at(2).value(), ExpiryChecker::OtherKeyNearExpiry); } { - ExpiryChecker checker(days{10}, days{1}, days{1}, days{1}); + ExpiryChecker checker(ExpiryCheckerSettings{days{10}, days{1}, days{1}, days{1}}); checker.setTimeProviderForTest(std::make_shared(fakedate)); QSignalSpy spy(&checker, &ExpiryChecker::expiryMessage); // Test if the correct treshold is taken checker.checkKey(key); checker.checkOwnKey(key); QCOMPARE(spy.count(), 1); QList arguments = spy.takeFirst(); QCOMPARE(arguments.at(0).value().keyID(), key.keyID()); QCOMPARE(arguments.at(1).toString(), msgOwnKey); QCOMPARE(arguments.at(2).value(), ExpiryChecker::OwnKeyNearExpiry); } { - ExpiryChecker checker(days{10}, days{1}, days{1}, days{1}); + ExpiryChecker checker(ExpiryCheckerSettings{days{10}, days{1}, days{1}, days{1}}); checker.setTimeProviderForTest(std::make_shared(fakedate)); QSignalSpy spy(&checker, &ExpiryChecker::expiryMessage); // Test if the correct treshold is taken checker.checkKey(key); checker.checkOwnSigningKey(key); QCOMPARE(spy.count(), 1); QList arguments = spy.takeFirst(); QCOMPARE(arguments.at(0).value().keyID(), key.keyID()); QCOMPARE(arguments.at(1).toString(), msgOwnSigningKey); QCOMPARE(arguments.at(2).value(), ExpiryChecker::OwnKeyNearExpiry); } } private: // OpenPGP keys // // pub rsa2048 2009-11-13 [SC] // 1BA323932B3FAA826132C79E8D9860C58F246DE6 // uid [ultimate] unittest key (no password) // sub rsa2048 2009-11-13 [E] // // pub ed25519 2019-01-22 [SC] [expired: 2021-01-21] // EB85BB5FA33A75E15E944E63F231550C4F47E38E // uid [ expired] alice@autocrypt.example // // S/MIME certificates // // ID: 0x212B49DC // S/N: 00D345203A186385C9 // (dec): 15223609549285197257 // Issuer: /CN=unittest cert/O=KDAB/C=US/EMail=test@example.com // Subject: /CN=unittest cert/O=KDAB/C=US/EMail=test@example.com // validity: 2010-06-29 13:48:23 through 2013-03-25 13:48:23 // key type: rsa1024 // chain length: unlimited // sha1 fpr: 24:D2:FC:A2:2E:B3:B8:0A:1E:37:71:D1:4C:C6:58:E3:21:2B:49:DC // sha2 fpr: 62:4B:A4:B8:7D:8F:99:AA:6B:46:E3:C8:C5:BE:BF:30:29:B6:EC:4E:CC:7D:1F:9F:A8:39:B6:CE:03:6F:C7:FB Key testKey(const char *email, Protocol protocol = UnknownProtocol) { const std::vector keys = KeyCache::instance()->findByEMailAddress(email); for (const auto &key : keys) { if (protocol == UnknownProtocol || key.protocol() == protocol) { return key; } } qWarning() << "No" << Formatting::displayName(protocol) << "test key found for" << email; return {}; } private: QSharedPointer mGnupgHome; std::shared_ptr mKeyCache; }; QTEST_MAIN(ExpiryCheckerTest) #include "expirycheckertest.moc" diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 67c97fb61..e51479dae 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,394 +1,397 @@ # SPDX-License-Identifier: CC0-1.0 # SPDX-FileCopyrightText: none # target_include_directories does not handle empty include paths include_directories( ${Boost_INCLUDE_DIRS} ${GPGME_INCLUDES} ) add_definitions(-DTRANSLATION_DOMAIN=\"libkleopatra\") #add_definitions( -DQT_NO_CAST_FROM_ASCII ) #add_definitions( -DQT_NO_CAST_TO_ASCII ) kde_enable_exceptions() add_definitions( -DGPGMEPP_ERR_SOURCE_DEFAULT=13 ) # 13 is GPG_ERR_SOURCE_KLEO, even if gpg-error's too old to know about add_subdirectory( pics ) add_library(KPim${KF_MAJOR_VERSION}Libkleo) add_library(KPim${KF_MAJOR_VERSION}::Libkleo ALIAS KPim${KF_MAJOR_VERSION}Libkleo) ########### next target ############### target_sources(KPim${KF_MAJOR_VERSION}Libkleo PRIVATE kleo/auditlogentry.cpp kleo/auditlogentry.h kleo/checksumdefinition.cpp kleo/checksumdefinition.h kleo/debug.cpp kleo/debug.h kleo/defaultkeyfilter.cpp kleo/defaultkeyfilter.h kleo/defaultkeygenerationjob.cpp kleo/defaultkeygenerationjob.h kleo/docaction.cpp kleo/docaction.h kleo/dn.cpp kleo/dn.h kleo/enum.cpp kleo/enum.h kleo/expirychecker.cpp kleo/expirychecker.h + kleo/expirycheckersettings.cpp + kleo/expirycheckersettings.h kleo/kconfigbasedkeyfilter.cpp kleo/kconfigbasedkeyfilter.h kleo/keyfilter.h kleo/keyfiltermanager.cpp kleo/keyfiltermanager.h kleo/keygroup.cpp kleo/keygroup.h kleo/keygroupconfig.cpp kleo/keygroupconfig.h kleo/keygroupimportexport.cpp kleo/keygroupimportexport.h kleo/keyresolver.cpp kleo/keyresolver.h kleo/keyresolvercore.cpp kleo/keyresolvercore.h kleo/keyserverconfig.cpp kleo/keyserverconfig.h kleo/kleoexception.cpp kleo/kleoexception.h kleo/oidmap.cpp kleo/oidmap.h kleo/predicates.h kleo/stl_util.h models/keycache.cpp models/keycache.h models/keycache_p.h models/keylist.h models/keylistmodel.cpp models/keylistmodel.h models/keylistmodelinterface.cpp models/keylistmodelinterface.h models/keylistsortfilterproxymodel.cpp models/keylistsortfilterproxymodel.h models/keyrearrangecolumnsproxymodel.cpp models/keyrearrangecolumnsproxymodel.h models/subkeylistmodel.cpp models/subkeylistmodel.h models/useridlistmodel.cpp models/useridlistmodel.h utils/algorithm.h utils/assuan.cpp utils/assuan.h utils/chrono.h utils/classify.cpp utils/classify.h utils/compat.cpp utils/compat.h utils/compliance.cpp utils/compliance.h utils/cryptoconfig.cpp utils/cryptoconfig.h utils/cryptoconfig_p.h utils/filesystemwatcher.cpp utils/filesystemwatcher.h utils/formatting.cpp utils/formatting.h utils/gnupg-registry.c utils/gnupg-registry.h utils/gnupg.cpp utils/gnupg.h utils/hex.cpp utils/hex.h utils/keyhelpers.cpp utils/keyhelpers.h utils/qtstlhelpers.cpp utils/qtstlhelpers.h utils/scdaemon.cpp utils/scdaemon.h utils/stringutils.cpp utils/stringutils.h utils/systeminfo.cpp utils/systeminfo.h utils/test.cpp utils/test.h utils/uniquelock.cpp utils/uniquelock.h ) ecm_qt_declare_logging_category(KPim${KF_MAJOR_VERSION}Libkleo HEADER libkleo_debug.h IDENTIFIER LIBKLEO_LOG CATEGORY_NAME org.kde.pim.libkleo DESCRIPTION "libkleo (kleo_core)" EXPORT LIBKLEO ) target_sources(KPim${KF_MAJOR_VERSION}Libkleo PRIVATE ui/auditlogviewer.cpp ui/auditlogviewer.h ui/cryptoconfigentryreaderport.cpp ui/cryptoconfigentryreaderport_p.h ui/cryptoconfigmodule.cpp ui/cryptoconfigmodule.h ui/cryptoconfigmodule_p.h ui/directoryserviceswidget.cpp ui/directoryserviceswidget.h ui/dnattributeorderconfigwidget.cpp ui/dnattributeorderconfigwidget.h ui/editdirectoryservicedialog.cpp ui/editdirectoryservicedialog.h ui/filenamerequester.cpp ui/filenamerequester.h ui/messagebox.cpp ui/messagebox.h ui/navigatabletreeview.cpp ui/navigatabletreeview.h ui/navigatabletreewidget.cpp ui/navigatabletreewidget.h ui/progressbar.cpp ui/progressbar.h ui/progressdialog.cpp ui/progressdialog.h ui/readerportselection.cpp ui/readerportselection.h ) ecm_qt_declare_logging_category(KPim${KF_MAJOR_VERSION}Libkleo HEADER kleo_ui_debug.h IDENTIFIER KLEO_UI_LOG CATEGORY_NAME org.kde.pim.kleo_ui DESCRIPTION "libkleo (kleo_ui)" OLD_CATEGORY_NAMES log_kleo_ui EXPORT LIBKLEO ) target_sources(KPim${KF_MAJOR_VERSION}Libkleo PRIVATE # make this a separate lib. ui/keyapprovaldialog.cpp ui/keyapprovaldialog.h ui/keylistview.cpp ui/keylistview.h ui/keyrequester.cpp ui/keyrequester.h ui/keyselectioncombo.cpp ui/keyselectioncombo.h ui/keyselectiondialog.cpp ui/keyselectiondialog.h ui/newkeyapprovaldialog.cpp ui/newkeyapprovaldialog.h ) if(MINGW) # we do not care about different signedness of passed pointer arguments set_source_files_properties(utils/gnupg-registry.c PROPERTIES COMPILE_OPTIONS "-Wno-pointer-sign") endif() target_link_libraries(KPim${KF_MAJOR_VERSION}Libkleo PUBLIC Gpgmepp PRIVATE Qt::Widgets KF${KF_MAJOR_VERSION}::I18n KF${KF_MAJOR_VERSION}::Completion KF${KF_MAJOR_VERSION}::ConfigCore KF${KF_MAJOR_VERSION}::ConfigWidgets KF${KF_MAJOR_VERSION}::CoreAddons KF${KF_MAJOR_VERSION}::WidgetsAddons KF${KF_MAJOR_VERSION}::ItemModels KF${KF_MAJOR_VERSION}::Codecs) if (QT_MAJOR_VERSION STREQUAL "6") target_link_libraries(KPim${KF_MAJOR_VERSION}Libkleo PRIVATE Qt6::Core5Compat PUBLIC QGpgmeQt6) else() target_link_libraries(KPim${KF_MAJOR_VERSION}Libkleo PUBLIC QGpgme) endif() # Boost::headers may not be available for old versions of Boost if (TARGET Boost::headers) target_link_libraries(KPim${KF_MAJOR_VERSION}Libkleo PRIVATE Boost::headers) endif() if (KPim${KF_MAJOR_VERSION}TextEdit_FOUND) add_definitions(-DHAVE_PIMTEXTEDIT) target_link_libraries(KPim${KF_MAJOR_VERSION}Libkleo PRIVATE KPim${KF_MAJOR_VERSION}::PimTextEdit) endif() if (COMPILE_WITH_UNITY_CMAKE_SUPPORT) set_target_properties(KPim${KF_MAJOR_VERSION}Libkleo PROPERTIES UNITY_BUILD ON) endif() ecm_generate_export_header(KPim${KF_MAJOR_VERSION}Libkleo BASE_NAME kleo VERSION ${PIM_VERSION} DEPRECATED_BASE_VERSION 0 DEPRECATION_VERSIONS 5.23 ) if(WIN32) target_link_libraries(KPim${KF_MAJOR_VERSION}Libkleo ${GPGME_VANILLA_LIBRARIES} ) endif() set_target_properties(KPim${KF_MAJOR_VERSION}Libkleo PROPERTIES VERSION ${LIBKLEO_VERSION} SOVERSION ${LIBKLEO_SOVERSION} EXPORT_NAME Libkleo ) install(TARGETS KPim${KF_MAJOR_VERSION}Libkleo EXPORT KPim${KF_MAJOR_VERSION}LibkleoTargets ${KDE_INSTALL_TARGETS_DEFAULT_ARGS} ) target_include_directories(KPim${KF_MAJOR_VERSION}Libkleo INTERFACE "$") target_include_directories(KPim${KF_MAJOR_VERSION}Libkleo PUBLIC "$") ecm_generate_headers(libkleo_CamelCase_HEADERS HEADER_NAMES AuditLogEntry ChecksumDefinition Debug DefaultKeyFilter DefaultKeyGenerationJob DocAction Dn Enum ExpiryChecker + ExpiryCheckerSettings KConfigBasedKeyFilter KeyFilter KeyFilterManager KeyGroup KeyGroupConfig KeyGroupImportExport KeyResolver KeyResolverCore KeyserverConfig KleoException OidMap Predicates Stl_Util REQUIRED_HEADERS libkleo_HEADERS PREFIX Libkleo RELATIVE kleo ) ecm_generate_headers(libkleo_CamelCase_models_HEADERS HEADER_NAMES KeyCache KeyList KeyListModel KeyListModelInterface KeyListSortFilterProxyModel KeyRearrangeColumnsProxyModel SubkeyListModel UserIDListModel REQUIRED_HEADERS libkleo_models_HEADERS PREFIX Libkleo RELATIVE models ) ecm_generate_headers(libkleo_CamelCase_utils_HEADERS HEADER_NAMES Algorithm Assuan Chrono Classify Compat Compliance CryptoConfig FileSystemWatcher Formatting GnuPG Hex KeyHelpers QtStlHelpers SCDaemon StringUtils SystemInfo Test UniqueLock REQUIRED_HEADERS libkleo_utils_HEADERS PREFIX Libkleo RELATIVE utils ) ecm_generate_headers(libkleo_CamelCase_ui_HEADERS HEADER_NAMES AuditLogViewer CryptoConfigModule DNAttributeOrderConfigWidget DirectoryServicesWidget EditDirectoryServiceDialog FileNameRequester KeyApprovalDialog KeyListView KeyRequester KeySelectionCombo KeySelectionDialog MessageBox NavigatableTreeView NavigatableTreeWidget NewKeyApprovalDialog ProgressDialog ReaderPortSelection REQUIRED_HEADERS libkleo_ui_HEADERS PREFIX Libkleo RELATIVE ui ) if (QT_MAJOR_VERSION STREQUAL "6") ecm_generate_pri_file(BASE_NAME Libkleo LIB_NAME KPim${KF_MAJOR_VERSION}Libkleo DEPS "QGpgme" FILENAME_VAR PRI_FILENAME INCLUDE_INSTALL_DIR ${KDE_INSTALL_INCLUDEDIR}/KPim${KF_MAJOR_VERSION}/Libkleo ) else() ecm_generate_pri_file(BASE_NAME Libkleo LIB_NAME KPim${KF_MAJOR_VERSION}Libkleo DEPS "QGpgmeQt6" FILENAME_VAR PRI_FILENAME INCLUDE_INSTALL_DIR ${KDE_INSTALL_INCLUDEDIR}/KPim${KF_MAJOR_VERSION}/Libkleo ) endif() install(FILES ${libkleo_CamelCase_HEADERS} ${libkleo_CamelCase_models_HEADERS} ${libkleo_CamelCase_ui_HEADERS} ${libkleo_CamelCase_utils_HEADERS} DESTINATION ${KDE_INSTALL_INCLUDEDIR}/KPim${KF_MAJOR_VERSION}/Libkleo/Libkleo COMPONENT Devel ) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/kleo_export.h ${libkleo_HEADERS} ${libkleo_models_HEADERS} ${libkleo_ui_HEADERS} ${libkleo_utils_HEADERS} DESTINATION ${KDE_INSTALL_INCLUDEDIR}/KPim${KF_MAJOR_VERSION}/Libkleo/libkleo COMPONENT Devel ) install(FILES ${PRI_FILENAME} DESTINATION ${ECM_MKSPECS_INSTALL_DIR}) if ( WIN32 ) install ( FILES libkleopatrarc-win32.desktop DESTINATION ${KDE_INSTALL_CONFDIR} RENAME libkleopatrarc ) else () install ( FILES libkleopatrarc.desktop DESTINATION ${KDE_INSTALL_CONFDIR} RENAME libkleopatrarc ) endif () if (BUILD_QCH) ecm_add_qch( KPim${KF_MAJOR_VERSION}Libkleo_QCH NAME KPim${KF_MAJOR_VERSION}Libkleo BASE_NAME KPim${KF_MAJOR_VERSION}Libkleo VERSION ${PIM_VERSION} ORG_DOMAIN org.kde SOURCES # using only public headers, to cover only public API ${libkleo_HEADERS} ${libkleo_models_HEADERS} ${libkleo_ui_HEADERS} ${libkleo_utils_HEADERS} #MD_MAINPAGE "${CMAKE_SOURCE_DIR}/README.md" #IMAGE_DIRS "${CMAKE_SOURCE_DIR}/docs/pics" LINK_QCHS Qt${QT_MAJOR_VERSION}Core_QCH Qt${QT_MAJOR_VERSION}Gui_QCH Qt${QT_MAJOR_VERSION}Widgets_QCH INCLUDE_DIRS ${CMAKE_CURRENT_BINARY_DIR} BLANK_MACROS KLEO_EXPORT TAGFILE_INSTALL_DESTINATION ${KDE_INSTALL_QTQCHDIR} QCH_INSTALL_DESTINATION ${KDE_INSTALL_QTQCHDIR} COMPONENT Devel ) endif() diff --git a/src/kleo/expirychecker.cpp b/src/kleo/expirychecker.cpp index d0b658505..2d67bf3be 100644 --- a/src/kleo/expirychecker.cpp +++ b/src/kleo/expirychecker.cpp @@ -1,474 +1,453 @@ /* This file is part of libkleopatra, the KDE keymanagement library SPDX-FileCopyrightText: 2004 Klarälvdalens Datakonsult AB SPDX-FileCopyrightText: 2021 Sandro Knauß SPDX-FileCopyrightText: 2023 g10 Code GmbH SPDX-FileContributor: Ingo Klöcker Based on kpgp.h Copyright (C) 2001,2002 the KPGP authors See file libkdenetwork/AUTHORS.kpgp for details SPDX-License-Identifier: LGPL-2.0-or-later */ #include "expirychecker.h" #include "debug.h" #include "dn.h" +#include "expirycheckersettings.h" #include #include #include #include #include #include #include #include using namespace Kleo; namespace { struct Expiration { enum Status { NeverExpires, Expires, Expired, } status; // duration is full days until expiry if status is Expires, // full days since expiry if status is Expired, // undefined if status is NeverExpires Kleo::chrono::days duration; }; } class Kleo::ExpiryCheckerPrivate { Kleo::ExpiryChecker *q; public: - ExpiryCheckerPrivate(ExpiryChecker *qq) + ExpiryCheckerPrivate(ExpiryChecker *qq, const ExpiryCheckerSettings &settings_) : q{qq} + , settings{settings_} { } Expiration calculateExpiration(const GpgME::Subkey &key) const; void checkKeyNearExpiry(const GpgME::Key &key, bool isOwnKey, bool isSigningKey, bool ca = false, int recur_limit = 100, const GpgME::Key &orig_key = GpgME::Key::null); - Kleo::chrono::days ownKeyThreshold; - Kleo::chrono::days otherKeyThreshold; - Kleo::chrono::days rootCertThreshold; - Kleo::chrono::days chainCertThreshold; + ExpiryCheckerSettings settings; std::set alreadyWarnedFingerprints; std::shared_ptr timeProvider; }; -ExpiryChecker::ExpiryChecker(Kleo::chrono::days ownKeyThreshold, - Kleo::chrono::days otherKeyThreshold, - Kleo::chrono::days rootCertThreshold, - Kleo::chrono::days chainCertThreshold) - : d{new ExpiryCheckerPrivate{this}} +ExpiryChecker::ExpiryChecker(const ExpiryCheckerSettings &settings) + : d{new ExpiryCheckerPrivate{this, settings}} { - d->ownKeyThreshold = ownKeyThreshold; - d->otherKeyThreshold = otherKeyThreshold; - d->rootCertThreshold = rootCertThreshold; - d->chainCertThreshold = chainCertThreshold; } ExpiryChecker::~ExpiryChecker() = default; -Kleo::chrono::days ExpiryChecker::ownKeyThreshold() const +ExpiryCheckerSettings ExpiryChecker::settings() const { - return d->ownKeyThreshold; -} - -Kleo::chrono::days ExpiryChecker::otherKeyThreshold() const -{ - return d->otherKeyThreshold; -} - -Kleo::chrono::days ExpiryChecker::rootCertThreshold() const -{ - return d->rootCertThreshold; -} - -Kleo::chrono::days ExpiryChecker::chainCertThreshold() const -{ - return d->chainCertThreshold; + return d->settings; } QString formatOpenPGPMessage(const GpgME::Key &key, Expiration expiration, bool isOwnKey, bool isSigningKey) { const auto keyInfo = ki18nc("User ID of key (KeyID key ID of key in hex notation)", "%1 (KeyID 0x%2)") .subs(QString::fromUtf8(key.userID(0).id())) .subs(QString::fromLatin1(key.keyID())); if (expiration.status == Expiration::Expired) { qCDebug(LIBKLEO_LOG) << "Key" << key << "expired" << expiration.duration.count() << "days ago"; if (expiration.duration.count() == 0) { KLocalizedString msg; if (isSigningKey) { msg = ki18n("

Your OpenPGP signing key

%1

expired less than a day ago.

"); } else if (isOwnKey) { msg = ki18n("

Your OpenPGP encryption key

%1

expired less than a day ago.

"); } else { msg = ki18n("

The OpenPGP key for

%1

expired less than a day ago.

"); } return msg.subs(keyInfo).toString(); } KLocalizedString msg; if (isSigningKey) { msg = ki18np( "

Your OpenPGP signing key

%2

" "

expired one day ago.

", "

Your OpenPGP signing key

%2

" "

expired %1 days ago.

"); } else if (isOwnKey) { msg = ki18np( "

Your OpenPGP encryption key

%2

" "

expired one day ago.

", "

Your OpenPGP encryption key

%2

" "

expired %1 days ago.

"); } else { msg = ki18np( "

The OpenPGP key for

%2

" "

expired one day ago.

", "

The OpenPGP key for

%2

" "

expired %1 days ago.

"); } return msg.subs(expiration.duration.count()).subs(keyInfo).toString(); } qCDebug(LIBKLEO_LOG) << "Key" << key << "expires in less than" << expiration.duration.count() + 1 << "days"; KLocalizedString msg; if (isSigningKey) { msg = ki18np( "

Your OpenPGP signing key

%2

" "

expires in less than a day.

", "

Your OpenPGP signing key

%2

" "

expires in less than %1 days.

"); } else if (isOwnKey) { msg = ki18np( "

Your OpenPGP encryption key

%2

" "

expires in less than a day.

", "

Your OpenPGP encryption key

%2

" "

expires in less than %1 days.

"); } else { msg = ki18np( "

The OpenPGP key for

%2

" "

expires in less than a day.

", "

The OpenPGP key for

%2

" "

expires in less than %1 days.

"); } return msg.subs(expiration.duration.count() + 1).subs(keyInfo).toString(); } QString formatSMIMEMessage(const GpgME::Key &key, const GpgME::Key &orig_key, Expiration expiration, bool isOwnKey, bool isSigningKey, bool ca) { const auto userCert = orig_key.isNull() ? key : orig_key; const auto userCertInfo = ki18nc("User ID of certificate (serial number serial no. of certificate)", "%1 (serial number %2)") .subs(Kleo::DN(userCert.userID(0).id()).prettyDN()) .subs(QString::fromLatin1(userCert.issuerSerial())); if (expiration.status == Expiration::Expired) { qCDebug(LIBKLEO_LOG) << "Certificate" << key << "expired" << expiration.duration.count() << "days ago"; if (ca) { if (key.isRoot()) { if (expiration.duration.count() == 0) { KLocalizedString msg; if (isSigningKey) { msg = ki18n( "

The root certificate

%2

" "

for your S/MIME signing certificate

%1

" "

expired less than a day ago.

"); } else if (isOwnKey) { msg = ki18n( "

The root certificate

%2

" "

for your S/MIME encryption certificate

%1

" "

expired less than a day ago.

"); } else { msg = ki18n( "

The root certificate

%2

" "

for S/MIME certificate

%1

" "

expired less than a day ago.

"); } return msg.subs(userCertInfo).subs(Kleo::DN(key.userID(0).id()).prettyDN()).toString(); } KLocalizedString msg; if (isSigningKey) { msg = ki18np( "

The root certificate

%3

" "

for your S/MIME signing certificate

%2

" "

expired one day ago.

", "

The root certificate

%3

" "

for your S/MIME signing certificate

%2

" "

expired %1 days ago.

"); } else if (isOwnKey) { msg = ki18np( "

The root certificate

%3

" "

for your S/MIME encryption certificate

%2

" "

expired one day ago.

", "

The root certificate

%3

" "

for your S/MIME encryption certificate

%2

" "

expired %1 days ago.

"); } else { msg = ki18np( "

The root certificate

%3

" "

for S/MIME certificate

%2

" "

expired one day ago.

", "

The root certificate

%3

" "

for S/MIME certificate

%2

" "

expired %1 days ago.

"); } return msg.subs(expiration.duration.count()).subs(userCertInfo).subs(Kleo::DN(key.userID(0).id()).prettyDN()).toString(); } else { if (expiration.duration.count() == 0) { KLocalizedString msg; if (isSigningKey) { msg = ki18n( "

The intermediate CA certificate

%2

" "

for your S/MIME signing certificate

%1

" "

expired less than a day ago.

"); } else if (isOwnKey) { msg = ki18n( "

The intermediate CA certificate

%2

" "

for your S/MIME encryption certificate

%1

" "

expired less than a day ago.

"); } else { msg = ki18n( "

The intermediate CA certificate

%2

" "

for S/MIME certificate

%1

" "

expired less than a day ago.

"); } return msg.subs(userCertInfo).subs(Kleo::DN(key.userID(0).id()).prettyDN()).toString(); } KLocalizedString msg; if (isSigningKey) { msg = ki18np( "

The intermediate CA certificate

%3

" "

for your S/MIME signing certificate

%2

" "

expired less than a day ago.

", "

The intermediate CA certificate

%3

" "

for your S/MIME signing certificate

%2

" "

expired %1 days ago.

"); } else if (isOwnKey) { msg = ki18np( "

The intermediate CA certificate

%3

" "

for your S/MIME encryption certificate

%2

" "

expired less than a day ago.

", "

The intermediate CA certificate

%3

" "

for your S/MIME encryption certificate

%2

" "

expired %1 days ago.

"); } else { msg = ki18np( "

The intermediate CA certificate

%3

" "

for S/MIME certificate

%2

" "

expired less than a day ago.

", "

The intermediate CA certificate

%3

" "

for S/MIME certificate

%2

" "

expired %1 days ago.

"); } return msg.subs(expiration.duration.count()).subs(userCertInfo).subs(Kleo::DN(key.userID(0).id()).prettyDN()).toString(); } } else { if (expiration.duration.count() == 0) { KLocalizedString msg; if (isSigningKey) { msg = ki18n("

Your S/MIME signing certificate

%1

expired less than a day ago.

"); } else if (isOwnKey) { msg = ki18n("

Your S/MIME encryption certificate

%1

expired less than a day ago.

"); } else { msg = ki18n("

The S/MIME certificate for

%1

expired less than a day ago.

"); } return msg.subs(userCertInfo).toString(); } KLocalizedString msg; if (isSigningKey) { msg = ki18np( "

Your S/MIME signing certificate

%2

" "

expired less than a day ago.

", "

Your S/MIME signing certificate

%2

" "

expired %1 days ago.

"); } else if (isOwnKey) { msg = ki18np( "

Your S/MIME encryption certificate

%2

" "

expired less than a day ago.

", "

Your S/MIME encryption certificate

%2

" "

expired %1 days ago.

"); } else { msg = ki18np( "

The S/MIME certificate for

%2

" "

expired less than a day ago.

", "

The S/MIME certificate for

%2

" "

expired %1 days ago.

"); } return msg.subs(expiration.duration.count()).subs(userCertInfo).toString(); } } qCDebug(LIBKLEO_LOG) << "Certificate" << key << "expires in less than" << expiration.duration.count() + 1 << "days"; KLocalizedString msg; if (ca) { if (key.isRoot()) { if (isSigningKey) { msg = ki18np( "

The root certificate

%3

" "

for your S/MIME signing certificate

%2;

" "

expires in less than a day.

", "

The root certificate

%3

" "

for your S/MIME signing certificate

%2;

" "

expires in less than %1 days.

"); } else if (isOwnKey) { msg = ki18np( "

The root certificate

%3

" "

for your S/MIME encryption certificate

%2;

" "

expires in less than a day.

", "

The root certificate

%3

" "

for your S/MIME encryption certificate

%2;

" "

expires in less than %1 days.

"); } else { msg = ki18np( "

The root certificate

%3

" "

for S/MIME certificate

%2;

" "

expires in less than a day.

", "

The root certificate

%3

" "

for S/MIME certificate

%2;

" "

expires in less than %1 days.

"); } } else { if (isSigningKey) { msg = ki18np( "

The intermediate CA certificate

%3

" "

for your S/MIME signing certificate

%2;

" "

expires in less than a day.

", "

The intermediate CA certificate

%3

" "

for your S/MIME signing certificate

%2;

" "

expires in less than %1 days.

"); } else if (isOwnKey) { msg = ki18np( "

The intermediate CA certificate

%3

" "

for your S/MIME encryption certificate

%2;

" "

expires in less than a day.

", "

The intermediate CA certificate

%3

" "

for your S/MIME encryption certificate

%2;

" "

expires in less than %1 days.

"); } else { msg = ki18np( "

The intermediate CA certificate

%3

" "

for S/MIME certificate

%2;

" "

expires in less than a day.

", "

The intermediate CA certificate

%3

" "

for S/MIME certificate

%2;

" "

expires in less than %1 days.

"); } } return msg.subs(expiration.duration.count() + 1).subs(userCertInfo).subs(Kleo::DN(key.userID(0).id()).prettyDN()).toString(); } if (isSigningKey) { msg = ki18np( "

Your S/MIME signing certificate

%2;

" "

expires in less than a day.

", "

Your S/MIME signing certificate

%2;

" "

expires in less than %1 days.

"); } else if (isOwnKey) { msg = ki18np( "

Your S/MIME encryption certificate

%2;

" "

expires in less than a day.

", "

Your S/MIME encryption certificate

%2;

" "

expires in less than %1 days.

"); } else { msg = ki18np( "

The S/MIME certificate for

%2;

" "

expires in less than a day.

", "

The S/MIME certificate for

%2;

" "

expires in less than %1 days.

"); } return msg.subs(expiration.duration.count() + 1).subs(userCertInfo).toString(); } Expiration ExpiryCheckerPrivate::calculateExpiration(const GpgME::Subkey &subkey) const { if (subkey.neverExpires()) { return {Expiration::NeverExpires, Kleo::chrono::days::zero()}; } const time_t t = timeProvider ? timeProvider->getTime() : std::time(nullptr); // casting the double-valued difference (returned by std::difftime) of two non-negative time_t to a time_t is no problem; // negative values for expiration time and current time can be safely ignored const time_t secsTillExpiry = static_cast(std::difftime(subkey.expirationTime(), t)); return {secsTillExpiry <= 0 ? Expiration::Expired : Expiration::Expires, std::chrono::duration_cast(std::chrono::seconds{std::abs(secsTillExpiry)})}; } void ExpiryCheckerPrivate::checkKeyNearExpiry(const GpgME::Key &key, bool isOwnKey, bool isSigningKey, bool ca, int recur_limit, const GpgME::Key &orig_key) { if (recur_limit <= 0) { qCDebug(LIBKLEO_LOG) << "Key chain too long (>100 certs)"; return; } const GpgME::Subkey subkey = key.subkey(0); const bool newMessage = !alreadyWarnedFingerprints.count(subkey.fingerprint()); const auto expiration = calculateExpiration(subkey); if (expiration.status == Expiration::NeverExpires) { return; } if (expiration.status == Expiration::Expired) { const QString msg = key.protocol() == GpgME::OpenPGP ? formatOpenPGPMessage(key, expiration, isOwnKey, isSigningKey) : formatSMIMEMessage(key, orig_key, expiration, isOwnKey, isSigningKey, ca); alreadyWarnedFingerprints.insert(subkey.fingerprint()); Q_EMIT q->expiryMessage(key, msg, isOwnKey ? ExpiryChecker::OwnKeyExpired : ExpiryChecker::OtherKeyExpired, newMessage); } else { - const auto threshold = ca ? (key.isRoot() ? rootCertThreshold : chainCertThreshold) : (isOwnKey ? ownKeyThreshold : otherKeyThreshold); + const auto threshold = ca // + ? (key.isRoot() ? settings.rootCertThreshold() : settings.chainCertThreshold()) // + : (isOwnKey ? settings.ownKeyThreshold() : settings.otherKeyThreshold()); if (threshold >= Kleo::chrono::days::zero() && expiration.duration <= threshold) { const QString msg = key.protocol() == GpgME::OpenPGP ? formatOpenPGPMessage(key, expiration, isOwnKey, isSigningKey) : formatSMIMEMessage(key, orig_key, expiration, isOwnKey, isSigningKey, ca); alreadyWarnedFingerprints.insert(subkey.fingerprint()); Q_EMIT q->expiryMessage(key, msg, isOwnKey ? ExpiryChecker::OwnKeyNearExpiry : ExpiryChecker::OtherKeyNearExpiry, newMessage); } } if (key.isRoot()) { return; } else if (key.protocol() != GpgME::CMS) { // Key chaining is only possible in SMIME return; } else if (const char *chain_id = key.chainID()) { QGpgME::Protocol *p = QGpgME::smime(); Q_ASSERT(p); std::unique_ptr job(p->keyListJob(false, false, true)); if (job.get()) { std::vector keys; job->exec(QStringList(QLatin1String(chain_id)), false, keys); if (!keys.empty()) { return checkKeyNearExpiry(keys.front(), isOwnKey, isSigningKey, true, recur_limit - 1, ca ? orig_key : key); } } } } void ExpiryChecker::checkOwnSigningKey(const GpgME::Key &key) const { d->checkKeyNearExpiry(key, /*isOwnKey*/ true, /*isSigningKey*/ true); } void ExpiryChecker::checkOwnKey(const GpgME::Key &key) const { d->checkKeyNearExpiry(key, /*isOwnKey*/ true, /*isSigningKey*/ false); } void ExpiryChecker::checkKey(const GpgME::Key &key) const { d->checkKeyNearExpiry(key, false, false); } void ExpiryChecker::setTimeProviderForTest(const std::shared_ptr &timeProvider) { d->timeProvider = timeProvider; } diff --git a/src/kleo/expirychecker.h b/src/kleo/expirychecker.h index e40b06fb2..528147484 100644 --- a/src/kleo/expirychecker.h +++ b/src/kleo/expirychecker.h @@ -1,78 +1,73 @@ /* This file is part of libkleopatra, the KDE keymanagement library SPDX-FileCopyrightText: 2004 Klarälvdalens Datakonsult AB SPDX-FileCopyrightText: 2021 Sandro Knauß SPDX-FileCopyrightText: 2023 g10 Code GmbH SPDX-FileContributor: Ingo Klöcker Based on kpgp.h Copyright (C) 2001,2002 the KPGP authors See file libkdenetwork/AUTHORS.kpgp for details SPDX-License-Identifier: LGPL-2.0-or-later */ #pragma once #include "kleo_export.h" #include #include #include #include namespace Kleo { class ExpiryCheckerPrivate; +class ExpiryCheckerSettings; class KLEO_EXPORT TimeProvider { public: virtual ~TimeProvider() = default; virtual time_t getTime() const = 0; }; class KLEO_EXPORT ExpiryChecker : public QObject { Q_OBJECT public: - ExpiryChecker(Kleo::chrono::days ownKeyThreshold, - Kleo::chrono::days otherKeyThreshold, - Kleo::chrono::days rootCertThreshold, - Kleo::chrono::days chainCertThreshold); + explicit ExpiryChecker(const ExpiryCheckerSettings &settings); ~ExpiryChecker() override; - Q_REQUIRED_RESULT Kleo::chrono::days ownKeyThreshold() const; - Q_REQUIRED_RESULT Kleo::chrono::days otherKeyThreshold() const; - Q_REQUIRED_RESULT Kleo::chrono::days rootCertThreshold() const; - Q_REQUIRED_RESULT Kleo::chrono::days chainCertThreshold() const; + Q_REQUIRED_RESULT ExpiryCheckerSettings settings() const; enum ExpiryInformation { OwnKeyExpired, OwnKeyNearExpiry, OtherKeyExpired, OtherKeyNearExpiry, }; Q_ENUM(ExpiryInformation) void checkOwnSigningKey(const GpgME::Key &key) const; void checkOwnKey(const GpgME::Key &key) const; void checkKey(const GpgME::Key &key) const; Q_SIGNALS: void expiryMessage(const GpgME::Key &key, QString msg, Kleo::ExpiryChecker::ExpiryInformation info, bool isNewMessage) const; public: void setTimeProviderForTest(const std::shared_ptr &); private: std::unique_ptr const d; }; } Q_DECLARE_METATYPE(GpgME::Key) diff --git a/src/kleo/expirycheckersettings.cpp b/src/kleo/expirycheckersettings.cpp new file mode 100644 index 000000000..10f4fd71e --- /dev/null +++ b/src/kleo/expirycheckersettings.cpp @@ -0,0 +1,89 @@ +/* + kleo/expirycheckersettings.cpp + + This file is part of libkleopatra, the KDE keymanagement library + SPDX-FileCopyrightText: 2023 g10 Code GmbH + SPDX-FileContributor: Ingo Klöcker + + SPDX-License-Identifier: GPL-2.0-or-later +*/ + +#include + +#include "expirycheckersettings.h" + +using namespace Kleo; + +class ExpiryCheckerSettings::Private +{ +public: + Kleo::chrono::days ownKeyThreshold; + Kleo::chrono::days otherKeyThreshold; + Kleo::chrono::days rootCertThreshold; + Kleo::chrono::days chainCertThreshold; +}; + +ExpiryCheckerSettings::ExpiryCheckerSettings(Kleo::chrono::days ownKeyThreshold, + Kleo::chrono::days otherKeyThreshold, + Kleo::chrono::days rootCertThreshold, + Kleo::chrono::days chainCertThreshold) + : d{new Private{ownKeyThreshold, otherKeyThreshold, rootCertThreshold, chainCertThreshold}} +{ +} + +ExpiryCheckerSettings::~ExpiryCheckerSettings() = default; + +ExpiryCheckerSettings::ExpiryCheckerSettings(const ExpiryCheckerSettings &other) + : d{new Private{*other.d}} +{ +} + +ExpiryCheckerSettings &ExpiryCheckerSettings::operator=(const ExpiryCheckerSettings &other) +{ + *d = *other.d; + return *this; +} + +ExpiryCheckerSettings::ExpiryCheckerSettings(ExpiryCheckerSettings &&other) = default; + +ExpiryCheckerSettings &ExpiryCheckerSettings::operator=(ExpiryCheckerSettings &&other) = default; + +void ExpiryCheckerSettings::setOwnKeyThreshold(Kleo::chrono::days threshold) +{ + d->ownKeyThreshold = threshold; +} + +Kleo::chrono::days ExpiryCheckerSettings::ownKeyThreshold() const +{ + return d->ownKeyThreshold; +} + +void ExpiryCheckerSettings::setOtherKeyThreshold(Kleo::chrono::days threshold) +{ + d->otherKeyThreshold = threshold; +} + +Kleo::chrono::days ExpiryCheckerSettings::otherKeyThreshold() const +{ + return d->otherKeyThreshold; +} + +void ExpiryCheckerSettings::setRootCertThreshold(Kleo::chrono::days threshold) +{ + d->rootCertThreshold = threshold; +} + +Kleo::chrono::days ExpiryCheckerSettings::rootCertThreshold() const +{ + return d->rootCertThreshold; +} + +void ExpiryCheckerSettings::setChainCertThreshold(Kleo::chrono::days threshold) +{ + d->chainCertThreshold = threshold; +} + +Kleo::chrono::days ExpiryCheckerSettings::chainCertThreshold() const +{ + return d->chainCertThreshold; +} diff --git a/src/kleo/expirycheckersettings.h b/src/kleo/expirycheckersettings.h new file mode 100644 index 000000000..16fd3616b --- /dev/null +++ b/src/kleo/expirycheckersettings.h @@ -0,0 +1,56 @@ +/* + kleo/expirycheckersettings.h + + This file is part of libkleopatra, the KDE keymanagement library + SPDX-FileCopyrightText: 2023 g10 Code GmbH + SPDX-FileContributor: Ingo Klöcker + + SPDX-License-Identifier: GPL-2.0-or-later +*/ + +#pragma once + +#include "kleo_export.h" + +#include + +#include + +#include + +namespace Kleo +{ + +class KLEO_EXPORT ExpiryCheckerSettings +{ +public: + ExpiryCheckerSettings(Kleo::chrono::days ownKeyThreshold, + Kleo::chrono::days otherKeyThreshold, + Kleo::chrono::days rootCertThreshold, + Kleo::chrono::days chainCertThreshold); + ~ExpiryCheckerSettings(); + + ExpiryCheckerSettings(const ExpiryCheckerSettings &other); + ExpiryCheckerSettings &operator=(const ExpiryCheckerSettings &other); + + ExpiryCheckerSettings(ExpiryCheckerSettings &&other); + ExpiryCheckerSettings &operator=(ExpiryCheckerSettings &&other); + + void setOwnKeyThreshold(Kleo::chrono::days threshold); + Q_REQUIRED_RESULT Kleo::chrono::days ownKeyThreshold() const; + + void setOtherKeyThreshold(Kleo::chrono::days threshold); + Q_REQUIRED_RESULT Kleo::chrono::days otherKeyThreshold() const; + + void setRootCertThreshold(Kleo::chrono::days threshold); + Q_REQUIRED_RESULT Kleo::chrono::days rootCertThreshold() const; + + void setChainCertThreshold(Kleo::chrono::days threshold); + Q_REQUIRED_RESULT Kleo::chrono::days chainCertThreshold() const; + +private: + class Private; + std::unique_ptr d; +}; + +}