summaryrefslogtreecommitdiffstats
path: root/src/network
diff options
context:
space:
mode:
authorRichard Moore <rich@kde.org>2011-11-02 15:07:43 +0100
committerQt by Nokia <qt-info@nokia.com>2011-11-06 21:00:39 +0100
commit6248b869d0e8ae7e0fe566c09f2393278142b547 (patch)
treef1d8419968a810c0336a74c8539eadefd25b1501 /src/network
parentefe02f9673dc948ef4b48b2abfeb15c978d2b438 (diff)
SSL certificates: add functionality to read extensions
... by adding a new class QSslCertificateExtension and methods in QSslCertificate to support extensions. This is needed e.g. for OCSP (checking revocation status of a certificate) or Extended Validation certificates. Change-Id: I5c5d9513fa640cd487786bb9a5af734afebd0828 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Diffstat (limited to 'src/network')
-rw-r--r--src/network/ssl/qsslcertificate.cpp245
-rw-r--r--src/network/ssl/qsslcertificate.h2
-rw-r--r--src/network/ssl/qsslcertificate_p.h3
-rw-r--r--src/network/ssl/qsslcertificateextension.cpp200
-rw-r--r--src/network/ssl/qsslcertificateextension.h90
-rw-r--r--src/network/ssl/qsslcertificateextension_p.h68
-rw-r--r--src/network/ssl/qsslsocket_openssl_symbols.cpp17
-rw-r--r--src/network/ssl/qsslsocket_openssl_symbols_p.h8
-rw-r--r--src/network/ssl/ssl.pri7
9 files changed, 628 insertions, 12 deletions
diff --git a/src/network/ssl/qsslcertificate.cpp b/src/network/ssl/qsslcertificate.cpp
index dd0be205d8..1810270d7c 100644
--- a/src/network/ssl/qsslcertificate.cpp
+++ b/src/network/ssl/qsslcertificate.cpp
@@ -112,6 +112,8 @@
#include "qsslcertificate_p.h"
#include "qsslkey.h"
#include "qsslkey_p.h"
+#include "qsslcertificateextension.h"
+#include "qsslcertificateextension_p.h"
#include <QtCore/qatomic.h>
#include <QtCore/qdatetime.h>
@@ -317,7 +319,7 @@ static QByteArray _q_SubjectInfoToString(QSslCertificate::SubjectInfo info)
/*!
\fn QString QSslCertificate::issuerInfo(SubjectInfo subject) const
-
+
Returns the issuer information for the \a subject from the
certificate, or an empty string if there is no information for
\a subject in the certificate.
@@ -429,12 +431,12 @@ QList<QByteArray> QSslCertificate::issuerInfoAttributes() const
certificate. The alternative names typically contain host
names, optionally with wildcards, that are valid for this
certificate.
-
+
These names are tested against the connected peer's host name, if
either the subject information for \l CommonName doesn't define a
valid host name, or the subject info name doesn't match the peer's
host name.
-
+
\sa subjectInfo()
*/
QMultiMap<QSsl::AlternativeNameEntryType, QString> QSslCertificate::subjectAlternativeNames() const
@@ -542,6 +544,226 @@ QSslKey QSslCertificate::publicKey() const
return key;
}
+/*
+ * Convert unknown extensions to a QVariant.
+ */
+static QVariant x509UnknownExtensionToValue(X509_EXTENSION *ext)
+{
+ // Get the extension specific method object if available
+ // we cast away the const-ness here because some versions of openssl
+ // don't use const for the parameters in the functions pointers stored
+ // in the object.
+ X509V3_EXT_METHOD *meth = const_cast<X509V3_EXT_METHOD *>(q_X509V3_EXT_get(ext));
+ if (!meth) {
+ ASN1_OCTET_STRING *value = q_X509_EXTENSION_get_data(ext);
+ QByteArray result( reinterpret_cast<const char *>(q_ASN1_STRING_data(value)),
+ q_ASN1_STRING_length(value));
+ return result;
+ }
+
+ //const unsigned char *data = ext->value->data;
+ void *ext_internal = q_X509V3_EXT_d2i(ext);
+
+ // If this extension can be converted
+ if (meth->i2v && ext_internal) {
+ STACK_OF(CONF_VALUE) *val = meth->i2v(meth, ext_internal, 0);
+
+ QVariantMap map;
+ QVariantList list;
+ bool isMap = false;
+
+ for (int j = 0; j < q_SKM_sk_num(CONF_VALUE, val); j++) {
+ CONF_VALUE *nval = q_SKM_sk_value(CONF_VALUE, val, j);
+ if (nval->name && nval->value) {
+ isMap = true;
+ map[QString::fromUtf8(nval->name)] = QString::fromUtf8(nval->value);
+ } else if (nval->name) {
+ list << QString::fromUtf8(nval->name);
+ } else if (nval->value) {
+ list << QString::fromUtf8(nval->value);
+ }
+ }
+
+ if (isMap)
+ return map;
+ else
+ return list;
+ } else if (meth->i2s && ext_internal) {
+ //qDebug() << meth->i2s(meth, ext_internal);
+ QVariant result(QString::fromUtf8(meth->i2s(meth, ext_internal)));
+ return result;
+ } else if (meth->i2r && ext_internal) {
+ QByteArray result;
+
+ BIO *bio = q_BIO_new(q_BIO_s_mem());
+ if (!bio)
+ return result;
+
+ meth->i2r(meth, ext_internal, bio, 0);
+
+ char *bio_buffer;
+ long bio_size = q_BIO_get_mem_data(bio, &bio_buffer);
+ result = QByteArray(bio_buffer, bio_size);
+
+ q_BIO_free(bio);
+ return result;
+ }
+
+ return QVariant();
+}
+
+/*
+ * Convert extensions to a variant. The naming of the keys of the map are
+ * taken from RFC 5280, however we decided the capitalisation in the RFC
+ * was too silly for the real world.
+ */
+static QVariant x509ExtensionToValue(X509_EXTENSION *ext)
+{
+ ASN1_OBJECT *obj = q_X509_EXTENSION_get_object(ext);
+ int nid = q_OBJ_obj2nid(obj);
+
+ switch (nid) {
+ case NID_basic_constraints:
+ {
+ BASIC_CONSTRAINTS *basic = reinterpret_cast<BASIC_CONSTRAINTS *>(q_X509V3_EXT_d2i(ext));
+
+ QVariantMap result;
+ result[QLatin1String("ca")] = basic->ca ? true : false;
+ if (basic->pathlen)
+ result[QLatin1String("pathLenConstraint")] = (qlonglong)q_ASN1_INTEGER_get(basic->pathlen);
+
+ q_BASIC_CONSTRAINTS_free(basic);
+ return result;
+ }
+ break;
+ case NID_info_access:
+ {
+ AUTHORITY_INFO_ACCESS *info = reinterpret_cast<AUTHORITY_INFO_ACCESS *>(q_X509V3_EXT_d2i(ext));
+
+ QVariantMap result;
+ for (int i=0; i < q_SKM_sk_num(ACCESS_DESCRIPTION, info); i++) {
+ ACCESS_DESCRIPTION *ad = q_SKM_sk_value(ACCESS_DESCRIPTION, info, i);
+
+ GENERAL_NAME *name = ad->location;
+ if (name->type == GEN_URI) {
+ int len = q_ASN1_STRING_length(name->d.uniformResourceIdentifier);
+ if (len < 0 || len >= 8192) {
+ // broken name
+ continue;
+ }
+
+ const char *uriStr = reinterpret_cast<const char *>(q_ASN1_STRING_data(name->d.uniformResourceIdentifier));
+ const QString uri = QString::fromUtf8(uriStr, len);
+
+ result[QString::fromUtf8(QSslCertificatePrivate::asn1ObjectName(ad->method))] = uri;
+ } else {
+ qWarning() << "Strange location type" << name->type;
+ }
+ }
+
+#if OPENSSL_VERSION_NUMBER >= 0x10000000L
+ q_sk_pop_free((_STACK*)info, reinterpret_cast<void(*)(void*)>(q_sk_free));
+#else
+ q_sk_pop_free((STACK*)info, reinterpret_cast<void(*)(void*)>(q_sk_free));
+#endif
+ return result;
+ }
+ break;
+ case NID_subject_key_identifier:
+ {
+ void *ext_internal = q_X509V3_EXT_d2i(ext);
+
+ // we cast away the const-ness here because some versions of openssl
+ // don't use const for the parameters in the functions pointers stored
+ // in the object.
+ X509V3_EXT_METHOD *meth = const_cast<X509V3_EXT_METHOD *>(q_X509V3_EXT_get(ext));
+
+ return QVariant(QString::fromUtf8(meth->i2s(meth, ext_internal)));
+ }
+ break;
+ case NID_authority_key_identifier:
+ {
+ AUTHORITY_KEYID *auth_key = reinterpret_cast<AUTHORITY_KEYID *>(q_X509V3_EXT_d2i(ext));
+
+ QVariantMap result;
+
+ // keyid
+ if (auth_key->keyid) {
+ QByteArray keyid(reinterpret_cast<const char *>(auth_key->keyid->data),
+ auth_key->keyid->length);
+ result[QLatin1String("keyid")] = keyid.toHex();
+ }
+
+ // issuer
+ // TODO: GENERAL_NAMES
+
+ // serial
+ if (auth_key->serial)
+ result[QLatin1String("serial")] = (qlonglong)q_ASN1_INTEGER_get(auth_key->serial);
+
+ q_AUTHORITY_KEYID_free(auth_key);
+ return result;
+ }
+ break;
+ }
+
+ return QVariant();
+}
+
+QSslCertificateExtension QSslCertificatePrivate::convertExtension(X509_EXTENSION *ext)
+{
+ QSslCertificateExtension result;
+
+ ASN1_OBJECT *obj = q_X509_EXTENSION_get_object(ext);
+ QByteArray oid = QSslCertificatePrivate::asn1ObjectId(obj);
+ QByteArray name = QSslCertificatePrivate::asn1ObjectName(obj);
+
+ result.d->oid = QString::fromUtf8(oid);
+ result.d->name = QString::fromUtf8(name);
+
+ bool critical = q_X509_EXTENSION_get_critical(ext);
+ result.d->critical = critical;
+
+ // Lets see if we have custom support for this one
+ QVariant extensionValue = x509ExtensionToValue(ext);
+ if (extensionValue.isValid()) {
+ result.d->value = extensionValue;
+ result.d->supported = true;
+
+ return result;
+ }
+
+ extensionValue = x509UnknownExtensionToValue(ext);
+ if (extensionValue.isValid()) {
+ result.d->value = extensionValue;
+ result.d->supported = false;
+ return result;
+ }
+
+ return result;
+}
+
+/*!
+ Returns a list containing the X509 extensions of this certificate.
+ \since 5.0
+ */
+QList<QSslCertificateExtension> QSslCertificate::extensions() const
+{
+ QList<QSslCertificateExtension> result;
+
+ if (!d->x509)
+ return result;
+
+ int count = q_X509_get_ext_count(d->x509);
+
+ for (int i=0; i < count; i++) {
+ X509_EXTENSION *ext = q_X509_get_ext(d->x509, i);
+ result << QSslCertificatePrivate::convertExtension(ext);
+ }
+
+ return result;
+}
+
/*!
Returns this certificate converted to a PEM (Base64) encoded
representation.
@@ -581,7 +803,7 @@ QByteArray QSslCertificate::toText() const
pattern matching one or more files, as specified by \a syntax.
Example:
-
+
\snippet doc/src/snippets/code/src_network_ssl_qsslcertificate.cpp 0
\sa fromData()
@@ -760,17 +982,22 @@ QByteArray QSslCertificatePrivate::text_from_X509(X509 *x509)
return result;
}
+QByteArray QSslCertificatePrivate::asn1ObjectId(ASN1_OBJECT *object)
+{
+ char buf[80]; // The openssl docs a buffer length of 80 should be more than enough
+ q_OBJ_obj2txt(buf, sizeof(buf), object, 1); // the 1 says always use the oid not the long name
+
+ return QByteArray(buf);
+}
+
+
QByteArray QSslCertificatePrivate::asn1ObjectName(ASN1_OBJECT *object)
{
int nid = q_OBJ_obj2nid(object);
if (nid != NID_undef)
return QByteArray(q_OBJ_nid2sn(nid));
- // This is used for unknown info so we get the OID as text
- char buf[80];
- q_i2t_ASN1_OBJECT(buf, sizeof(buf), object);
-
- return QByteArray(buf);
+ return asn1ObjectId(object);
}
static QMap<QByteArray, QString> _q_mapFromX509Name(X509_NAME *name)
diff --git a/src/network/ssl/qsslcertificate.h b/src/network/ssl/qsslcertificate.h
index 0498d162c4..07a8df308c 100644
--- a/src/network/ssl/qsslcertificate.h
+++ b/src/network/ssl/qsslcertificate.h
@@ -65,6 +65,7 @@ class QDateTime;
class QIODevice;
class QSslError;
class QSslKey;
+class QSslCertificateExtension;
class QStringList;
class QSslCertificatePrivate;
@@ -114,6 +115,7 @@ public:
QDateTime effectiveDate() const;
QDateTime expiryDate() const;
QSslKey publicKey() const;
+ QList<QSslCertificateExtension> extensions() const;
QByteArray toPem() const;
QByteArray toDer() const;
diff --git a/src/network/ssl/qsslcertificate_p.h b/src/network/ssl/qsslcertificate_p.h
index 3cfcef7b57..c4a833460a 100644
--- a/src/network/ssl/qsslcertificate_p.h
+++ b/src/network/ssl/qsslcertificate_p.h
@@ -57,6 +57,7 @@
//
#include "qsslsocket_p.h"
+#include "qsslcertificateextension.h"
#include <QtCore/qdatetime.h>
#include <QtCore/qmap.h>
@@ -92,6 +93,7 @@ public:
void init(const QByteArray &data, QSsl::EncodingFormat format);
+ static QByteArray asn1ObjectId(ASN1_OBJECT *object);
static QByteArray asn1ObjectName(ASN1_OBJECT *object);
static QByteArray QByteArray_from_X509(X509 *x509, QSsl::EncodingFormat format);
static QByteArray text_from_X509(X509 *x509);
@@ -99,6 +101,7 @@ public:
static QList<QSslCertificate> certificatesFromPem(const QByteArray &pem, int count = -1);
static QList<QSslCertificate> certificatesFromDer(const QByteArray &der, int count = -1);
static bool isBlacklisted(const QSslCertificate &certificate);
+ static QSslCertificateExtension convertExtension(X509_EXTENSION *ext);
friend class QSslSocketBackendPrivate;
diff --git a/src/network/ssl/qsslcertificateextension.cpp b/src/network/ssl/qsslcertificateextension.cpp
new file mode 100644
index 0000000000..b154ce70a5
--- /dev/null
+++ b/src/network/ssl/qsslcertificateextension.cpp
@@ -0,0 +1,200 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Richard J. Moore <rich@kde.org>
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtNetwork module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \class QSslCertificateExtension
+ \brief The QSslCertificateExtension provides an API for accessing the extensions of an X509 certificate.
+ \since 5.0
+
+ \rentrant
+ \ingroup network
+ \ingroup ssl
+ \inmodule QtNetwork
+
+ QSslCertificateExtension provides access to an extension stored in
+ an X509 certificate. The information available depends on the type
+ of extension being accessed.
+
+ All X509 certificate extensions have the following properties:
+
+ \table
+ \header
+ \o Property
+ \o Description
+ \row
+ \o name
+ \o The human readable name of the extension, eg. 'basicConstraints'.
+ \row
+ \o criticality
+ \o This is a boolean value indicating if the extension is critical
+ to correctly interpreting the certificate.
+ \row
+ \o oid
+ \o The ASN.1 object identifier that specifies which extension this
+ is.
+ \row
+ \o supported
+ \o If this is true the structure of the extension's value will not
+ change between Qt versions.
+ \row
+ \o value
+ \o A QVariant with a structure dependent on the type of extension.
+ \endtable
+
+ Whilst this class provides access to any type of extension, only
+ some are guaranteed to be returned in a format that will remain
+ unchanged between releases. The isSupported() method returns true
+ for extensions where this is the case.
+
+ The extensions currently supported, and the structure of the value
+ returned are as follows:
+
+ \table
+ \header
+ \o Name
+ \o OID
+ \o Details
+ \row
+ \o basicConstraints
+ \o 2.5.29.19
+ \o Returned as a QVariantMap. The key 'ca' contains a boolean value,
+ the optional key 'pathLenConstraint' contains an integer.
+ \row
+ \o authorityInfoAccess
+ \o 1.3.6.1.5.5.7.1.1
+ \o Returned as a QVariantMap. There is a key for each access method,
+ with the value being a URI.
+ \row
+ \o subjectKeyIdentifier
+ \o 2.5.29.14
+ \o Returned as a QVariant containing a QString. The string is the key
+ identifier.
+ \row
+ \o authorityKeyIdentifier
+ \o 2.5.29.35
+ \o Returned as a QVariantMap. The optional key 'keyid' contains the key
+ identifier as a hex string stored in a QByteArray. The optional key
+ 'serial' contains the authority key serial number as a qlonglong.
+ Currently there is no support for the general names field of this
+ extension.
+ \endtable
+
+ In addition to the supported extensions above, many other common extensions
+ will be returned in a reasonably structured way. Extensions that the SSL
+ backend has no support for at all will be returned as a QByteArray.
+
+ Further information about the types of extensions certificates can
+ contain can be found in RFC 5280.
+
+ \sa QSslCertificate::extensions()
+ */
+
+#include "qsslcertificateextension.h"
+#include "qsslcertificateextension_p.h"
+
+QT_BEGIN_NAMESPACE
+
+QSslCertificateExtension::QSslCertificateExtension()
+ : d(new QSslCertificateExtensionPrivate)
+{
+}
+
+QSslCertificateExtension::QSslCertificateExtension(const QSslCertificateExtension &other)
+ : d(other.d)
+{
+}
+
+QSslCertificateExtension::~QSslCertificateExtension()
+{
+}
+
+QSslCertificateExtension &QSslCertificateExtension::operator=(const QSslCertificateExtension &other)
+{
+ d = other.d;
+ return *this;
+}
+
+/*!
+ Returns the ASN.1 OID of this extension.
+ */
+QString QSslCertificateExtension::oid() const
+{
+ return d->oid;
+}
+
+/*!
+ Returns the name of the extension. If no name is known for the
+ extension then the OID will be returned.
+ */
+QString QSslCertificateExtension::name() const
+{
+ return d->name;
+}
+
+/*!
+ Returns the value of the extension. The structure of the value
+ returned depends on the extension type.
+ */
+QVariant QSslCertificateExtension::value() const
+{
+ return d->value;
+}
+
+/*!
+ Returns the criticality of the extension.
+ */
+bool QSslCertificateExtension::isCritical() const
+{
+ return d->critical;
+}
+
+/*!
+ Returns the true if this extension is supported. In this case,
+ supported simply means that the structure of the QVariant returned
+ by the value() accessor will remain unchanged between versions.
+ Unsupported extensions can be freely used, however there is no
+ guarantee that the returned data will have the same structure
+ between versions.
+ */
+bool QSslCertificateExtension::isSupported() const
+{
+ return d->supported;
+}
diff --git a/src/network/ssl/qsslcertificateextension.h b/src/network/ssl/qsslcertificateextension.h
new file mode 100644
index 0000000000..200ae3e091
--- /dev/null
+++ b/src/network/ssl/qsslcertificateextension.h
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Richard J. Moore <rich@kde.org>
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtNetwork module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSSLCERTIFICATEEXTENSION_H
+#define QSSLCERTIFICATEEXTENSION_H
+
+#include <QtCore/qnamespace.h>
+#include <QtCore/qshareddata.h>
+#include <QtCore/qstring.h>
+#include <QtCore/qvariant.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Network)
+
+#ifndef QT_NO_OPENSSL
+
+class QSslCertificateExtensionPrivate;
+
+class Q_NETWORK_EXPORT QSslCertificateExtension
+{
+public:
+ QSslCertificateExtension();
+ QSslCertificateExtension(const QSslCertificateExtension &other);
+ ~QSslCertificateExtension();
+
+ QSslCertificateExtension &operator=(const QSslCertificateExtension &other);
+
+ QString oid() const;
+ QString name() const;
+ QVariant value() const;
+ bool isCritical() const;
+
+ bool isSupported() const;
+
+private:
+ friend class QSslCertificatePrivate;
+ QSharedDataPointer<QSslCertificateExtensionPrivate> d;
+};
+
+#endif // QT_NO_OPENSSL
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+
+#endif // QSSLCERTIFICATEEXTENSION_H
+
+
diff --git a/src/network/ssl/qsslcertificateextension_p.h b/src/network/ssl/qsslcertificateextension_p.h
new file mode 100644
index 0000000000..877175b666
--- /dev/null
+++ b/src/network/ssl/qsslcertificateextension_p.h
@@ -0,0 +1,68 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Richard J. Moore <rich@kde.org>
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtNetwork module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSSLCERTIFICATEEXTESNION_P_H
+#define QSSLCERTIFICATEEXTESNION_P_H
+
+#include "qsslcertificateextension.h"
+
+QT_BEGIN_NAMESPACE
+
+class QSslCertificateExtensionPrivate : public QSharedData
+{
+public:
+ inline QSslCertificateExtensionPrivate()
+ : critical(false),
+ supported(false)
+ {
+ }
+
+ QString oid;
+ QString name;
+ QVariant value;
+ bool critical;
+ bool supported;
+};
+
+QT_END_NAMESPACE
+
+#endif // QSSLCERTIFICATEEXTESNION_P_H
+
diff --git a/src/network/ssl/qsslsocket_openssl_symbols.cpp b/src/network/ssl/qsslsocket_openssl_symbols.cpp
index be8da0eaf0..7696d15542 100644
--- a/src/network/ssl/qsslsocket_openssl_symbols.cpp
+++ b/src/network/ssl/qsslsocket_openssl_symbols.cpp
@@ -135,7 +135,7 @@ DEFINEFUNC2(int, i2d_X509, X509 *a, a, unsigned char **b, b, return -1, return)
DEFINEFUNC(const char *, OBJ_nid2sn, int a, a, return 0, return)
DEFINEFUNC(const char *, OBJ_nid2ln, int a, a, return 0, return)
DEFINEFUNC3(int, i2t_ASN1_OBJECT, char *a, a, int b, b, ASN1_OBJECT *c, c, return -1, return)
-
+DEFINEFUNC4(int, OBJ_obj2txt, char *a, a, int b, b, ASN1_OBJECT *c, c, int d, d, return -1, return)
DEFINEFUNC(int, OBJ_obj2nid, const ASN1_OBJECT *a, a, return NID_undef, return)
#ifdef SSLEAY_MACROS
@@ -259,6 +259,13 @@ DEFINEFUNC(void, X509_free, X509 *a, a, return, DUMMYARG)
DEFINEFUNC2(X509_EXTENSION *, X509_get_ext, X509 *a, a, int b, b, return 0, return)
DEFINEFUNC(int, X509_get_ext_count, X509 *a, a, return 0, return)
DEFINEFUNC4(void *, X509_get_ext_d2i, X509 *a, a, int b, b, int *c, c, int *d, d, return 0, return)
+DEFINEFUNC(const X509V3_EXT_METHOD *, X509V3_EXT_get, X509_EXTENSION *a, a, return 0, return)
+DEFINEFUNC(void *, X509V3_EXT_d2i, X509_EXTENSION *a, a, return 0, return)
+DEFINEFUNC(int, X509_EXTENSION_get_critical, X509_EXTENSION *a, a, return 0, return)
+DEFINEFUNC(ASN1_OCTET_STRING *, X509_EXTENSION_get_data, X509_EXTENSION *a, a, return 0, return)
+DEFINEFUNC(void, BASIC_CONSTRAINTS_free, BASIC_CONSTRAINTS *a, a, return, DUMMYARG)
+DEFINEFUNC(void, AUTHORITY_KEYID_free, AUTHORITY_KEYID *a, a, return, DUMMYARG)
+DEFINEFUNC2(int, ASN1_STRING_print, BIO *a, a, const ASN1_STRING *b, b, return 0, return)
DEFINEFUNC(X509_NAME *, X509_get_issuer_name, X509 *a, a, return 0, return)
DEFINEFUNC(X509_NAME *, X509_get_subject_name, X509 *a, a, return 0, return)
DEFINEFUNC(int, X509_verify_cert, X509_STORE_CTX *a, a, return -1, return)
@@ -698,6 +705,7 @@ bool q_resolveOpenSslSymbols()
RESOLVEFUNC(OBJ_nid2sn)
RESOLVEFUNC(OBJ_nid2ln)
RESOLVEFUNC(i2t_ASN1_OBJECT)
+ RESOLVEFUNC(OBJ_obj2txt)
RESOLVEFUNC(OBJ_obj2nid)
#ifdef SSLEAY_MACROS // ### verify
RESOLVEFUNC(PEM_ASN1_read_bio)
@@ -786,6 +794,13 @@ bool q_resolveOpenSslSymbols()
RESOLVEFUNC(X509_get_ext)
RESOLVEFUNC(X509_get_ext_count)
RESOLVEFUNC(X509_get_ext_d2i)
+ RESOLVEFUNC(X509V3_EXT_get)
+ RESOLVEFUNC(X509V3_EXT_d2i)
+ RESOLVEFUNC(X509_EXTENSION_get_critical)
+ RESOLVEFUNC(X509_EXTENSION_get_data)
+ RESOLVEFUNC(BASIC_CONSTRAINTS_free)
+ RESOLVEFUNC(AUTHORITY_KEYID_free)
+ RESOLVEFUNC(ASN1_STRING_print)
RESOLVEFUNC(X509_get_issuer_name)
RESOLVEFUNC(X509_get_subject_name)
RESOLVEFUNC(X509_verify_cert)
diff --git a/src/network/ssl/qsslsocket_openssl_symbols_p.h b/src/network/ssl/qsslsocket_openssl_symbols_p.h
index d1705b3680..ad7a0a7557 100644
--- a/src/network/ssl/qsslsocket_openssl_symbols_p.h
+++ b/src/network/ssl/qsslsocket_openssl_symbols_p.h
@@ -239,6 +239,7 @@ int q_i2d_X509(X509 *a, unsigned char **b);
const char *q_OBJ_nid2sn(int a);
const char *q_OBJ_nid2ln(int a);
int q_i2t_ASN1_OBJECT(char *buf, int buf_len, ASN1_OBJECT *obj);
+int q_OBJ_obj2txt(char *buf, int buf_len, ASN1_OBJECT *obj, int no_name);
int q_OBJ_obj2nid(const ASN1_OBJECT *a);
#ifdef SSLEAY_MACROS
// ### verify
@@ -369,6 +370,13 @@ void q_X509_free(X509 *a);
X509_EXTENSION *q_X509_get_ext(X509 *a, int b);
int q_X509_get_ext_count(X509 *a);
void *q_X509_get_ext_d2i(X509 *a, int b, int *c, int *d);
+const X509V3_EXT_METHOD *q_X509V3_EXT_get(X509_EXTENSION *a);
+void *q_X509V3_EXT_d2i(X509_EXTENSION *a);
+int q_X509_EXTENSION_get_critical(X509_EXTENSION *a);
+ASN1_OCTET_STRING *q_X509_EXTENSION_get_data(X509_EXTENSION *a);
+void q_BASIC_CONSTRAINTS_free(BASIC_CONSTRAINTS *a);
+void q_AUTHORITY_KEYID_free(AUTHORITY_KEYID *a);
+int q_ASN1_STRING_print(BIO *a, const ASN1_STRING *b);
X509_NAME *q_X509_get_issuer_name(X509 *a);
X509_NAME *q_X509_get_subject_name(X509 *a);
int q_X509_verify_cert(X509_STORE_CTX *ctx);
diff --git a/src/network/ssl/ssl.pri b/src/network/ssl/ssl.pri
index 8b2e2c1917..9ba8d01f51 100644
--- a/src/network/ssl/ssl.pri
+++ b/src/network/ssl/ssl.pri
@@ -20,7 +20,9 @@ symbian {
ssl/qsslsocket.h \
ssl/qsslsocket_openssl_p.h \
ssl/qsslsocket_openssl_symbols_p.h \
- ssl/qsslsocket_p.h
+ ssl/qsslsocket_p.h \
+ ssl/qsslcertificateextension.h \
+ ssl/qsslcertificateextension_p.h
SOURCES += ssl/qssl.cpp \
ssl/qsslcertificate.cpp \
ssl/qsslconfiguration.cpp \
@@ -29,7 +31,8 @@ symbian {
ssl/qsslkey.cpp \
ssl/qsslsocket.cpp \
ssl/qsslsocket_openssl.cpp \
- ssl/qsslsocket_openssl_symbols.cpp
+ ssl/qsslsocket_openssl_symbols.cpp \
+ ssl/qsslcertificateextension.cpp
# Add optional SSL libs
LIBS_PRIVATE += $$OPENSSL_LIBS