Skip to content

Commit

Permalink
Merge branch 'main' into WE-145-squash
Browse files Browse the repository at this point in the history
  • Loading branch information
lauris71 authored Jun 10, 2024
2 parents eadbc5a + 65f8399 commit ff22514
Show file tree
Hide file tree
Showing 10 changed files with 67 additions and 62 deletions.
8 changes: 4 additions & 4 deletions .github/workflows/cmake-linux-codeql.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,14 @@ jobs:
with:
submodules: recursive

- uses: github/codeql-action/init@v2
- uses: github/codeql-action/init@v3
with:
languages: cpp
queries: +security-and-quality

- uses: github/codeql-action/autobuild@v2
- uses: github/codeql-action/autobuild@v3

- uses: github/codeql-action/analyze@v2
- uses: github/codeql-action/analyze@v3
with:
upload: False
output: sarif-results
Expand All @@ -39,6 +39,6 @@ jobs:
input: sarif-results/cpp.sarif
output: sarif-results/cpp.sarif

- uses: github/codeql-action/upload-sarif@v2
- uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: sarif-results/cpp.sarif
2 changes: 1 addition & 1 deletion src/controller/command-handlers/authenticate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ QVariantMap Authenticate::onConfirm(WebEidUI* window,
const auto signatureAlgorithm =
QString::fromStdString(cardCertAndPin.cardInfo->eid().authSignatureAlgorithm());

auto pin = getPin(cardCertAndPin.cardInfo->eid().smartcard(), window);
auto pin = getPin(cardCertAndPin.cardInfo->eid(), window);

try {
const auto signature =
Expand Down
2 changes: 1 addition & 1 deletion src/controller/command-handlers/sign.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ void Sign::emitCertificatesReady(const std::vector<CardCertificateAndPinInfo>& c

QVariantMap Sign::onConfirm(WebEidUI* window, const CardCertificateAndPinInfo& cardCertAndPin)
{
auto pin = getPin(cardCertAndPin.cardInfo->eid().smartcard(), window);
auto pin = getPin(cardCertAndPin.cardInfo->eid(), window);

try {
const auto signature = signHash(cardCertAndPin.cardInfo->eid(), pin, docHash, hashAlgo);
Expand Down
6 changes: 3 additions & 3 deletions src/controller/command-handlers/signauthutils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,10 @@ inline void eraseData(T& data)
}
}

pcsc_cpp::byte_vector getPin(const pcsc_cpp::SmartCard& card, WebEidUI* window)
pcsc_cpp::byte_vector getPin(const ElectronicID& card, WebEidUI* window)
{
// Doesn't apply to PIN pads.
if (card.readerHasPinPad()) {
if (card.smartcard().readerHasPinPad() || card.providesExternalPinDialog()) {
return {};
}

Expand All @@ -94,7 +94,7 @@ pcsc_cpp::byte_vector getPin(const pcsc_cpp::SmartCard& card, WebEidUI* window)

// TODO: Avoid making copies of the PIN in memory.
auto pinQByteArray = pin.toUtf8();
auto pinBytes = pcsc_cpp::byte_vector {pinQByteArray.begin(), pinQByteArray.end()};
pcsc_cpp::byte_vector pinBytes {pinQByteArray.begin(), pinQByteArray.end()};

// TODO: Verify that the buffers are actually zeroed and no copies remain.
eraseData<QString, QChar>(pin);
Expand Down
12 changes: 8 additions & 4 deletions src/controller/command-handlers/signauthutils.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,17 @@

#pragma once

#include "electronic-id/enums.hpp"
#include "pcsc-cpp/pcsc-cpp-utils.hpp"
#include "pcsc-cpp/pcsc-cpp.hpp"

#include <QVariantMap>

class WebEidUI;
class QSslCertificate;

namespace electronic_id
{
class ElectronicID;
class SignatureAlgorithm;
} // namespace electronic_id

void requireArgumentsAndOptionalLang(QStringList argNames, const QVariantMap& args,
const std::string& argDescriptions);
Expand All @@ -41,6 +45,6 @@ extern template QString validateAndGetArgument<QString>(const QString& argName,
extern template QByteArray
validateAndGetArgument<QByteArray>(const QString& argName, const QVariantMap& args, bool allowNull);

pcsc_cpp::byte_vector getPin(const pcsc_cpp::SmartCard& card, WebEidUI* window);
pcsc_cpp::byte_vector getPin(const electronic_id::ElectronicID& card, WebEidUI* window);

QVariantMap signatureAlgoToVariantMap(const electronic_id::SignatureAlgorithm signatureAlgo);
3 changes: 2 additions & 1 deletion src/controller/controller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -354,7 +354,8 @@ void Controller::onCriticalFailure(const QString& error)
{
qCritical() << "Exiting due to command" << std::string(commandType())
<< "fatal error:" << error;
_result = makeErrorObject(RESP_TECH_ERROR, QStringLiteral("Technical error, see application logs"));
_result =
makeErrorObject(RESP_TECH_ERROR, QStringLiteral("Technical error, see application logs"));
writeResponseToStdOut(isInStdinMode, _result, commandType());
disposeUI();
WebEidUI::showFatalError();
Expand Down
58 changes: 31 additions & 27 deletions src/ui/webeiddialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,7 @@ void WebEidDialog::onSmartCardStatusUpdate(const RetriableError status)

setTrText(ui->connectCardLabel, std::get<0>(retriableErrorToTextTitleAndIcon(status)));
setTrText(ui->messagePageTitleLabel, std::get<1>(retriableErrorToTextTitleAndIcon(status)));
ui->cardChipIcon->setPixmap(std::get<2>(retriableErrorToTextTitleAndIcon(status)));
ui->cardChipIcon->setPixmap(pixmap(std::get<2>(retriableErrorToTextTitleAndIcon(status))));

// In case the insert card page is not shown, switch back to it.
ui->helpButton->show();
Expand All @@ -320,6 +320,7 @@ void WebEidDialog::onMultipleCertificatesReady(
switch (currentCommand) {
case CommandType::GET_SIGNING_CERTIFICATE:
setupOK([this] {
ui->okButton->setDisabled(true);
if (auto* button =
qobject_cast<CertificateButton*>(ui->selectionGroup->checkedButton())) {
emit accepted(button->certificateInfo());
Expand All @@ -338,6 +339,7 @@ void WebEidDialog::onMultipleCertificatesReady(
onMultipleCertificatesReady(origin, certificateAndPinInfos);
});
setupOK([this, origin] {
ui->okButton->setDisabled(true);
// Authenticate continues with the selected certificate to onSingleCertificateReady().
if (auto* button =
qobject_cast<CertificateButton*>(ui->selectionGroup->checkedButton())) {
Expand Down Expand Up @@ -372,7 +374,10 @@ void WebEidDialog::onSingleCertificateReady(const QUrl& origin,
switch (currentCommand) {
case CommandType::GET_SIGNING_CERTIFICATE:
setupCertificateAndPinInfo({certAndPin});
setupOK([this, certAndPin] { emit accepted(certAndPin); });
setupOK([this, certAndPin] {
ui->okButton->setDisabled(true);
emit accepted(certAndPin);
});
ui->selectionGroup->buttons().at(0)->click();
ui->pageStack->setCurrentIndex(int(Page::SELECT_CERTIFICATE));
return;
Expand Down Expand Up @@ -413,8 +418,7 @@ void WebEidDialog::onSingleCertificateReady(const QUrl& origin,
ui->pinTitleLabel->hide();
} else if (useExternalPinDialog) {
connectOkToCachePinAndEmitSelectedCertificate(certAndPin);
ui->pinInput->setText(
QString::fromLatin1("unused")); // Dummy value as empty PIN is not allowed.
ui->okButton->setEnabled(true);
} else if (certAndPin.pinInfo.readerHasPinPad) {
setupPinPadProgressBarAndEmitWait(certAndPin);
} else {
Expand Down Expand Up @@ -520,7 +524,7 @@ void WebEidDialog::onRetryImpl(Text text)
setTrText(ui->connectCardLabel, std::forward<Text>(text));
setTrText(ui->messagePageTitleLabel, QT_TR_NOOP("Operation failed"));
ui->cardChipIcon->setPixmap(pixmap("no-id-card"_L1));
setupOK([this] { emit retry(); }, QT_TR_NOOP("Try again"), true);
setupOK(&WebEidDialog::retry, QT_TR_NOOP("Try again"), true);
ui->pageStack->setCurrentIndex(int(Page::ALERT));
}

Expand Down Expand Up @@ -583,7 +587,7 @@ void WebEidDialog::setupCertificateAndPinInfo(
}
}

void WebEidDialog::setupPinPrompt(const PinInfo& pinInfo)
void WebEidDialog::setupPinPrompt(PinInfo pinInfo)
{
ui->okButton->setHidden(pinInfo.readerHasPinPad);
ui->cancelButton->setHidden(pinInfo.readerHasPinPad);
Expand All @@ -595,9 +599,9 @@ void WebEidDialog::setupPinPrompt(const PinInfo& pinInfo)
ui->pinErrorLabel->setVisible(showPinError);
showPinInputWarning(showPinError);
if (showPinError) {
setTrText(ui->pinErrorLabel, [pinInfo]() -> QString {
setTrText(ui->pinErrorLabel, [count = pinInfo.pinRetriesCount.first]() -> QString {
return tr("The PIN has been entered incorrectly at least once. %n attempts left.",
nullptr, int(pinInfo.pinRetriesCount.first));
nullptr, count);
});
}
}
Expand Down Expand Up @@ -643,17 +647,17 @@ void WebEidDialog::setupPinInput(const CardCertificateAndPinInfo& certAndPin)
certAndPin.cardInfo->eid().allowsUsingLettersAndSpecialCharactersInPin()
? QStringLiteral("[0-9 -/:-@[-`{-~\\p{L}]{%1,%2}")
: QStringLiteral("[0-9]{%1,%2}");
const auto numericMinMaxRegexp =
QRegularExpression(regexpWithOrWithoutLetters.arg(certAndPin.pinInfo.pinMinMaxLength.first)
.arg(certAndPin.pinInfo.pinMinMaxLength.second));
const QRegularExpression numericMinMaxRegexp(
regexpWithOrWithoutLetters.arg(certAndPin.pinInfo.pinMinMaxLength.first)
.arg(certAndPin.pinInfo.pinMinMaxLength.second));
ui->pinInputValidator->setRegularExpression(numericMinMaxRegexp);
ui->pinInput->setMaxLength(int(certAndPin.pinInfo.pinMinMaxLength.second));
ui->pinInput->setFocus();
connectOkToCachePinAndEmitSelectedCertificate(certAndPin);
}

template <typename Func>
void WebEidDialog::setupOK(Func&& func, const char* text, bool enabled)
void WebEidDialog::setupOK(Func func, const char* text, bool enabled)
{
ui->okButton->disconnect();
connect(ui->okButton, &QPushButton::clicked, this, std::forward<Func>(func));
Expand Down Expand Up @@ -699,50 +703,50 @@ QPixmap WebEidDialog::pixmap(QLatin1String name)
.arg(name, Application::isDarkTheme() ? "_dark"_L1 : QLatin1String())};
}

std::tuple<const char*, const char*, QPixmap>
WebEidDialog::retriableErrorToTextTitleAndIcon(const RetriableError error)
constexpr std::tuple<const char*, const char*, QLatin1String>
WebEidDialog::retriableErrorToTextTitleAndIcon(const RetriableError error) noexcept
{
switch (error) {
case RetriableError::SMART_CARD_SERVICE_IS_NOT_RUNNING:
return {
QT_TR_NOOP("The smart card service required to use the ID-card is not running. Please "
"start the smart card service and try again."),
QT_TR_NOOP("Launch the Smart Card service"), pixmap("cardreader"_L1)};
QT_TR_NOOP("Launch the Smart Card service"), "cardreader"_L1};
case RetriableError::NO_SMART_CARD_READERS_FOUND:
return {QT_TR_NOOP("<b>Card reader not connected.</b> Please connect the card reader to "
"the computer."),
QT_TR_NOOP("Connect the card reader"), pixmap("cardreader"_L1)};
QT_TR_NOOP("Connect the card reader"), "cardreader"_L1};

case RetriableError::NO_SMART_CARDS_FOUND:
case RetriableError::PKCS11_TOKEN_NOT_PRESENT:
return {QT_TR_NOOP("<b>ID-card not found.</b> Please insert the ID-card into the reader."),
QT_TR_NOOP("Insert the ID-card"), pixmap("no-id-card"_L1)};
QT_TR_NOOP("Insert the ID-card"), "no-id-card"_L1};
case RetriableError::SMART_CARD_WAS_REMOVED:
case RetriableError::PKCS11_TOKEN_REMOVED:
return {QT_TR_NOOP(
"The ID-card was removed from the reader. Please insert the ID-card into the "
"reader."),
QT_TR_NOOP("Insert the ID-card"), pixmap("no-id-card"_L1)};
QT_TR_NOOP("Insert the ID-card"), "no-id-card"_L1};

case RetriableError::SMART_CARD_TRANSACTION_FAILED:
return {
QT_TR_NOOP(
"Operation failed. Make sure that the ID-card and the card reader are connected "
"correctly."),
QT_TR_NOOP("Check the ID-card and the reader connection"), pixmap("no-id-card"_L1)};
QT_TR_NOOP("Check the ID-card and the reader connection"), "no-id-card"_L1};
case RetriableError::FAILED_TO_COMMUNICATE_WITH_CARD_OR_READER:
return {
QT_TR_NOOP(
"Connection to the ID-card or reader failed. Make sure that the ID-card and the "
"card reader are connected correctly."),
QT_TR_NOOP("Check the ID-card and the reader connection"), pixmap("no-id-card"_L1)};
QT_TR_NOOP("Check the ID-card and the reader connection"), "no-id-card"_L1};

case RetriableError::SMART_CARD_CHANGE_REQUIRED:
return {
QT_TR_NOOP(
"The desired operation cannot be performed with the inserted ID-card. Make sure "
"that the ID-card is supported by the Web eID application."),
QT_TR_NOOP("Operation not supported"), pixmap("no-id-card"_L1)};
QT_TR_NOOP("Operation not supported"), "no-id-card"_L1};

case RetriableError::SMART_CARD_COMMAND_ERROR:
return {QT_TR_NOOP("Error communicating with the card."), QT_TR_NOOP("Operation failed"),
Expand All @@ -755,20 +759,20 @@ WebEidDialog::retriableErrorToTextTitleAndIcon(const RetriableError error)
"An error occurred in the Smart Card service required to use the ID-card. Make "
"sure that the ID-card and the card reader are connected correctly or relaunch "
"the Smart Card service."),
QT_TR_NOOP("Operation failed"), pixmap("no-id-card"_L1)};
QT_TR_NOOP("Operation failed"), "no-id-card"_L1};

case RetriableError::UNSUPPORTED_CARD:
return {
QT_TR_NOOP(
"The card in the reader is not supported. Make sure that the entered ID-card is "
"supported by the Web eID application."),
QT_TR_NOOP("Operation not supported"), pixmap("no-id-card"_L1)};
QT_TR_NOOP("Operation not supported"), "no-id-card"_L1};

case RetriableError::NO_VALID_CERTIFICATE_AVAILABLE:
return {QT_TR_NOOP(
"The inserted ID-card does not contain a certificate for the requested "
"operation. Please insert an ID-card that supports the requested operation."),
QT_TR_NOOP("Operation not supported"), pixmap("no-id-card"_L1)};
QT_TR_NOOP("Operation not supported"), "no-id-card"_L1};

case RetriableError::PIN_VERIFY_DISABLED:
return {
Expand All @@ -777,10 +781,10 @@ WebEidDialog::retriableErrorToTextTitleAndIcon(const RetriableError error)
"used. Read more <a "
"href=\"https://www.id.ee/en/article/using-pinpad-card-reader-drivers/\">here</"
"a>."),
QT_TR_NOOP("Card driver error"), QStringLiteral(":/images/cardreader.svg")};
QT_TR_NOOP("Card driver error"), "cardreader"_L1};

case RetriableError::UNKNOWN_ERROR:
return {QT_TR_NOOP("Unknown error"), QT_TR_NOOP("Unknown error"), pixmap("no-id-card"_L1)};
return {QT_TR_NOOP("Unknown error"), QT_TR_NOOP("Unknown error"), "no-id-card"_L1};
}
return {QT_TR_NOOP("Unknown error"), QT_TR_NOOP("Unknown error"), pixmap("no-id-card"_L1)};
return {QT_TR_NOOP("Unknown error"), QT_TR_NOOP("Unknown error"), "no-id-card"_L1};
}
8 changes: 4 additions & 4 deletions src/ui/webeiddialog.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,19 +98,19 @@ class WebEidDialog final : public WebEidUI
void setTrText(QWidget* label, Text text) const;
void
setupCertificateAndPinInfo(const std::vector<CardCertificateAndPinInfo>& cardCertAndPinInfos);
void setupPinPrompt(const PinInfo& pinInfo);
void setupPinPrompt(PinInfo pinInfo);
void setupPinPadProgressBarAndEmitWait(const CardCertificateAndPinInfo& certAndPin);
void setupPinInput(const CardCertificateAndPinInfo& certAndPin);
template <typename Func>
void setupOK(Func&& func, const char* text = {}, bool enabled = false);
void setupOK(Func func, const char* text = {}, bool enabled = false);
void displayPinBlockedError();

void showPinInputWarning(bool show);
void resizeHeight();

static QPixmap pixmap(QLatin1String name);
static std::tuple<const char*, const char*, QPixmap>
retriableErrorToTextTitleAndIcon(RetriableError error);
constexpr static std::tuple<const char*, const char*, QLatin1String>
retriableErrorToTextTitleAndIcon(RetriableError error) noexcept;

class Private;
Private* ui;
Expand Down
28 changes: 12 additions & 16 deletions tests/tests/changecertificatevaliduntil.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,14 @@

#include "pcsc-mock/pcsc-mock.hpp"

#include <ctime>
#include <string>
#include <QDate>

PcscMock::byte_vector::iterator findUTCDateTime(PcscMock::byte_vector::iterator first,
PcscMock::byte_vector::iterator last)
inline PcscMock::byte_vector::iterator findUTCDateTime(PcscMock::byte_vector::iterator first,
PcscMock::byte_vector::iterator last)
{
static const unsigned char UTC_DATETIME_TAG = 0x17;
static const unsigned char LENGTH_TAG = 0x0d;
constexpr unsigned char UTC_DATETIME_TAG = 0x17;
constexpr unsigned char LENGTH_TAG = 0x0d;

for (; first != last; ++first) {
if (*first == UTC_DATETIME_TAG && first + 1 != last && *(first + 1) == LENGTH_TAG) {
Expand All @@ -41,9 +41,9 @@ PcscMock::byte_vector::iterator findUTCDateTime(PcscMock::byte_vector::iterator
return last;
}

PcscMock::ApduScript replaceCertValidUntilYear(const PcscMock::ApduScript& script,
const size_t certBytesStartOffset,
const std::string& twoDigitYear)
inline PcscMock::ApduScript replaceCertValidUntilYear(const PcscMock::ApduScript& script,
const size_t certBytesStartOffset,
std::string_view twoDigitYear)
{
if (twoDigitYear.size() != 2) {
throw std::invalid_argument("replaceCertValidUntilYear: twoDigitYear size must be 2, "
Expand Down Expand Up @@ -85,17 +85,13 @@ PcscMock::ApduScript replaceCertValidUntilYear(const PcscMock::ApduScript& scrip
return scriptCopy;
}

PcscMock::ApduScript replaceCertValidUntilTo2010(const PcscMock::ApduScript& script)
inline PcscMock::ApduScript replaceCertValidUntilTo2010(const PcscMock::ApduScript& script)
{
return replaceCertValidUntilYear(script, 4, "10");
}

PcscMock::ApduScript replaceCertValidUntilToNextYear(const PcscMock::ApduScript& script)
inline PcscMock::ApduScript replaceCertValidUntilToNextYear(const PcscMock::ApduScript& script)
{
const auto t = std::time(nullptr);
const auto now = std::localtime(&t);
// UTCDateTime needs 2-digit year since 2000, tm_year is years since 1900, add +1 for next year
const auto yearInt = now->tm_year + 1900 - 2000 + 1;
const auto yearStr = std::to_string(yearInt);
return replaceCertValidUntilYear(script, 4, yearStr);
// UTCDateTime needs 2-digit year since 2000, add +1 for next year
return replaceCertValidUntilYear(script, 4, std::to_string(QDate::currentDate().year() - 2000 + 1));
}

0 comments on commit ff22514

Please sign in to comment.