# HG changeset patch # User Andre Heinecke # Date 1392893908 0 # Node ID dc1e1e9e62ce7fdd358987e61cef326e8473fdff # Parent fec1a610d43f451ea5d54d269a6222b6ce58e23c Add certificate class and use it diff -r fec1a610d43f -r dc1e1e9e62ce CMakeLists.txt --- 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") diff -r fec1a610d43f -r dc1e1e9e62ce tests/CMakeLists.txt --- 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}") diff -r fec1a610d43f -r dc1e1e9e62ce ui/certificate.cpp --- /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 + +QString Certificate::shortDescription() { + if (!isValid()) { + return QObject::tr("Invalid Certificate"); + } + return mShortDescription; +} diff -r fec1a610d43f -r dc1e1e9e62ce ui/certificate.h --- /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 +#include + +#ifdef Q_OS_WIN +#include +#include +#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 diff -r fec1a610d43f -r dc1e1e9e62ce ui/certificate_linux.cpp --- /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 diff -r fec1a610d43f -r dc1e1e9e62ce ui/certificate_win.cpp --- /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 + +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 diff -r fec1a610d43f -r dc1e1e9e62ce ui/certificate_win.h --- /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 + +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 diff -r fec1a610d43f -r dc1e1e9e62ce ui/certificatelist.cpp --- 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; diff -r fec1a610d43f -r dc1e1e9e62ce ui/certificatelist.h --- 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 #include "../cinst/listutil.h" +#include "certificate.h" class CertificateList : public QObject { @@ -32,8 +33,8 @@ private: QString mFileName; - QList mCertificatesInstall; - QList mCertificatesRemove; + QList mCertificatesInstall; + QList mCertificatesRemove; list_status_t mStatus; QDateTime mDate; };