1 /*!
2 * \copyright Copyright (c) 2019-2021 Governikus GmbH & Co. KG, Germany
3 */
4
5 #include "SurveyModel.h"
6
7 #include "DeviceInfo.h"
8 #include "Env.h"
9 #include "LogHandler.h"
10 #include "NetworkManager.h"
11 #include "SecureStorage.h"
12 #include "TlsChecker.h"
13
14 #include <QCoreApplication>
15 #include <QDebug>
16 #include <QJsonDocument>
17 #include <QJsonObject>
18 #include <QLoggingCategory>
19 #include <QNetworkReply>
20 #include <QNetworkRequest>
21
22 Q_DECLARE_LOGGING_CATEGORY(network)
23
24 using namespace governikus;
25
26 #define VALUE_NAME(_name, _key)\
27 inline QLatin1String _name(){\
28 return QLatin1String(_key);\
29 }
30
31
32 namespace
33 {
34 VALUE_NAME(ROM, "Rom")
35 VALUE_NAME(BUILD_NUMBER, "BuildNumber")
36 VALUE_NAME(ANDROID_VERSION, "AndroidVersion")
37 VALUE_NAME(KERNEL_VERSION, "KernelVersion")
38 VALUE_NAME(MAXIMUM_NFC_PACKET_LENGTH, "MaximumNfcPacketLength")
39 VALUE_NAME(VENDOR, "Vendor")
40 VALUE_NAME(MODEL_NUMBER, "ModelNumber")
41 VALUE_NAME(MODEL_NAME, "ModelName")
42 VALUE_NAME(AUSWEISAPP_VERSION_NUMBER, "AusweisAppVersionNumber")
43 } // namespace
44
45
SurveyModel()46 SurveyModel::SurveyModel()
47 : QAbstractListModel()
48 , mBuildNumber(DeviceInfo::getOSBuildNumber())
49 , mAndroidVersion(DeviceInfo::getOSVersion())
50 , mKernelVersion(DeviceInfo::getKernelVersion())
51 , mMaximumNfcPacketLength(0)
52 , mVendor(DeviceInfo::getVendor())
53 , mModelNumber(DeviceInfo::getModelNumber())
54 , mModelName(DeviceInfo::getModelName())
55 , mAusweisAppVersionNumber(QCoreApplication::applicationVersion())
56 {
57 buildDataObject();
58 }
59
60
rowCount(const QModelIndex &) const61 int SurveyModel::rowCount(const QModelIndex&) const
62 {
63 return mData.size();
64 }
65
66
data(const QModelIndex & pIndex,int pRole) const67 QVariant SurveyModel::data(const QModelIndex& pIndex, int pRole) const
68 {
69 if (pIndex.isValid() && pIndex.row() < rowCount())
70 {
71 auto entry = mData[pIndex.row()];
72 if (pRole == TITLE)
73 {
74 return entry.first;
75 }
76 if (pRole == VALUE)
77 {
78 return entry.second;
79 }
80 }
81 return QVariant();
82 }
83
84
roleNames() const85 QHash<int, QByteArray> SurveyModel::roleNames() const
86 {
87 QHash<int, QByteArray> roles = QAbstractListModel::roleNames();
88 roles.insert(TITLE, "title");
89 roles.insert(VALUE, "value");
90 return roles;
91 }
92
93
buildDataObject()94 void SurveyModel::buildDataObject()
95 {
96 beginResetModel();
97 mData.clear();
98 mData += qMakePair(tr("Vendor"), mVendor);
99 mData += qMakePair(tr("Model Name"), mModelName);
100 mData += qMakePair(tr("Model Number"), mModelNumber);
101 mData += qMakePair(tr("Build Number"), mBuildNumber);
102 mData += qMakePair(tr("Android version"), mAndroidVersion);
103 mData += qMakePair(tr("Kernel version"), mKernelVersion);
104 mData += qMakePair(tr("Max. NFC Packet Length"), QString::number(mMaximumNfcPacketLength));
105 mData += qMakePair(tr("AusweisApp2 Version"), mAusweisAppVersionNumber);
106 endResetModel();
107 }
108
109
toJsonByteArray() const110 QByteArray SurveyModel::toJsonByteArray() const
111 {
112 QJsonObject rom;
113 rom[BUILD_NUMBER()] = mBuildNumber;
114 rom[ANDROID_VERSION()] = mAndroidVersion;
115 rom[KERNEL_VERSION()] = mKernelVersion;
116 rom[MAXIMUM_NFC_PACKET_LENGTH()] = QJsonValue(mMaximumNfcPacketLength);
117
118 QJsonObject mainObject;
119 mainObject[ROM()] = rom;
120 mainObject[VENDOR()] = mVendor;
121 mainObject[MODEL_NUMBER()] = mModelNumber;
122 mainObject[MODEL_NAME()] = mModelName;
123 mainObject[AUSWEISAPP_VERSION_NUMBER()] = mAusweisAppVersionNumber;
124
125 #ifndef QT_NO_DEBUG
126 if (QCoreApplication::applicationName().startsWith(QLatin1String("Test")))
127 {
128 return QJsonDocument(mainObject).toJson(QJsonDocument::Indented);
129 }
130 #endif
131
132 return QJsonDocument(mainObject).toJson(QJsonDocument::Compact);
133 }
134
135
setMaximumNfcPacketLength(int pMaximumNfcPacketLength)136 void SurveyModel::setMaximumNfcPacketLength(int pMaximumNfcPacketLength)
137 {
138 mMaximumNfcPacketLength = pMaximumNfcPacketLength;
139 buildDataObject();
140 }
141
142
transmitSurvey()143 void SurveyModel::transmitSurvey()
144 {
145 const QUrl whitelistServerBaseUrl = Env::getSingleton<SecureStorage>()->getWhitelistServerBaseUrl();
146 const QUrl postSurveyUrl(whitelistServerBaseUrl.toString() + QStringLiteral("/new"));
147 QNetworkRequest request(postSurveyUrl);
148 request.setHeader(QNetworkRequest::ContentTypeHeader, QLatin1String("application/json; charset=UTF-8"));
149
150 const QByteArray jsonData = toJsonByteArray();
151 mReply.reset(Env::getSingleton<NetworkManager>()->post(request, jsonData), &QNetworkReply::deleteLater);
152
153 connect(mReply.data(), &QNetworkReply::sslErrors, this, &SurveyModel::onSslErrors);
154 connect(mReply.data(), &QNetworkReply::encrypted, this, &SurveyModel::onSslHandshakeDone);
155 connect(mReply.data(), &QNetworkReply::finished, this, &SurveyModel::onNetworkReplyFinished);
156
157 qDebug().noquote() << "Sent survey to whitelist server:" << jsonData;
158 }
159
160
onSslErrors(const QList<QSslError> & pErrors)161 void SurveyModel::onSslErrors(const QList<QSslError>& pErrors)
162 {
163 TlsChecker::containsFatalError(mReply, pErrors);
164 }
165
166
onSslHandshakeDone()167 void SurveyModel::onSslHandshakeDone()
168 {
169 const auto& cfg = mReply->sslConfiguration();
170 TlsChecker::logSslConfig(cfg, spawnMessageLogger(network));
171
172 if (!Env::getSingleton<NetworkManager>()->checkUpdateServerCertificate(mReply))
173 {
174 qCCritical(network) << "Untrusted certificate of Whitelist server found:" << cfg.peerCertificate();
175 mReply->abort();
176 }
177 }
178
179
onNetworkReplyFinished()180 void SurveyModel::onNetworkReplyFinished()
181 {
182 if (mReply)
183 {
184 mReply->disconnect(this);
185 mReply.reset();
186 }
187 }
188