SSL certificates: add functionality to read extensions
authorRichard Moore <rich@kde.org>
Wed, 2 Nov 2011 14:07:43 +0000 (15:07 +0100)
committerQt by Nokia <qt-info@nokia.com>
Sun, 6 Nov 2011 20:00:39 +0000 (21:00 +0100)
... 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>
src/network/ssl/qsslcertificate.cpp
src/network/ssl/qsslcertificate.h
src/network/ssl/qsslcertificate_p.h
src/network/ssl/qsslcertificateextension.cpp [new file with mode: 0644]
src/network/ssl/qsslcertificateextension.h [new file with mode: 0644]
src/network/ssl/qsslcertificateextension_p.h [new file with mode: 0644]
src/network/ssl/qsslsocket_openssl_symbols.cpp
src/network/ssl/qsslsocket_openssl_symbols_p.h
src/network/ssl/ssl.pri

index dd0be20..1810270 100644 (file)
 #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)
index 0498d16..07a8df3 100644 (file)
@@ -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;
index 3cfcef7..c4a8334 100644 (file)
@@ -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 (file)
index 0000000..b154ce7
--- /dev/null
@@ -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 (file)
index 0000000..200ae3e
--- /dev/null
@@ -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 (file)
index 0000000..877175b
--- /dev/null
@@ -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
+
index be8da0e..7696d15 100644 (file)
@@ -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)
index d1705b3..ad7a0a7 100644 (file)
@@ -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);
index 8b2e2c1..9ba8d01 100644 (file)
@@ -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