[PATCH] (issue123) Add possibility to open native certificate dialog
Wald Commits
scm-commit at wald.intevation.org
Mon Sep 29 13:13:14 CEST 2014
# HG changeset patch
# User Andre Heinecke <andre.heinecke at intevation.de>
# Date 1411989178 -7200
# Node ID 265583011f24d7970eaf0cc39f951bd22bab4b84
# Parent d3d66d43365fd3d810a556998c761aeac9c6777a
(issue123) Add possibility to open native certificate dialog
This is currently only implemented for windows.
diff -r d3d66d43365f -r 265583011f24 cinst/CMakeLists.txt
--- a/cinst/CMakeLists.txt Mon Sep 29 13:02:41 2014 +0200
+++ b/cinst/CMakeLists.txt Mon Sep 29 13:12:58 2014 +0200
@@ -30,6 +30,7 @@
if (WIN32)
set(WIN_EXTRA_LIBS -lcrypt32 -luserenv -lshell32)
+ set(WIN_EXTRA_LIBS_NSS -lcrypt32)
endif(WIN32)
target_link_libraries(trustbridge-certificate-installer
@@ -87,7 +88,8 @@
trustbridge_common
${POLARSSL_LIBRARIES}
${NSS_LIBRARIES}
- ${PROFILING_LIBS})
+ ${PROFILING_LIBS}
+ ${WIN_EXTRA_LIBS_NSS})
set_target_properties(trustbridge-nss-installer PROPERTIES COMPILE_FLAGS "-std=c99")
install(TARGETS trustbridge-nss-installer DESTINATION bin)
diff -r d3d66d43365f -r 265583011f24 cinst/windowsstore.c
--- a/cinst/windowsstore.c Mon Sep 29 13:02:41 2014 +0200
+++ b/cinst/windowsstore.c Mon Sep 29 13:12:58 2014 +0200
@@ -15,43 +15,7 @@
#include "strhelp.h"
#include "logging.h"
#include "util.h"
-
-static PCCERT_CONTEXT
-b64_to_cert_context(char *b64_data, size_t b64_size)
-{
- size_t buf_size = 0;
- char *buf = NULL;
- PCCERT_CONTEXT pCert = NULL;
- int ret = -1;
-
- ret = str_base64_decode (&buf, &buf_size, b64_data, b64_size);
-
- if (ret != 0)
- {
- ERRORPRINTF ("decoding certificate failed\n");
- return NULL;
- }
-
- pCert = CertCreateContext (CERT_STORE_CERTIFICATE_CONTEXT,
- X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
- (const PBYTE) buf,
- (DWORD) buf_size,
- 0,
- NULL);
- free (buf); /* Windows has a copy */
-
- if (pCert == NULL)
- {
- char *error = getLastErrorMsg();
- if (error)
- {
- ERRORPRINTF ("Failed to create cert context: %s \n", error);
- free (error);
- }
- return NULL;
- }
- return pCert;
-}
+#include "certhelp.h"
void
do_remove(HCERTSTORE hStore, char **to_remove)
diff -r d3d66d43365f -r 265583011f24 common/certhelp.c
--- a/common/certhelp.c Mon Sep 29 13:02:41 2014 +0200
+++ b/common/certhelp.c Mon Sep 29 13:12:58 2014 +0200
@@ -50,3 +50,42 @@
}
return str;
}
+
+#ifdef WIN32
+PCCERT_CONTEXT
+b64_to_cert_context(char *b64_data, size_t b64_size)
+{
+ size_t buf_size = 0;
+ char *buf = NULL;
+ PCCERT_CONTEXT pCert = NULL;
+ int ret = -1;
+
+ ret = str_base64_decode (&buf, &buf_size, b64_data, b64_size);
+
+ if (ret != 0)
+ {
+ ERRORPRINTF ("decoding certificate failed\n");
+ return NULL;
+ }
+
+ pCert = CertCreateContext (CERT_STORE_CERTIFICATE_CONTEXT,
+ X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
+ (const PBYTE) buf,
+ (DWORD) buf_size,
+ 0,
+ NULL);
+ free (buf); /* Windows has a copy */
+
+ if (pCert == NULL)
+ {
+ char *error = getLastErrorMsg();
+ if (error)
+ {
+ ERRORPRINTF ("Failed to create cert context: %s \n", error);
+ free (error);
+ }
+ return NULL;
+ }
+ return pCert;
+}
+#endif
diff -r d3d66d43365f -r 265583011f24 common/certhelp.h
--- a/common/certhelp.h Mon Sep 29 13:02:41 2014 +0200
+++ b/common/certhelp.h Mon Sep 29 13:12:58 2014 +0200
@@ -24,6 +24,12 @@
#define CERT_OID_O (unsigned char *)OID_AT_ORGANIZATION "\0"
#define CERT_OID_OU (unsigned char *)OID_AT_ORG_UNIT "\0"
#define CERT_OID_SN (unsigned char *)OID_AT_SERIAL_NUMBER "\0"
+
+#ifdef WIN32
+#include <windows.h>
+#include <wincrypt.h>
+#endif
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -58,6 +64,23 @@
*/
char *x509_parse_subject(unsigned char *derdata, size_t derlen,
unsigned char *oid);
+
+#ifdef WIN32
+/**
+ * @brief Parse a X509 ASN encoded base64 encoded certificate.
+ *
+ * This function creates a Windows cert contect for the certificate
+ * encoded in b64_data. The new certificate has to be freed with
+ * CertFreeCertificateContext.
+ *
+ * @param[in] b64_data pointer to the certificate data.
+ * @param[in] b64_size sizeof the the data. (Without terminating \0)
+ *
+ * @returns NULL on error.
+ */
+PCCERT_CONTEXT b64_to_cert_context(char *b64_data, size_t b64_size);
+#endif
+
#ifdef __cplusplus
}
#endif
diff -r d3d66d43365f -r 265583011f24 ui/certificate.cpp
--- a/ui/certificate.cpp Mon Sep 29 13:02:41 2014 +0200
+++ b/ui/certificate.cpp Mon Sep 29 13:12:58 2014 +0200
@@ -16,6 +16,10 @@
#include "certhelp.h"
#include "listutil.h"
+#ifdef WIN32
+#include <cryptuiapi.h>
+#endif
+
/* Qt wrapper around certhelp functions. */
QString getX509Value(x509_name *namebuf, unsigned char *oid) {
QString retval;
@@ -196,3 +200,64 @@
mBaseLine.replace(0, 1, "R");
}
}
+
+#ifdef WIN32
+bool Certificate::showNativeUI(void *parent)
+{
+ /* Cut of the first two chars (e.g. I: and decode) */
+ bool retval = false;
+ QByteArray pemData = QByteArray(
+ mBaseLine.right(mBaseLine.size() - 2).toLatin1());
+ PCCERT_CONTEXT pCert = b64_to_cert_context (pemData.data(), pemData.size());
+ typedef BOOL (CALLBACK* LPFNVIEWDLG)(DWORD,const void *,HWND,LPCWSTR,DWORD,void *);
+ LPFNVIEWDLG funcPtr;
+
+ /* CryptUIDlgViewContext is not part of mingw 3.1.0
+ * so we workaround this by geting the process address dynamically. */
+ HMODULE hmod = LoadLibraryW(L"cryptui");
+
+ if (!hmod) {
+ qDebug() << "Failed to open Cryptui.dll";
+ goto done;
+ }
+
+ funcPtr = (LPFNVIEWDLG) GetProcAddress (hmod, "CryptUIDlgViewContext");
+ if (!funcPtr) {
+ qDebug() << "Failed to find Address of CryptUIDlgViewContext";
+ goto done;
+ }
+
+ if (pCert == NULL) {
+ qDebug() << "Failed to parse certificate.";
+ goto done;
+ }
+
+ if (!funcPtr(CERT_STORE_CERTIFICATE_CONTEXT,
+ pCert,
+ (HWND) parent,
+ NULL, // Default Title
+ 0,
+ NULL)) {
+ qDebug() << "Failed to view certificate.";
+ retval = false;
+ goto done;
+ }
+
+ retval = true;
+done:
+
+ if (pCert) {
+ CertFreeCertificateContext(pCert);
+ }
+ if (hmod) {
+ FreeLibrary(hmod);
+ }
+ return retval;
+}
+#else
+bool Certificate::showNativeUI(void *parent)
+{
+ qDebug() << "Not implemented.";
+ return false;
+}
+#endif
diff -r d3d66d43365f -r 265583011f24 ui/certificate.h
--- a/ui/certificate.h Mon Sep 29 13:02:41 2014 +0200
+++ b/ui/certificate.h Mon Sep 29 13:12:58 2014 +0200
@@ -161,6 +161,19 @@
friend inline bool operator==(const Certificate& lhs, const Certificate& rhs) {
return lhs.base64Line() == rhs.base64Line();
}
+
+ /** @brief Show the certificate in a native ui dialog.
+ *
+ * The dialog is external and handled by the OS on windows
+ * on GNU/Linux gcr-viewer is used.
+ *
+ * If parentWindow is not NULL it is used as a handle to the
+ * parent Window. Unused on GNU/Linux
+ *
+ * @returns true on success. false if no native dialog could be shown.
+ */
+ bool showNativeUI(void *parentWindow);
+
private:
/** @brief Helper function to parse the details of a certificate **/
void parseDetails(const QByteArray& cert);
diff -r d3d66d43365f -r 265583011f24 ui/certificateitemwidget.cpp
--- a/ui/certificateitemwidget.cpp Mon Sep 29 13:02:41 2014 +0200
+++ b/ui/certificateitemwidget.cpp Mon Sep 29 13:12:58 2014 +0200
@@ -63,16 +63,25 @@
QLocale::system().toString(mCertificate.validFrom().date(), QLocale::ShortFormat)).arg(
QLocale::system().toString(mCertificate.validTo().date(), QLocale::ShortFormat));
const QString fpstring = tr("Fingerprint (SHA1): <code>%1</code>").arg(mCertificate.fingerprint());
+#ifdef Q_OS_WIN
+ mLabel->setText(QString::fromLatin1("<big><b><a href=showUi>%1</a></b></big><br/>%2<br/>%3<br/>%4").arg
+ (mCertificate.subjectCN()).arg(mCertificate.subjectO()).arg(validity).arg
+ (fpstring));
+#else
mLabel->setText(QString::fromLatin1("<big><b>%1</b></big><br/>%2<br/>%3<br/>%4").arg
(mCertificate.subjectCN()).arg(mCertificate.subjectO()).arg(validity).arg
(fpstring));
+#endif
mLabel->setTextFormat(Qt::RichText);
mLabel->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
mLabel->setTextInteractionFlags(
+ Qt::LinksAccessibleByMouse |
+ Qt::LinksAccessibleByKeyboard |
Qt::TextSelectableByMouse |
Qt::TextSelectableByKeyboard);
+ connect(mLabel, SIGNAL(linkActivated(const QString&)), this, SLOT(showCertDlg()));
mButton->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
connect(mButton, SIGNAL(toggled (bool)),
this, SLOT(currentStateChanged(bool)));
@@ -85,6 +94,14 @@
this->setLayout(layout);
}
+void CertificateItemWidget::showCertDlg()
+{
+ /* This is a totally evil cast but legitimate on Windows
+ * HANDLES are only 32 bit even on Windows 64 bit */
+ qDebug() << "Showing native ui: " << mCertificate.showNativeUI((void*)effectiveWinId());
+ return;
+}
+
bool CertificateItemWidget::state()
{
if (!mButton->isEnabled()) {
diff -r d3d66d43365f -r 265583011f24 ui/certificateitemwidget.h
--- a/ui/certificateitemwidget.h Mon Sep 29 13:02:41 2014 +0200
+++ b/ui/certificateitemwidget.h Mon Sep 29 13:12:58 2014 +0200
@@ -66,8 +66,12 @@
QToolButton *mButton;
private slots:
+ /** @brief called when the certificate state has been changed */
void currentStateChanged(bool state);
+ /** @brief Used to open the native cert dialog of the certificate */
+ void showCertDlg();
+
signals:
void stateChanged(bool state, const Certificate &cert);
};
More information about the Trustbridge-commits
mailing list