changeset 21:dc1e1e9e62ce

Add certificate class and use it
author Andre Heinecke <aheinecke@intevation.de>
date Thu, 20 Feb 2014 10:58:28 +0000
parents fec1a610d43f
children bc302bbceaf5
files CMakeLists.txt tests/CMakeLists.txt ui/certificate.cpp ui/certificate.h ui/certificate_linux.cpp ui/certificate_win.cpp ui/certificate_win.h ui/certificatelist.cpp ui/certificatelist.h
diffstat 9 files changed, 203 insertions(+), 8 deletions(-) [+]
line wrap: on
line diff
--- a/CMakeLists.txt	Thu Feb 20 10:57:20 2014 +0000
+++ b/CMakeLists.txt	Thu Feb 20 10:58:28 2014 +0000
@@ -17,14 +17,21 @@
 include_directories(${Qt5Widgets_INCLUDE_DIRS})
 add_definitions(${Qt5Widgets_DEFINITIONS})
 
+set(CERTIFICATELIST_SOURCES
+    ${CMAKE_SOURCE_DIR}/ui/certificatelist.cpp
+    ${CMAKE_SOURCE_DIR}/ui/certificate.cpp
+    ${CMAKE_SOURCE_DIR}/ui/certificate_win.cpp
+    ${CMAKE_SOURCE_DIR}/ui/certificate_linux.cpp
+    ${CMAKE_SOURCE_DIR}/cinst/listutil.c
+)
+
 set(M13UI_SOURCES
     ${CMAKE_SOURCE_DIR}/ui/mainwindow.cpp
-    ${CMAKE_SOURCE_DIR}/ui/certificatelist.cpp
     ${CMAKE_SOURCE_DIR}/ui/downloader.cpp
     ${CMAKE_SOURCE_DIR}/ui/downloader_win.cpp
     ${CMAKE_SOURCE_DIR}/ui/downloader_linux.cpp
-    ${CMAKE_SOURCE_DIR}/cinst/listutil.c
     ${CMAKE_SOURCE_DIR}/ui/main.cpp
+    ${CERTIFICATELIST_SOURCES}
 )
 
 # Seperated to make it easier to include the sources in tests
@@ -39,7 +46,7 @@
 set(WARN_HARDENING_FLAGS " -Wextra -Wconversion -Wformat-security")
 
 # Hardening flags
-set(HARDENING_FLAGS " -Wall -Werror -fstack-protector-all")
+set(HARDENING_FLAGS " -Wall -Werror -fstack-protector-all -fno-exceptions")
 set(HARDENING_FLAGS " ${HARDENING_FLAGS} -Wstack-protector")
 set(HARDENING_FLAGS " ${HARDENING_FLAGS} --param ssp-buffer-size=4")
 set(HARDENING_FLAGS " ${HARDENING_FLAGS} -D_FORTIFY_SOURCE=2 -O2")
--- a/tests/CMakeLists.txt	Thu Feb 20 10:57:20 2014 +0000
+++ b/tests/CMakeLists.txt	Thu Feb 20 10:58:28 2014 +0000
@@ -15,5 +15,5 @@
 # Add the current source dir to the definition
 # so that it can be used in file names in the tests.
 add_definitions(-DSOURCE_DIR="${CMAKE_CURRENT_SOURCE_DIR}")
