1 /*!
2 * \copyright Copyright (c) 2014-2021 Governikus GmbH & Co. KG, Germany
3 */
4
5 #include "CertificateDescription.h"
6 #include "KnownOIDs.h"
7
8 #include <QCoreApplication>
9 #include <QDebug>
10 #include <QRegularExpression>
11
12
13 using namespace governikus;
14
15
16 namespace
17 {
takeWhileNonEmpty(const QStringList & lines)18 QStringList takeWhileNonEmpty(const QStringList& lines)
19 {
20 QStringList result;
21 for (const auto& line : lines)
22 {
23 const QString trimmedLine = line.trimmed();
24 if (trimmedLine.isEmpty())
25 {
26 return result;
27 }
28 else
29 {
30 result += trimmedLine;
31 }
32 }
33
34 return result;
35 }
36
37
getField(const QString & pData,const QStringList & pSearchItems)38 QString getField(const QString& pData, const QStringList& pSearchItems)
39 {
40 const QLatin1Char NEW_LINE('\n');
41 const QRegularExpression REGEX_EMPTY_SECTION(QStringLiteral("^\\R{2,}"));
42
43 for (const auto& item : pSearchItems)
44 {
45 const auto pos = pData.indexOf(item);
46 if (pos != -1)
47 {
48 const QString rest = pData.mid(pos + item.length());
49 if (REGEX_EMPTY_SECTION.match(rest).hasMatch())
50 {
51 continue;
52 }
53
54 const QStringList lines = takeWhileNonEmpty(rest.trimmed().split(NEW_LINE));
55 if (lines.isEmpty())
56 {
57 continue;
58 }
59
60 return lines.join(NEW_LINE);
61 }
62 }
63
64 return QString();
65 }
66
67
68 } // namespace
69
70
71 namespace governikus
72 {
73
74 ASN1_SEQUENCE(CertificateDescription) = {
75 ASN1_SIMPLE(CertificateDescription, mDescriptionType, ASN1_OBJECT),
76 ASN1_EXP(CertificateDescription, mIssuerName, ASN1_UTF8STRING, 1),
77 ASN1_EXP_OPT(CertificateDescription, mIssuerURL, ASN1_PRINTABLESTRING, 2),
78 ASN1_EXP(CertificateDescription, mSubjectName, ASN1_UTF8STRING, 3),
79 ASN1_EXP_OPT(CertificateDescription, mSubjectURL, ASN1_PRINTABLESTRING, 4),
80 ASN1_EXP(CertificateDescription, mTermsOfUsage, ASN1_ANY, 5),
81 ASN1_EXP_OPT(CertificateDescription, mRedirectURL, ASN1_PRINTABLESTRING, 6),
82 ASN1_EXP_SET_OF_OPT(CertificateDescription, mCommCertificates, ASN1_OCTET_STRING, 7),
83 }
84
85
86 ASN1_SEQUENCE_END(CertificateDescription)
87
88 IMPLEMENT_ASN1_FUNCTIONS(CertificateDescription)
89 IMPLEMENT_ASN1_OBJECT(CertificateDescription)
90
91 } // namespace governikus
92
93
fromHex(const QByteArray & pHexValue)94 QSharedPointer<const CertificateDescription> CertificateDescription::fromHex(const QByteArray& pHexValue)
95 {
96 return decode(QByteArray::fromHex(pHexValue));
97 }
98
99
decode(const QByteArray & pBytes)100 QSharedPointer<const CertificateDescription> CertificateDescription::decode(const QByteArray& pBytes)
101 {
102 return decodeObject<CertificateDescription>(pBytes);
103 }
104
105
encode()106 QByteArray CertificateDescription::encode()
107 {
108 return encodeObject(this);
109 }
110
111
setDescriptionType(const QByteArray & pOidAsText)112 void CertificateDescription::setDescriptionType(const QByteArray& pOidAsText)
113 {
114 ASN1_OBJECT_free(mDescriptionType);
115 mDescriptionType = Asn1ObjectUtil::parseFrom(pOidAsText);
116 }
117
118
getDescriptionType() const119 QByteArray CertificateDescription::getDescriptionType() const
120 {
121 return Asn1ObjectUtil::convertTo(mDescriptionType);
122 }
123
124
setIssuerName(const QString & pIssuerName)125 void CertificateDescription::setIssuerName(const QString& pIssuerName)
126 {
127 Asn1StringUtil::setValue(pIssuerName, mIssuerName);
128 }
129
130
getIssuerName() const131 QString CertificateDescription::getIssuerName() const
132 {
133 return Asn1StringUtil::getValue(mIssuerName);
134 }
135
136
setIssuerUrl(const QString & pIssuerUrl)137 void CertificateDescription::setIssuerUrl(const QString& pIssuerUrl)
138 {
139 if (mIssuerURL == nullptr)
140 {
141 mIssuerURL = ASN1_PRINTABLESTRING_new();
142 }
143 Asn1StringUtil::setValue(pIssuerUrl, mIssuerURL);
144 }
145
146
getIssuerUrl() const147 QString CertificateDescription::getIssuerUrl() const
148 {
149 return Asn1StringUtil::getValue(mIssuerURL);
150 }
151
152
setSubjectName(const QString & pSubjectName)153 void CertificateDescription::setSubjectName(const QString& pSubjectName)
154 {
155 Asn1StringUtil::setValue(pSubjectName, mSubjectName);
156 }
157
158
getSubjectName() const159 QString CertificateDescription::getSubjectName() const
160 {
161 return Asn1StringUtil::getValue(mSubjectName);
162 }
163
164
setSubjectUrl(const QString & pSubjectUrl)165 void CertificateDescription::setSubjectUrl(const QString& pSubjectUrl)
166 {
167 if (mSubjectURL == nullptr)
168 {
169 mSubjectURL = ASN1_PRINTABLESTRING_new();
170 }
171 Asn1StringUtil::setValue(pSubjectUrl, mSubjectURL);
172 }
173
174
getSubjectUrl() const175 QString CertificateDescription::getSubjectUrl() const
176 {
177 return Asn1StringUtil::getValue(mSubjectURL);
178 }
179
180
getTermsOfUsageType() const181 CertificateDescription::TermsOfUsageType CertificateDescription::getTermsOfUsageType() const
182 {
183 if (getDescriptionType() == KnownOIDs::TermsOfUsageType::ID_PLAIN_FORMAT)
184 {
185 return TermsOfUsageType::PLAIN_TEXT;
186 }
187 if (getDescriptionType() == KnownOIDs::TermsOfUsageType::ID_HTML_FORMAT)
188 {
189 return TermsOfUsageType::HTML;
190 }
191 return TermsOfUsageType::PDF;
192 }
193
194
getTermsOfUsage() const195 QString CertificateDescription::getTermsOfUsage() const
196 {
197 QString string;
198 if (mTermsOfUsage->type == V_ASN1_UTF8STRING)
199 {
200 string = Asn1StringUtil::getValue(mTermsOfUsage->value.utf8string);
201 }
202 else if (mTermsOfUsage->type == V_ASN1_IA5STRING)
203 {
204 string = Asn1StringUtil::getValue(mTermsOfUsage->value.ia5string);
205 }
206 else if (mTermsOfUsage->type == V_ASN1_OCTET_STRING && mTermsOfUsage->value.octet_string != nullptr)
207 {
208 string = QString::fromLatin1(Asn1TypeUtil::encode(mTermsOfUsage).toHex().toUpper());
209 }
210
211 return string;
212 }
213
214
setRedirectUrl(const QString & pRedirectUrl)215 void CertificateDescription::setRedirectUrl(const QString& pRedirectUrl)
216 {
217 if (mRedirectURL == nullptr)
218 {
219 mRedirectURL = ASN1_PRINTABLESTRING_new();
220 }
221 Asn1StringUtil::setValue(pRedirectUrl, mRedirectURL);
222 }
223
224
getRedirectUrl() const225 QString CertificateDescription::getRedirectUrl() const
226 {
227 return Asn1StringUtil::getValue(mRedirectURL);
228 }
229
230
getCommCertificates() const231 QSet<QString> CertificateDescription::getCommCertificates() const
232 {
233 QSet<QString> commCerts;
234 if (mCommCertificates != nullptr)
235 {
236 const auto size = sk_ASN1_OCTET_STRING_num(mCommCertificates);
237 commCerts.reserve(size);
238 for (int i = 0; i < size; i++)
239 {
240 const ASN1_OCTET_STRING* octetString = sk_ASN1_OCTET_STRING_value(mCommCertificates, i);
241 QByteArray byteBuf(reinterpret_cast<char*>(octetString->data), octetString->length);
242 commCerts += QString::fromLatin1(byteBuf.toHex().toUpper());
243 }
244 }
245 return commCerts;
246 }
247
248
getServiceProviderAddress() const249 QString CertificateDescription::getServiceProviderAddress() const
250 {
251 static const QStringList SEARCH_ITEMS({
252 QStringLiteral("Name, Anschrift und E-Mail-Adresse des Diensteanbieters:")
253 });
254
255 return getField(getTermsOfUsage(), SEARCH_ITEMS);
256 }
257
258
getPurpose() const259 QString CertificateDescription::getPurpose() const
260 {
261 static const QStringList SEARCH_ITEMS({
262 QStringLiteral("Gesch\u00E4ftszweck:"),
263 QStringLiteral("Zweck des Auslesevorgangs:"),
264 QStringLiteral("Verwendung der Daten:"),
265 QStringLiteral("Zweck der Daten\u00FCbermittlung:")
266 });
267
268 return getField(getTermsOfUsage(), SEARCH_ITEMS);
269 }
270
271
getDataSecurityOfficer() const272 QString CertificateDescription::getDataSecurityOfficer() const
273 {
274 static const QStringList SEARCH_ITEMS({QStringLiteral(
275 "Hinweis auf die f\u00FCr den Diensteanbieter zust\u00E4ndigen Stellen, "
276 "die die Einhaltung der Vorschriften zum Datenschutz kontrollieren:")});
277
278 return getField(getTermsOfUsage(), SEARCH_ITEMS);
279 }
280