Line | Source Code | Coverage |
---|
1 | | - |
2 | | - |
3 | | - |
4 | | - |
5 | | - |
6 | | - |
7 | | - |
8 | | - |
9 | static QMap<QByteArray, QString> _q_mapFromX509Name(X509_NAME *name); | - |
10 | | - |
11 | | - |
12 | | - |
13 | | - |
14 | | - |
15 | | - |
16 | | - |
17 | QSslCertificate::QSslCertificate(QIODevice *device, QSsl::EncodingFormat format) | - |
18 | : d(new QSslCertificatePrivate) | - |
19 | { | - |
20 | QSslSocketPrivate::ensureInitialized(); | - |
21 | if (device) | - |
22 | d->init(device->readAll(), format); | - |
23 | } | - |
24 | | - |
25 | | - |
26 | | - |
27 | | - |
28 | | - |
29 | | - |
30 | | - |
31 | QSslCertificate::QSslCertificate(const QByteArray &data, QSsl::EncodingFormat format) | - |
32 | : d(new QSslCertificatePrivate) | - |
33 | { | - |
34 | QSslSocketPrivate::ensureInitialized(); | - |
35 | d->init(data, format); | - |
36 | } | - |
37 | | - |
38 | | - |
39 | | - |
40 | | - |
41 | QSslCertificate::QSslCertificate(const QSslCertificate &other) : d(other.d) | - |
42 | { | - |
43 | } | - |
44 | | - |
45 | | - |
46 | | - |
47 | | - |
48 | QSslCertificate::~QSslCertificate() | - |
49 | { | - |
50 | } | - |
51 | | - |
52 | | - |
53 | | - |
54 | | - |
55 | | - |
56 | QSslCertificate &QSslCertificate::operator=(const QSslCertificate &other) | - |
57 | { | - |
58 | d = other.d; | - |
59 | return *this; | - |
60 | } | - |
61 | bool QSslCertificate::operator==(const QSslCertificate &other) const | - |
62 | { | - |
63 | if (d == other.d) | - |
64 | return true; | - |
65 | if (d->null && other.d->null) | - |
66 | return true; | - |
67 | if (d->x509 && other.d->x509) | - |
68 | return q_X509_cmp(d->x509, other.d->x509) == 0; | - |
69 | return false; | - |
70 | } | - |
71 | bool QSslCertificate::isNull() const | - |
72 | { | - |
73 | return d->null; | - |
74 | } | - |
75 | bool QSslCertificate::isBlacklisted() const | - |
76 | { | - |
77 | return QSslCertificatePrivate::isBlacklisted(*this); | - |
78 | } | - |
79 | | - |
80 | | - |
81 | | - |
82 | | - |
83 | | - |
84 | | - |
85 | | - |
86 | void QSslCertificate::clear() | - |
87 | { | - |
88 | if (isNull()) | - |
89 | return; | - |
90 | d = new QSslCertificatePrivate; | - |
91 | } | - |
92 | | - |
93 | | - |
94 | | - |
95 | | - |
96 | QByteArray QSslCertificate::version() const | - |
97 | { | - |
98 | QMutexLocker lock(QMutexPool::globalInstanceGet(d.data())); | - |
99 | if (d->versionString.isEmpty() && d->x509) | - |
100 | d->versionString = | - |
101 | QByteArray::number(qlonglong(q_ASN1_INTEGER_get(d->x509->cert_info->version)) + 1); | - |
102 | | - |
103 | return d->versionString; | - |
104 | } | - |
105 | | - |
106 | | - |
107 | | - |
108 | | - |
109 | QByteArray QSslCertificate::serialNumber() const | - |
110 | { | - |
111 | QMutexLocker lock(QMutexPool::globalInstanceGet(d.data())); | - |
112 | if (d->serialNumberString.isEmpty() && d->x509) { | - |
113 | ASN1_INTEGER *serialNumber = d->x509->cert_info->serialNumber; | - |
114 | QByteArray hexString; | - |
115 | hexString.reserve(serialNumber->length * 3); | - |
116 | for (int a = 0; a < serialNumber->length; ++a) { | - |
117 | hexString += QByteArray::number(serialNumber->data[a], 16).rightJustified(2, '0'); | - |
118 | hexString += ':'; | - |
119 | } | - |
120 | hexString.chop(1); | - |
121 | d->serialNumberString = hexString; | - |
122 | } | - |
123 | return d->serialNumberString; | - |
124 | } | - |
125 | | - |
126 | | - |
127 | | - |
128 | | - |
129 | | - |
130 | | - |
131 | QByteArray QSslCertificate::digest(QCryptographicHash::Algorithm algorithm) const | - |
132 | { | - |
133 | return QCryptographicHash::hash(toDer(), algorithm); | - |
134 | } | - |
135 | | - |
136 | static QByteArray _q_SubjectInfoToString(QSslCertificate::SubjectInfo info) | - |
137 | { | - |
138 | QByteArray str; | - |
139 | switch (info) { | - |
140 | case QSslCertificate::Organization: str = QByteArray("O"); break; | - |
141 | case QSslCertificate::CommonName: str = QByteArray("CN"); break; | - |
142 | case QSslCertificate::LocalityName: str = QByteArray("L"); break; | - |
143 | case QSslCertificate::OrganizationalUnitName: str = QByteArray("OU"); break; | - |
144 | case QSslCertificate::CountryName: str = QByteArray("C"); break; | - |
145 | case QSslCertificate::StateOrProvinceName: str = QByteArray("ST"); break; | - |
146 | case QSslCertificate::DistinguishedNameQualifier: str = QByteArray("dnQualifier"); break; | - |
147 | case QSslCertificate::SerialNumber: str = QByteArray("serialNumber"); break; | - |
148 | case QSslCertificate::EmailAddress: str = QByteArray("emailAddress"); break; | - |
149 | } | - |
150 | return str; | - |
151 | } | - |
152 | QStringList QSslCertificate::issuerInfo(SubjectInfo info) const | - |
153 | { | - |
154 | QMutexLocker lock(QMutexPool::globalInstanceGet(d.data())); | - |
155 | | - |
156 | if (d->issuerInfo.isEmpty() && d->x509) | - |
157 | d->issuerInfo = | - |
158 | _q_mapFromX509Name(q_X509_get_issuer_name(d->x509)); | - |
159 | | - |
160 | return d->issuerInfo.values(_q_SubjectInfoToString(info)); | - |
161 | } | - |
162 | QStringList QSslCertificate::issuerInfo(const QByteArray &attribute) const | - |
163 | { | - |
164 | QMutexLocker lock(QMutexPool::globalInstanceGet(d.data())); | - |
165 | | - |
166 | if (d->issuerInfo.isEmpty() && d->x509) | - |
167 | d->issuerInfo = | - |
168 | _q_mapFromX509Name(q_X509_get_issuer_name(d->x509)); | - |
169 | | - |
170 | return d->issuerInfo.values(attribute); | - |
171 | } | - |
172 | QStringList QSslCertificate::subjectInfo(SubjectInfo info) const | - |
173 | { | - |
174 | QMutexLocker lock(QMutexPool::globalInstanceGet(d.data())); | - |
175 | | - |
176 | if (d->subjectInfo.isEmpty() && d->x509) | - |
177 | d->subjectInfo = | - |
178 | _q_mapFromX509Name(q_X509_get_subject_name(d->x509)); | - |
179 | | - |
180 | return d->subjectInfo.values(_q_SubjectInfoToString(info)); | - |
181 | } | - |
182 | | - |
183 | | - |
184 | | - |
185 | | - |
186 | | - |
187 | | - |
188 | | - |
189 | QStringList QSslCertificate::subjectInfo(const QByteArray &attribute) const | - |
190 | { | - |
191 | QMutexLocker lock(QMutexPool::globalInstanceGet(d.data())); | - |
192 | | - |
193 | if (d->subjectInfo.isEmpty() && d->x509) | - |
194 | d->subjectInfo = | - |
195 | _q_mapFromX509Name(q_X509_get_subject_name(d->x509)); | - |
196 | | - |
197 | return d->subjectInfo.values(attribute); | - |
198 | } | - |
199 | QList<QByteArray> QSslCertificate::subjectInfoAttributes() const | - |
200 | { | - |
201 | QMutexLocker lock(QMutexPool::globalInstanceGet(d.data())); | - |
202 | | - |
203 | if (d->subjectInfo.isEmpty() && d->x509) | - |
204 | d->subjectInfo = | - |
205 | _q_mapFromX509Name(q_X509_get_subject_name(d->x509)); | - |
206 | | - |
207 | return d->subjectInfo.uniqueKeys(); | - |
208 | } | - |
209 | QList<QByteArray> QSslCertificate::issuerInfoAttributes() const | - |
210 | { | - |
211 | QMutexLocker lock(QMutexPool::globalInstanceGet(d.data())); | - |
212 | | - |
213 | if (d->issuerInfo.isEmpty() && d->x509) | - |
214 | d->issuerInfo = | - |
215 | _q_mapFromX509Name(q_X509_get_issuer_name(d->x509)); | - |
216 | | - |
217 | return d->issuerInfo.uniqueKeys(); | - |
218 | } | - |
219 | QMultiMap<QSsl::AlternativeNameEntryType, QString> QSslCertificate::subjectAlternativeNames() const | - |
220 | { | - |
221 | QMultiMap<QSsl::AlternativeNameEntryType, QString> result; | - |
222 | | - |
223 | if (!d->x509) | - |
224 | return result; | - |
225 | | - |
226 | STACK *altNames = (STACK*)q_X509_get_ext_d2i(d->x509, 85, 0, 0); | - |
227 | | - |
228 | if (altNames) { | - |
229 | for (int i = 0; i < ((int (*)(const STACK *))q_sk_num)((altNames)); ++i) { | - |
230 | const GENERAL_NAME *genName = ((GENERAL_NAME * (*)(const STACK *, int))q_sk_value)((altNames), (i)); | - |
231 | if (genName->type != 2 && genName->type != 1) | - |
232 | continue; | - |
233 | | - |
234 | int len = q_ASN1_STRING_length(genName->d.ia5); | - |
235 | if (len < 0 || len >= 8192) { | - |
236 | | - |
237 | continue; | - |
238 | } | - |
239 | | - |
240 | const char *altNameStr = reinterpret_cast<const char *>(q_ASN1_STRING_data(genName->d.ia5)); | - |
241 | const QString altName = QString::fromLatin1(altNameStr, len); | - |
242 | if (genName->type == 2) | - |
243 | result.insert(QSsl::DnsEntry, altName); | - |
244 | else if (genName->type == 1) | - |
245 | result.insert(QSsl::EmailEntry, altName); | - |
246 | } | - |
247 | q_sk_pop_free((STACK*)altNames, reinterpret_cast<void(*)(void*)>(q_sk_free)); | - |
248 | } | - |
249 | | - |
250 | return result; | - |
251 | } | - |
252 | | - |
253 | | - |
254 | | - |
255 | | - |
256 | | - |
257 | | - |
258 | | - |
259 | QDateTime QSslCertificate::effectiveDate() const | - |
260 | { | - |
261 | return d->notValidBefore; | - |
262 | } | - |
263 | | - |
264 | | - |
265 | | - |
266 | | - |
267 | | - |
268 | | - |
269 | | - |
270 | QDateTime QSslCertificate::expiryDate() const | - |
271 | { | - |
272 | return d->notValidAfter; | - |
273 | } | - |
274 | Qt::HANDLE QSslCertificate::handle() const | - |
275 | { | - |
276 | return Qt::HANDLE(d->x509); | - |
277 | } | - |
278 | | - |
279 | | - |
280 | | - |
281 | | - |
282 | QSslKey QSslCertificate::publicKey() const | - |
283 | { | - |
284 | if (!d->x509) | - |
285 | return QSslKey(); | - |
286 | | - |
287 | QSslKey key; | - |
288 | | - |
289 | key.d->type = QSsl::PublicKey; | - |
290 | X509_PUBKEY *xkey = d->x509->cert_info->key; | - |
291 | EVP_PKEY *pkey = q_X509_PUBKEY_get(xkey); | - |
292 | qt_noop(); | - |
293 | | - |
294 | if (q_EVP_PKEY_type(pkey->type) == 6) { | - |
295 | key.d->rsa = q_EVP_PKEY_get1_RSA(pkey); | - |
296 | key.d->algorithm = QSsl::Rsa; | - |
297 | key.d->isNull = false; | - |
298 | } else if (q_EVP_PKEY_type(pkey->type) == 116) { | - |
299 | key.d->dsa = q_EVP_PKEY_get1_DSA(pkey); | - |
300 | key.d->algorithm = QSsl::Dsa; | - |
301 | key.d->isNull = false; | - |
302 | } else if (q_EVP_PKEY_type(pkey->type) == 28) { | - |
303 | | - |
304 | } else { | - |
305 | | - |
306 | } | - |
307 | | - |
308 | q_EVP_PKEY_free(pkey); | - |
309 | return key; | - |
310 | } | - |
311 | | - |
312 | | - |
313 | | - |
314 | | - |
315 | static QVariant x509UnknownExtensionToValue(X509_EXTENSION *ext) | - |
316 | { | - |
317 | | - |
318 | | - |
319 | | - |
320 | | - |
321 | X509V3_EXT_METHOD *meth = const_cast<X509V3_EXT_METHOD *>(q_X509V3_EXT_get(ext)); | - |
322 | if (!meth) { | - |
323 | ASN1_OCTET_STRING *value = q_X509_EXTENSION_get_data(ext); | - |
324 | QByteArray result( reinterpret_cast<const char *>(q_ASN1_STRING_data(value)), | - |
325 | q_ASN1_STRING_length(value)); | - |
326 | return result; | - |
327 | } | - |
328 | | - |
329 | | - |
330 | void *ext_internal = q_X509V3_EXT_d2i(ext); | - |
331 | | - |
332 | | - |
333 | if (meth->i2v && ext_internal) { | - |
334 | STACK *val = meth->i2v(meth, ext_internal, 0); | - |
335 | | - |
336 | QVariantMap map; | - |
337 | QVariantList list; | - |
338 | bool isMap = false; | - |
339 | | - |
340 | for (int j = 0; j < ((int (*)(const STACK *))q_sk_num)(val); j++) { | - |
341 | CONF_VALUE *nval = ((CONF_VALUE * (*)(const STACK *, int))q_sk_value)(val, j); | - |
342 | if (nval->name && nval->value) { | - |
343 | isMap = true; | - |
344 | map[QString::fromUtf8(nval->name)] = QString::fromUtf8(nval->value); | - |
345 | } else if (nval->name) { | - |
346 | list << QString::fromUtf8(nval->name); | - |
347 | } else if (nval->value) { | - |
348 | list << QString::fromUtf8(nval->value); | - |
349 | } | - |
350 | } | - |
351 | | - |
352 | if (isMap) | - |
353 | return map; | - |
354 | else | - |
355 | return list; | - |
356 | } else if (meth->i2s && ext_internal) { | - |
357 | | - |
358 | QVariant result(QString::fromUtf8(meth->i2s(meth, ext_internal))); | - |
359 | return result; | - |
360 | } else if (meth->i2r && ext_internal) { | - |
361 | QByteArray result; | - |
362 | | - |
363 | BIO *bio = q_BIO_new(q_BIO_s_mem()); | - |
364 | if (!bio) | - |
365 | return result; | - |
366 | | - |
367 | meth->i2r(meth, ext_internal, bio, 0); | - |
368 | | - |
369 | char *bio_buffer; | - |
370 | long bio_size = (int)q_BIO_ctrl(bio,3,0,(char *)&bio_buffer); | - |
371 | result = QByteArray(bio_buffer, bio_size); | - |
372 | | - |
373 | q_BIO_free(bio); | - |
374 | return result; | - |
375 | } | - |
376 | | - |
377 | return QVariant(); | - |
378 | } | - |
379 | | - |
380 | | - |
381 | | - |
382 | | - |
383 | | - |
384 | | - |
385 | static QVariant x509ExtensionToValue(X509_EXTENSION *ext) | - |
386 | { | - |
387 | ASN1_OBJECT *obj = q_X509_EXTENSION_get_object(ext); | - |
388 | int nid = q_OBJ_obj2nid(obj); | - |
389 | | - |
390 | switch (nid) { | - |
391 | case 87: | - |
392 | { | - |
393 | BASIC_CONSTRAINTS *basic = reinterpret_cast<BASIC_CONSTRAINTS *>(q_X509V3_EXT_d2i(ext)); | - |
394 | | - |
395 | QVariantMap result; | - |
396 | result[QLatin1String("ca")] = basic->ca ? true : false; | - |
397 | if (basic->pathlen) | - |
398 | result[QLatin1String("pathLenConstraint")] = (qlonglong)q_ASN1_INTEGER_get(basic->pathlen); | - |
399 | | - |
400 | q_BASIC_CONSTRAINTS_free(basic); | - |
401 | return result; | - |
402 | } | - |
403 | break; | - |
404 | case 177: | - |
405 | { | - |
406 | AUTHORITY_INFO_ACCESS *info = reinterpret_cast<AUTHORITY_INFO_ACCESS *>(q_X509V3_EXT_d2i(ext)); | - |
407 | | - |
408 | QVariantMap result; | - |
409 | for (int i=0; i < ((int (*)(const STACK *))q_sk_num)(info); i++) { | - |
410 | ACCESS_DESCRIPTION *ad = ((ACCESS_DESCRIPTION * (*)(const STACK *, int))q_sk_value)(info, i); | - |
411 | | - |
412 | GENERAL_NAME *name = ad->location; | - |
413 | if (name->type == 6) { | - |
414 | int len = q_ASN1_STRING_length(name->d.uniformResourceIdentifier); | - |
415 | if (len < 0 || len >= 8192) { | - |
416 | | - |
417 | continue; | - |
418 | } | - |
419 | | - |
420 | const char *uriStr = reinterpret_cast<const char *>(q_ASN1_STRING_data(name->d.uniformResourceIdentifier)); | - |
421 | const QString uri = QString::fromUtf8(uriStr, len); | - |
422 | | - |
423 | result[QString::fromUtf8(QSslCertificatePrivate::asn1ObjectName(ad->method))] = uri; | - |
424 | } else { | - |
425 | QMessageLogger("ssl/qsslcertificate.cpp", 697, __PRETTY_FUNCTION__).warning() << "Strange location type" << name->type; | - |
426 | } | - |
427 | } | - |
428 | | - |
429 | | - |
430 | | - |
431 | | - |
432 | q_sk_pop_free((STACK*)info, reinterpret_cast<void(*)(void*)>(q_sk_free)); | - |
433 | | - |
434 | return result; | - |
435 | } | - |
436 | break; | - |
437 | case 82: | - |
438 | { | - |
439 | void *ext_internal = q_X509V3_EXT_d2i(ext); | - |
440 | | - |
441 | | - |
442 | | - |
443 | | - |
444 | X509V3_EXT_METHOD *meth = const_cast<X509V3_EXT_METHOD *>(q_X509V3_EXT_get(ext)); | - |
445 | | - |
446 | return QVariant(QString::fromUtf8(meth->i2s(meth, ext_internal))); | - |
447 | } | - |
448 | break; | - |
449 | case 90: | - |
450 | { | - |
451 | AUTHORITY_KEYID *auth_key = reinterpret_cast<AUTHORITY_KEYID *>(q_X509V3_EXT_d2i(ext)); | - |
452 | | - |
453 | QVariantMap result; | - |
454 | | - |
455 | | - |
456 | if (auth_key->keyid) { | - |
457 | QByteArray keyid(reinterpret_cast<const char *>(auth_key->keyid->data), | - |
458 | auth_key->keyid->length); | - |
459 | result[QLatin1String("keyid")] = keyid.toHex(); | - |
460 | } | - |
461 | | - |
462 | | - |
463 | | - |
464 | | - |
465 | | - |
466 | if (auth_key->serial) | - |
467 | result[QLatin1String("serial")] = (qlonglong)q_ASN1_INTEGER_get(auth_key->serial); | - |
468 | | - |
469 | q_AUTHORITY_KEYID_free(auth_key); | - |
470 | return result; | - |
471 | } | - |
472 | break; | - |
473 | } | - |
474 | | - |
475 | return QVariant(); | - |
476 | } | - |
477 | | - |
478 | QSslCertificateExtension QSslCertificatePrivate::convertExtension(X509_EXTENSION *ext) | - |
479 | { | - |
480 | QSslCertificateExtension result; | - |
481 | | - |
482 | ASN1_OBJECT *obj = q_X509_EXTENSION_get_object(ext); | - |
483 | QByteArray oid = QSslCertificatePrivate::asn1ObjectId(obj); | - |
484 | QByteArray name = QSslCertificatePrivate::asn1ObjectName(obj); | - |
485 | | - |
486 | result.d->oid = QString::fromUtf8(oid); | - |
487 | result.d->name = QString::fromUtf8(name); | - |
488 | | - |
489 | bool critical = q_X509_EXTENSION_get_critical(ext); | - |
490 | result.d->critical = critical; | - |
491 | | - |
492 | | - |
493 | QVariant extensionValue = x509ExtensionToValue(ext); | - |
494 | if (extensionValue.isValid()) { | - |
495 | result.d->value = extensionValue; | - |
496 | result.d->supported = true; | - |
497 | | - |
498 | return result; | - |
499 | } | - |
500 | | - |
501 | extensionValue = x509UnknownExtensionToValue(ext); | - |
502 | if (extensionValue.isValid()) { | - |
503 | result.d->value = extensionValue; | - |
504 | result.d->supported = false; | - |
505 | return result; | - |
506 | } | - |
507 | | - |
508 | return result; | - |
509 | } | - |
510 | | - |
511 | | - |
512 | | - |
513 | | - |
514 | | - |
515 | QList<QSslCertificateExtension> QSslCertificate::extensions() const | - |
516 | { | - |
517 | QList<QSslCertificateExtension> result; | - |
518 | | - |
519 | if (!d->x509) | - |
520 | return result; | - |
521 | | - |
522 | int count = q_X509_get_ext_count(d->x509); | - |
523 | | - |
524 | for (int i=0; i < count; i++) { | - |
525 | X509_EXTENSION *ext = q_X509_get_ext(d->x509, i); | - |
526 | result << QSslCertificatePrivate::convertExtension(ext); | - |
527 | } | - |
528 | | - |
529 | return result; | - |
530 | } | - |
531 | | - |
532 | | - |
533 | | - |
534 | | - |
535 | | - |
536 | QByteArray QSslCertificate::toPem() const | - |
537 | { | - |
538 | if (!d->x509) | - |
539 | return QByteArray(); | - |
540 | return d->QByteArray_from_X509(d->x509, QSsl::Pem); | - |
541 | } | - |
542 | | - |
543 | | - |
544 | | - |
545 | | - |
546 | | - |
547 | QByteArray QSslCertificate::toDer() const | - |
548 | { | - |
549 | if (!d->x509) | - |
550 | return QByteArray(); | - |
551 | return d->QByteArray_from_X509(d->x509, QSsl::Der); | - |
552 | } | - |
553 | | - |
554 | | - |
555 | | - |
556 | | - |
557 | | - |
558 | | - |
559 | | - |
560 | QString QSslCertificate::toText() const | - |
561 | { | - |
562 | if (!d->x509) | - |
563 | return QString(); | - |
564 | return d->text_from_X509(d->x509); | - |
565 | } | - |
566 | QList<QSslCertificate> QSslCertificate::fromPath(const QString &path, | - |
567 | QSsl::EncodingFormat format, | - |
568 | QRegExp::PatternSyntax syntax) | - |
569 | { | - |
570 | | - |
571 | | - |
572 | | - |
573 | QString sourcePath = QDir::fromNativeSeparators(path); | - |
574 | | - |
575 | | - |
576 | QString pathPrefix = sourcePath.left(sourcePath.lastIndexOf(QLatin1Char('/'))); | - |
577 | | - |
578 | | - |
579 | int pos = -1; | - |
580 | if (syntax == QRegExp::Wildcard) evaluated: syntax == QRegExp::Wildcard yes Evaluation Count:22 | yes Evaluation Count:242 |
| 22-242 |
581 | pos = pathPrefix.indexOf(QRegExp(QLatin1String("[*?[]"))); executed: pos = pathPrefix.indexOf(QRegExp(QLatin1String("[*?[]"))); Execution Count:22 | 22 |
582 | else if (syntax != QRegExp::FixedString) evaluated: syntax != QRegExp::FixedString yes Evaluation Count:16 | yes Evaluation Count:226 |
| 16-226 |
583 | pos = sourcePath.indexOf(QRegExp(QLatin1String("[\\$\\(\\)\\*\\+\\.\\?\\[\\]\\^\\{\\}\\|]"))); executed: pos = sourcePath.indexOf(QRegExp(QLatin1String("[\\$\\(\\)\\*\\+\\.\\?\\[\\]\\^\\{\\}\\|]"))); Execution Count:16 | 16 |
584 | if (pos != -1) { evaluated: pos != -1 yes Evaluation Count:20 | yes Evaluation Count:244 |
| 20-244 |
585 | | - |
586 | pathPrefix = pathPrefix.left(pos); | - |
587 | if (pathPrefix.contains(QLatin1Char('/'))) partially evaluated: pathPrefix.contains(QLatin1Char('/')) no Evaluation Count:0 | yes Evaluation Count:20 |
| 0-20 |
588 | pathPrefix = pathPrefix.left(pathPrefix.lastIndexOf(QLatin1Char('/'))); never executed: pathPrefix = pathPrefix.left(pathPrefix.lastIndexOf(QLatin1Char('/'))); | 0 |
589 | else | - |
590 | pathPrefix.clear(); executed: pathPrefix.clear(); Execution Count:20 | 20 |
591 | } else { | - |
592 | | - |
593 | if (QFileInfo(sourcePath).isFile()) { evaluated: QFileInfo(sourcePath).isFile() yes Evaluation Count:212 | yes Evaluation Count:32 |
| 32-212 |
594 | QFile file(sourcePath); | - |
595 | if (file.open(QIODevice::OpenMode openMode = QIODevice::ReadOnly; | - |
596 | if (format == QSsl::Pem) evaluated: format == QSsl::Pem yes Evaluation Count:210 | yes Evaluation Count:2 |
| 2-210 |
597 | openMode |= QIODevice::Text; executed: openMode |= QIODevice::Text; Execution Count:210 | 210 |
598 | if (file.open(openMode)) partially evaluated: file.open(openMode) yes Evaluation Count:212 | no Evaluation Count:0 |
| 0-212 |
599 | return QSslCertificate::fromData(file.readAll(), format); executed: return QSslCertificate::fromData(file.readAll(), format); Execution Count:212 | 212 |
600 | return QList<QSslCertificate>(); never executed: return QList<QSslCertificate>(); | 0 |
601 | } | - |
602 | } executed: } Execution Count:32 | 32 |
603 | | - |
604 | | - |
605 | int startIndex = 0; | - |
606 | if (pathPrefix.isEmpty()) { evaluated: pathPrefix.isEmpty() yes Evaluation Count:26 | yes Evaluation Count:26 |
| 26 |
607 | pathPrefix = QLatin1String("."); | - |
608 | startIndex = 2; | - |
609 | } executed: } Execution Count:26 | 26 |
610 | | - |
611 | | - |
612 | QList<QSslCertificate> certs; | - |
613 | QRegExp pattern(sourcePath, Qt::CaseSensitive, syntax); | - |
614 | QDirIterator it(pathPrefix, QDir::Files, QDirIterator::FollowSymlinks | QDirIterator::Subdirectories); | - |
615 | while (it.hasNext()) { evaluated: it.hasNext() yes Evaluation Count:1928 | yes Evaluation Count:52 |
| 52-1928 |
616 | QString filePath = startIndex == 0 ? it.next() : it.next().mid(startIndex); evaluated: startIndex == 0 yes Evaluation Count:342 | yes Evaluation Count:1586 |
| 342-1586 |
617 | if (!pattern.exactMatch(filePath)) evaluated: !pattern.exactMatch(filePath) yes Evaluation Count:1818 | yes Evaluation Count:110 |
| 110-1818 |
618 | continue; executed: continue; Execution Count:1818 | 1818 |
619 | | - |
620 | QFile file(filePath); | - |
621 | if (file.open(QIODevice::OpenMode openMode = QIODevice::ReadOnly; | - |
622 | if (format == QSsl::Pem) evaluated: format == QSsl::Pem yes Evaluation Count:78 | yes Evaluation Count:32 |
| 32-78 |
623 | openMode |= QIODevice::Text; executed: openMode |= QIODevice::Text; Execution Count:78 | 78 |
624 | if (file.open(openMode)) partially evaluated: file.open(openMode) yes Evaluation Count:110 | no Evaluation Count:0 |
| 0-110 |
625 | certs += QSslCertificate::fromData(file.readAll(), format); executed: certs += QSslCertificate::fromData(file.readAll(), format); Execution Count:110 | 110 |
626 | } executed: } Execution Count:110 | 110 |
627 | return certs; executed: return certs; Execution Count:52 | 52 |
628 | } | - |
629 | QList<QSslCertificate> QSslCertificate::fromDevice(QIODevice *device, QSsl::EncodingFormat format) | - |
630 | { | - |
631 | if (!device) { | - |
632 | QMessageLogger("ssl/qsslcertificate.cpp", 918924, __PRETTY_FUNCTION__).warning("QSslCertificate::fromDevice: cannot read from a null device"); | - |
633 | return QList<QSslCertificate>(); | - |
634 | } | - |
635 | return fromData(device->readAll(), format); | - |
636 | } | - |
637 | QList<QSslCertificate> QSslCertificate::fromData(const QByteArray &data, QSsl::EncodingFormat format) | - |
638 | { | - |
639 | return (format == QSsl::Pem) | - |
640 | ? QSslCertificatePrivate::certificatesFromPem(data) | - |
641 | : QSslCertificatePrivate::certificatesFromDer(data); | - |
642 | } | - |
643 | QList<QSslError> QSslCertificate::verify(QList<QSslCertificate> certificateChain, const QString &hostName) | - |
644 | { | - |
645 | return QSslSocketBackendPrivate::verify(certificateChain, hostName); | - |
646 | } | - |
647 | | - |
648 | void QSslCertificatePrivate::init(const QByteArray &data, QSsl::EncodingFormat format) | - |
649 | { | - |
650 | if (!data.isEmpty()) { | - |
651 | QList<QSslCertificate> certs = (format == QSsl::Pem) | - |
652 | ? certificatesFromPem(data, 1) | - |
653 | : certificatesFromDer(data, 1); | - |
654 | if (!certs.isEmpty()) { | - |
655 | *this = *certs.first().d; | - |
656 | if (x509) | - |
657 | x509 = q_X509_dup(x509); | - |
658 | } | - |
659 | } | - |
660 | } | - |
661 | | - |
662 | | - |
663 | | - |
664 | | - |
665 | | - |
666 | QByteArray QSslCertificatePrivate::QByteArray_from_X509(X509 *x509, QSsl::EncodingFormat format) | - |
667 | { | - |
668 | if (!x509) { | - |
669 | QMessageLogger("ssl/qsslcertificate.cpp", 978984, __PRETTY_FUNCTION__).warning("QSslSocketBackendPrivate::X509_to_QByteArray: null X509"); | - |
670 | return QByteArray(); | - |
671 | } | - |
672 | | - |
673 | | - |
674 | int length = q_i2d_X509(x509, 0); | - |
675 | QByteArray array; | - |
676 | array.resize(length); | - |
677 | char *data = array.data(); | - |
678 | char **dataP = &data; | - |
679 | unsigned char **dataPu = (unsigned char **)dataP; | - |
680 | if (q_i2d_X509(x509, dataPu) < 0) | - |
681 | return QByteArray(); | - |
682 | | - |
683 | if (format == QSsl::Der) | - |
684 | return array; | - |
685 | | - |
686 | | - |
687 | array = array.toBase64(); | - |
688 | QByteArray tmp; | - |
689 | for (int i = 0; i <= array.size() - 64; i += 64) { | - |
690 | tmp += QByteArray::fromRawData(array.data() + i, 64); | - |
691 | tmp += '\n'; | - |
692 | } | - |
693 | if (int remainder = array.size() % 64) { | - |
694 | tmp += QByteArray::fromRawData(array.data() + array.size() - remainder, remainder); | - |
695 | tmp += '\n'; | - |
696 | } | - |
697 | | - |
698 | return "-----BEGIN CERTIFICATE-----" "\n" + tmp + "-----END CERTIFICATE-----" "\n"; | - |
699 | } | - |
700 | | - |
701 | QString QSslCertificatePrivate::text_from_X509(X509 *x509) | - |
702 | { | - |
703 | if (!x509) { | - |
704 | QMessageLogger("ssl/qsslcertificate.cpp", 10131019, __PRETTY_FUNCTION__).warning("QSslSocketBackendPrivate::text_from_X509: null X509"); | - |
705 | return QString(); | - |
706 | } | - |
707 | | - |
708 | QByteArray result; | - |
709 | BIO *bio = q_BIO_new(q_BIO_s_mem()); | - |
710 | if (!bio) | - |
711 | return QString(); | - |
712 | | - |
713 | q_X509_print(bio, x509); | - |
714 | | - |
715 | QVarLengthArray<char, 16384> data; | - |
716 | int count = q_BIO_read(bio, data.data(), 16384); | - |
717 | if ( count > 0 ) { | - |
718 | result = QByteArray( data.data(), count ); | - |
719 | } | - |
720 | | - |
721 | q_BIO_free(bio); | - |
722 | | - |
723 | return QString::fromLatin1(result); | - |
724 | } | - |
725 | | - |
726 | QByteArray QSslCertificatePrivate::asn1ObjectId(ASN1_OBJECT *object) | - |
727 | { | - |
728 | char buf[80]; | - |
729 | q_OBJ_obj2txt(buf, sizeof(buf), object, 1); | - |
730 | | - |
731 | return QByteArray(buf); | - |
732 | } | - |
733 | | - |
734 | | - |
735 | QByteArray QSslCertificatePrivate::asn1ObjectName(ASN1_OBJECT *object) | - |
736 | { | - |
737 | int nid = q_OBJ_obj2nid(object); | - |
738 | if (nid != 0) | - |
739 | return QByteArray(q_OBJ_nid2sn(nid)); | - |
740 | | - |
741 | return asn1ObjectId(object); | - |
742 | } | - |
743 | | - |
744 | static QMap<QByteArray, QString> _q_mapFromX509Name(X509_NAME *name) | - |
745 | { | - |
746 | QMap<QByteArray, QString> info; | - |
747 | for (int i = 0; i < q_X509_NAME_entry_count(name); ++i) { | - |
748 | X509_NAME_ENTRY *e = q_X509_NAME_get_entry(name, i); | - |
749 | | - |
750 | QByteArray name = QSslCertificatePrivate::asn1ObjectName(q_X509_NAME_ENTRY_get_object(e)); | - |
751 | unsigned char *data = 0; | - |
752 | int size = q_ASN1_STRING_to_UTF8(&data, q_X509_NAME_ENTRY_get_data(e)); | - |
753 | info.insertMulti(name, QString::fromUtf8((char*)data, size)); | - |
754 | q_CRYPTO_free(data); | - |
755 | } | - |
756 | | - |
757 | return info; | - |
758 | } | - |
759 | | - |
760 | QSslCertificate QSslCertificatePrivate::QSslCertificate_from_X509(X509 *x509) | - |
761 | { | - |
762 | QSslCertificate certificate; | - |
763 | if (!x509 || !QSslSocket::supportsSsl()) | - |
764 | return certificate; | - |
765 | | - |
766 | ASN1_TIME *nbef = ((x509)->cert_info->validity->notBefore); | - |
767 | ASN1_TIME *naft = ((x509)->cert_info->validity->notAfter); | - |
768 | certificate.d->notValidBefore = q_getTimeFromASN1(nbef); | - |
769 | certificate.d->notValidAfter = q_getTimeFromASN1(naft); | - |
770 | certificate.d->null = false; | - |
771 | certificate.d->x509 = q_X509_dup(x509); | - |
772 | | - |
773 | return certificate; | - |
774 | } | - |
775 | | - |
776 | static bool matchLineFeed(const QByteArray &pem, int *offset) | - |
777 | { | - |
778 | char ch = 0; | - |
779 | | - |
780 | | - |
781 | while (*offset < pem.size() && (ch = pem.at(*offset)) == ' ') | - |
782 | ++*offset; | - |
783 | | - |
784 | if (ch == '\n') { | - |
785 | *offset += 1; | - |
786 | return true; | - |
787 | } | - |
788 | if (ch == '\r' && pem.size() > (*offset + 1) && pem.at(*offset + 1) == '\n') { | - |
789 | *offset += 2; | - |
790 | return true; | - |
791 | } | - |
792 | return false; | - |
793 | } | - |
794 | | - |
795 | QList<QSslCertificate> QSslCertificatePrivate::certificatesFromPem(const QByteArray &pem, int count) | - |
796 | { | - |
797 | QList<QSslCertificate> certificates; | - |
798 | QSslSocketPrivate::ensureInitialized(); | - |
799 | | - |
800 | int offset = 0; | - |
801 | while (count == -1 || certificates.size() < count) { | - |
802 | int startPos = pem.indexOf("-----BEGIN CERTIFICATE-----", offset); | - |
803 | if (startPos == -1) | - |
804 | break; | - |
805 | startPos += sizeof("-----BEGIN CERTIFICATE-----") - 1; | - |
806 | if (!matchLineFeed(pem, &startPos)) | - |
807 | break; | - |
808 | | - |
809 | int endPos = pem.indexOf("-----END CERTIFICATE-----", startPos); | - |
810 | if (endPos == -1) | - |
811 | break; | - |
812 | | - |
813 | offset = endPos + sizeof("-----END CERTIFICATE-----") - 1; | - |
814 | if (offset < pem.size() && !matchLineFeed(pem, &offset)) | - |
815 | break; | - |
816 | | - |
817 | QByteArray decoded = QByteArray::fromBase64( | - |
818 | QByteArray::fromRawData(pem.data() + startPos, endPos - startPos)); | - |
819 | | - |
820 | const unsigned char *data = (const unsigned char *)decoded.data(); | - |
821 | | - |
822 | | - |
823 | | - |
824 | | - |
825 | if (X509 *x509 = q_d2i_X509(0, &data, decoded.size())) { | - |
826 | certificates << QSslCertificate_from_X509(x509); | - |
827 | q_X509_free(x509); | - |
828 | } | - |
829 | } | - |
830 | | - |
831 | return certificates; | - |
832 | } | - |
833 | | - |
834 | QList<QSslCertificate> QSslCertificatePrivate::certificatesFromDer(const QByteArray &der, int count) | - |
835 | { | - |
836 | QList<QSslCertificate> certificates; | - |
837 | QSslSocketPrivate::ensureInitialized(); | - |
838 | | - |
839 | | - |
840 | | - |
841 | const unsigned char *data = (const unsigned char *)der.data(); | - |
842 | | - |
843 | | - |
844 | | - |
845 | int size = der.size(); | - |
846 | | - |
847 | while (count == -1 || certificates.size() < count) { | - |
848 | if (X509 *x509 = q_d2i_X509(0, &data, size)) { | - |
849 | certificates << QSslCertificate_from_X509(x509); | - |
850 | q_X509_free(x509); | - |
851 | } else { | - |
852 | break; | - |
853 | } | - |
854 | size -= ((char *)data - der.data()); | - |
855 | } | - |
856 | | - |
857 | return certificates; | - |
858 | } | - |
859 | | - |
860 | | - |
861 | | - |
862 | static const char *certificate_blacklist[] = { | - |
863 | "04:7e:cb:e9:fc:a5:5f:7b:d0:9e:ae:36:e1:0c:ae:1e", "mail.google.com", | - |
864 | "f5:c8:6a:f3:61:62:f1:3a:64:f5:4f:6d:c9:58:7c:06", "www.google.com", | - |
865 | "d7:55:8f:da:f5:f1:10:5b:b2:13:28:2b:70:77:29:a3", "login.yahoo.com", | - |
866 | "39:2a:43:4f:0e:07:df:1f:8a:a3:05:de:34:e0:c2:29", "login.yahoo.com", | - |
867 | "3e:75:ce:d4:6b:69:30:21:21:88:30:ae:86:a8:2a:71", "login.yahoo.com", | - |
868 | "e9:02:8b:95:78:e4:15:dc:1a:71:0a:2b:88:15:44:47", "login.skype.com", | - |
869 | "92:39:d5:34:8f:40:d1:69:5a:74:54:70:e1:f2:3f:43", "addons.mozilla.org", | - |
870 | "b0:b7:13:3e:d0:96:f9:b5:6f:ae:91:c8:74:bd:3a:c0", "login.live.com", | - |
871 | "d8:f3:5f:4e:b7:87:2b:2d:ab:06:92:e3:15:38:2f:b0", "global trustee", | - |
872 | | - |
873 | "05:e2:e6:a4:cd:09:ea:54:d6:65:b0:75:fe:22:a2:56", "*.google.com", | - |
874 | "0c:76:da:9c:91:0c:4e:2c:9e:fe:15:d0:58:93:3c:4c", "DigiNotar Root CA", | - |
875 | "f1:4a:13:f4:87:2b:56:dc:39:df:84:ca:7a:a1:06:49", "DigiNotar Services CA", | - |
876 | "36:16:71:55:43:42:1b:9d:e6:cb:a3:64:41:df:24:38", "DigiNotar Services 1024 CA", | - |
877 | "0a:82:bd:1e:14:4e:88:14:d7:5b:1a:55:27:be:bf:3e", "DigiNotar Root CA G2", | - |
878 | "a4:b6:ce:e3:2e:d3:35:46:26:3c:b3:55:3a:a8:92:21", "CertiID Enterprise Certificate Authority", | - |
879 | "5b:d5:60:9c:64:17:68:cf:21:0e:35:fd:fb:05:ad:41", "DigiNotar Qualified CA", | - |
880 | | - |
881 | "46:9c:2c:b0", "DigiNotar Services 1024 CA", | - |
882 | "07:27:10:0d", "DigiNotar Cyber CA", | - |
883 | "07:27:0f:f9", "DigiNotar Cyber CA", | - |
884 | "07:27:10:03", "DigiNotar Cyber CA", | - |
885 | "01:31:69:b0", "DigiNotar PKIoverheid CA Overheid en Bedrijven", | - |
886 | "01:31:34:bf", "DigiNotar PKIoverheid CA Organisatie - G2", | - |
887 | "d6:d0:29:77:f1:49:fd:1a:83:f2:b9:ea:94:8c:5c:b4", "DigiNotar Extended Validation CA", | - |
888 | "1e:7d:7a:53:3d:45:30:41:96:40:0f:71:48:1f:45:04", "DigiNotar Public CA 2025", | - |
889 | | - |
890 | | - |
891 | | - |
892 | "46:9c:2c:af", "DigiNotar Root CA", | - |
893 | "46:9c:3c:c9", "DigiNotar Root CA", | - |
894 | | - |
895 | "07:27:14:a9", "Digisign Server ID (Enrich)", | - |
896 | "4c:0e:63:6a", "Digisign Server ID - (Enrich)", | - |
897 | "72:03:21:05:c5:0c:08:57:3d:8e:a5:30:4e:fe:e8:b0", "UTN-USERFirst-Hardware", | - |
898 | "41", "MD5 Collisions Inc. (http://www.phreedom.org/md5)", | - |
899 | | - |
900 | "08:27", "*.EGO.GOV.TR", | - |
901 | "08:64", "e-islem.kktcmerkezbankasi.org", | - |
902 | 0 | - |
903 | }; | - |
904 | | - |
905 | bool QSslCertificatePrivate::isBlacklisted(const QSslCertificate &certificate) | - |
906 | { | - |
907 | for (int a = 0; certificate_blacklist[a] != 0; a++) { | - |
908 | QString blacklistedCommonName = QString::fromUtf8(certificate_blacklist[(a+1)]); | - |
909 | if (certificate.serialNumber() == certificate_blacklist[a++] && | - |
910 | (certificate.subjectInfo(QSslCertificate::CommonName).contains(blacklistedCommonName) || | - |
911 | certificate.issuerInfo(QSslCertificate::CommonName).contains(blacklistedCommonName))) | - |
912 | return true; | - |
913 | } | - |
914 | return false; | - |
915 | } | - |
916 | | - |
917 | | - |
918 | QDebug operator<<(QDebug debug, const QSslCertificate &certificate) | - |
919 | { | - |
920 | debug << "QSslCertificate(" | - |
921 | << certificate.version() | - |
922 | << ',' << certificate.serialNumber() | - |
923 | << ',' << certificate.digest().toBase64() | - |
924 | << ',' << certificate.issuerInfo(QSslCertificate::Organization) | - |
925 | << ',' << certificate.subjectInfo(QSslCertificate::Organization) | - |
926 | << ',' << certificate.subjectAlternativeNames() | - |
927 | | - |
928 | << ',' << certificate.effectiveDate() | - |
929 | << ',' << certificate.expiryDate() | - |
930 | | - |
931 | << ')'; | - |
932 | return debug; | - |
933 | } | - |
934 | QDebug operator<<(QDebug debug, QSslCertificate::SubjectInfo info) | - |
935 | { | - |
936 | switch (info) { | - |
937 | case QSslCertificate::Organization: debug << "Organization"; break; | - |
938 | case QSslCertificate::CommonName: debug << "CommonName"; break; | - |
939 | case QSslCertificate::CountryName: debug << "CountryName"; break; | - |
940 | case QSslCertificate::LocalityName: debug << "LocalityName"; break; | - |
941 | case QSslCertificate::OrganizationalUnitName: debug << "OrganizationalUnitName"; break; | - |
942 | case QSslCertificate::StateOrProvinceName: debug << "StateOrProvinceName"; break; | - |
943 | case QSslCertificate::DistinguishedNameQualifier: debug << "DistinguishedNameQualifier"; break; | - |
944 | case QSslCertificate::SerialNumber: debug << "SerialNumber"; break; | - |
945 | case QSslCertificate::EmailAddress: debug << "EmailAddress"; break; | - |
946 | } | - |
947 | return debug; | - |
948 | } | - |
949 | | - |
950 | | - |
951 | | - |
952 | | - |
| | |