-add_m13_test(certlistparsertest.cpp "${CMAKE_SOURCE_DIR}/cinst/listutil.c;${CMAKE_SOURCE_DIR}/ui/certificatelist.cpp")
+add_m13_test(certlistparsertest.cpp "${CERTIFICATELIST_SOURCES}")
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ui/certificate.cpp	Thu Feb 20 10:58:28 2014 +0000
@@ -0,0 +1,9 @@
+#include "certificate.h"
+#include <QObject>
+
+QString Certificate::shortDescription() {
+    if (!isValid()) {
+        return QObject::tr("Invalid Certificate");
+    }
+    return mShortDescription;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ui/certificate.h	Thu Feb 20 10:58:28 2014 +0000
@@ -0,0 +1,45 @@
+#ifndef CERTIFICATE_H
+#define CERTIFICATE_H
+/**
+ * @file certificate.h
+ * @brief Class around native certificates.
+ *
+ */
+
+#include <QByteArray>
+#include <QString>
+
+#ifdef Q_OS_WIN
+#include <windows.h>
+#include <wincrypt.h>
+#endif
+
+class Certificate
+{
+public:
+    /** @brief construct a certificate from an X509 ASN1 encoded byte array.
+     **/
+    Certificate(const QByteArray& asn1data);
+
+    ~Certificate();
+
+    /** @brief check if this certificate could be parsed */
+    bool isValid() {return mValid;}
+
+    /** @brief get a short description of the certificate
+     *
+     *  This description should be used as a short overview
+     *  for this certificate
+     *
+     **/
+    QString shortDescription();
+
+private:
+    bool mValid;
+    QString mShortDescription;
+
+#ifdef Q_OS_WIN
+    PCCERT_CONTEXT mPCertContext;
+#endif
+};
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ui/certificate_linux.cpp	Thu Feb 20 10:58:28 2014 +0000
@@ -0,0 +1,8 @@
+#include "certificate.h"
+#ifdef Q_OS_LINUX
+Certificate::Certificate(const QByteArray& asn1data) : mValid(false) {
+}
+
+Certificate::~Certificate() {
+}
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ui/certificate_win.cpp	Thu Feb 20 10:58:28 2014 +0000
@@ -0,0 +1,58 @@
+#include "certificate.h"
+
+#ifdef Q_OS_WIN
+
+#include <QDebug>
+
+Certificate::Certificate(const QByteArray& asn1data) : mValid(false) {
+
+    // asn1data is expected to be \0 terminated as this is what
+    // qt does in ::fromBase64 so the actual asn1data is
+    // size() - 1 and not size()
+    Q_ASSERT (asn1data[asn1data.size()] == '\0');
+    DWORD sizeOfName = 0;
+
+    DWORD sizeOfCert = asn1data.size() - 1;
+
+    mPCertContext = CertCreateCertificateContext(X509_ASN_ENCODING,
+            (const BYTE *) asn1data.constData(), sizeOfCert);
+
+    if (!mPCertContext) {
+        qDebug() << "Error creating certificate context. Err: " <<
+            GetLastError();
+        return;
+    }
+
+    sizeOfName = CertGetNameStringW(mPCertContext,
+                                    CERT_NAME_FRIENDLY_DISPLAY_TYPE,
+                                    0,
+                                    NULL,
+                                    NULL,
+                                    0);
+
+    if (sizeOfName <= 1) {
+        // Probably some fallbacks would be nice here? Let's see if this
+        // is a problem in testing.
+        qDebug() << "Failed to get friendly name. Don't know what to do!";
+    } else {
+        WCHAR certName[sizeOfName];
+        DWORD actSize = CertGetNameStringW(mPCertContext,
+                                           CERT_NAME_FRIENDLY_DISPLAY_TYPE,
+                                           0,
+                                           NULL,
+                                           certName,
+                                           sizeOfName);
+        Q_ASSERT (actSize == sizeOfName);
+
+        mShortDescription = QString::fromWCharArray(certName, sizeOfName);
+    }
+
+}
+
+Certificate::~Certificate() {
+    if (mPCertContext) {
+        CertFreeCertificateContext(mPCertContext);
+    }
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ui/certificate_win.h	Thu Feb 20 10:58:28 2014 +0000
@@ -0,0 +1,65 @@
+#include "certificate.h"
+
+#ifdef Q_OS_WIN
+
+#include <QDebug>
+
+Certificate::Certificate(const QByteArray& asn1data) : mValid(false) {
+
+    // asn1data is expected to be \0 terminated as this is what
+    // qt does in ::fromBase64 so the actual asn1data is
+    // size() - 1 and not size()
+    Q_ASSERT (asn1data[asn1data.size()] == '\0');
+    DWORD sizeOfName = 0;
+
+    DWORD sizeOfCert = asn1data.size() - 1;
+
+    mPCertContext = CertCreateCertificateContext(X509_ASN_ENCODING,
+            (const BYTE *) asn1data.constData(), sizeOfCert);
+
+    if (!mPCertContext) {
+        qDebug() << "Error creating certificate context. Err: " <<
+            GetLastError();
+        return;
+    }
+
+    sizeOfName = CertGetNameStringW(pCertContext,
+                                    CERT_NAME_FRIENDLY_DISPLAY_TYPE,
+                                    0,
+                                    NULL,
+                                    NULL,
+                                    0);
+
+    if (sizeOfName <= 1) {
+        // Probably some fallbacks would be nice here? Let's see if this
+        // is a problem in testing.
+        qDebug() << "Failed to get friendly name. Don't know what to do!";
+    } else {
+        WCHAR certName[sizeOfName];
+        DWORD actSize = CertGetNameStringW(pCertContext,
+                                           CERT_NAME_FRIENDLY_DISPLAY_TYPE,
+                                           0,
+                                           NULL,
+                                           certName,
+                                           sizeOfName);
+        Q_ASSERT (actSize == sizeOfName);
+
+        mShortDescription = QString::fromWCharArray(certName, sizeOfName);
+    }
+
+}
+
+Certificate::~Certificate() {
+    if (mPCertContext) {
+        CertFreeCertificateContext(pCertContext);
+    }
+}
+
+QString Certificate::shortDescription() {
+    if (!isValid()) {
+        return QString::fromLatin1(tr("Invalid Certificate"));
+    }
+    return mShortDescription;
+}
+
+#endif
--- a/ui/certificatelist.cpp	Thu Feb 20 10:57:20 2014 +0000
+++ b/ui/certificatelist.cpp	Thu Feb 20 10:58:28 2014 +0000
@@ -43,9 +43,11 @@
 
             mDate = QDateTime::fromMSecsSinceEpoch(timestamp * 1000);
         } else if (curLine.startsWith("I:")) {
-            mCertificatesInstall << QByteArray::fromBase64(curLine.remove(0,2).toLatin1());
+            mCertificatesInstall << Certificate(
+                    QByteArray::fromBase64(curLine.remove(0,2).toLatin1()));
         } else if (curLine.startsWith("R:")) {
-            mCertificatesInstall << QByteArray::fromBase64(curLine.remove(0,2).toLatin1());
+            mCertificatesInstall << Certificate(
+                    QByteArray::fromBase64(curLine.remove(0,2).toLatin1()));
         } else if (curLine.startsWith("S:")) {
             // Signature is verified in readAndVerifyList
             continue;
--- a/ui/certificatelist.h	Thu Feb 20 10:57:20 2014 +0000
+++ b/ui/certificatelist.h	Thu Feb 20 10:58:28 2014 +0000
@@ -19,6 +19,7 @@
 #include <QObject>
 
 #include "../cinst/listutil.h"
+#include "certificate.h"
 
 class CertificateList : public QObject
 {
@@ -32,8 +33,8 @@
 
 private:
     QString mFileName;
-    QList<QByteArray> mCertificatesInstall;
-    QList<QByteArray> mCertificatesRemove;
+    QList<Certificate> mCertificatesInstall;
+    QList<Certificate> mCertificatesRemove;
     list_status_t mStatus;
     QDateTime mDate;
 };

http://wald.intevation.org/projects/trustbridge/