/*! * \copyright Copyright (c) 2017-2018 Governikus GmbH & Co. KG, Germany */ #include "RemoteServiceSettings.h" #include "DeviceInfo.h" #include #include #include #include #include using namespace governikus; namespace { SETTINGS_NAME(SETTINGS_GROUP_NAME_REMOTEREADER, "remotereader") SETTINGS_NAME(SETTINGS_NAME_DEVICE_NAME, "serverName") SETTINGS_NAME(SETTINGS_NAME_PIN_PAD_MODE, "pinPadMode") SETTINGS_NAME(SETTINGS_ARRAY_NAME_TRUSTED_CERTIFICATES, "trustedCertificates") SETTINGS_NAME(SETTINGS_NAME_TRUSTED_CERTIFICATE_ITEM, "certificate") SETTINGS_NAME(SETTINGS_NAME_TRUSTED_REMOTE_INFO, "trustedRemoteInfo") SETTINGS_NAME(SETTINGS_NAME_KEY, "key") SETTINGS_NAME(SETTINGS_NAME_CERTIFICATE, "certificate") } QString RemoteServiceSettings::generateFingerprint(const QSslCertificate& pCert) { return pCert.isNull() ? QString() : QString::fromLatin1(pCert.digest(QCryptographicHash::Sha256).toHex()); } RemoteServiceSettings::RemoteServiceSettings() : AbstractSettings() , mStore(getStore()) { mStore->beginGroup(SETTINGS_GROUP_NAME_REMOTEREADER()); if (!mStore->contains(SETTINGS_NAME_DEVICE_NAME())) { setServerName(QString()); } } RemoteServiceSettings::~RemoteServiceSettings() { } void RemoteServiceSettings::save() { mStore->sync(); } QString RemoteServiceSettings::getDefaultServerName() { QString name = DeviceInfo::getName(); if (name.isEmpty()) { return tr("Remote Reader"); } return name; } QString RemoteServiceSettings::getServerName() const { return mStore->value(SETTINGS_NAME_DEVICE_NAME(), QString()).toString(); } void RemoteServiceSettings::setServerName(const QString& pName) { if (pName.isEmpty()) { mStore->setValue(SETTINGS_NAME_DEVICE_NAME(), getDefaultServerName()); return; } mStore->setValue(SETTINGS_NAME_DEVICE_NAME(), pName); } bool RemoteServiceSettings::getPinPadMode() const { return mStore->value(SETTINGS_NAME_PIN_PAD_MODE(), false).toBool(); } void RemoteServiceSettings::setPinPadMode(bool pPinPadMode) { mStore->setValue(SETTINGS_NAME_PIN_PAD_MODE(), pPinPadMode); } QList RemoteServiceSettings::getTrustedCertificates() const { const int itemCount = mStore->beginReadArray(SETTINGS_ARRAY_NAME_TRUSTED_CERTIFICATES()); QList certificates; certificates.reserve(itemCount); for (int i = 0; i < itemCount; ++i) { mStore->setArrayIndex(i); const auto& cert = mStore->value(SETTINGS_NAME_TRUSTED_CERTIFICATE_ITEM(), QByteArray()).toByteArray(); certificates << QSslCertificate(cert); } mStore->endArray(); return certificates; } void RemoteServiceSettings::setUniqueTrustedCertificates(const QSet& pCertificates) { mStore->beginGroup(SETTINGS_ARRAY_NAME_TRUSTED_CERTIFICATES()); mStore->remove(QString()); mStore->endGroup(); mStore->beginWriteArray(SETTINGS_ARRAY_NAME_TRUSTED_CERTIFICATES()); int i = 0; for (const auto& cert : pCertificates) { mStore->setArrayIndex(i++); mStore->setValue(SETTINGS_NAME_TRUSTED_CERTIFICATE_ITEM(), cert.toPem()); } mStore->endArray(); syncRemoteInfos(pCertificates); Q_EMIT fireTrustedCertificatesChanged(); } void RemoteServiceSettings::setTrustedCertificates(const QList& pCertificates) { setUniqueTrustedCertificates(pCertificates.toSet()); // remove duplicates } void RemoteServiceSettings::addTrustedCertificate(const QSslCertificate& pCertificate) { auto certs = getTrustedCertificates(); certs << pCertificate; setTrustedCertificates(certs); } void RemoteServiceSettings::removeTrustedCertificate(const QSslCertificate& pCertificate) { auto certs = getTrustedCertificates(); certs.removeAll(pCertificate); setTrustedCertificates(certs); } void RemoteServiceSettings::removeTrustedCertificate(const QString& pFingerprint) { const auto& certs = getTrustedCertificates(); for (const auto& cert : certs) { if (generateFingerprint(cert) == pFingerprint) { removeTrustedCertificate(cert); return; } } } QSslCertificate RemoteServiceSettings::getCertificate() const { return QSslCertificate(mStore->value(SETTINGS_NAME_CERTIFICATE(), QByteArray()).toByteArray()); } void RemoteServiceSettings::setCertificate(const QSslCertificate& pCert) const { mStore->setValue(SETTINGS_NAME_CERTIFICATE(), pCert.toPem()); } QSslKey RemoteServiceSettings::getKey() const { const auto& data = mStore->value(SETTINGS_NAME_KEY(), QByteArray()).toByteArray(); if (data.contains("BEGIN RSA PRIVATE KEY")) { return QSslKey(data, QSsl::Rsa); } return QSslKey(); } void RemoteServiceSettings::setKey(const QSslKey& pKey) const { mStore->setValue(SETTINGS_NAME_KEY(), pKey.toPem()); } RemoteServiceSettings::RemoteInfo RemoteServiceSettings::getRemoteInfo(const QSslCertificate& pCertificate) const { return getRemoteInfo(generateFingerprint(pCertificate)); } RemoteServiceSettings::RemoteInfo RemoteServiceSettings::getRemoteInfo(const QString& pFingerprint) const { const auto& infos = getRemoteInfos(); for (const auto& item : infos) { if (item.getFingerprint() == pFingerprint) { return item; } } return RemoteInfo(); } QVector RemoteServiceSettings::getRemoteInfos() const { QVector infos; const auto& data = mStore->value(SETTINGS_NAME_TRUSTED_REMOTE_INFO(), QByteArray()).toByteArray(); const auto& array = QJsonDocument::fromJson(data).array(); for (const auto& item : array) { const auto& obj = item.toObject(); auto fingerprint = obj[QLatin1String("fingerprint")].toString(); auto name = obj[QLatin1String("name")].toString(); auto lastConnected = QDateTime::fromString(obj[QLatin1String("lastConnected")].toString(), Qt::ISODateWithMs); infos << RemoteInfo(fingerprint, lastConnected, name); } return infos; } void RemoteServiceSettings::setRemoteInfos(const QVector& pInfos) { QJsonArray array; for (const auto& item : pInfos) { QJsonObject obj; obj[QLatin1String("fingerprint")] = item.getFingerprint(); obj[QLatin1String("name")] = item.getName(); obj[QLatin1String("lastConnected")] = item.getLastConnected().toString(Qt::ISODateWithMs); array << obj; } mStore->setValue(SETTINGS_NAME_TRUSTED_REMOTE_INFO(), QJsonDocument(array).toJson(QJsonDocument::Compact)); Q_EMIT fireTrustedRemoteInfosChanged(); } void RemoteServiceSettings::syncRemoteInfos(const QSet& pCertificates) { QStringList trustedFingerprints; for (const auto& cert : pCertificates) { trustedFingerprints << generateFingerprint(cert); } QVector syncedInfo; // remove outdated entries const auto& infos = getRemoteInfos(); for (const auto& info : infos) { if (trustedFingerprints.contains(info.getFingerprint())) { trustedFingerprints.removeOne(info.getFingerprint()); syncedInfo << info; } } // add new entries for (const auto& fingerprint : qAsConst(trustedFingerprints)) { syncedInfo << RemoteInfo(fingerprint, QDateTime::currentDateTime()); } setRemoteInfos(syncedInfo); } bool RemoteServiceSettings::updateRemoteInfo(const RemoteInfo& pInfo) { if (pInfo.getFingerprint().isEmpty()) { return false; } auto infos = getRemoteInfos(); QMutableVectorIterator iter(infos); while (iter.hasNext()) { iter.next(); if (iter.value().getFingerprint() == pInfo.getFingerprint()) { iter.setValue(pInfo); setRemoteInfos(infos); return true; } } return false; } RemoteServiceSettings::RemoteInfo::RemoteInfo(const QString& pFingerprint, const QDateTime& pLastConnected, const QString& pName) : mFingerprint(pFingerprint) , mName(pName) , mLastConnected(pLastConnected) { } const QString& RemoteServiceSettings::RemoteInfo::getFingerprint() const { return mFingerprint; } const QString& RemoteServiceSettings::RemoteInfo::getName() const { return mName; } void RemoteServiceSettings::RemoteInfo::setName(const QString& pName) { mName = pName; } const QDateTime& RemoteServiceSettings::RemoteInfo::getLastConnected() const { return mLastConnected; } void RemoteServiceSettings::RemoteInfo::setLastConnected(const QDateTime& pLastConnected) { mLastConnected = pLastConnected; } bool RemoteServiceSettings::RemoteInfo::operator==(const RemoteInfo& pOther) const { return mFingerprint == pOther.mFingerprint && mName == pOther.mName && mLastConnected == pOther.mLastConnected; } bool RemoteServiceSettings::RemoteInfo::operator!=(const RemoteInfo& pOther) const { return !(*this == pOther); }