summaryrefslogtreecommitdiffstats
path: root/src/network/ssl/qsslcertificate.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/network/ssl/qsslcertificate.cpp')
-rw-r--r--src/network/ssl/qsslcertificate.cpp150
1 files changed, 150 insertions, 0 deletions
diff --git a/src/network/ssl/qsslcertificate.cpp b/src/network/ssl/qsslcertificate.cpp
index 47ea3343ea..bae78f4347 100644
--- a/src/network/ssl/qsslcertificate.cpp
+++ b/src/network/ssl/qsslcertificate.cpp
@@ -122,6 +122,7 @@
#include "qsslcertificate.h"
#include "qsslcertificate_p.h"
+#include "qasn1element_p.h"
#include "qsslkey_p.h"
#include <QtCore/qdir.h>
@@ -641,6 +642,155 @@ static const char *certificate_blacklist[] = {
0
};
+bool QSslCertificatePrivate::parse(const QByteArray &data)
+{
+#ifndef QT_NO_OPENSSL
+ Q_UNUSED(data);
+#else
+ QAsn1Element root;
+
+ QDataStream dataStream(data);
+ if (!root.read(dataStream) || root.type() != QAsn1Element::SequenceType)
+ return false;
+
+ QDataStream rootStream(root.value());
+ QAsn1Element cert;
+ if (!cert.read(rootStream) || cert.type() != QAsn1Element::SequenceType)
+ return false;
+
+ // version or serial number
+ QAsn1Element elem;
+ QDataStream certStream(cert.value());
+ if (!elem.read(certStream))
+ return false;
+
+ if (elem.type() == QAsn1Element::Context0Type) {
+ QDataStream versionStream(elem.value());
+ if (!elem.read(versionStream) || elem.type() != QAsn1Element::IntegerType)
+ return false;
+
+ versionString = QByteArray::number(elem.value()[0] + 1);
+ if (!elem.read(certStream))
+ return false;
+ } else {
+ versionString = QByteArray::number(1);
+ }
+
+ // serial number
+ if (elem.type() != QAsn1Element::IntegerType)
+ return false;
+
+ QByteArray hexString;
+ hexString.reserve(elem.value().size() * 3);
+ for (int a = 0; a < elem.value().size(); ++a) {
+ const quint8 b = elem.value().at(a);
+ if (b || !hexString.isEmpty()) { // skip leading zeros
+ hexString += QByteArray::number(b, 16).rightJustified(2, '0');
+ hexString += ':';
+ }
+ }
+ hexString.chop(1);
+ serialNumberString = hexString;
+
+ // algorithm ID
+ if (!elem.read(certStream) || elem.type() != QAsn1Element::SequenceType)
+ return false;
+
+ //qDebug() << "algorithm ID" << elem.type() << elem.length << elem.value().toHex();
+
+ // issuer info
+ if (!elem.read(certStream) || elem.type() != QAsn1Element::SequenceType)
+ return false;
+
+ QByteArray issuerDer = data.mid(dataStream.device()->pos() - elem.value().length(), elem.value().length());
+ issuerInfo = elem.toInfo();
+
+ // validity period
+ if (!elem.read(certStream) || elem.type() != QAsn1Element::SequenceType)
+ return false;
+
+ QDataStream validityStream(elem.value());
+ if (!elem.read(validityStream) || (elem.type() != QAsn1Element::UtcTimeType && elem.type() != QAsn1Element::GeneralizedTimeType))
+ return false;
+
+ notValidBefore = elem.toDateTime();
+ if (!elem.read(validityStream) || (elem.type() != QAsn1Element::UtcTimeType && elem.type() != QAsn1Element::GeneralizedTimeType))
+ return false;
+
+ notValidAfter = elem.toDateTime();
+
+ // subject name
+ if (!elem.read(certStream) || elem.type() != QAsn1Element::SequenceType)
+ return false;
+
+ QByteArray subjectDer = data.mid(dataStream.device()->pos() - elem.value().length(), elem.value().length());
+ subjectInfo = elem.toInfo();
+ subjectMatchesIssuer = issuerDer == subjectDer;
+
+ // public key
+ qint64 keyStart = certStream.device()->pos();
+ if (!elem.read(certStream) || elem.type() != QAsn1Element::SequenceType)
+ return false;
+
+ publicKeyDerData.resize(certStream.device()->pos() - keyStart);
+ QDataStream keyStream(elem.value());
+ if (!elem.read(keyStream) || elem.type() != QAsn1Element::SequenceType)
+ return false;
+
+
+ // key algorithm
+ if (!elem.read(elem.value()) || elem.type() != QAsn1Element::ObjectIdentifierType)
+ return false;
+
+ const QByteArray oid = elem.toObjectId();
+ if (oid == "1.2.840.113549.1.1.1")
+ publicKeyAlgorithm = QSsl::Rsa;
+ else if (oid == "1.2.840.10040.4.1")
+ publicKeyAlgorithm = QSsl::Dsa;
+ else
+ publicKeyAlgorithm = QSsl::Opaque;
+
+ certStream.device()->seek(keyStart);
+ certStream.readRawData(publicKeyDerData.data(), publicKeyDerData.size());
+
+ // extensions
+ while (elem.read(certStream)) {
+ if (elem.type() == QAsn1Element::Context3Type) {
+ if (elem.read(elem.value()) && elem.type() == QAsn1Element::SequenceType) {
+ QDataStream extStream(elem.value());
+ while (elem.read(extStream) && elem.type() == QAsn1Element::SequenceType) {
+ QAsn1Element oidElem, valElem;
+ QDataStream seqStream(elem.value());
+ if (oidElem.read(seqStream) && oidElem.type() == QAsn1Element::ObjectIdentifierType &&
+ valElem.read(seqStream) && valElem.type() == QAsn1Element::OctetStringType) {
+ // alternative name
+ if (oidElem.toObjectId() == QByteArray("2.5.29.17")) {
+ QAsn1Element sanElem;
+ if (sanElem.read(valElem.value()) && sanElem.type() == QAsn1Element::SequenceType) {
+ QDataStream nameStream(sanElem.value());
+ QAsn1Element nameElem;
+ while (nameElem.read(nameStream)) {
+ if (nameElem.type() == QAsn1Element::Rfc822NameType) {
+ subjectAlternativeNames.insert(QSsl::EmailEntry, QString::fromLatin1(nameElem.value(), nameElem.value().size()));
+ } else if (nameElem.type() == QAsn1Element::DnsNameType) {
+ subjectAlternativeNames.insert(QSsl::DnsEntry, QString::fromLatin1(nameElem.value(), nameElem.value().size()));
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ derData = data.left(dataStream.device()->pos());
+ null = false;
+
+#endif // QT_NO_OPENSSL
+ return true;
+}
+
bool QSslCertificatePrivate::isBlacklisted(const QSslCertificate &certificate)
{
for (int a = 0; certificate_blacklist[a] != 0; a++) {