File indexing completed on 2024-04-28 05:34:16
0001 // SPDX-FileCopyrightText: 2021 Daniel Vrátil <dvratil@kde.org> 0002 // 0003 // SPDX-License-Identifier: LGPL-2.1-or-later 0004 0005 #include "otpprovider.h" 0006 0007 #include <QUrl> 0008 #include <QUrlQuery> 0009 #include <QDebug> 0010 #include <QDateTime> 0011 0012 #include <KLocalizedString> 0013 0014 #include <chrono> 0015 0016 #include <liboath/oath.h> 0017 0018 using namespace PlasmaPass; 0019 using namespace std::chrono_literals; 0020 0021 namespace { 0022 0023 static const QString otpAuthSchema = QStringLiteral("otpauth://"); 0024 static const QString secretQueryItem = QStringLiteral("secret"); 0025 0026 QString parseOtpType(const QUrl &url) 0027 { 0028 return url.host(); 0029 } 0030 0031 } // namespace 0032 0033 OTPProvider::OTPProvider(const QString &path, QObject *parent) 0034 : ProviderBase(path, parent) 0035 { 0036 setSecretTimeout(30s); 0037 } 0038 0039 ProviderBase::HandlingResult OTPProvider::handleSecret(QStringView secret) 0040 { 0041 if (!secret.startsWith(otpAuthSchema)) { 0042 return HandlingResult::Continue; 0043 } 0044 0045 QUrl url(secret.toString()); 0046 const auto otpType = parseOtpType(url); 0047 if (otpType == QLatin1String("totp")) { 0048 handleTOTP(url); 0049 } else { 0050 setError(i18n("Unsupported OTP type %1", otpType)); 0051 return HandlingResult::Stop; 0052 } 0053 0054 return HandlingResult::Stop; 0055 } 0056 0057 0058 void OTPProvider::handleTOTP(const QUrl &url) 0059 { 0060 const QUrlQuery query(url.query()); 0061 const auto secret = query.queryItemValue(secretQueryItem).toUtf8(); 0062 0063 char *decodedSecret = {}; 0064 size_t decodedSecretLen = 0; 0065 oath_base32_decode(secret.data(), secret.size(), &decodedSecret, &decodedSecretLen); 0066 0067 char output_otp[6] = {}; 0068 oath_totp_generate(decodedSecret, decodedSecretLen, 0069 QDateTime::currentDateTime().toSecsSinceEpoch(), 0070 OATH_TOTP_DEFAULT_TIME_STEP_SIZE, 0071 OATH_TOTP_DEFAULT_START_TIME, 0072 6, 0073 output_otp); 0074 0075 setSecret(QString::fromLatin1(output_otp, sizeof(output_otp))); 0076 } 0077 0078 #include "moc_otpprovider.cpp"