ssl/qsslcertificate.cpp

Switch to Source codePreprocessed file
LineSource CodeCoverage
1 -
2 -
3 -
4 -
5 -
6 -
7 -
8 -
9static QMap<QByteArray, QString> _q_mapFromX509Name(X509_NAME *name); -
10 -
11 -
12 -
13 -
14 -
15 -
16 -
17QSslCertificate::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 -
31QSslCertificate::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 -
41QSslCertificate::QSslCertificate(const QSslCertificate &other) : d(other.d) -
42{ -
43}
-
44 -
45 -
46 -
47 -
48QSslCertificate::~QSslCertificate() -
49{ -
50} -
51 -
52 -
53 -
54 -
55 -
56QSslCertificate &QSslCertificate::operator=(const QSslCertificate &other) -
57{ -
58 d = other.d; -
59 return *this;
-
60} -
61bool 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} -
71bool QSslCertificate::isNull() const -
72{ -
73 return d->null;
-
74} -
75bool QSslCertificate::isBlacklisted() const -
76{ -
77 return QSslCertificatePrivate::isBlacklisted(*this);
-
78} -
79 -
80 -
81 -
82 -
83 -
84 -
85 -
86void QSslCertificate::clear() -
87{ -
88 if (isNull())
-
89 return;
-
90 d = new QSslCertificatePrivate; -
91}
-
92 -
93 -
94 -
95 -
96QByteArray 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 -
109QByteArray 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 -
131QByteArray QSslCertificate::digest(QCryptographicHash::Algorithm algorithm) const -
132{ -
133 return QCryptographicHash::hash(toDer(), algorithm);
-
134} -
135 -
136static 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} -
152QStringList 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} -
162QStringList 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} -
172QStringList 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 -
189QStringList 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} -
199QList<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} -
209QList<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} -
219QMultiMap<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 -
259QDateTime QSslCertificate::effectiveDate() const -
260{ -
261 return d->notValidBefore;
-
262} -
263 -
264 -
265 -
266 -
267 -
268 -
269 -
270QDateTime QSslCertificate::expiryDate() const -
271{ -
272 return d->notValidAfter;
-
273} -
274Qt::HANDLE QSslCertificate::handle() const -
275{ -
276 return Qt::HANDLE(d->x509);
-
277} -
278 -
279 -
280 -
281 -
282QSslKey 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 -
315static 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 -
385static 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;
dead code: 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;
dead code: 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;
dead code: 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;
dead code: break;
-
473 } -
474 -
475 return QVariant();
-
476} -
477 -
478QSslCertificateExtension 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 -
515QList<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 -
536QByteArray 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 -
547QByteArray 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 -
560QString QSslCertificate::toText() const -
561{ -
562 if (!d->x509)
-
563 return QString();
-
564 return d->text_from_X509(d->x509);
-
565} -
566QList<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
TRUEFALSE
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
TRUEFALSE
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
TRUEFALSE
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('/'))
TRUEFALSE
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()
TRUEFALSE
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
TRUEFALSE
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)
TRUEFALSE
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()
TRUEFALSE
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()
TRUEFALSE
yes
Evaluation Count:1928
yes
Evaluation Count:52
52-1928
616 QString filePath = startIndex == 0 ? it.next() : it.next().mid(startIndex);
evaluated: startIndex == 0
TRUEFALSE
yes
Evaluation Count:342
yes
Evaluation Count:1586
342-1586
617 if (!pattern.exactMatch(filePath))
evaluated: !pattern.exactMatch(filePath)
TRUEFALSE
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
TRUEFALSE
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)
TRUEFALSE
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} -
629QList<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} -
637QList<QSslCertificate> QSslCertificate::fromData(const QByteArray &data, QSsl::EncodingFormat format) -
638{ -
639 return (format == QSsl::Pem) -
640 ? QSslCertificatePrivate::certificatesFromPem(data) -
641 : QSslCertificatePrivate::certificatesFromDer(data);
-
642} -
643QList<QSslError> QSslCertificate::verify(QList<QSslCertificate> certificateChain, const QString &hostName) -
644{ -
645 return QSslSocketBackendPrivate::verify(certificateChain, hostName);
-
646} -
647 -
648void 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 -
666QByteArray 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 -
701QString 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 -
726QByteArray 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 -
735QByteArray 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 -
744static 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 -
760QSslCertificate 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 -
776static 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 -
795QList<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 -
834QList<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 -
862static 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 -
905bool 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 -
918QDebug 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} -
934QDebug 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 -
Switch to Source codePreprocessed file

Generated by Squish Coco Non-Commercial