Mercurial > trustbridge
changeset 654:129e611eaf50
Merge branch trustbridge-refactor
author | Andre Heinecke <andre.heinecke@intevation.de> |
---|---|
date | Wed, 25 Jun 2014 15:16:24 +0200 |
parents | e41a2537b84d (diff) 39f03316f675 (current diff) |
children | 0ca15d937490 |
files | ui/CMakeLists.txt ui/mainwindow.cpp ui/mainwindow.h |
diffstat | 55 files changed, 2692 insertions(+), 208 deletions(-) [+] |
line wrap: on
line diff
--- a/.hgtags Wed Jun 25 14:56:19 2014 +0200 +++ b/.hgtags Wed Jun 25 15:16:24 2014 +0200 @@ -1,1 +1,2 @@ 421b69eeffe31d9d2ed5c6f6eb45c3856d8323ae 0.6 +10f0b9ceb29d60232845ed25438f886c4058de54 0.65
--- a/CMakeLists.txt Wed Jun 25 14:56:19 2014 +0200 +++ b/CMakeLists.txt Wed Jun 25 15:16:24 2014 +0200 @@ -99,6 +99,8 @@ add_dependencies(static_check flawfinder) endif (FLAWFINDER_PATH) +add_subdirectory(common) + add_subdirectory(cinst) if(Qt5Widgets_FOUND) add_subdirectory(ui) @@ -106,8 +108,6 @@ message(STATUS "WARNING: Could not find qt. GUI parts will not be built.") endif() -add_subdirectory(common) - # Documentation configure_file (doc/Doxyfile.in doc/Doxyfile) add_subdirectory(doc)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/INSTALL Wed Jun 25 15:16:24 2014 +0200 @@ -0,0 +1,146 @@ +Installation Instructions +************************* + +For Debian based GNU / Linux +============================ +Tested development platform: Ubuntu 13.10. + +The following commands build qt5 and polarssl which are dependencies of the Software. +For build dependencies please refer to the Qt documentation +( qtbase/src/plugins/platforms/xcb/README ). +Polarssl needs cmake and build-essentials. + + export YOURPREFIX=<Prefix of your choice (default /usr)> + export PATH=$YOURPREFIX/bin:$PATH + + curl https://download.qt-project.org/official_releases/qt/5.3/5.3.0/single/qt-everywhere-opensource-src-5.3.0.tar.xz.mirrorlist | grep SHA-256 + +e6f47e69a5ce707452dd4bad1fd1919201a71e88be1b06afe1d302a3935daf1f + + http://qt-mirror.dannhauer.de/official_releases/qt/5.3/5.3.0/single/qt-everywhere-opensource-src-5.3.0.tar.xz + + sha256sum qt-everywhere-opensource-src-5.3.0.tar.xz + + tar -xvmlf qt-everywhere-opensource-src-5.3.0.tar.xz + + cd qt-everywhere-opensource-src-5.3.0/qtbase + +build dependencies have to to be installed at this point, +see ../qtbase/src/plugins/platforms/xcb/README + + ./configure --prefix=$YOURPREFIX \ + -opensource \ + -release -nomake tests -nomake examples -confirm-license \ + -static -no-cups -no-nis -no-icu -fontconfig \ + -no-directfb -no-opengl -no-kms -no-eglfs -no-egl -no-openssl -no-glib + nice make -j8 + make install + + cd qttools/src/linguist + qmake + nice make -j8 + make install -k + + curl -O https://polarssl.org/download/polarssl-1.3.7-gpl.tgz + 6beef0281160bf07fefefd6b412dd1ce4c39261cf5300835aef442253f0400e5 polarssl-1.3.7-gpl.tgz + + tar -xf polarssl-1.3.7-gpl.tgz + cd polarssl-1.3.7 + mkdir build + cd build + cmake .. -DCMAKE_C_FLAGS=-fpic -DCMAKE_INSTALL_PREFIX=$YOURPREFIX + make && make test && make install + +To compile the software you can use plain cmake. An out of source build is +highly suggested. For build options see CMakeList.txt + + hg clone https://wald.intevation.org/hg/trustbridge/ + cd trustbridge + mkdir build-linux + cd build-linux + cmake .. -DCMAKE_PREFIX_PATH=$YOURPREFIX + + +Hiawatha (for Downloader unit test) +=================================== +Hiawatha is used in the downloader unit tests to provide a testbench +for the ssl connection. To build it you may need libxslt-dev as additional +dependency. + + wget https://www.hiawatha-webserver.org/files/hiawatha-9.5.tar.gz + sha256sum hiawatha-9.5.tar.gz + +c181011db1af187006190fc186689a0707a6f1e7b524c2a4347840e8fdf68b4f hiawatha-9.5.tar.gz + + tar -xf hiawatha-9.5.tar.gz + cp polarssl-1.3.7-gpl.tgz hiawatha-9.5/polarssl/polarssl.tgz + cd hiawatha-9.5/polarssl + sed -i 's/wget.*//' upgrade + ./upgrade 1.3.7 + cd .. + mkdir build + cd build + cmake .. -DCMAKE_INSTALL_PREFIX=$YOURPREFIX + make && make install + +Osslsigncode (for binverify unit test) +====================================== +Osslsigncode is used to create PKCS#7 embedded signatures for Windows Authenticode +it is needed for the Windows part of the binverify unit test on the build system. + +Currently (23.06.2014) there is no released version with the OpenSSL exception +available so we need to use the git version. + + git clone git://git.code.sf.net/p/osslsigncode/osslsigncode osslsigncode + cd osslsigncode + git checkout 03848a9c60f957bf13bab39512d8fcfb4cb1fc98 + ./autogen.sh + ./configure --prefix=$YOURPREFIX + make && make install + + # for a windows binary (optional) + OPENSSL_CFLAGS=-I$MXETARGET/include OPENSSL_LIBS="-L$MXETARGET/lib -lcrypto -lz -lgdi32" ./configure --without-curl --host=i686-w64-mingw32 --prefix=$MXETARGET + +For Microsoft Windows +===================== +The Windows variant can be cross compiled on Debian based GNU / Linux systems. +The minimum requirement is Debian stable. +Tested development platform: Ubuntu 13.10. + +Dependencies on the Host system: + git autoconf automake bash bison bzip2 \ + cmake flex gettext git g++ intltool \ + libffi-dev libtool libltdl-dev libssl-dev \ + libxml-parser-perl make openssl patch perl \ + pkg-config scons sed unzip wget xz-utils autopoint \ + gperf + +Build the windows binaries: + MXEPATH=$YOURPREFIX/win + git clone https://github.com/mxe/mxe.git $MXEPATH + cd $MXEPATH + echo "MXE_TARGETS := i686-w64-mingw32.static" > settings.mk + make polarssl + make qtbase + +Workaround Qt CMake Bugs: + find $MXEPATH/usr/i686-w64-mingw32.static/qt5/lib/cmake -name \*.cmake | \ + xargs sed -i 's/\/\([a-z]*\)\.lib/\/lib\1\.a/g' + sed -i 's/^_qt5gui_find_extra_libs.*//' \ + $MXEPATH/usr/i686-w64-mingw32.static/qt5/lib/cmake/Qt5Gui/Qt5GuiConfigExtras.cmake + +Make an NSS build available in the MXE prefix: + # TODO -> Document how to build NSS,.. + cp -r <magic nss folder> $MXEPATH/usr/i686-w64-mingw32.static/ + +Compile the software: + cd trustbridge + mkdir build-windows + cd build-windows + MXETARGET=$MXEPATH/usr/i686-w64-mingw32.static/ + cmake .. \ + -DCMAKE_PREFIX_PATH="$MXETARGET/qt5;$MXETARGET;" \ + -DNSS_INCLUDEDIR="/nss-3.12.7/include;/nss-3.12.7/public/nss" \ + -DNSS_LIBDIR="/nss-3.12.7/lib" \ + -DCMAKE_TOOLCHAIN_FILE="$MXETARGET/share/cmake/mxe-conf.cmake" \ + -DCMAKE_VERBOSE_MAKEFILE=True
--- a/cinst/main.c Wed Jun 25 14:56:19 2014 +0200 +++ b/cinst/main.c Wed Jun 25 15:16:24 2014 +0200 @@ -84,7 +84,7 @@ if (*to_install || *to_remove) { - printf ("Error invalid parameters.\n"); + ERRORPRINTF ("Error invalid parameters.\n"); return -1; } @@ -113,13 +113,13 @@ size_t len = strlen (buf); /* fgets ensures buf is terminated */ if (len <= 3) { - printf ("Line too short.\n"); + ERRORPRINTF ("Line too short.\n"); fclose (f); return ERR_INVALID_INPUT; } if (lines_read++ > MAX_LINES) { - printf ("Too many lines\n"); + ERRORPRINTF ("Too many lines\n"); fclose (f); return ERR_TOO_MUCH_INPUT; }
--- a/cinst/mozilla.c Wed Jun 25 14:56:19 2014 +0200 +++ b/cinst/mozilla.c Wed Jun 25 15:16:24 2014 +0200 @@ -442,13 +442,14 @@ cert = CERT_DecodeCertFromPackage((char *)dercert->data, (int)dercert->len); trust = (CERTCertTrust *)xmalloc(sizeof(CERTCertTrust)); - CERT_DecodeTrustString(trust, "C"); + CERT_DecodeTrustString(trust, "C,C,C"); if ((PK11_ImportCert(pk11slot, cert, CK_INVALID_HANDLE, cert_name, PR_FALSE) == SECSuccess) && (CERT_ChangeCertTrust(CERT_GetDefaultCertDB(), cert, trust) == SECSuccess)) { + log_certificate_der (pdir, dercert->data, dercert->len, true); success = true; } else @@ -491,6 +492,7 @@ if (SEC_DeletePermCertificate(cert) == SECSuccess) { success = true; + log_certificate_der (pdir, dercert->data, dercert->len, false); } else { @@ -524,7 +526,7 @@ * formatted certificate. The function must return true on success * and false on failure. * - * This function is intended wor use with the import_cert and + * This function is intended for use with the import_cert and * remove_cert functions. * * @param[in] fn the function to apply
--- a/cinst/nssstore_linux.c Wed Jun 25 14:56:19 2014 +0200 +++ b/cinst/nssstore_linux.c Wed Jun 25 15:16:24 2014 +0200 @@ -20,6 +20,7 @@ #include <stdlib.h> #include <limits.h> #include <errno.h> +#include <pwd.h> #include "nssstore.h" #include "logging.h" @@ -158,15 +159,15 @@ if (pid == (pid_t) 0) { /* Drop privileges */ - if (setuid (uid) || setgid (gid)) + if (setgid (gid) || setuid (uid)) { + syslog_error_printf("Failed to drop privileges: %s", strerror(errno)); exit(-1); } close (pipe_fd[1]); dup2 (pipe_fd[0], 0); close (pipe_fd[0]); - /* TODO find path based on current executable */ execve (argv[0], argv, envp); exit (127); } @@ -238,7 +239,8 @@ int write_stores_nss (char **to_install, char **to_remove) { - uid_t my_uid = getuid(); + struct passwd *usr_it = NULL; + uid_t my_uid = geteuid(); if (my_uid != 0) { @@ -269,8 +271,32 @@ return 0; } - printf ("Installation as root is not yet implemented\n"); - /* TODO root parse /etc/passwd for users with a home directory */ + + setpwent(); + + while ((usr_it = getpwent ()) != NULL) + { + /* Skip obvious system accounts */ + if (strcmp(usr_it->pw_shell, "/usr/sbin/nologin") == 0 || + strcmp(usr_it->pw_shell, "/bin/false") == 0) + { + continue; + } + /* A check if the home directory starts with /home might be + appropiate */ + start_procces_for_user (to_install, + to_remove, + usr_it->pw_uid, + usr_it->pw_gid, + usr_it->pw_dir); + + } + + endpwent(); + + waitpid (-1, NULL, 0); + + DEBUGPRINTF ("NSS installation done\n"); return 0; } #endif
--- a/cinst/windowsstore.c Wed Jun 25 14:56:19 2014 +0200 +++ b/cinst/windowsstore.c Wed Jun 25 15:16:24 2014 +0200 @@ -28,7 +28,7 @@ if (ret != 0) { - printf ("decoding certificate failed\n"); + ERRORPRINTF ("decoding certificate failed\n"); return NULL; } @@ -45,7 +45,7 @@ char *error = getLastErrorMsg(); if (error) { - printf ("Failed to create cert context: %s \n", error); + ERRORPRINTF ("Failed to create cert context: %s \n", error); free (error); } return NULL; @@ -58,6 +58,7 @@ { PCCERT_CONTEXT pCert = NULL; unsigned int i = 0; + bool elevated = is_elevated(); if (!to_remove) { @@ -76,7 +77,7 @@ char *error = getLastErrorMsg(); if (error) { - printf ("Failed to create cert context: %s \n", error); + ERRORPRINTF ("Failed to create cert context: %s \n", error); free (error); } continue; @@ -93,7 +94,7 @@ if (pCert == NULL) { - printf ("Did not find certificate\n"); + ERRORPRINTF ("Did not find certificate\n"); continue; } @@ -104,10 +105,12 @@ pCertContext by calling the CertFreeCertificateContext function, even if an error is encountered. */ char *error = getLastErrorMsg(); - printf ("Error deleting certificate. %s", error); + ERRORPRINTF ("Error deleting certificate. %s", error); free (error); continue; } + log_certificate (elevated ? "Local Machine" : "Current User", + to_remove[i], false); } return; } @@ -117,6 +120,7 @@ { int i = 0, ret = -1; + bool elevated = is_elevated(); if (!to_install) { @@ -144,7 +148,7 @@ NULL); if (found_cert != NULL) { - printf ("Certificate already in store\n"); + DEBUGPRINTF ("Certificate already in store\n"); CertFreeCertificateContext (found_cert); CertFreeCertificateContext (pc_to_add); continue; @@ -160,10 +164,12 @@ char *error = getLastErrorMsg(); if (error) { - printf ("Failed to add certificate: %s \n", error); + ERRORPRINTF ("Failed to add certificate: %s \n", error); free (error); } } + log_certificate (elevated ? "Local Machine" : "Current User", + to_install[i], true); } return; }
--- a/common/CMakeLists.txt Wed Jun 25 14:56:19 2014 +0200 +++ b/common/CMakeLists.txt Wed Jun 25 15:16:24 2014 +0200 @@ -5,6 +5,8 @@ # and comes with ABSOLUTELY NO WARRANTY! # See LICENSE.txt for details. +include_directories(${CMAKE_CURRENT_BINARY_DIR}) + set (trustbridge_common_src certhelp.c listutil.c @@ -12,6 +14,27 @@ portpath.c strhelp.c util.c + binverify.c + selftest.c ) +if(WIN32) + # Add the event messages + if (MINGW) + STRING(REGEX REPLACE "windres" "windmc" MC_COMPILER ${CMAKE_RC_COMPILER}) + else() + # untested + set(MC_COMPILER "mc.exe") + endif() + + add_custom_command( + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/events.h + ${CMAKE_CURRENT_BINARY_DIR}/events.rc + ${CMAKE_CURRENT_BINARY_DIR}/MSG00407.bin + ${CMAKE_CURRENT_BINARY_DIR}/MSG00409.bin + COMMAND ${MC_COMPILER} ${CMAKE_SOURCE_DIR}/common/events.mc -a -U -r ${CMAKE_CURRENT_BINARY_DIR} -h ${CMAKE_CURRENT_BINARY_DIR} + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/events.mc) + set(trustbridge_common_src ${trustbridge_common_src} ${CMAKE_CURRENT_BINARY_DIR}/events.h) +endif() + add_library(trustbridge_common STATIC ${trustbridge_common_src})
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/common/binverify.c Wed Jun 25 15:16:24 2014 +0200 @@ -0,0 +1,227 @@ +/* Copyright (C) 2014 by Bundesamt für Sicherheit in der Informationstechnik + * Software engineering by Intevation GmbH + * + * This file is Free Software under the GNU GPL (v>=2) + * and comes with ABSOLUTELY NO WARRANTY! + * See LICENSE.txt for details. + */ + +#include "binverify.h" + +#include "strhelp.h" +#include "logging.h" + +#ifdef RELEASE_BUILD +#include "pubkey-release.h" +#else +#include "pubkey-test.h" +#endif + +bin_verify_result +verify_binary(const char *filename, size_t name_len) { +#ifdef WIN32 + return verify_binary_win(filename, name_len); +#else + /* TODO */ + if (filename && name_len) + return VerifyValid; + return VerifyUnknownError; +#endif +} + +#ifdef WIN32 + +#include <polarssl/x509_crt.h> + +#include <windows.h> +#include <wincrypt.h> +#include <wintrust.h> +#include <stdio.h> + + +/** @brief Check if the certificate @a pCCertContext is pinned + * + * Compares the certificate's binary data (public key and attributes) + * with each other to validate that the certificate pCCertContext has + * exactly the same data as the builtin public certificate. + * + * @param[in] pCCertContext pointer to the certificate to check + * + * @returns true if the certificate matches, false otherwise. + */ +static bool +check_certificate (PCCERT_CONTEXT pCCertContext) +{ + x509_crt codesign_cert; + int ret = 0; + DWORD dwI = 0; + bool retval = false; + + if (pCCertContext == NULL) + { + ERRORPRINTF ("Invalid call to check_certificate"); + return false; + } + + x509_crt_init(&codesign_cert); + + /* Parse the pinned certificate */ + ret = x509_crt_parse(&codesign_cert, + public_key_codesign_pem, + public_key_codesign_pem_size); + if (ret != 0) + { + ERRORPRINTF ("x509_crt_parse failed with -0x%04x\n\n", -ret); + goto done; + } + + if (codesign_cert.raw.len != pCCertContext->cbCertEncoded || + codesign_cert.raw.len <= 0) + { + ERRORPRINTF ("Certificate size mismatch"); + goto done; + } + + /* Check that the certificate is exactly the same as the pinned one */ + for (dwI = 0; dwI < pCCertContext->cbCertEncoded; dwI++) + { + if (pCCertContext->pbCertEncoded[dwI] != codesign_cert.raw.p[dwI]) + { + ERRORPRINTF ("Certificate content mismatch"); + goto done; + } + } + + retval = true; + +done: + x509_crt_free(&codesign_cert); + return retval; +} + +bin_verify_result +verify_binary_win(const char *filename, size_t name_len) { + bin_verify_result retval = VerifyUnknownError; + WCHAR *filenameW = NULL; + BOOL result = FALSE; + DWORD dwEncoding = 0, + dwContentType = 0, + dwFormatType = 0, + dwSignerInfoSize = 0; + HCERTSTORE hStore = NULL; + HCRYPTMSG hMsg = NULL; + PCERT_INFO pSignerCert = NULL; + PCCERT_CONTEXT pSignerCertContext = NULL; + + if (!filename || name_len > MAX_PATH || strlen(filename) != name_len) + { + ERRORPRINTF ("Invalid parameters\n"); + return VerifyUnknownError; + } + + filenameW = utf8_to_wchar(filename, name_len); + + result = CryptQueryObject (CERT_QUERY_OBJECT_FILE, + filenameW, + CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED, + CERT_QUERY_FORMAT_FLAG_BINARY, + 0, + &dwEncoding, + &dwContentType, + &dwFormatType, + &hStore, + &hMsg, + NULL); + + if (!result || !hMsg) + { + PRINTLASTERROR ("Failed to query crypto object"); + retval = VerifyReadFailed; + goto done; + } + + /* Get the cert info so that we can look up the signer in the store later */ + if (CryptMsgGetParam(hMsg, + CMSG_SIGNER_CERT_INFO_PARAM, + 0, + NULL, + &dwSignerInfoSize) && dwSignerInfoSize > 0) + { + pSignerCert = xmalloc (dwSignerInfoSize); + } + else + { + ERRORPRINTF ("Failed to get signer cert size."); + retval = VerifyUnknownError; + goto done; + } + + if (!(CryptMsgGetParam(hMsg, + CMSG_SIGNER_CERT_INFO_PARAM, + 0, + pSignerCert, + &dwSignerInfoSize))) + { + ERRORPRINTF ("Failed to get signer cert."); + retval = VerifyUnknownError; + goto done; + } + + pSignerCertContext = CertGetSubjectCertificateFromStore( + hStore, + PKCS_7_ASN_ENCODING | X509_ASN_ENCODING, + pSignerCert); + + if (!pSignerCertContext) + { + ERRORPRINTF ("Failed to find signer cert in store."); + retval = VerifyUnknownError; + goto done; + } + + /* Verify that the signature is actually valid */ + if(!CryptMsgControl(hMsg, + 0, + CMSG_CTRL_VERIFY_SIGNATURE, + pSignerCertContext->pCertInfo)) + { + ERRORPRINTF ("The signature is invalid. \n"); + retval = VerifyInvalidSignature; + syslog_error_printf ("Software update embedded signature is invalid."); + goto done; + } + + if(check_certificate(pSignerCertContext)) + { + DEBUGPRINTF ("Valid signature with pinned certificate."); + retval = VerifyValid; + goto done; + } + else + { + ERRORPRINTF ("Certificate mismatch. \n"); + retval = VerifyInvalidCertificate; + syslog_error_printf ("Software update embedded signature " + "created with wrong certificate."); + goto done; + } + +done: + xfree(filenameW); + xfree(pSignerCert); + + if(pSignerCertContext) + { + CertFreeCertificateContext(pSignerCertContext); + } + if (hStore) + { + CertCloseStore(hStore, 0); + } + if (hMsg) + { + CryptMsgClose(hMsg); + } + return retval; +} +#endif /* WIN32 */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/common/binverify.h Wed Jun 25 15:16:24 2014 +0200 @@ -0,0 +1,64 @@ +/* Copyright (C) 2014 by Bundesamt für Sicherheit in der Informationstechnik + * Software engineering by Intevation GmbH + * + * This file is Free Software under the GNU GPL (v>=2) + * and comes with ABSOLUTELY NO WARRANTY! + * See LICENSE.txt for details. + */ + +#ifndef BINVERIFY_H +#define BINVERIFY_H +/* @file binverify.h + * @brief Verification of binary files + */ +#include <stdbool.h> +#include <stddef.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @enum bin_verify_result + * @brief Result of a verification + */ +typedef enum { + VerifyValid = 100, /*! Could be read and signature matched */ + VerifyUnknownError = 1, /*! The expected unexpected */ + VerifyInvalidSignature = 4, /*! Signature was invalid */ + VerifyInvalidCertificate = 5, /*! Certificate mismatch */ + VerifyReadFailed = 6, /*! File exists but could not read the file */ +} bin_verify_result; + +/** + * @brief verify a binary + * + * This function checks that a binary is signed by a built + * in certificate. + * + * Caution: This function works on file names only which could + * be modified after this check. + * + * The verification is done using Windows crypto API based on + * embedded PKCS 7 "authenticode" signatures embedded into the + * file. + * + * @param[in] filename absolute null terminated UTF-8 encoded path to the file. + * @param[in] name_len length of the filename. + * + * @returns the verification result. + */ +bin_verify_result verify_binary(const char *filename, size_t name_len); + +#ifdef WIN32 +/** + * @brief windows implementation of verify_binary + */ +bin_verify_result verify_binary_win(const char *filename, size_t name_len); +#endif /* WIN32 */ + +#ifdef __cplusplus +} +#endif + +#endif /* BINVERIFY_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/common/events.mc Wed Jun 25 15:16:24 2014 +0200 @@ -0,0 +1,109 @@ +; /* Copyright (C) 2014 by Bundesamt für Sicherheit in der Informationstechnik +; Software engineering by Intevation GmbH +; +; This file is Free Software under the GNU GPL (v>=2) +; and comes with ABSOLUTELY NO WARRANTY! +; See LICENSE.txt for details. */ + + +SeverityNames=(Success=0x0:STATUS_SEVERITY_SUCCESS +Informational=0x1:STATUS_SEVERITY_INFORMATIONAL +Warning=0x2:STATUS_SEVERITY_WARNING +Error=0x3:STATUS_SEVERITY_ERROR +) + +FacilityNames=(System=0x0:FACILITY_SYSTEM + Runtime=0x2:FACILITY_RUNTIME + Stubs=0x3:FACILITY_STUBS + Io=0x4:FACILITY_IO_ERROR_CODE + ) + +LanguageNames=(English=0x409:MSG00409) +LanguageNames=(German=0x407:MSG00407) + +MessageIdTypedef=WORD + +MessageId=0x1 +SymbolicName=EVENT_CAT_TB +Language=English +Trustbridge +. +Language=German +Trustbridge +. + +MessageId=0x2 +SymbolicName=EVENT_CAT_CINST +Language=English +Certificate Installer +. +Language=German +Zertifikatsinstaller +. + + +MessageId=0x3 +SymbolicName=EVENT_CAT_NSS +Language=English +NSS +. +Language=German +NSS +. +;/* THE MESSAGES */ + +MessageIdTypedef=DWORD + +MessageId=0x100 +Severity=Informational +Facility=Runtime +SymbolicName=MSG_DEFAULT_INFO +Language=English +%1 +. +Language=German +%1 +. + +MessageId=0x101 +Severity=Error +Facility=Runtime +SymbolicName=MSG_DEFAULT_ERROR +Language=English +%1 +. +Language=German +%1 +. + +;/* Keep the following two lines in line with the linux counterparts in +; logging.c */ +MessageId=0x102 +Severity=Informational +Facility=Runtime +SymbolicName=MSG_CERT_INSTALL +Language=English +Installation of root certificate: %1%n +Sha256 thumbprint:<%2>%n +Certificate store: "%3" +. +Language=German +Installation des Wurzelzertifikats: %1%n +Sha256 Fingerabdruck:<%2>%n +Zertifikatsspeicher: "%3" +. + +MessageId=0x103 +Severity=Informational +Facility=Runtime +SymbolicName=MSG_CERT_REMOVE +Language=English +Removal of root certificate: %1%n +Sha256 thumbprint:<%2>%n +Certificate store: "%3" +. +Language=German +Entfernung des Wurzelzertifikats: %1%n +Sha256 Fingerabdruck:<%2>%n +Zertifikatsspeicher: "%3" +.
--- a/common/listutil.c Wed Jun 25 14:56:19 2014 +0200 +++ b/common/listutil.c Wed Jun 25 15:16:24 2014 +0200 @@ -17,6 +17,7 @@ #include <string.h> #include "strhelp.h" +#include "logging.h" #ifdef RELEASE_BUILD #include "pubkey-release.h" @@ -168,7 +169,7 @@ ret = pk_parse_public_key(&pub_key_ctx, public_key_pem, public_key_pem_size); if (ret != 0) { - printf("pk_parse_public_key failed with -0x%04x\n\n", -ret); + ERRORPRINTF ("pk_parse_public_key failed with -0x%04x\n\n", -ret); pk_free(&pub_key_ctx); return ret; } @@ -177,7 +178,7 @@ signature, sig_size); if (ret != 0) { - printf("pk_verify failed with -0x%04x\n\n", -ret); + ERRORPRINTF ("pk_verify failed with -0x%04x\n\n", -ret); } pk_free(&pub_key_ctx); @@ -249,7 +250,7 @@ if (!data || !size) { - printf ("Invalid call to get_certs_to_remove \n"); + ERRORPRINTF ("Invalid call to get_certs_to_remove \n"); return NULL; }
--- a/common/listutil.h Wed Jun 25 14:56:19 2014 +0200 +++ b/common/listutil.h Wed Jun 25 15:16:24 2014 +0200 @@ -23,15 +23,15 @@ * @brief Status of the List Operations */ typedef enum { - Valid = 100, // Could be read and signature matched - UnknownError = 1, // The expected unexpected - TooLarge = 2, // Failed because the file exeeds the limit - InvalidFormat = 3, // File does not appear to be in list format - InvalidSignature = 4, // Signature was invalid - SeekFailed = 5, // Could not seek in the file - ReadFailed = 6, // File exists but could not read the file - IncompatibleVersion = 7, // The Format Version does not match - NoList = 8 // No list parsed + Valid = 100, /*! Could be read and signature matched */ + UnknownError = 1, /*! The expected unexpected */ + TooLarge = 2, /*! Failed because the file exeeds the limit */ + InvalidFormat = 3, /*! File does not appear to be in list format */ + InvalidSignature = 4, /*! Signature was invalid */ + SeekFailed = 5, /*! Could not seek in the file */ + ReadFailed = 6, /*! File exists but could not read the file */ + IncompatibleVersion = 7, /*! The Format Version does not match */ + NoList = 8 /*! No list parsed */ } list_status_t; /* Definitions based on the format */
--- a/common/logging.c Wed Jun 25 14:56:19 2014 +0200 +++ b/common/logging.c Wed Jun 25 15:16:24 2014 +0200 @@ -9,8 +9,112 @@ #include "strhelp.h" #include <stdio.h> +#include <stdarg.h> +#include <stdbool.h> + +#include <strhelp.h> + +#include <certhelp.h> + +#include <polarssl/sha256.h> #ifdef WIN32 +# include <windows.h> +# include "events.h" +#else +# include <syslog.h> +#endif + +#ifdef WIN32 + +/** @brief helper to prepare common logging information */ +static void +win_do_log(WORD type, WORD category, DWORD eventID, WORD numStrings, LPCWSTR *strings) +{ + HANDLE log_src = NULL, + process_token = NULL; + PTOKEN_USER user_struct = NULL; + PSID user_sid = NULL; + BOOL success = FALSE; + + log_src = RegisterEventSourceW (NULL, L"" LOG_NAME); + + if (log_src == NULL) + { + PRINTLASTERROR ("Failed to open log source."); + return; + } + + /* Get the current user sid for logging */ + OpenProcessToken (GetCurrentProcess(), TOKEN_READ, &process_token); + if (process_token) + { + DWORD size = 0; + + // check how much space is needed + GetTokenInformation (process_token, TokenUser, NULL, 0, &size); + if (ERROR_INSUFFICIENT_BUFFER == GetLastError()) + { + user_struct = xmalloc (size); + GetTokenInformation (process_token, TokenUser, user_struct, size, &size); + user_sid = user_struct->User.Sid; + } + } + + success = ReportEventW (log_src, + type, + category, + eventID, + user_sid, + numStrings, + 0, + strings, + NULL); + if (!success) + { + PRINTLASTERROR ("Failed to report event."); + } + + if (process_token) + { + CloseHandle(process_token); + } + xfree (user_struct); + + if (!DeregisterEventSource (log_src)) + { + PRINTLASTERROR ("Failed to close log source."); + } +} + +static void +win_log(const char *format, va_list ap, bool error) +{ + wchar_t *wmsg = NULL; + char buffer[MAX_LOG+1]; + vsnprintf (buffer, MAX_LOG, format, ap); + + buffer[MAX_LOG] = '\0'; + + wmsg = utf8_to_wchar (buffer, strlen(buffer)); + if (wmsg == NULL) + { + ERRORPRINTF ("Failed to convert log message to utf-16"); + return; + } + + win_do_log (error ? EVENTLOG_ERROR_TYPE : EVENTLOG_INFORMATION_TYPE, + EVENT_CAT_TB, + error ? MSG_DEFAULT_ERROR : MSG_DEFAULT_INFO, + 1, + (const WCHAR **) &wmsg); + + + xfree (wmsg); + + return; +} + char * getLastErrorMsg() { @@ -44,4 +148,122 @@ return retval; } +#else /* WIN32 */ + +static void +linux_log (const char *format, va_list ap, bool error) +{ + openlog (LOG_NAME, LOG_CONS | LOG_PID | LOG_NDELAY, LOG_USER); + vsyslog ( error ? LOG_ERR : LOG_INFO, format, ap); +} + +#endif /* WIN32 */ + +void +log_certificate(const char* store, char *b64cert, bool install) +{ + char *der_data = NULL; + size_t der_size = 0; + int ret = 0; + + ret = str_base64_decode (&der_data, &der_size, b64cert, strlen(b64cert)); + + if (ret != 0) + { + ERRORPRINTF ("Error decoding certificate.\n"); + return; + } + + log_certificate_der (store, (unsigned char *) der_data, der_size, install); + + xfree (der_data); +} + +void +log_certificate_der(const char *store, unsigned char *der_data, size_t der_size, bool install) +{ + char subject[MAX_LOG + 1]; + int ret = 0, + i = 0; + x509_crt chain; + unsigned char sha256sum[32]; + char fingerprint[32 * 3 + 1]; + + x509_crt_init(&chain); + if (x509_crt_parse_der(&chain, (const unsigned char *)der_data, + der_size) != 0) + { + ERRORPRINTF("Failed to parse cert.."); + return; + } + + ret = x509_dn_gets(subject, MAX_LOG, &(chain.subject)); + + if (ret == -1) + { + ERRORPRINTF("Failed to parse subject.."); + return; + } + subject[MAX_LOG] = '\0'; + + sha256 (chain.raw.p, chain.raw.len, sha256sum, 0); + + for (i = 0; i < 31; i++) + { + snprintf (fingerprint + (i * 3), 4, "%02X:", sha256sum[i]); + } + snprintf (fingerprint + (31 * 3), 3, "%02X", sha256sum[31]); + + fingerprint[32*3] = '\0'; + +#ifdef WIN32 + { + wchar_t *wstrings[3]; + + wstrings[0] = utf8_to_wchar (subject, strnlen (subject, MAX_LOG)); + wstrings[1] = utf8_to_wchar (fingerprint, strnlen (fingerprint, MAX_LOG)); + wstrings[2] = utf8_to_wchar (store, strnlen (store, MAX_LOG)); + + win_do_log (EVENTLOG_INFORMATION_TYPE, + EVENT_CAT_CINST, + install ? MSG_CERT_INSTALL : MSG_CERT_REMOVE, + 3, + (const WCHAR**) wstrings); + xfree (wstrings[0]); + xfree (wstrings[1]); + xfree (wstrings[2]); + } +#else + /* Please keep the following line in line with message from events.mc */ + syslog_info_printf ("%s of root certificate: %s Sha256 thumbprint:<%s>. Certificate store \"%s\"", + install ? "Installation" : "Removal", + subject, fingerprint, store); #endif + x509_crt_free (&chain); +} + +void +syslog_info_printf(const char *format, ...) +{ + va_list args; + va_start (args, format); +#ifdef WIN32 + win_log (format, args, false); +#else + linux_log (format, args, false); +#endif + va_end (args); +} + +void +syslog_error_printf(const char *format, ...) +{ + va_list args; + va_start (args, format); +#ifdef WIN32 + win_log (format, args, true); +#else + linux_log (format, args, true); +#endif + va_end (args); +}
--- a/common/logging.h Wed Jun 25 14:56:19 2014 +0200 +++ b/common/logging.h Wed Jun 25 15:16:24 2014 +0200 @@ -18,6 +18,13 @@ */ #include <stdio.h> +#include <stdbool.h> + +/** @def Maximum length of log messages */ +#define MAX_LOG 511 + +/** @def The name used for logging */ +#define LOG_NAME "TrustBridge" #ifdef WIN32 @@ -108,6 +115,51 @@ ERRORPRINTF ("Failed to get error information\n"); +/** + * @brief log an informational message into the syslog / event log + * + * The message length is limited to MAX_LOG characters. Log messages + * are expected to be in UTF-8 encoding. + * + * Function paramters are the same as for the printf familiy. + */ +void syslog_info_printf(const char *format, ...); + +/** + * @brief log an error message into the syslog / event log + * + * The message length is limited to MAX_LOG characters. Log messages + * are expected to be in UTF-8 encoding. + * + * Function paramters are the same as for the printf familiy. + */ +void syslog_error_printf(const char *format, ...); + + /** + * @brief log a certificate install / remove event from base64 data. + * + * Logs a message in the event / syslog to mark a certificate + * installation or removal. + * + * @param[in] store name of the certificate store. + * @param[in] b64cert base64 encoded certificate. + * @param[in] install weather to log this as installation or removal + */ +void log_certificate(const char *store, char *b64cert, bool install); + +/** + * @brief log a certificate install / remove event from der data. + * + * Logs a message in the event / syslog to mark a certificate + * installation or removal. + * + * @param[in] store name of the certificate store. + * @param[in] der_data pointer to der data of the certificate. + * @param[in] der_size size of the der_data + * @param[in] install weather to log this as installation or removal + */ +void log_certificate_der(const char *store, unsigned char *der_data, size_t der_size, bool install); + #ifdef __cplusplus } #endif
--- a/common/pubkey-test.h Wed Jun 25 14:56:19 2014 +0200 +++ b/common/pubkey-test.h Wed Jun 25 15:16:24 2014 +0200 @@ -23,4 +23,43 @@ "-----END PUBLIC KEY-----\n"; static const size_t public_key_pem_size = 625; + +/* Key used for codesigning */ +static const unsigned char public_key_codesign_pem[] = +"-----BEGIN CERTIFICATE-----\n" +"MIIFqTCCA5GgAwIBAgIBATANBgkqhkiG9w0BAQUFADBZMSAwHgYDVQQDExdQdWJs\n" +"aWMgVHJ1c3RCcmlkZ2UgVGVzdDEoMCYGA1UEChMfUHVibGljIHNlY3JldCBkbyBu\n" +"b3QgdHJ1c3QgdGhpczELMAkGA1UEBhMCREUwHhcNMTMwMTAxMDAwMDAwWhcNMTUx\n" +"MjMxMjM1OTU5WjBlMSwwKgYDVQQDEyNQdWJsaWMgVHJ1c3RCcmlkZ2UgY29kZXNp\n" +"Z25pbmcgdGVzdDEoMCYGA1UEChMfUHVibGljIHNlY3JldCBkbyBub3QgdHJ1c3Qg\n" +"dGhpczELMAkGA1UEBhMCREUwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC\n" +"AQDIz9IetAtdqJJ7aSfJcLmA9Mb4nxrqEJ5E6PMejDJZmmHNjyhCVp1qsLYmyC60\n" +"m7qJ4OBENx0v2n5LiCUHJpJ4mzAklkWn1GffUkzWgQ2VHw5Nr44NWEwkUUa5/jT7\n" +"Sxts2DWuaLz2r7oi6BUQpoRmQRPwwzFPONcCSw9iAvTU6oVI2jW1opEW3t10UwY3\n" +"5/muryPsUz6y5VkBIc73VC0wByXoAruEPBBpMgOVw1+npOaJ1PL1XXQ/P6xziZo0\n" +"Ab/tKvN6IpEHrNEGv1gScJt//pKKklvIyXm9UdIY9XpB6aauzthKpTFJXGYySlXx\n" +"bD1a5sq0i2sAK/p8RvErVWg3EfBlUrQryJxONPVqribczZIWcgKVEFfXjX1tQqiC\n" +"qRCgO4M6zhNIKLkAicp0DvYs8M4hIoPng98nqK6kSpfXR6Y4b9DU3yEktH7wGrwL\n" +"jKATVM2l2yTF17Pjxkr2tH0XWrChfS+oV6Qzm9JQ/vmLKz5piLKpt5SXuZny+j0Y\n" +"68ch709sVTuuPm4RAm5c5t0SCwEippClFpkZynYRsJVrjG9ZTrdvULxZao8GBzJx\n" +"Lb+tCaKP60BRoUuRfwGMKZbU6j6ujOCy5bZIoJaKgHgyAHXRuS4PIjY9K2BGM5vI\n" +"seA2GEdAJNmZPAQJE5rxkrsAH9n8QtmHucEqzCZVFcLuCwIDAQABo3AwbjAJBgNV\n" +"HRMEAjAAMB0GA1UdDgQWBBSMgUaKY3L65wH5M4il/gbHCeVm4TAfBgNVHSMEGDAW\n" +"gBTl/kZGRoa0cm82zW7CPn3yqk4MeTAOBgNVHQ8BAQEEBAMCAYAwEQYJYIZIAYb4\n" +"QgEBBAQDAgAQMA0GCSqGSIb3DQEBBQUAA4ICAQAdmpf8k+ZKuhDvNwMCrf1JIZh3\n" +"uJxlCHFke/ypsMT2E6p/GZpD/lLyRHbk7V5aEYdmBaK6Dem0KYhRuDclWscpQdXl\n" +"96wx1IDNueMkj5ZDmpBLFl/nqxlM9HfHo8YTE9dRgzJAR8+dFR8HyRSayKo+pz4L\n" +"FkNFT5Jtm9kKLIN+mSGKMBmpY4owfpeh7K6YyASoOHL9Zk8A0I7iZX8FB5KujrlG\n" +"WJahjSAyvLvy98XDCf9/SyX73F1ol5ycAb/du+G5VZFDEI8sv/7fIdTx/AUR30Ac\n" +"f3tqXZ4HwxWc0gofT0J2z/I4FZ/sT/1SNHReGNrG9GNn5bxjwpSXfc5A1bjhRfxd\n" +"x73xKEInjpgo6AXY7wfNk1V+2z7keVOpaDEZUOsd/x/C+L8FsUh2JJHZp/hKX6Co\n" +"AD///pxqNfvH5pPLUINC7VRUOTynUas7p9UvkPeJjqnWY6pmjeb4Fs6Z6vn0+Opy\n" +"HP1MjLL41a+U9VxuNb6SfRDoeT19pqK6ovT2gbc61OvTI0lE97ChC622rjnV0c/N\n" +"QYqkeTQG/IjPk0QFrYQxMqq6QKgds2nheYd4LyLGhk72pKWr28Hfj1ElcoTFFbWP\n" +"ndI+uZePkkCsVYNMXbIAIpqLb++1ftl+L+itqxTyq+0tPObIL3WG9rzBGz8X6WT0\n" +"KIzi4KAn66e5/iWZng==\n" +"-----END CERTIFICATE-----\n"; + +static const size_t public_key_codesign_pem_size = 2025; + #endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/common/selftest.c Wed Jun 25 15:16:24 2014 +0200 @@ -0,0 +1,46 @@ +#include "selftest.h" +#include "binverify.h" +#include "strhelp.h" +#include "logging.h" + +bool +selftest() +{ +#ifdef WIN32 + wchar_t wPath[MAX_PATH]; + char *utf8path = NULL; + + if (!GetModuleFileNameW (NULL, wPath, MAX_PATH - 1)) + { + PRINTLASTERROR ("Failed to obtain module file name. Path too long?"); + return false; + } + + /* wPath might not be 0 terminated */ + wPath[MAX_PATH - 1] = '\0'; + + utf8path = wchar_to_utf8 (wPath, wcsnlen(wPath, MAX_PATH)); + + if (utf8path == NULL) + { + ERRORPRINTF ("Failed to convert module path to utf-8"); + return false; + } + + if (!verify_binary (utf8path, strlen(utf8path)) != VerifyValid) + { + ERRORPRINTF ("Verification of the binary failed"); + syslog_error_printf ("Integrity check failed."); + xfree(utf8path); + return false; + } + + xfree(utf8path); +#else + if (!verify_binary ("/proc/self/exe", 14) != VerifyValid) + { + syslog_error_printf ("Integrity check failed."); + return false; + } +#endif +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/common/selftest.h Wed Jun 25 15:16:24 2014 +0200 @@ -0,0 +1,36 @@ +#ifndef COMMON_SELFTEST_H +#define COMMON_SELFTEST_H +/* Copyright (C) 2014 by Bundesamt für Sicherheit in der Informationstechnik + * Software engineering by Intevation GmbH + * + * This file is Free Software under the GNU GPL (v>=2) + * and comes with ABSOLUTELY NO WARRANTY! + * See LICENSE.txt for details. + */ + +/** @file self test against manipulation + * + * The selftest is intended to detect untargeted manipulation or + * corruption of the executable. Circumvention of the selftest + * by targeted manipulation of the binary can, of course, not + * be detected. + */ + +#include <stdbool.h> + +#ifdef __cplusplus +extern "C" { +#endif +/** @brief check that the current process is signed by the correct certificate + * + * Checks that the certificate is signed with a valid signature and the + * builtin public certificate. + * + * @returns true if the selftest is successful. false on error. + */ +bool selftest(); + +#ifdef __cplusplus +} +#endif +#endif // COMMON_SELFTEST_H
--- a/common/util.c Wed Jun 25 14:56:19 2014 +0200 +++ b/common/util.c Wed Jun 25 15:16:24 2014 +0200 @@ -7,10 +7,14 @@ */ #include "util.h" #include "logging.h" +#include "strhelp.h" #ifndef _WIN32 #include <unistd.h> #include <sys/types.h> +#include <pwd.h> +#include <grp.h> +#include <string.h> #else #include <windows.h> #endif @@ -42,7 +46,58 @@ bool is_admin() { #ifndef _WIN32 - /* TODO implement */ + struct passwd *current_user = getpwuid (geteuid()); + int ngroups = 0, + ret = 0, + i = 0; + gid_t * groups = NULL; + + if (current_user == NULL) + { + ERRORPRINTF ("Failed to obtain user information."); + return false; + } + + ret = getgrouplist (current_user->pw_name, current_user->pw_gid, NULL, + &ngroups); + + if (ret != -1 || ngroups <= 0) + { + ERRORPRINTF ("Unknown error in getgrouplist call"); + return false; + } + + groups = xmalloc (((unsigned int)ngroups) * sizeof (gid_t)); + + ret = getgrouplist (current_user->pw_name, current_user->pw_gid, groups, + &ngroups); + + if (ret != ngroups) + { + ERRORPRINTF ("Group length mismatch."); + xfree (groups); + return false; + } + + for (i = 0; i < ngroups; i++) + { + struct group *gr = getgrgid (groups[i]); + if (gr == NULL) + { + ERRORPRINTF ("Error in group enumeration"); + xfree (groups); + return false; + } + if (strcmp("sudo", gr->gr_name) == 0) + { + DEBUGPRINTF ("User is in sudo group \n"); + xfree (groups); + return true; + } + } + + DEBUGPRINTF ("User is not in sudo group"); + return false; #else bool retval = false;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/extras/testplan/README.txt Wed Jun 25 15:16:24 2014 +0200 @@ -0,0 +1,36 @@ += Test plan for TrustBridge + +TrustBridge uses the Free Software test plan framework + [[https://wald.intevation.org/projects/intests/]] +to fill out test plans with a simple web server. +InTEsts can also produce PDF output. + +To start, fetch the current version of inTests: + +{{{ + hg clone https://hg.intevation.org/intests +}}} + + +== Completing a test plan + +# Create a working copy of original testplan.xml into the intests directory: + {{{ + cd intests + cp /path/to/testplan.xml testplan.xml + }}} +# Start web server [optional with port number]: + {{{ + python main.py testplan.xml [PORT] + }}} +# Enter test information + (date, OS, tester, version, comment) +# Run all tests of each test suite and + record the test results (yes = passed, no = failed, n/a). +# Quit web server +# Create test plan protocol as PDF: +{{{ + xsltproc --stringparam lang de xforms/xml2tex.xsl testplan.xml > tex/testplan.tex + cd tex + make testplan.pdf +}}}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/extras/testplan/testplan.xml Wed Jun 25 15:16:24 2014 +0200 @@ -0,0 +1,108 @@ +<?xml version="1.0"?> +<testplan> + <meta> + <product-name>TrustBridge</product-name> + <product-version/> + <date/> + <tester/> + <test-date/> + <test-system/> + <test-version>0.1</test-version> + <test-duration/> + <comment/> + </meta> + <testsuite id="ts1" description="Verwaltungsanwendung"> + <general-precondition/> + <test id="t1.1" description="Anwendung starten"> + <precondition/> + <steps> + <step>Verwaltungsanwendung (trustbridge-admin) starten.</step> + </steps> + <results> + <result value="">Die Anwendung startet</result> + </results> + </test> + <test id="t1.2" description="Zertifikatsliste erstellen"> + <precondition/> + <steps> + <step>Mehrere Zertifikate hinzufügen (z.B. aus ui/tests/data)</step> + <step>Liste erstellen</step> + <step>Signaturzertifikat angeben (z.B. ui/tests/data/testkey-priv.pem)</step> + <step>Ausgabeverzeichnis angeben</step> + <step>Liste erstellen</step> + </steps> + <results> + <result value="">Liste wurde erfolgreich im Ausgabeverzeichnis gespeichert</result> + <result value="">Liste wurde erfolgreich im Archivverzeichnis (~/.local share/BSI/trustbridge-admin/) gespeichert</result> + </results> + </test> + <test id="t1.3" description="Zertifikatsliste aktualisieren"> + <precondition/> + <steps> + <step>Ein Zertifikat aus der Liste entfernen</step> + <step>Ein weiteres Zertifikate hinzufügen (z.B. aus ui/tests/data)</step> + <step>Liste erstellen (Signaturzertifikat und Ausgabeverzeichnis unverändert lassen)</step> + <step>Liste erstellen</step> + </steps> + <results> + <result value="">Liste wurde erfolgreich im Ausgabeverzeichnis gespeichert</result> + <result value="">Liste wurde erfolgreich im Archivverzeichnis (~/.local share/BSI/trustbridge-admin/) gespeichert</result> + </results> + </test> + <test id="t1.4" description="Letzte Zertifikatsliste automatisch laden"> + <precondition/> + <steps> + <step>Verwaltungsanwendung neustarten</step> + </steps> + <results> + <result value="">Die zuletzt erstellte Zertifikatsliste wird angezeigt</result> + </results> + </test> + <test id="t1.5" description="Installationspaket erzeugen"> + <precondition/> + <steps> + <step>Installationspaket erstellen...</step> + <step>Verzeichnis des Binärpakets angeben (enthält meta.ini)</step> + <step>Code-Signing-Zertifikat angeben (z.B. ui/tests/data/codesign/codesigning.pem)</step> + <step>Ausgabeverzeichnis angeben</step> + <step>Installationspaket erzeugen</step> + </steps> + <results> + <result>Installationspaket für Windows (NSIS-Installer) wurde im Ausgabeverzeichnis erstellt.</result> + <result>Installationspaket für Ubuntu wurde im Ausgabeverzeichnis erstellt.</result> + </results> + </test> + <test id="t1.6" description="Anwendung beenden"> + <precondition/> + <steps> + <step>Verwaltungsanwendung beenden.</step> + </steps> + <results> + <result value="">Die Anwendung schließt sich</result> + </results> + </test> + </testsuite> + <testsuite id="ts2" description="Clientanwendung"> + <general-precondition>Der TrustBridge Client Installer liegt vor.</general-precondition> + <test id="t2.1" description="Installation unter Windows (mit Administratorrechten)"> + <precondition>Nutzer besitzt Adminstratorrechte.</precondition> + <steps> + <step>NSIS-Installer ausführen (mit Vorbelegung)</step> + </steps> + <results> + <result>Anwendung startet nach Installation automatisch.</result> + <result>Eintrag im Startmenü ist vorhanden</result> + </results> + </test> + <test id="t2.2" description="Installation unter Windows (ohne Administratorrechten)"> + <precondition>Nutzer besitzt keine Adminstratorrechte.</precondition> + <steps> + <step>NSIS-Installer ausführen (mit Vorbelegung)</step> + </steps> + <results> + <result>Anwendung startet nach Installation automatisch.</result> + <result>Eintrag im Startmenü ist vorhanden</result> + </results> + </test> + </testsuite> +</testplan>
--- a/packaging/tmp-createpackage.sh.in Wed Jun 25 14:56:19 2014 +0200 +++ b/packaging/tmp-createpackage.sh.in Wed Jun 25 15:16:24 2014 +0200 @@ -1,4 +1,4 @@ -# Copyright (C) 2014 by Bundesamt für Sicherheit in der Informationstechnik +# Copyright (C) 2014 by Bundesamt für Sicherheit in der Informationstechnik # Software engineering by Intevation GmbH # # This file is Free Software under the GNU GPL (v>=2) @@ -21,7 +21,7 @@ echo $TMPDIR makensis -Dfiles_dir=$TMPDIR \ - -Dcompany="Bundesamt für Sicherheit in der Informationstechnik" \ + -Dcompany="Bundesamt für Sicherheit in der Informationstechnik" \ -Dversion_number=@PROJECT_VERSION@ \ -Dsetupname="@CMAKE_BINARY_DIR@/TrustBridge-@PROJECT_VERSION@.exe" \ -Dproductname="TrustBridge" \
--- a/packaging/trustbridge.nsi Wed Jun 25 14:56:19 2014 +0200 +++ b/packaging/trustbridge.nsi Wed Jun 25 15:16:24 2014 +0200 @@ -1,4 +1,4 @@ -; Copyright (C) 2014 by Bundesamt für Sicherheit in der Informationstechnik +; Copyright (C) 2014 by Bundesamt für Sicherheit in der Informationstechnik ; Software engineering by Intevation GmbH ; ; This file is Free Software under the GNU GPL (v>=2) @@ -29,6 +29,7 @@ !include "MultiUser.nsh" !include "MUI2.nsh" +!include "FileFunc.nsh" ;-------------------------------- ;Version Information (for installer file properties) @@ -66,7 +67,7 @@ !define MUI_UNICON "resources\uninstall.ico" ; MUI welcome page text -!define MUI_WELCOMEPAGE_TITLE "Willkommen bei der Installation des ${productname}" +!define MUI_WELCOMEPAGE_TITLE "Willkommen bei der Installation von ${productname}" !define MUI_WELCOMEPAGE_TEXT "Dieser Assistent wird Sie durch die Installation von \ ${productname} begleiten. $\r$\n$\r$\n\ ${productname} ist eine Anwendung um Wurzelzertifikate auf ihrem System \ @@ -88,10 +89,10 @@ !define MUI_FINISHPAGE_TEXT "${productname} wurde auf Ihrem \ Computer installliert. $\r$\n$\r$\n\ Klicken Sie auf 'Fertig stellen', um den Installations-Assistenten\ -zu schließen." -!define MUI_FINISHPAGE_RUN $INSTDIR\trustbridge.exe -!define MUI_FINISHPAGE_RUN_TEXT "Anwendung starten" -!define MUI_FINISHPAGE_RUN_FUNCTION RunAsUser +zu schließen." +;!define MUI_FINISHPAGE_RUN $INSTDIR\trustbridge.exe +;!define MUI_FINISHPAGE_RUN_TEXT "Anwendung starten" +;!define MUI_FINISHPAGE_RUN_FUNCTION RunAsUser !define MUI_FINISHPAGE_LINK "Mehr unter http://www.bsi.bund.de" !define MUI_FINISHPAGE_LINK_LOCATION "http://www.bsi.bund.de" @@ -112,7 +113,24 @@ ; Install Functions Function ".onInit" + Var /GLOBAL is_update + Var /GLOBAL changed_dir + ${GetParameters} $R0 + ClearErrors + ${GetOptions} $R0 /UPDATE= $is_update + +; Check if the install directory was modified on the command line + StrCmp "$INSTDIR" "$PROGRAMFILES\${productname_short}" unmodified 0 + ; It is modified. Save that value. + StrCpy $changed_dir "$INSTDIR" + +; MULITUSER_INIT overwrites directory setting from command line !insertmacro MULTIUSER_INIT + StrCpy $INSTDIR "$changed_dir" + goto initDone +unmodified: + !insertmacro MULTIUSER_INIT +initDone: FunctionEnd ; If we run elevated we do not want to run @@ -134,13 +152,22 @@ SetOutPath "$INSTDIR" !include "filelist.nsh" +;Create uninstaller + WriteUninstaller "$INSTDIR\Uninstall.exe" + +; Code below is not run on updates + StrCmp $is_update '1' done + WriteRegStr SHCTX "Software\${productname_short}" "" $INSTDIR -; Set up autostart - WriteRegStr SHCTX "Software\Microsoft\Windows\CurrentVersion\Run" "TrustBridge" "$INSTDIR\trustbridge.exe --tray" + WriteRegStr SHCTX "Software\${productname_short}" "" $INSTDIR -;Create uninstaller - WriteUninstaller "$INSTDIR\Uninstall.exe" +; Register logging + WriteRegStr SHCTX "System\CurrentControlSet\services\eventlog\Application\${productname_short}" "CategoryMessageFile" "$INSTDIR\trustbridge.exe" + WriteRegStr SHCTX "System\CurrentControlSet\services\eventlog\Application\${productname_short}" "EventMessageFile" "$INSTDIR\trustbridge.exe" + WriteRegStr SHCTX "System\CurrentControlSet\services\eventlog\Application\${productname_short}" "ParameterMessageFile" "$INSTDIR\trustbridge.exe" + WriteRegDword SHCTX "System\CurrentControlSet\services\eventlog\Application\${productname_short}" "TypesSupported" 5 + WriteRegDword SHCTX "System\CurrentControlSet\services\eventlog\Application\${productname_short}" "CategoryCount" 3 !insertmacro MUI_STARTMENU_WRITE_BEGIN Application @@ -149,6 +176,7 @@ CreateShortCut "$SMPROGRAMS\$StartMenuFolder\${productname}.lnk" "$INSTDIR\trustbridge.exe" !insertmacro MUI_STARTMENU_WRITE_END +done: SectionEnd
--- a/ui/CMakeLists.txt Wed Jun 25 14:56:19 2014 +0200 +++ b/ui/CMakeLists.txt Wed Jun 25 15:16:24 2014 +0200 @@ -7,7 +7,8 @@ include_directories(${Qt5Widgets_INCLUDE_DIRS}) include_directories(${POLARSSL_INCLUDE_DIR}) -include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../common) +include_directories(${CMAKE_SOURCE_DIR}/common) +include_directories(${CMAKE_BINARY_DIR}/common) add_definitions(${Qt5Widgets_DEFINITIONS}) find_package(Qt5LinguistTools) @@ -36,13 +37,15 @@ ${CMAKE_CURRENT_SOURCE_DIR}/certificateitemwidget.cpp ${CMAKE_CURRENT_SOURCE_DIR}/separatoritemdelegate.cpp ${CMAKE_CURRENT_SOURCE_DIR}/installwrapper.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/img/icon.rc ${CMAKE_CURRENT_SOURCE_DIR}/aboutdialog.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/processhelp_win.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/processhelp_linux.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/processwaitdialog.cpp ${CERTIFICATELIST_SOURCES} ${DOWNLOADER_SOURCES} ) -set(ADMINSTRATOR_SOURCES +set(ADMINISTRATOR_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/administratorwindow.cpp ${CMAKE_CURRENT_SOURCE_DIR}/certificatetablemodel.cpp ${CMAKE_CURRENT_SOURCE_DIR}/certificatetabledelegate.cpp @@ -59,7 +62,7 @@ ${CMAKE_CURRENT_SOURCE_DIR}/certs.qrc ) -set(ADMINSTRATOR_RESOURCES +set(ADMINISTRATOR_RESOURCES ${CMAKE_CURRENT_SOURCE_DIR}/icons.qrc ) @@ -97,6 +100,8 @@ -ladvapi32 -lshell32 -luser32 -lkernel32 -lz -lsicuin -lsicuuc -lsicudt -lpcre16) set(EXTRA_STATIC_LIBS Qt5::QWindowsIntegrationPlugin ${WINDOWS_EXTRA_LIBS} -lwinhttp -lcrypt32) + + add_definitions(-DUNICODE) endif() set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${Qt5Widgets_EXECUTABLE_COMPILE_FLAGS}") @@ -106,16 +111,34 @@ # Adding resources here in an extra variable to enable reuse of # TRUSTBRIDGE_SOURCES in the test subdirectory. -set(TRUSTBRIDGE_MAIN_WITH_RESOURCES ${CMAKE_CURRENT_SOURCE_DIR}/main.cpp) +set(TRUSTBRIDGE_MAIN_WITH_RESOURCES ${CMAKE_CURRENT_SOURCE_DIR}/main.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/img/icon.rc) qt5_add_resources(TRUSTBRIDGE_MAIN_WITH_RESOURCES ${TRUSTBRIDGE_RESOURCES}) -set(ADMINSTRATOR_MAIN_WITH_RESOURCES ${CMAKE_CURRENT_SOURCE_DIR}/administrator.cpp) -qt5_add_resources(ADMINSTRATOR_MAIN_WITH_RESOURCES ${ADMINSTRATOR_RESOURCES}) +set(ADMINISTRATOR_MAIN_WITH_RESOURCES ${CMAKE_CURRENT_SOURCE_DIR}/administrator.cpp) +qt5_add_resources(ADMINISTRATOR_MAIN_WITH_RESOURCES ${ADMINISTRATOR_RESOURCES}) if(WIN32) # This option causes cmake to use the appropiate liker flags to hide # the console Window on Windows set (_add_executable_params WIN32) + + # Add the event messages + if (MINGW) + STRING(REGEX REPLACE "windres" "windmc" MC_COMPILER ${CMAKE_RC_COMPILER}) + else() + # untested + set(MC_COMPILER "mc.exe") + endif() + + add_custom_command( + OUTPUT ${CMAKE_BINARY_DIR}/common/events.h + ${CMAKE_BINARY_DIR}/common/events.rc + ${CMAKE_BINARY_DIR}/common/MSG00407.bin + ${CMAKE_BINARY_DIR}/common/MSG00409.bin + COMMAND ${MC_COMPILER} ${CMAKE_SOURCE_DIR}/common/events.mc -r ${CMAKE_BINARY_DIR}/common -h ${CMAKE_BINARY_DIR}/common + DEPENDS ${CMAKE_SOURCE_DIR}/common/events.mc) + set_property(SOURCE ${CMAKE_CURRENT_SOURCE_DIR}/img/icon.rc APPEND PROPERTY OBJECT_DEPENDS ${CMAKE_BINARY_DIR}/common/events.rc) endif() if(Qt5LinguistTools_FOUND) @@ -125,11 +148,11 @@ # This would probably be better placed in a macro configure_file(l10n/administrator.qrc.in administrator.qrc) qt5_add_resources(ADMINISTRATOR_L10N ${CMAKE_CURRENT_BINARY_DIR}/administrator.qrc) - qt5_create_translation(ADMINISTRATOR_TRANSLATION ${ADMINSTRATOR_SOURCES} + qt5_create_translation(ADMINISTRATOR_TRANSLATION ${ADMINISTRATOR_SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/l10n/administrator_de_DE.ts) add_executable(trustbridge-admin ${_add_executable_params} - ${ADMINSTRATOR_MAIN_WITH_RESOURCES} + ${ADMINISTRATOR_MAIN_WITH_RESOURCES} ${ADMINISTRATOR_L10N} ${ADMINISTRATOR_TRANSLATION} ) @@ -149,14 +172,14 @@ message (STATUS "WARNING: Could not find qt linguist tools. Translation will not be included.") add_executable(trustbridge-admin ${_add_executable_params} - ${ADMINSTRATOR_MAIN_WITH_RESOURCES}) + ${ADMINISTRATOR_MAIN_WITH_RESOURCES}) add_executable(trustbridge ${_add_executable_params} ${TRUSTBRIDGE_MAIN_WITH_RESOURCES}) endif() add_library(ui_common STATIC ${UICOMMON_SOURCES}) -add_library(tbadminlib STATIC ${ADMINSTRATOR_SOURCES}) +add_library(tbadminlib STATIC ${ADMINISTRATOR_SOURCES}) add_library(tblib STATIC ${TRUSTBRIDGE_SOURCES}) target_link_libraries(trustbridge-admin
--- a/ui/aboutdialog.h Wed Jun 25 14:56:19 2014 +0200 +++ b/ui/aboutdialog.h Wed Jun 25 15:16:24 2014 +0200 @@ -17,6 +17,7 @@ class AboutDialog : public QDialog { + Q_OBJECT public: /** @brief Create a help dialog */ AboutDialog(QMainWindow *parent);
--- a/ui/administratorwindow.cpp Wed Jun 25 14:56:19 2014 +0200 +++ b/ui/administratorwindow.cpp Wed Jun 25 15:16:24 2014 +0200 @@ -231,6 +231,8 @@ QFile logFile(logFilePath); if (!logFile.open(QIODevice::Append)) { + QMessageBox::warning(this, tr("Error!"), tr("Failed to open log file: ") + + logFilePath + tr(" Changes are not logged!")); qDebug() << "Failed to open log file: " << logFilePath; return; } @@ -239,7 +241,8 @@ newCertList.readList(currentCerts.toLocal8Bit()); QByteArray entries = createLogEntries(newCertList); if(logFile.write(entries) != entries.size()) { - qDebug() << "Failed to write log file: " << logFilePath; + QMessageBox::warning(this, tr("Error!"), tr("Failed to write log file: ") + + logFilePath + tr(" Changes are not logged!")); return; } logFile.close();
--- a/ui/createinstallerdialog.cpp Wed Jun 25 14:56:19 2014 +0200 +++ b/ui/createinstallerdialog.cpp Wed Jun 25 15:16:24 2014 +0200 @@ -19,10 +19,25 @@ #include <QStyle> #include <QApplication> #include <QMessageBox> +#include <QTemporaryDir> + +/* Static information used in codesigning */ +#ifndef SIGN_HASH +#define SIGN_HASH "sha256" +#endif +#ifndef SIGN_URL +#define SIGN_URL "https://wald.intevation.org/projects/trustbridge/" +#endif +#ifndef SIGN_PUBLISHER +#define SIGN_PUBLISHER "TrustBridge Test with ümlaut" +#endif + CreateInstallerDialog::CreateInstallerDialog(QMainWindow *parent) : QDialog(parent), - mProgress(this) + mProgress(this), + mInstallerPath(), + mCurrentWorkingDir(NULL) { QSettings settings; setWindowTitle(tr("Create binary installer")); @@ -116,7 +131,6 @@ setLayout(topLayout); mProgress.setWindowModality(Qt::WindowModal); - mProgress.setLabelText(tr("Creating installer package...")); mProgress.setCancelButton(0); mProgress.setRange(0,0); mProgress.setMinimumDuration(0); @@ -162,9 +176,18 @@ void CreateInstallerDialog::processFinished(int exitCode, QProcess::ExitStatus exitStatus) { + if (mCurrentWorkingDir) { + delete mCurrentWorkingDir; + mCurrentWorkingDir = NULL; + } FinishedDialog *fin = new FinishedDialog(0, tr("Created installer in %1.") .arg(mSaveFile->text()), mNSISProc.readAll(), false); qDebug() << "Finished: " << mNSISProc.readAll(); + mProgress.setLabelText(tr("Signing installer package...")); + if (!signFile(mInstallerPath)) { + showErrorMessage(tr("Failed to sign installer package.")); + QFile::remove(mInstallerPath); + } mProgress.cancel(); fin->show(); close(); @@ -172,12 +195,17 @@ void CreateInstallerDialog::processError(QProcess::ProcessError error) { + if (mCurrentWorkingDir) { + delete mCurrentWorkingDir; + mCurrentWorkingDir = NULL; + } qDebug() << "Error: " << mNSISProc.readAll(); mProgress.cancel(); } void CreateInstallerDialog::createInstaller() { + mProgress.setLabelText(tr("Creating installer package...")); QDir binDir(mBinaryFolder->text()); QDir outDir(mSaveFile->text()); if (mBinaryFolder->text().isEmpty() || !binDir.exists()) { @@ -201,28 +229,39 @@ return; } + QTemporaryDir *signedFilesDir = codesignBinaries(binDir.path() + "/windows"); + + if (!signedFilesDir) { + /* Error messages should have been shown by the codesign function */ + return; + } + + mProgress.setLabelText(tr("Creating NSIS package...")); + /* Copy windows directory contents to tmpdir */ QStringList arguments; mNSISProc.setProgram("makensis"); mNSISProc.setProcessChannelMode(QProcess::MergedChannels); mNSISProc.setWorkingDirectory(outDir.path()); #ifdef Q_OS_WIN - arguments << QString::fromLatin1("/Dfiles_dir=") + binDir.path().replace("/", "\\") + "\\windows"; + arguments << QString::fromLatin1("/Dfiles_dir=") + signedFilesDir->path().replace("/", "\\"); arguments << "/Dpath_sep=\\"; foreach (const QString &key, keys) { QString value = options.value(key, QString()).toString(); if (key == "setupname") { value = value.arg(outDir.path().replace("/", "\\") + "\\"); + mInstallerPath = value; } arguments << QString::fromLatin1("/D%1=%2").arg(key, value); } #else - arguments << QString::fromLatin1("-Dfiles_dir=") + binDir.path() + "/windows"; + arguments << QString::fromLatin1("-Dfiles_dir=") + signedFilesDir->path(); arguments << "-Dpath_sep=/"; foreach (const QString &key, keys) { QString value = options.value(key, QString()).toString(); if (key == "setupname") { value = value.arg(outDir.path() + "/"); + mInstallerPath = value; } arguments << QString::fromLatin1("-D%1=%2").arg(key, value); } @@ -242,6 +281,85 @@ } } +bool CreateInstallerDialog::signFile(QString filePath) { + QProcess signProc; + signProc.setProcessChannelMode(QProcess::MergedChannels); + signProc.setProgram("osslsigncode"); + QStringList arguments; + + QSettings mySettings; + + QString publisher = mySettings.value("sign_publisher", SIGN_PUBLISHER).toString(); + QString url = mySettings.value("sign_url", SIGN_URL).toString(); + QString hash = mySettings.value("sign_hash", SIGN_HASH).toString(); + + arguments << "sign" << "-certs" << mCertFile->text() << "-key" + << mCertFile->text() << "-n" << publisher << "-i" << + url << "-h" << hash << "-in" << filePath << "-out" << filePath + ".signed"; + + qDebug() << "Starting osslsigncode with arguments: " << arguments; + signProc.setArguments(arguments); + signProc.start(); + + if (!signProc.waitForFinished(30000)) { + qDebug() << "Signing takes longer then 30 seconds. Aborting."; + return false; + } + + if (signProc.exitStatus() != QProcess::NormalExit || + signProc.exitCode() != 0) { + qDebug() << "Error process returned: " << signProc.exitCode(); + qDebug() << "Output: " << signProc.readAllStandardOutput(); + return false; + } + + if (!QFile::remove(filePath)) { + qDebug() << "Failed to remove file."; + return false; + } + if (!QFile::copy(filePath + ".signed", filePath)) { + qDebug() << "Failed to copy signed file in place."; + return false; + } + if (!QFile::remove(filePath + ".signed")) { + qDebug() << "Failed to remove signed."; + return false; + } + return true; +} + + +QTemporaryDir *CreateInstallerDialog::codesignBinaries(const QDir& sourceDir) { + QTemporaryDir* target = new QTemporaryDir(); + /* Copy all files from the source dir to a temporary location */ + mProgress.setLabelText(tr("Signing binaries...")); + + mProgress.show(); + foreach (const QFileInfo& entry, sourceDir.entryInfoList()) { + QString targetPath = target->path() + QString::fromLatin1("/") + entry.fileName(); + if (entry.fileName() == "." || entry.fileName() == "..") { + continue; + } + if (!QFile::copy(entry.absoluteFilePath(), targetPath)) { + qDebug() << "Failed to copy: " << entry.absoluteFilePath() << " to: " << targetPath; + showErrorMessage(tr("Failed to copy binaries to temporary location.")); + mProgress.cancel(); + return NULL; + } + if (entry.suffix() == "exe") { + if (!signFile(targetPath)) { + showErrorMessage(tr("Failed to sign binaries with osslsigncode.\n" + "Please check that %1 is a valid code signing certificate and that" + "osslsigncode can be found in the PATH.").arg(mCertFile->text())); + mProgress.cancel(); + return NULL; + } + } + } + mProgress.cancel(); + return target; +} + FinishedDialog::FinishedDialog(QDialog *parent, QString msg, QString details, bool isErr): QDialog(parent)
--- a/ui/createinstallerdialog.h Wed Jun 25 14:56:19 2014 +0200 +++ b/ui/createinstallerdialog.h Wed Jun 25 15:16:24 2014 +0200 @@ -13,12 +13,14 @@ #include <QLineEdit> #include <QProcess> #include <QProgressDialog> +#include <QDir> /** * @file createinstallerdialog.h * @brief The dialog to show settings and create an installer. */ class QListWidget; +class QTemporaryDir; class CreateInstallerDialog : public QDialog { @@ -38,6 +40,8 @@ QProcess mNSISProc; QProgressDialog mProgress; + QString mInstallerPath; + QTemporaryDir *mCurrentWorkingDir; /** @brief show an error message with QMessageBox * @@ -49,8 +53,44 @@ void openCertificateSelect(); void openFolderSelect(); void openSaveLocation(); + + /**@brief entry point for installer creation + * + * check the selected parameters (certificate / folder etc.) and + * create the nsis installer. This also creates the signatures. */ void createInstaller(); + /**@brief Create tempoary dir with signed binaries from sourcedir + * + * Copies all files from the sourceDir to a temporary directory + * and signs all .exe files in that directory. + * + * The caller needs to delete the temporary directory. If an error + * occurs NULL is returned. + * + * @param[in] sourceDir the directory with the binaries to sign + * @returns a pointer to a temporary dir containing the signed binaries + * or NULL. + */ + QTemporaryDir *codesignBinaries(const QDir& sourceDir); + + /**@brief Sign a file with the codesigning certificate from mCertFile + * + * Calls osslsigncode to sign the file pointed to in filePath. + * The signing operation is logged. + * + * Sign information (hash algo / publisher / url) can be set at + * build time or in the settings with the variables: + * + * sign_hash # the hash algorithm to use. Values are the same as in singtool + * sign_publisher # the publisher information + * sign_url # the product url to use in the signature + * + * @param[in] filePath the absolute path to the file. + * @returns true on success, false on error + */ + bool signFile(QString filePath); + /* Slots for the creator process */ void processError(QProcess::ProcessError error); void processFinished(int exitCode, QProcess::ExitStatus exitStatus);
--- a/ui/helpdialog.h Wed Jun 25 14:56:19 2014 +0200 +++ b/ui/helpdialog.h Wed Jun 25 15:16:24 2014 +0200 @@ -17,6 +17,7 @@ class HelpDialog : public QDialog { + Q_OBJECT public: /** @brief Create a help dialog */ HelpDialog(QMainWindow *parent);
--- a/ui/img/icon.rc Wed Jun 25 14:56:19 2014 +0200 +++ b/ui/img/icon.rc Wed Jun 25 15:16:24 2014 +0200 @@ -1,1 +1,2 @@ +#include "events.rc" IDI_ICON1 ICON DISCARDABLE "icon.ico"
--- a/ui/installwrapper.cpp Wed Jun 25 14:56:19 2014 +0200 +++ b/ui/installwrapper.cpp Wed Jun 25 15:16:24 2014 +0200 @@ -150,20 +150,46 @@ } #else /* WIN32 */ QProcess installerProcess; - installerProcess.setProgram(cinstProcInfo.absoluteFilePath()); QStringList parameters; choicesFile.setAutoRemove(false); parameters << "list=" + mCertListFile << "choices=" + choicesFile.fileName(); - installerProcess.setArguments(parameters); - - qDebug() << "Starting process " << cinstFileName <<" params: " << parameters; - installerProcess.start(); - if (!installerProcess.waitForStarted() || - installerProcess.state() == QProcess::NotRunning) { - emit error (tr("Failed to start installer process.")); - return; + bool sudo_started = false; + bool use_sudo = is_admin(); + if (use_sudo) { + QStringList sudoPrograms; + sudoPrograms << "gksudo" << "kdesudo" << "sudo"; + QStringList sudoParams; + sudoParams << cinstProcInfo.absoluteFilePath() << parameters; + installerProcess.setArguments(sudoParams); + + foreach (const QString &sProg, sudoPrograms) { + installerProcess.setProgram(sProg); + qDebug() << "Starting process " << sProg <<" params: " << sudoParams; + installerProcess.start(); + if (!installerProcess.waitForStarted() || + installerProcess.state() == QProcess::NotRunning) { + continue; + } else { + sudo_started = true; + break; + } + } + } + + /* Fallback to start without sudo */ + if (!use_sudo || !sudo_started) { + installerProcess.setProgram(cinstProcInfo.absoluteFilePath()); + installerProcess.setArguments(parameters); + + qDebug() << "Starting process " << cinstFileName <<" params: " << parameters; + installerProcess.start(); + if (!installerProcess.waitForStarted() || + installerProcess.state() == QProcess::NotRunning) { + emit error (tr("Failed to start installer process.")); + return; + } } installerProcess.waitForFinished();
--- a/ui/l10n/administrator_de_DE.ts Wed Jun 25 14:56:19 2014 +0200 +++ b/ui/l10n/administrator_de_DE.ts Wed Jun 25 15:16:24 2014 +0200 @@ -18,26 +18,26 @@ <translation type="vanished">TrustBridge ist ein sicherer Wurzelzertifikatsinstaller für Windows und Linux.</translation> </message> <message> - <location filename="../aboutdialog.cpp" line="50"/> + <location filename="../aboutdialog.cpp" line="53"/> <source>TrustBridge is a root certificate installer for Windows and Linux.</source> <translation>TrustBridge ist ein Wurzelzertifikatsinstaller für Windows und Linux.</translation> </message> <message> - <location filename="../aboutdialog.cpp" line="52"/> + <location filename="../aboutdialog.cpp" line="58"/> <source>The root certificate lists are managed by the German <a href="https://www.bsi.bund.de">Federal Office for Information Security (BSI)</a>. </source> <translation>Die Liste der Wurzelzertifikate wird vom <a href="https://www.bsi.bund.de">Bundesamt für Sicherheit in der Informationstechnik (BSI)</a> verwaltet.</translation> </message> <message> - <location filename="../aboutdialog.cpp" line="55"/> + <location filename="../aboutdialog.cpp" line="64"/> <source>The software was developed by the companies <a href="http://www.intevation.de">Intevation GmbH</a> and <a href="http://www.dn-systems.de">DN-Systems GmbH</a>, <br> contracted by the German Federal Office for Information Security (BSI). </source> <translation>Die Software wurde entwickelt von den Unternehmen <a href="http://www.intevation.net">Intevation GmbH</a> und <a href="http://www.dn-systems.com">DN-Systems GmbH</a>, <br> beauftragt durch das Bundesamt für Sicherheit in der Informationstechnik (BSI).</translation> </message> <message> - <location filename="../aboutdialog.cpp" line="59"/> + <location filename="../aboutdialog.cpp" line="71"/> <source>TrustBridge is Free Software licensed under GNU GPL v2+. Copyright (C) 2014 by Bundesamt für Sicherheit in der Informationstechnik</source> @@ -46,7 +46,7 @@ Copyright (C) 2014 by Bundesamt für Sicherheit in der Informationstechnik (BSI)</translation> </message> <message> - <location filename="../aboutdialog.cpp" line="73"/> + <location filename="../aboutdialog.cpp" line="88"/> <source>Close</source> <translation>Schließen</translation> </message> @@ -54,78 +54,139 @@ <context> <name>AdministratorWindow</name> <message> - <location filename="../administratorwindow.cpp" line="33"/> - <location filename="../administratorwindow.cpp" line="101"/> + <location filename="../administratorwindow.cpp" line="34"/> + <location filename="../administratorwindow.cpp" line="102"/> <source>TrustBridge Administration</source> <translation>TrustBridge Verwaltung</translation> </message> <message> - <location filename="../administratorwindow.cpp" line="51"/> + <location filename="../administratorwindow.cpp" line="52"/> <source>Menu</source> <translation>Menü</translation> </message> <message> - <location filename="../administratorwindow.cpp" line="53"/> + <location filename="../administratorwindow.cpp" line="54"/> <source>Create installer ...</source> <translation>Installationspaket erstellen ...</translation> </message> <message> - <location filename="../administratorwindow.cpp" line="54"/> + <location filename="../administratorwindow.cpp" line="55"/> <source>About TrustBridge</source> <translation>Über TrustBridge</translation> </message> <message> - <location filename="../administratorwindow.cpp" line="56"/> + <location filename="../administratorwindow.cpp" line="57"/> <source>Quit</source> <translation>Beenden</translation> </message> <message> - <location filename="../administratorwindow.cpp" line="77"/> + <location filename="../administratorwindow.cpp" line="78"/> <source>All managed root certificates of the certificate list: </source> <translatorcomment>The english original should be improved</translatorcomment> <translation>In der Liste enthaltene Zertifikate:</translation> </message> <message> - <location filename="../administratorwindow.cpp" line="143"/> + <location filename="../administratorwindow.cpp" line="144"/> <source>Select certificate list file</source> <translation>Zertifikatsliste auswählen</translation> </message> <message> - <location filename="../administratorwindow.cpp" line="146"/> + <location filename="../administratorwindow.cpp" line="150"/> + <location filename="../administratorwindow.cpp" line="234"/> + <location filename="../administratorwindow.cpp" line="244"/> <source>Error!</source> <translation>Fehler!</translation> </message> <message> - <location filename="../administratorwindow.cpp" line="146"/> + <location filename="../administratorwindow.cpp" line="150"/> <source>Failed to load the certificate list.</source> <translation>Fehler beim Laden der Zertifikatsliste.</translation> </message> <message> + <location filename="../administratorwindow.cpp" line="234"/> + <source>Failed to open log file: </source> + <translation>Fehler beim Öffnen der Log-Datei:</translation> + </message> + <message> + <location filename="../administratorwindow.cpp" line="235"/> + <location filename="../administratorwindow.cpp" line="245"/> + <source> Changes are not logged!</source> + <translation> Änderungen wurden nicht geloggt!</translation> + </message> + <message> + <location filename="../administratorwindow.cpp" line="244"/> + <source>Failed to write log file: </source> + <translation>Fehler beim Schreiben der Log-Datei: </translation> + </message> + <message> + <location filename="../administratorwindow.cpp" line="262"/> + <source> new certificatelist </source> + <translation> neue Zertifikatsliste </translation> + </message> + <message> + <location filename="../administratorwindow.cpp" line="264"/> + <source> based on list from </source> + <translation> basiert auf der Liste vom </translation> + </message> + <message> + <location filename="../administratorwindow.cpp" line="267"/> + <source>signing certificate: +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../administratorwindow.cpp" line="268"/> + <source>new certificates: +</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../administratorwindow.cpp" line="282"/> + <source>certificates marked to remove: +</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>signing certificate: +</source> + <translation type="obsolete">signiertes Zertifikat: </translation> + </message> + <message> + <source>new certificates: +</source> + <translation type="obsolete">neues Zertifikat:</translation> + </message> + <message> + <source>certificates marked to remove: +</source> + <translation type="obsolete">Zertifikate als gelöscht markiert:</translation> + </message> + <message> <source>All managed root certificates of the certificate list:</source> <translation type="vanished">Alle verwalteten Wurzelzertifikate der Zertifikatsliste:</translation> </message> <message> - <location filename="../administratorwindow.cpp" line="103"/> + <location filename="../administratorwindow.cpp" line="104"/> <source>Management application of the BSI certificate installer</source> <translation>Verwaltungsanwendung des BSI-Zertifikatsinstallers</translation> </message> <message> - <location filename="../administratorwindow.cpp" line="113"/> + <location filename="../administratorwindow.cpp" line="114"/> <source>Save list</source> <translation>Liste speichern</translation> </message> <message> - <location filename="../administratorwindow.cpp" line="115"/> + <location filename="../administratorwindow.cpp" line="116"/> <source>Load list</source> <translation>Liste laden</translation> </message> <message> - <location filename="../administratorwindow.cpp" line="117"/> + <location filename="../administratorwindow.cpp" line="118"/> <source>Add certificate</source> <translation>Zertifikat hinzufügen</translation> </message> <message> - <location filename="../administratorwindow.cpp" line="119"/> + <location filename="../administratorwindow.cpp" line="120"/> <source>Remove certificate</source> <translation>Zertifikat entfernen</translation> </message> @@ -134,12 +195,45 @@ <translation type="vanished">Zertifikatslistendatei auswählen</translation> </message> <message> - <location filename="../administratorwindow.cpp" line="163"/> + <location filename="../administratorwindow.cpp" line="171"/> <source>Select certificate</source> <translation>Zertifikat auswählen</translation> </message> </context> <context> + <name>CertificateDiffDialog</name> + <message> + <location filename="../certificatediffdialog.cpp" line="22"/> + <source>TrustBridge - List changes</source> + <translation>TrustBridge - Listenänderungen</translation> + </message> + <message> + <location filename="../certificatediffdialog.cpp" line="33"/> + <source>The following certificates are changed:</source> + <translation>Die folgenden Zertifikate wurden geändert:</translation> + </message> + <message> + <location filename="../certificatediffdialog.cpp" line="41"/> + <source>New</source> + <translation>Neu</translation> + </message> + <message> + <location filename="../certificatediffdialog.cpp" line="41"/> + <source>Remove</source> + <translation>Entfernen</translation> + </message> + <message> + <location filename="../certificatediffdialog.cpp" line="50"/> + <source>Ok</source> + <translation>Ok</translation> + </message> + <message> + <location filename="../certificatediffdialog.cpp" line="51"/> + <source>Cancel</source> + <translation>Abbrechen</translation> + </message> +</context> +<context> <name>CertificateTabelModel</name> <message> <location filename="../certificatetablemodel.cpp" line="16"/> @@ -313,8 +407,8 @@ <context> <name>CreateInstallerDialog</name> <message> - <location filename="../createinstallerdialog.cpp" line="28"/> - <location filename="../createinstallerdialog.cpp" line="53"/> + <location filename="../createinstallerdialog.cpp" line="43"/> + <location filename="../createinstallerdialog.cpp" line="68"/> <source>Create binary installer</source> <translation>Installationspaket erstellen</translation> </message> @@ -331,93 +425,126 @@ <translation type="vanished">Code Signing Zertifikat auswählen (privater Schlüssel):</translation> </message> <message> - <location filename="../createinstallerdialog.cpp" line="55"/> + <location filename="../createinstallerdialog.cpp" line="70"/> <source>Create and sign a TrustBridge binary installer.</source> <translation>Erzeugt und signiert ein TrustBridge-Installationspaket.</translation> </message> <message> - <location filename="../createinstallerdialog.cpp" line="66"/> + <location filename="../createinstallerdialog.cpp" line="81"/> <source>Select binary folder:</source> <translation>Binärverzeichnis auswählen:</translation> </message> <message> - <location filename="../createinstallerdialog.cpp" line="67"/> + <location filename="../createinstallerdialog.cpp" line="82"/> <source>Select code signing certificate:</source> <translation>Code-Signing-Zertifikat auswählen:</translation> </message> <message> - <location filename="../createinstallerdialog.cpp" line="68"/> + <location filename="../createinstallerdialog.cpp" line="83"/> <source>Select output folder:</source> <translation>Ausgabeverzeichnis auswählen:</translation> </message> <message> - <location filename="../createinstallerdialog.cpp" line="97"/> + <location filename="../createinstallerdialog.cpp" line="112"/> <source>Create installer</source> <translation>Installationspaket erzeugen</translation> </message> <message> - <location filename="../createinstallerdialog.cpp" line="99"/> + <location filename="../createinstallerdialog.cpp" line="114"/> <source>Cancel</source> <translation>Abbrechen</translation> </message> <message> - <location filename="../createinstallerdialog.cpp" line="119"/> + <location filename="../createinstallerdialog.cpp" line="208"/> <source>Creating installer package...</source> <translation>Installationspaket wird erstellt...</translation> </message> <message> - <location filename="../createinstallerdialog.cpp" line="131"/> + <location filename="../createinstallerdialog.cpp" line="145"/> <source>Select certificate</source> <translation>Zertifikat auswählen</translation> </message> <message> - <location filename="../createinstallerdialog.cpp" line="142"/> + <location filename="../createinstallerdialog.cpp" line="156"/> <source>Select binary folder</source> <translation>Binärverzeichnis auswählen</translation> </message> <message> - <location filename="../createinstallerdialog.cpp" line="160"/> + <location filename="../createinstallerdialog.cpp" line="174"/> <source>Error!</source> <translation>Fehler!</translation> </message> <message> - <location filename="../createinstallerdialog.cpp" line="165"/> + <location filename="../createinstallerdialog.cpp" line="183"/> <source>Created installer in %1.</source> <translation>Installationspaket erstellt in %1.</translation> </message> <message> - <location filename="../createinstallerdialog.cpp" line="184"/> + <location filename="../createinstallerdialog.cpp" line="186"/> + <source>Signing installer package...</source> + <translation>Installationspaket signieren...</translation> + </message> + <message> + <location filename="../createinstallerdialog.cpp" line="188"/> + <source>Failed to sign installer package.</source> + <translation>Fehler beim Signieren des Installationspakets.</translation> + </message> + <message> + <location filename="../createinstallerdialog.cpp" line="212"/> <source>Please select an existing input folder.</source> <translation>Bitte wählen Sie ein existierendes Eingabeverzeichnis.</translation> </message> <message> - <location filename="../createinstallerdialog.cpp" line="188"/> + <location filename="../createinstallerdialog.cpp" line="216"/> <source>Please select a codesigning certificate.</source> <translation>Bitte wählen Sie ein Code-Signing-Zertifikat.</translation> </message> <message> - <location filename="../createinstallerdialog.cpp" line="192"/> + <location filename="../createinstallerdialog.cpp" line="220"/> <source>Please select a output folder.</source> <translation>Bitte wählen Sie ein Ausgabeverzeichnis.</translation> </message> <message> - <location filename="../createinstallerdialog.cpp" line="199"/> + <location filename="../createinstallerdialog.cpp" line="227"/> <source>Folder %1 does not appear to contain a meta.ini</source> <translation>Das Verzeichnis %1 enthält keine meta.ini Datei</translation> </message> <message> - <location filename="../createinstallerdialog.cpp" line="240"/> + <location filename="../createinstallerdialog.cpp" line="239"/> + <source>Creating NSIS package...</source> + <translation>NSIS-Paket wird erstellt...</translation> + </message> + <message> + <location filename="../createinstallerdialog.cpp" line="279"/> <source>Failed to start makensis. Please ensure that makensis is installed and in your PATH variable.</source> <translation>Fehler beim Starten von makensis. Bitte versichern Sie sich, dass makensis korrekt installiert und in der PATH-Variable enthalten ist.</translation> </message> <message> + <location filename="../createinstallerdialog.cpp" line="335"/> + <source>Signing binaries...</source> + <translation>Binärpakete werden signiert...</translation> + </message> + <message> + <location filename="../createinstallerdialog.cpp" line="345"/> + <source>Failed to copy binaries to temporary location.</source> + <translation>Fehler beim Kopieren der Binärdaten in temporären Ort.</translation> + </message> + <message> + <location filename="../createinstallerdialog.cpp" line="351"/> + <source>Failed to sign binaries with osslsigncode. +Please check that %1 is a valid code signing certificate and thatosslsigncode can be found in the PATH.</source> + <translatorcomment>TODO: missing blank in EN string</translatorcomment> + <translation>Fehler beim Signieren der Binärpakete mit osslsigncode. +Bitte prüfen Sie, dass %1 ein gültiges Code-Signing-Zertifikat ist und osslsigncode im PATH gefunden wird.</translation> + </message> + <message> <source>Select source archive</source> <translation type="vanished">Archiv auswählen</translation> </message> <message> - <location filename="../createinstallerdialog.cpp" line="152"/> + <location filename="../createinstallerdialog.cpp" line="166"/> <source>Select target location</source> <translation>Zielort auswählen</translation> </message> @@ -425,22 +552,22 @@ <context> <name>FinishedDialog</name> <message> - <location filename="../createinstallerdialog.cpp" line="259"/> + <location filename="../createinstallerdialog.cpp" line="377"/> <source>Success!</source> <translation>Erfolgreich!</translation> </message> <message> - <location filename="../createinstallerdialog.cpp" line="263"/> + <location filename="../createinstallerdialog.cpp" line="381"/> <source>Error!</source> <translation>Fehler!</translation> </message> <message> - <location filename="../createinstallerdialog.cpp" line="271"/> + <location filename="../createinstallerdialog.cpp" line="389"/> <source>Details</source> <translation>Details</translation> </message> <message> - <location filename="../createinstallerdialog.cpp" line="275"/> + <location filename="../createinstallerdialog.cpp" line="393"/> <source>OK</source> <translation>OK</translation> </message>
--- a/ui/l10n/trustbridge_de_DE.ts Wed Jun 25 14:56:19 2014 +0200 +++ b/ui/l10n/trustbridge_de_DE.ts Wed Jun 25 15:16:24 2014 +0200 @@ -18,26 +18,26 @@ <translation type="vanished">TrustBridge ist eine sicherer Wurzelzertifikatsinstaller für Windows und Linux.</translation> </message> <message> - <location filename="../aboutdialog.cpp" line="50"/> + <location filename="../aboutdialog.cpp" line="53"/> <source>TrustBridge is a root certificate installer for Windows and Linux.</source> - <translation type="unfinished">TrustBridge ist eine Wurzelzertifikatsinstaller für Windows und Linux.</translation> + <translation>TrustBridge ist eine Wurzelzertifikatsinstaller für Windows und Linux.</translation> </message> <message> - <location filename="../aboutdialog.cpp" line="52"/> + <location filename="../aboutdialog.cpp" line="58"/> <source>The root certificate lists are managed by the German <a href="https://www.bsi.bund.de">Federal Office for Information Security (BSI)</a>. </source> <translation>Die Liste der Wurzelzertifikate wird vom <a href="https://www.bsi.bund.de">Bundesamt für Sicherheit in der Informationstechnik (BSI)</a> verwaltet.</translation> </message> <message> - <location filename="../aboutdialog.cpp" line="55"/> + <location filename="../aboutdialog.cpp" line="64"/> <source>The software was developed by the companies <a href="http://www.intevation.de">Intevation GmbH</a> and <a href="http://www.dn-systems.de">DN-Systems GmbH</a>, <br> contracted by the German Federal Office for Information Security (BSI). </source> <translation>Die Liste der Wurzelzertifikate wird vom <a href="https://www.bsi.bund.de">Bundesamt für Sicherheit in der Informationstechnik (BSI)</a> verwaltet.</translation> </message> <message> - <location filename="../aboutdialog.cpp" line="59"/> + <location filename="../aboutdialog.cpp" line="71"/> <source>TrustBridge is Free Software licensed under GNU GPL v2+. Copyright (C) 2014 by Bundesamt für Sicherheit in der Informationstechnik</source> @@ -46,7 +46,7 @@ Copyright (C) 2014 by Bundesamt für Sicherheit in der Informationstechnik (BSI)</translation> </message> <message> - <location filename="../aboutdialog.cpp" line="73"/> + <location filename="../aboutdialog.cpp" line="88"/> <source>Close</source> <translation>Schließen</translation> </message> @@ -116,7 +116,7 @@ <context> <name>MainWindow</name> <message> - <location filename="../mainwindow.cpp" line="178"/> + <location filename="../mainwindow.cpp" line="228"/> <source>An updated certificate list is available. Click here to install.</source> <translation>Eine aktualisierte Zertifikatsliste ist verfügbar. Klicken Sie hier zum Installieren.</translation> </message> @@ -134,34 +134,34 @@ <translation type="vanished">Möchten Sie die neue Version installieren?</translation> </message> <message> - <location filename="../mainwindow.cpp" line="334"/> + <location filename="../mainwindow.cpp" line="399"/> <source>Check for Updates</source> <translation>Aktualisierungen prüfen</translation> </message> <message> - <location filename="../mainwindow.cpp" line="336"/> - <location filename="../mainwindow.cpp" line="369"/> - <location filename="../mainwindow.cpp" line="449"/> + <location filename="../mainwindow.cpp" line="401"/> + <location filename="../mainwindow.cpp" line="434"/> + <location filename="../mainwindow.cpp" line="514"/> <source>Quit</source> <translation>Beenden</translation> </message> <message> - <location filename="../mainwindow.cpp" line="354"/> + <location filename="../mainwindow.cpp" line="419"/> <source>TrustBridge</source> <translation>TrustBridge</translation> </message> <message> - <location filename="../mainwindow.cpp" line="362"/> + <location filename="../mainwindow.cpp" line="427"/> <source>Menu</source> <translation>Menü</translation> </message> <message> - <location filename="../mainwindow.cpp" line="364"/> + <location filename="../mainwindow.cpp" line="429"/> <source>Force Update</source> <translation>Aktualisierung erzwingen</translation> </message> <message> - <location filename="../mainwindow.cpp" line="425"/> + <location filename="../mainwindow.cpp" line="490"/> <source>Settings</source> <translation>Einstellungen</translation> </message> @@ -170,131 +170,144 @@ <translation type="vanished">Statusdialog</translation> </message> <message> - <location filename="../mainwindow.cpp" line="186"/> - <source><h3>An update for %1 is available.</h3> + <location filename="../mainwindow.cpp" line="236"/> + <source>An update for %1 is available. Click here to download and install the update.</source> - <translation type="unfinished"></translation> + <translation>Eine Aktualisierung für %1 ist verfügbar. +Hier klicken, um Download und Installation zu starten.</translation> </message> <message> - <location filename="../mainwindow.cpp" line="366"/> + <location filename="../mainwindow.cpp" line="431"/> <source>Help</source> <translation>Hilfe</translation> </message> <message> - <location filename="../mainwindow.cpp" line="367"/> + <location filename="../mainwindow.cpp" line="432"/> <source>About</source> <translatorcomment>"TrustBridge" ergänzen</translatorcomment> <translation>Über TrustBridge</translation> </message> <message> - <location filename="../mainwindow.cpp" line="396"/> + <location filename="../mainwindow.cpp" line="461"/> <source>Managed Certificates</source> <translation>Verwaltete Zertifikate</translation> </message> <message> - <location filename="../mainwindow.cpp" line="402"/> - <location filename="../mainwindow.cpp" line="540"/> - <location filename="../mainwindow.cpp" line="570"/> + <location filename="../mainwindow.cpp" line="467"/> + <location filename="../mainwindow.cpp" line="605"/> + <location filename="../mainwindow.cpp" line="635"/> <source>Current List Date: %1</source> <translation>Datum der aktuellen Liste: %1</translation> </message> <message> - <location filename="../mainwindow.cpp" line="426"/> + <location filename="../mainwindow.cpp" line="491"/> <source>Autoupdate</source> <translation>Automatische Aktualisierung</translation> </message> <message> - <location filename="../mainwindow.cpp" line="427"/> + <location filename="../mainwindow.cpp" line="492"/> <source>Autostart</source> <translation>Start der Anwendung bei Systemstart</translation> </message> <message> - <location filename="../mainwindow.cpp" line="445"/> + <location filename="../mainwindow.cpp" line="510"/> <source>Install selected</source> <translation>Jetzt installieren</translation> </message> <message> - <location filename="../mainwindow.cpp" line="466"/> + <location filename="../mainwindow.cpp" line="531"/> <source>Details</source> <translation>Details</translation> </message> <message> - <location filename="../mainwindow.cpp" line="467"/> + <location filename="../mainwindow.cpp" line="532"/> <source>Subject Common Name:</source> <translation>Inhaber CN:</translation> </message> <message> - <location filename="../mainwindow.cpp" line="468"/> + <location filename="../mainwindow.cpp" line="533"/> <source>Subject Organisation:</source> <translation>Inhaber Organisation:</translation> </message> <message> - <location filename="../mainwindow.cpp" line="469"/> + <location filename="../mainwindow.cpp" line="534"/> <source>Issuer Common Name:</source> <translation>Aussteller CN:</translation> </message> <message> - <location filename="../mainwindow.cpp" line="470"/> + <location filename="../mainwindow.cpp" line="535"/> <source>Issuer Organisation:</source> <translation>Aussteller Organisation:</translation> </message> <message> - <location filename="../mainwindow.cpp" line="471"/> + <location filename="../mainwindow.cpp" line="536"/> <source>Valid from:</source> <translation>Gültig ab:</translation> </message> <message> - <location filename="../mainwindow.cpp" line="472"/> + <location filename="../mainwindow.cpp" line="537"/> <source>Valid to:</source> <translation>Gültig bis:</translation> </message> <message> - <location filename="../mainwindow.cpp" line="473"/> + <location filename="../mainwindow.cpp" line="538"/> <source>Fingerprint:</source> <translation>Fingerprint:</translation> </message> <message> - <location filename="../mainwindow.cpp" line="572"/> + <location filename="../mainwindow.cpp" line="637"/> <source>New List Date: %1</source> <translation>Datum der neuen Liste: %1</translation> </message> <message> - <location filename="../mainwindow.cpp" line="577"/> + <location filename="../mainwindow.cpp" line="642"/> <source>New certificates to install</source> <translation>Neu zu installierende Zertifikate</translation> </message> <message> - <location filename="../mainwindow.cpp" line="584"/> + <location filename="../mainwindow.cpp" line="649"/> <source>New certificates to remove</source> <translation>Neu zu löschende Zertifikate</translation> </message> <message> - <location filename="../mainwindow.cpp" line="591"/> + <location filename="../mainwindow.cpp" line="656"/> <source>Old certificates to install</source> <translation>Bisher installierte Zertifikate</translation> </message> <message> - <location filename="../mainwindow.cpp" line="598"/> + <location filename="../mainwindow.cpp" line="663"/> <source>Old certificates to remove</source> <translation>Bisher gelöschte Zertifikate</translation> </message> <message> - <location filename="../mainwindow.cpp" line="673"/> + <location filename="../mainwindow.cpp" line="738"/> <source>Error executing update</source> <translation>Fehler bei der Aktualisierung</translation> </message> <message> - <location filename="../mainwindow.cpp" line="718"/> + <location filename="../mainwindow.cpp" line="783"/> <source>Installing certificates...</source> <translation>Zertifikate werden installiert...</translation> </message> </context> <context> + <name>ProcessWaitDialog</name> + <message> + <location filename="../processwaitdialog.cpp" line="23"/> + <source>Applications need to be closed.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../processwaitdialog.cpp" line="26"/> + <source>Close all running firefox and thunderbird instances to continue installation!</source> + <translation type="unfinished"></translation> + </message> +</context> +<context> <name>QObject</name> <message> - <location filename="../main.cpp" line="72"/> <source>Couldn't detect any system tray on this system. This software can only be used in a desktop environment.</source> - <translation>Es konnte kein SystemTray auf diesem System gefunden werden. Diese Software kann nur in einer Desktopumgebung verwendet werden.</translation> + <translation type="vanished">Es konnte kein SystemTray auf diesem System gefunden werden. Diese Software kann nur in einer Desktopumgebung verwendet werden.</translation> </message> </context> <context>
--- a/ui/main.cpp Wed Jun 25 14:56:19 2014 +0200 +++ b/ui/main.cpp Wed Jun 25 15:16:24 2014 +0200 @@ -6,6 +6,9 @@ * See LICENSE.txt for details. */ #include "mainwindow.h" +#include "processhelp.h" +#include "logging.h" +#include "selftest.h" #include <QApplication> #include <QSystemTrayIcon> @@ -35,6 +38,14 @@ int main(int argc, char **argv) { + /* First verify integrity even before calling QApplication*/ + if (!selftest()) { + syslog_error_printf ("Integrity check failed."); +#ifdef RELEASE_BUILD + return -1; +#endif + } + QApplication app (argc, argv); QApplication::setQuitOnLastWindowClosed(false); @@ -55,6 +66,12 @@ return 0; } + if (ProcessHelp::otherProcessesExist(APPNAME)) { + qDebug() << "Another " << APPNAME << " process is already running. Exiting."; + ProcessHelp::activateWindowForProcess(APPNAME); + return 0; + } + QTranslator translator; if (QLocale::system().name() == "C") { /* Useful for testing / development as the primary target is german */
--- a/ui/mainwindow.cpp Wed Jun 25 14:56:19 2014 +0200 +++ b/ui/mainwindow.cpp Wed Jun 25 15:16:24 2014 +0200 @@ -29,6 +29,19 @@ #include <QButtonGroup> #include <QToolButton> +#include "certificatelist.h" +#include "downloader.h" +#include "helpdialog.h" +#include "aboutdialog.h" +#include "certificateitemdelegate.h" +#include "separatoritemdelegate.h" +#include "installwrapper.h" +#include "util.h" +#include "logging.h" +#include "binverify.h" +#include "processhelp.h" +#include "processwaitdialog.h" + // The amount of time in minutes stay silent if we have // something to say #define NAG_INTERVAL_MINUTES 70 @@ -38,23 +51,24 @@ #endif #define SERVER_URL "https://files.intevation.de:443" -#define LIST_RESOURCE "/users/aheinecke/zertifikatsliste.txt" -#define SW_RESOURCE "/users/aheinecke/TrustBridge.exe" -#ifdef Q_OS_WIN -#define SW_RESOURCE_VERSION "/users/aheinecke/TrustBridge-%1.exe" -#else -#define SW_RESOURCE_VERSION "/users/aheinecke/TrustBridge-%1.sh" -#endif -#include "certificatelist.h" -#include "downloader.h" -#include "helpdialog.h" -#include "aboutdialog.h" -#include "certificateitemdelegate.h" -#include "separatoritemdelegate.h" -#include "installwrapper.h" -#include "util.h" -#include "logging.h" +#ifdef RELEASE_BUILD +# define LIST_RESOURCE "/users/aheinecke/zertifikatsliste.txt" +# define SW_RESOURCE "/users/aheinecke/TrustBridge.exe" +# ifdef Q_OS_WIN +# define SW_RESOURCE_VERSION "/users/aheinecke/TrustBridge-%1.exe" +# else +# define SW_RESOURCE_VERSION "/users/aheinecke/TrustBridge-%1.sh" +# endif +#else // RELEASE_BUILD +# define LIST_RESOURCE "/users/aheinecke/development/zertifikatsliste.txt" +# define SW_RESOURCE "/users/aheinecke/development/TrustBridge.exe" +# ifdef Q_OS_WIN +# define SW_RESOURCE_VERSION "/users/aheinecke/development/TrustBridge-development.exe" +# else +# define SW_RESOURCE_VERSION "/users/aheinecke/development/TrustBridge-development.sh" +# endif +#endif MainWindow::MainWindow(bool trayMode): mTrayMode(trayMode) @@ -103,26 +117,34 @@ } if (mCurState == NewSoftwareAvailable) { - checkUpdates(true); - mCurState = DownloadingSW; + verifySWData(); + QString swFileName = mSettings.value("Software/available").toString(); + if (swFileName.isEmpty()) { + checkUpdates(true); + mCurState = DownloadingSW; + return; + } + installNewSW(swFileName, + mSettings.value("Software/availableDate").toDateTime()); } } void MainWindow::showMessage() { - if (!isVisible() && !mCurMessage.isEmpty()) { + if (mCurMessage.isEmpty()) { + return; + } + if (mCurState == NewSoftwareAvailable || !isVisible()) { mTrayIcon->showMessage(QApplication::applicationName(), mCurMessage, - QSystemTrayIcon::Information, 5000); + QSystemTrayIcon::Information, 10000); mMessageTimer->start(); // Restart the timer so that we don't spam } } -void MainWindow::verifyAvailableData() +void MainWindow::verifyListData() { QString availableFileName = mSettings.value("List/available").toString(); QString installedFileName = mSettings.value("List/installed").toString(); - QString swFileName = mSettings.value("Software/available").toString(); - if (!availableFileName.isEmpty()) { mListToInstall.readList(availableFileName.toLocal8Bit().constData()); if (!mListToInstall.isValid()) { @@ -154,12 +176,40 @@ mSettings.remove("List/installed"); mSettings.remove("List/installedDate"); } +} - if (!swFileName.isEmpty()) { - // TODO Verify integrity of the software - } else { +void MainWindow::verifySWData() +{ + QString swFileName = mSettings.value("Software/available").toString(); + + if (swFileName.isEmpty()) { + mSettings.remove("Software/availableDate"); + return; + } + + QFileInfo fi(swFileName); + if (!fi.exists()) { mSettings.remove("Software/available"); mSettings.remove("Software/availableDate"); + qDebug() << "Software does not yet exist."; + return; + } + if (!fi.isExecutable()) { + qWarning() << "Downloaded file: " << swFileName << " is not executable."; + QFile::remove(swFileName); + mSettings.remove("Software/available"); + mSettings.remove("Software/availableDate"); + return; + } + bin_verify_result verifyResult = verify_binary(swFileName.toUtf8().constData(), + swFileName.toUtf8().size()); + qDebug() << "Binary verify result: " << verifyResult; + if (verifyResult != VerifyValid) { + qDebug() << "Failed to verify downloaded data."; + QFile::remove(swFileName); + mSettings.remove("Software/available"); + mSettings.remove("Software/availableDate"); + return; } } @@ -168,7 +218,7 @@ mSettings.setValue("List/available", fileName); mSettings.setValue("List/availableDate", modDate); - verifyAvailableData(); + verifyListData(); if (!mListToInstall.isValid()) { /* Downloader provided invalid files */ /* TODO: Error count. Error handling. Otherwise @@ -198,20 +248,29 @@ void MainWindow::installNewSW(const QString& fileName, const QDateTime& modDate) { QFileInfo instProcInfo = QFileInfo(fileName); - if (!instProcInfo.isExecutable()) { - qWarning() << "Downloaded file: " << fileName << " is not executable."; - setState(TransferError); + QString filePath = QDir::toNativeSeparators(instProcInfo.absoluteFilePath()); + + if (verify_binary(filePath.toUtf8().constData(), + filePath.toUtf8().size()) != VerifyValid) { + qDebug() << "Invalid software. Not installing"; return; - } - QString filePath = QDir::toNativeSeparators(instProcInfo.absoluteFilePath()); + } + QFileInfo fi(QCoreApplication::applicationFilePath()); + QDir installDir = fi.absoluteDir(); + #ifdef WIN32 + QString parameters = QString::fromLatin1("/S /UPDATE=1 /D=") + + installDir.path().replace("/", "\\") + ""; + SHELLEXECUTEINFOW shExecInfo; memset (&shExecInfo, 0, sizeof(SHELLEXECUTEINFOW)); shExecInfo.cbSize = sizeof(SHELLEXECUTEINFOW); shExecInfo.lpFile = reinterpret_cast<LPCWSTR> (filePath.utf16()); + shExecInfo.lpParameters = reinterpret_cast<LPCWSTR> (parameters.utf16()); - shExecInfo.fMask = SEE_MASK_NOASYNC; + // shExecInfo.fMask = SEE_MASK_NOASYNC; + shExecInfo.nShow = SW_SHOWDEFAULT; if (!is_admin()) { shExecInfo.lpVerb = L"open"; @@ -219,7 +278,8 @@ shExecInfo.lpVerb = L"runas"; } - qDebug() << "Starting process: " << filePath; + qDebug() << "Starting process: " << filePath + << " with arguments: " << parameters; if (!ShellExecuteExW(&shExecInfo)) { /* Execution failed, maybe the user aborted the UAC check? */ @@ -231,9 +291,13 @@ return; } #else /* WIN32 */ - qDebug() << "Starting process " << filePath; + QStringList parameters; + parameters << "/S" << "/UPDATE=1" + << QString::fromLatin1("/D=%1").arg(installDir.path()); - if (!QProcess::startDetached(filePath)) { + qDebug() << "Starting process " << filePath << " args: " << parameters; + + if (!QProcess::startDetached(filePath, parameters)) { qDebug() << "Failed to start process."; return; } @@ -245,7 +309,7 @@ void MainWindow::checkUpdates(bool downloadSW) { - verifyAvailableData(); + verifyListData(); if (!mSettings.contains("Software/installedDate") || mSettings.value("Software/installedVersion").toString() != QApplication::applicationVersion()) { @@ -495,7 +559,7 @@ installButton->setIcon(QIcon(":/img/edit-redo.png")); #endif connect(quitButton, SIGNAL(clicked()), this, SLOT(closeApp())); - connect(installButton, SIGNAL(clicked()), this, SLOT(installCerts())); + connect(installButton, SIGNAL(clicked()), this, SLOT(checkAndInstallCerts())); connect(searchUpdates, SIGNAL(clicked()), this, SLOT(checkUpdates())); updatesHeaderActionLayout->addWidget(installButton); @@ -980,9 +1044,32 @@ qApp->quit(); } +void MainWindow::checkAndInstallCerts() +{ + /* Checking before opening the dialog should be cheaper */ + QList<int> pids = ProcessHelp::getProcessesIdForName("firefox"); + pids.append(ProcessHelp::getProcessesIdForName("thunderbird")); + + if (pids.isEmpty()) { + installCerts(); + return; + } + + QStringList pNames; + pNames << "firefox" << "thunderbird"; + + ProcessWaitDialog *waitDialog = new ProcessWaitDialog(this, pNames); + + connect(waitDialog, SIGNAL(accepted()), this, SLOT(installCerts())); + connect(waitDialog, SIGNAL(accepted()), waitDialog, SLOT(deleteLater())); + + waitDialog->exec(); + return; +} + void MainWindow::togglePages(int button) { - mUpdatesPanel->hide(); + UpdatesPanel->hide(); mInstallPanel->hide(); mRemovePanel->hide(); mInfoPanel->hide(); @@ -1037,3 +1124,4 @@ mUpdatesWidget->resize(old.width(), old.height() - mUpdatesManual->height()); } } +>>>>>>> other
--- a/ui/mainwindow.h Wed Jun 25 14:56:19 2014 +0200 +++ b/ui/mainwindow.h Wed Jun 25 15:16:24 2014 +0200 @@ -83,6 +83,13 @@ void toggleUpdatesManual(); void listChanged(int selected); + /** @brief check for running software that needs to close before installing + * + * This function calls installCerts if no software is running otherwise + * it informs the user about the software that still needs to be closed. + */ + void checkAndInstallCerts(); + /** @brief get the last modified date on the download server for * the current version. * @@ -136,15 +143,25 @@ void installNewSW(const QString& fileName, const QDateTime& modDate); private: - /** @brief check the integrity of available files. + /** @brief check the integrity of available certificate lists. * - * Do not use this as a trust check as this only works on + * Note: Do not use this as a local trust check as this only works on * FileNames where the underlying files can change. This * is just meant to check if the downloaded data was somehow * removed or corrupted. It also initializes mListToInstall * and mInstalledList. */ - void verifyAvailableData(); + void verifyListData(); + + /** @brief check the integrity of available software updates. + * + * Note: Do not use this as a local trust check as this only works on + * FileNames where the underlying files can change. This + * is just meant to check if the downloaded data was somehow + * removed or corrupted. + */ + void verifySWData(); + void createTrayIcon(); void createActions(); void createContent();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ui/processhelp.h Wed Jun 25 15:16:24 2014 +0200 @@ -0,0 +1,49 @@ +/* Copyright (C) 2014 by Bundesamt für Sicherheit in der Informationstechnik + * Software engineering by Intevation GmbH + * + * This file is Free Software under the GNU GPL (v>=2) + * and comes with ABSOLUTELY NO WARRANTY! + * See LICENSE.txt for details. + * + * Parts of this code (especially windows) are based on kpimutils processes.cpp + * available under LGPL 2.1 or later. + */ +#ifndef PROCESSHELP_H +#define PROCESSHELP_H + +#include <QList> +#include <QString> + +/** + * @file Static helper functions for process handling + * @brief process handling functions + */ + +namespace ProcessHelp +{ +/** +* @brief look up process id's for a processName +* +* Looks up processes run by the current user. +* +* @param[in] processName the name of the process to look for +* @returns a list of pids that match this process. May be empty +*/ +const QList<int> getProcessesIdForName(const QString &processName); + +/** +* @brief check if another process with the same name exists +* +* @param[in] processName name of the process to look for. +* +* @returns true if one or more processes (other than the current process) exist +*/ +bool otherProcessesExist(const QString &processName); + +/** +* @brief Activates the window for first found process +* @param [in] executableName executableName (without path and .exe extension) +*/ +void activateWindowForProcess(const QString &executableName); +} +#endif // PROCESSHELP_H
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ui/processhelp_linux.cpp Wed Jun 25 15:16:24 2014 +0200 @@ -0,0 +1,30 @@ +/* Copyright (C) 2014 by Bundesamt für Sicherheit in der Informationstechnik + * Software engineering by Intevation GmbH + * + * This file is Free Software under the GNU GPL (v>=2) + * and comes with ABSOLUTELY NO WARRANTY! + * See LICENSE.txt for details. + */ +#ifndef WIN32 + +#include "processhelp.h" + +const QList<int> ProcessHelp::getProcessesIdForName(const QString &processName) { + // TODO + Q_UNUSED(processName); + return QList<int>(); +} + +bool ProcessHelp::otherProcessesExist(const QString &processName) { + // TODO + Q_UNUSED(processName); + return false; +} + +void ProcessHelp::activateWindowForProcess(const QString &executableName) { + // TODO + Q_UNUSED(executableName); + return; +} + +#endif /* Not WIN32 */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ui/processhelp_win.cpp Wed Jun 25 15:16:24 2014 +0200 @@ -0,0 +1,171 @@ +/* Copyright (C) 2014 by Bundesamt für Sicherheit in der Informationstechnik + * Software engineering by Intevation GmbH + * + * This file is Free Software under the GNU GPL (v>=2) + * and comes with ABSOLUTELY NO WARRANTY! + * See LICENSE.txt for details. */ + +#ifdef WIN32 +#include "processhelp.h" +#include "strhelp.h" + +#include <windows.h> +#include <tlhelp32.h> +#include <psapi.h> +#include <unistd.h> + +#include <QDebug> + +struct EnumWindowsStruct { + EnumWindowsStruct() : windowId(0) {} + DWORD pid; + HWND windowId; +}; + +PSID copySid(PSID from) +{ + if (!from) { + return 0; + } + + int sidLength = GetLengthSid(from); + PSID to = (PSID) xmalloc(sidLength); + CopySid(sidLength, to, from); + return to; +} + +static PSID getProcessOwner(HANDLE hProcess) +{ + HANDLE hToken = NULL; + PSID sid; + + OpenProcessToken(hProcess, TOKEN_READ, &hToken); + if (hToken) { + DWORD size; + PTOKEN_USER userStruct; + + // check how much space is needed + GetTokenInformation(hToken, TokenUser, NULL, 0, &size); + if (ERROR_INSUFFICIENT_BUFFER == GetLastError()) { + userStruct = reinterpret_cast<PTOKEN_USER>(new BYTE[size]); + GetTokenInformation(hToken, TokenUser, userStruct, size, &size); + + sid = copySid(userStruct->User.Sid); + CloseHandle(hToken); + delete [] userStruct; + return sid; + } + } + return 0; +} + +BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam) +{ + if (GetWindowLong(hwnd, GWL_STYLE) & WS_VISIBLE) { + + DWORD pidwin; + + GetWindowThreadProcessId(hwnd, &pidwin); + if (pidwin == ((EnumWindowsStruct *)lParam)->pid) { + ((EnumWindowsStruct *)lParam)->windowId = hwnd; + return FALSE; + } + } + return TRUE; +} + + +static HANDLE getProcessHandle(int processID) +{ + return OpenProcess(SYNCHRONIZE | + PROCESS_QUERY_INFORMATION | + PROCESS_VM_READ | + PROCESS_TERMINATE, + false, processID); +} + +const QList<int> ProcessHelp::getProcessesIdForName(const QString &processName) +{ + HANDLE h; + PROCESSENTRY32 pe32; + QList <int> pids; + + h = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); + if (h == INVALID_HANDLE_VALUE) { + return pids; + } + + pe32.dwSize = sizeof(PROCESSENTRY32); // Necessary according to MSDN + if (!Process32First(h, &pe32)) { + return pids; + } + + pids.clear(); + + const QString processNameLower = processName.toLower().replace(".exe", ""); + const QString processNameExe = processNameLower + ".exe"; + + do { + const QString exeFile = QString::fromWCharArray(pe32.szExeFile).toLower(); + if (exeFile == processNameLower || exeFile == processNameExe) { + PSID user_sid = getProcessOwner(GetCurrentProcess()); + if (user_sid) { + // Also check that we are the owner of that process + HANDLE hProcess = getProcessHandle(pe32.th32ProcessID); + if (!hProcess) { + continue; + } + + PSID sid = getProcessOwner(hProcess); + PSID userSid = getProcessOwner(GetCurrentProcess()); + if (!sid || (userSid && !EqualSid(userSid, sid))) { + free(sid); + continue; + } + } + pids.append((int)pe32.th32ProcessID); + qDebug() << "found PID: " << (int)pe32.th32ProcessID; + } + } while (Process32Next(h, &pe32)); + CloseHandle(h); + return pids; +} + +bool ProcessHelp::otherProcessesExist(const QString &processName) +{ + const QList<int> pids = getProcessesIdForName(processName); + int myPid = getpid(); + foreach(int pid, pids) { + if (myPid != pid) { + qDebug() << "Found another process with id: " << pid; + return true; + } + } + return false; +} + +void ProcessHelp::activateWindowForProcess(const QString &executableName) +{ + const QList<int> pids = getProcessesIdForName(executableName); + int myPid = getpid(); + int foundPid = 0; + foreach(int pid, pids) { + if (myPid != pid) { + qDebug() << "activateWindowForProcess(): PID to activate:" << pid; + foundPid = pid; + break; + } + } + if (foundPid == 0) { + return; + } + EnumWindowsStruct winStruct; + winStruct.pid = foundPid; + EnumWindows(EnumWindowsProc, (LPARAM)&winStruct); + if (winStruct.windowId == 0) { + return; + } + SetForegroundWindow(winStruct.windowId); +} +#endif // WIN32 +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ui/processwaitdialog.cpp Wed Jun 25 15:16:24 2014 +0200 @@ -0,0 +1,56 @@ +/* Copyright (C) 2014 by Bundesamt für Sicherheit in der Informationstechnik + * Software engineering by Intevation GmbH + * + * This file is Free Software under the GNU GPL (v>=2) + * and comes with ABSOLUTELY NO WARRANTY! + * See LICENSE.txt for details. + */ +#include <QHBoxLayout> +#include <QListWidget> +#include <QTimer> +#include <QList> +#include <QLabel> +#include <QApplication> + +#include "processwaitdialog.h" +#include "processhelp.h" + +ProcessWaitDialog::ProcessWaitDialog(QWidget *parent, const QStringList& processNames) : + QDialog(parent), + mProcessNames(processNames) { + QHBoxLayout *theLayout = new QHBoxLayout(this); + + setWindowTitle(tr("Applications need to be closed.")); + setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint); + + QLabel *warnLabel = new QLabel(tr("Close all running firefox and thunderbird instances to continue installation!")); + QLabel *warnIcon = new QLabel(); + warnIcon->setPixmap(QApplication::style()->standardPixmap(QStyle::SP_MessageBoxWarning)); + + theLayout->addWidget(warnIcon); + theLayout->addWidget(warnLabel); + + theLayout->setSizeConstraint(QLayout::SetFixedSize); + // mProcessList = new QListWidget(); +// theLayout->addWidget(mProcessList); + updateProcesses(); +} + +void ProcessWaitDialog::updateProcesses() { + QList<int> pids; + foreach (const QString& pName, mProcessNames) { + pids.append(ProcessHelp::getProcessesIdForName(pName)); + } + if (pids.isEmpty()) { + accept(); + return; + } + + /* mProcessList->clear(); + + foreach (int pId, pids) { + mProcessList->addItem(QString::fromLatin1("Pid ") + pId); + } +*/ + QTimer::singleShot(500, this, SLOT(updateProcesses())); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ui/processwaitdialog.h Wed Jun 25 15:16:24 2014 +0200 @@ -0,0 +1,45 @@ +/* Copyright (C) 2014 by Bundesamt für Sicherheit in der Informationstechnik + * Software engineering by Intevation GmbH + * + * This file is Free Software under the GNU GPL (v>=2) + * and comes with ABSOLUTELY NO WARRANTY! + * See LICENSE.txt for details. */ +#ifndef PROCESSWAITDIALOG_H +#define PROCESSWAITDIALOG_H + +#include <QDialog> +#include <QStringList> + +/** @file Dialog to show that some processes need to be closed + * + * This dialog informs about processes that are still running and + * need to be closed. + */ + +class ProcessWaitDialog : public QDialog +{ + Q_OBJECT + +public: + /** @brief create the dialog + * + * The dialog is modal and will stay open until no more processes + * with names from processnames exist. + * + * @param[in] parent the parent dialog + * @param[in] processNames the names of the processes to wait for. + */ + ProcessWaitDialog(QWidget *parent, const QStringList& processNames); + +private slots: + + /** @brief update the process list */ + void updateProcesses(); + +private: + + QListWidget *mProcessList; + const QStringList mProcessNames; +}; + +#endif // PROCESSWAITDIALOG_H
--- a/ui/sslconnection.cpp Wed Jun 25 14:56:19 2014 +0200 +++ b/ui/sslconnection.cpp Wed Jun 25 15:16:24 2014 +0200 @@ -31,6 +31,7 @@ mPinnedCert(certificate), mInitialized(false), mConnected(false), + mNeedsReset(false), mServerFD(-1), mErrorState(NoError) {
--- a/ui/tests/CMakeLists.txt Wed Jun 25 14:56:19 2014 +0200 +++ b/ui/tests/CMakeLists.txt Wed Jun 25 15:16:24 2014 +0200 @@ -15,13 +15,18 @@ find_package(Qt5Test) include_directories(${Qt5Test_INCLUDE_DIRS}) find_program(HIAWATHA_EXECUTABLE hiawatha) +find_program(OSSLSIGNCODE_EXECUTABLE osslsigncode) if (NOT HIAWATHA_EXECUTABLE) - message (STATUS "WARNING: hiawatha webserver not found. Downloader tests will fail.") + message (STATUS "WARNING: hiawatha webserver not found. Downloader will not be run.") else() add_definitions(-DHIAWATHA_EXECUTABLE="${HIAWATHA_EXECUTABLE}") endif() +if (WIN32 AND NOT OSSLSIGNCODE_EXECUTABLE) + message (STATUS "WARNING: osslsigncode not found. Authenticode tests will not be run.") +endif() + macro(add_custom_test _source _additional_sources) set(_test ${_source}) get_filename_component(_name ${_source} NAME_WE) @@ -65,7 +70,46 @@ if (WIN32) add_custom_test(windowsstoretest.cpp "${CMAKE_SOURCE_DIR}/cinst/windowsstore.c") -endif (WIN32) + + if (OSSLSIGNCODE_EXECUTABLE) + add_custom_test (binverifytest.cpp "") + add_custom_command( + TARGET binverifytest + POST_BUILD + COMMAND ${OSSLSIGNCODE_EXECUTABLE} sign -certs ${CMAKE_CURRENT_SOURCE_DIR}/data/codesign/codesigning.pem + -key ${CMAKE_CURRENT_SOURCE_DIR}/data/codesign/codesigning.key + -h sha256 -in ${CMAKE_CURRENT_BINARY_DIR}/fakeinst.exe + -out ${CMAKE_CURRENT_BINARY_DIR}/fakeinst-signed.exe + ) + add_custom_command( + TARGET binverifytest + POST_BUILD + COMMAND ${OSSLSIGNCODE_EXECUTABLE} sign -certs ${CMAKE_CURRENT_SOURCE_DIR}/data/codesign/codesigning.pem + -key ${CMAKE_CURRENT_SOURCE_DIR}/data/codesign/codesigning-other.key + -h sha256 -in ${CMAKE_CURRENT_BINARY_DIR}/fakeinst.exe + -out ${CMAKE_CURRENT_BINARY_DIR}/fakeinst-other-key.exe + ) + add_custom_command( + TARGET binverifytest + POST_BUILD + COMMAND ${OSSLSIGNCODE_EXECUTABLE} sign -certs ${CMAKE_CURRENT_SOURCE_DIR}/data/codesign/codesigning-other.pem + -key ${CMAKE_CURRENT_SOURCE_DIR}/data/codesign/codesigning-other.key + -h sha256 -in ${CMAKE_CURRENT_BINARY_DIR}/fakeinst.exe + -out ${CMAKE_CURRENT_BINARY_DIR}/fakeinst-other-cert.exe + ) + add_custom_command( + TARGET binverifytest + POST_BUILD + COMMAND ${OSSLSIGNCODE_EXECUTABLE} sign -certs ${CMAKE_CURRENT_SOURCE_DIR}/data/codesign/codesigning.pem + -key ${CMAKE_CURRENT_SOURCE_DIR}/data/codesign/codesigning.key + -h sha256 -in ${CMAKE_CURRENT_BINARY_DIR}/fakeinst.exe + -out ${CMAKE_CURRENT_BINARY_DIR}/fakeinst-invalid.exe && + ${CMAKE_STRIP} ${CMAKE_CURRENT_BINARY_DIR}/fakeinst-invalid.exe + ) + endif() +else () + add_custom_test (binverifytest.cpp "") +endif () if (NSS_FOUND) include_directories(${NSS_INCLUDE_DIRS}) @@ -99,7 +143,7 @@ RESULT_VARIABLE result ERROR_VARIABLE output) if (NOT ${result} EQUAL 0) - message(FATAL_ERROR "Could not create symbolic link for: ${target} --> ${output}") + message(STATUS "Could not create symbolic link for: ${target} --> ${output}. NSS Test might fail.") endif() endif() endif()
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ui/tests/binverifytest.cpp Wed Jun 25 15:16:24 2014 +0200 @@ -0,0 +1,71 @@ +/* Copyright (C) 2014 by Bundesamt für Sicherheit in der Informationstechnik + * Software engineering by Intevation GmbH + * + * This file is Free Software under the GNU GPL (v>=2) + * and comes with ABSOLUTELY NO WARRANTY! + * See LICENSE.txt for details. + */ +#include "binverify.h" +#include "binverifytest.h" + +#include <QTest> + +#ifdef Q_OS_WIN +# define EXE_SUFFIX ".exe" +#else +# define EXE_SUFFIX "" +#endif + +/* Some general robustness checks */ +void BinVerifyTest::testMiscErrors() +{ + QVERIFY (verify_binary (NULL, 10) != VerifyValid); + QVERIFY (verify_binary ("foo", 10) != VerifyValid); + QVERIFY (verify_binary ("bar", -1) != VerifyValid); + /* On windows the next line will check that a valid microsoft + * signed executable is not valid for us (pinning). On linux + * it will just fail with a read error which we tested above */ +#ifdef Q_OS_WIN + QVERIFY (verify_binary ("c:\\Windows\\System32\\mmc.exe", + strlen("c:\\Windows\\System32\\mmc.exe")) != VerifyInvalidCertificate); +#endif + QVERIFY (verify_binary ("/dev/null", strlen("/dev/null")) != VerifyValid); +} + +/* Check that a signature with only a different key (of the same size) + * is not validated (Invalid signature because key and cert don't match)*/ +void BinVerifyTest::testOtherKey() +{ + QVERIFY(VerifyInvalidSignature == verify_binary ("fakeinst-other-key" EXE_SUFFIX, + strlen("fakeinst-other-key" EXE_SUFFIX))); +} + +/* Check that an invalid signature is not validated */ +void BinVerifyTest::testInvalidSig() +{ + QVERIFY(VerifyValid != verify_binary ("fakeinst-invalid" EXE_SUFFIX, + strlen("fakeinst-invalid" EXE_SUFFIX))); +} + +/* Check that a signature with a different (valid) certificate is not validated */ +void BinVerifyTest::testOtherCert() +{ + QVERIFY(VerifyInvalidCertificate == verify_binary ("fakeinst-other-cert" EXE_SUFFIX, + strlen("fakeinst-other-cert" EXE_SUFFIX))); +} + +/* Check that no signature is not validated */ +void BinVerifyTest::testNoSignature() +{ + QVERIFY(VerifyValid != verify_binary ("fakeinst" EXE_SUFFIX, + strlen("fakeinst" EXE_SUFFIX))); +} + +/* Check that a valid signed executable is verified */ +void BinVerifyTest::testValidBinary() +{ + QVERIFY (VerifyValid == verify_binary ("fakeinst-signed" EXE_SUFFIX, + strlen("fakeinst-signed" EXE_SUFFIX))); +} + +QTEST_GUILESS_MAIN (BinVerifyTest);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ui/tests/binverifytest.h Wed Jun 25 15:16:24 2014 +0200 @@ -0,0 +1,26 @@ +/* Copyright (C) 2014 by Bundesamt für Sicherheit in der Informationstechnik + * Software engineering by Intevation GmbH + * + * This file is Free Software under the GNU GPL (v>=2) + * and comes with ABSOLUTELY NO WARRANTY! + * See LICENSE.txt for details. + */ +#ifndef COMMONTEST_H +#define COMMONTEST_H + +#include <QObject> + +class BinVerifyTest: public QObject +{ + Q_OBJECT + +private Q_SLOTS: + void testNoSignature(); + void testMiscErrors(); + void testValidBinary(); + void testOtherKey(); + void testOtherCert(); + void testInvalidSig(); +}; +#endif +
--- a/ui/tests/data/NOTES Wed Jun 25 14:56:19 2014 +0200 +++ b/ui/tests/data/NOTES Wed Jun 25 15:16:24 2014 +0200 @@ -87,3 +87,46 @@ mkdir nss certutil -d nss -A -i valid_ssl_rsa.pem -n "test" -t c,C certutil -d nss -D -n "test" + +# Code signing +mkdir codesign +cd codesign +# Root CA +gen_key filename=codesigning_root.key +cert_write issuer_name="CN=Public TrustBridge Test,O=Public secret do not trust this,C=DE" \ +selfsign=1 issuer_key=codesigning_root.key \ +not_before=20130101000000 not_after=20151231235959 \ +is_ca=1 max_pathlen=0 output_file=codesigning_root.pem + +# Codesign cert +gen_key filename=codesigning.key +cert_req filename=codesigning.key output_file=codesigning.csr \ +subject_name="CN=Public TrustBridge codesigning test,O=Public secret do not trust this,C=DE" \ +key_usage=digital_signature \ +ns_cert_type=object_signing + +# Sign it: +cert_write request_file=codesigning.csr issuer_crt=codesigning_root.pem \ +issuer_key=codesigning_root.key output_file=codesigning.pem \ +not_before=20130101000000 not_after=20151231235959 \ +key_usage=digital_signature \ +ns_cert_type=object_signing + +osslsigncode sign -certs codesigning.pem -key codesigning.key \ + -n "TrustBridgeTest" -i https://wald.intevation.org/projects/trustbridge/ \ + -h sha256 \ + -in ~/ubuntu/src/m13-repo/build-windows/TrustBridge-0.6+21-aee3eb10bbba.exe \ + -out TrustBridge-0.6+21-aee3eb10bbba-signed.exe + +# Different test certificates. +gen_key filename=codesigning-other.key +cert_req filename=codesigning-other.key output_file=codesigning-other.csr \ +subject_name="CN=Public TrustBridge codesigning test,O=Public secret do not trust this,C=DE" \ +key_usage=digital_signature \ +ns_cert_type=object_signing + +cert_write request_file=codesigning-other.csr issuer_crt=codesigning_root.pem \ +issuer_key=codesigning_root.key output_file=codesigning-other.pem \ +not_before=20130101000000 not_after=20151231235959 \ +key_usage=digital_signature \ +ns_cert_type=object_signing
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ui/tests/data/codesign/codesigning-other.key Wed Jun 25 15:16:24 2014 +0200 @@ -0,0 +1,51 @@ +-----BEGIN RSA PRIVATE KEY----- +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 +-----END RSA PRIVATE KEY-----
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ui/tests/data/codesign/codesigning-other.pem Wed Jun 25 15:16:24 2014 +0200 @@ -0,0 +1,33 @@ +-----BEGIN CERTIFICATE----- +MIIFqTCCA5GgAwIBAgIBATANBgkqhkiG9w0BAQUFADBZMSAwHgYDVQQDExdQdWJs +aWMgVHJ1c3RCcmlkZ2UgVGVzdDEoMCYGA1UEChMfUHVibGljIHNlY3JldCBkbyBu +b3QgdHJ1c3QgdGhpczELMAkGA1UEBhMCREUwHhcNMTMwMTAxMDAwMDAwWhcNMTUx +MjMxMjM1OTU5WjBlMSwwKgYDVQQDEyNQdWJsaWMgVHJ1c3RCcmlkZ2UgY29kZXNp +Z25pbmcgdGVzdDEoMCYGA1UEChMfUHVibGljIHNlY3JldCBkbyBub3QgdHJ1c3Qg +dGhpczELMAkGA1UEBhMCREUwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC +AQCq39hi9rzq5kuPboqQ2slvqKYcVu8+jFftAEAiSEz7nQYpm44/9Bkpx0B41kbs +56mqRzjoMzUmBM8Wyda5k+bTFOHHtjwtMaG4C3BzN1ANtp1zw08be4q+fZWaVBo3 +bImbFWCU1ZYm7m2QLXd/M+QME3f5abur6/S1jwWsD2IA87p1GysGUZjRc5wHFHbS +FrtQSNXZ+2xUpiDApb3CfAX6RlTTDs5pPMtLwkiChg+0nHaTlMFjpaAZBGsV2v/V +IdX17MAsqWB73++4k0z85pI8t+CY5zGeX5naOJChLuiIkhqAgYeq5XVJxoC+xoJz +u5B6d4PcrUzTcjaj+plxcIGDkB1u2q1ZkrYiJX/hxJgebmD2YwSdJ1KWPAP8wc6N +t00bWa/5QcH3nxHTAx12IxNOrnnyXKIO6h6HnivGlznVtP6IyGWOGQzuGrHQ8RfD +ANnyiE7onEJHPyTUcdOzBX2DrfXmgRklswhtU4ttZSIdwnD4kP23X6Mm7E11jXPd +yz3mWqVv7H7AhU/c7B2R5wWZWbk9FYJHh3frEYIR7+mfeRXcq1XGYVM7UDOvfyIY +awyF0qgrd2xbg9WeE2gRXjJrlSndYqBdzREatUyOkTTZtZETZa/U3x3i4ZE1En22 +wzuSvHfttzENIYvmJOhYxqnGSIafvqHGzaxG/O6r3Wn4zwIDAQABo3AwbjAJBgNV +HRMEAjAAMB0GA1UdDgQWBBS0lOBu/DAejrDytCTEGB+6rDLVizAfBgNVHSMEGDAW +gBTl/kZGRoa0cm82zW7CPn3yqk4MeTAOBgNVHQ8BAQEEBAMCAYAwEQYJYIZIAYb4 +QgEBBAQDAgAQMA0GCSqGSIb3DQEBBQUAA4ICAQA2ublxGKfS6s5iAz8OAuMdGKg0 +oxacGX378xBctl7s+PORwx7kOo1X96d8KuQyWf9LXSZv1uPPRnEO+atMF2hswqcS +gFx/Y32vEz8dGeqye6qOGfQOBD7M4wZ7ww/CiTJJBVbQ54WrU3zoy5Fga/ijXOtY +i0AaZaoFfureK6+fCua9h+SRE7OljDCpSHigWTIY9MQ6fe7T8wXTnxhopdgT8k0R +NXL/UNEUm/y79xIFfBpsVQbqMwhvtu4j6qGEmT6DhDcbnlQU8kwTkf5dYopC2kBT +4atKKvWrfyoF2jDPSbwB0/ZztmRQtvE+Ve4+bGZREEy/0cviGmuGkzRXdfA/Ckl8 +4em9A01C8PzQ49psN+YGnl0OSiVXweHJzYnEy7/jep8ImHp8uXr2fT3sdreiUh9v +tv9j12Yy0AlgJp6TsgVPIpbS1CtZqF9vqojKAef3NxNZLjGKOdwlvlP+c0/A3xne +kubVCuGaVCrBvvZ3lOoqiDrkYjhaDADJoyQwNhU75Ah7fziJ1pjIyPUePYwJaOoc +b3ntUNAtLNy8EXTI0jhlJH4uo8aMi3eO52kNrRUScBtySATSCyB7k2gkdSfCnF03 +LUbDV2nTFK5NJ7+8rz/LNStu60nO5j1poVAPflbfz9mMNgb0wmncIyMr6w+Ixwpd +qSaFDC+2vJwwzhGmlg== +-----END CERTIFICATE-----
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ui/tests/data/codesign/codesigning.key Wed Jun 25 15:16:24 2014 +0200 @@ -0,0 +1,51 @@ +-----BEGIN RSA PRIVATE KEY----- +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 +-----END RSA PRIVATE KEY-----
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ui/tests/data/codesign/codesigning.pem Wed Jun 25 15:16:24 2014 +0200 @@ -0,0 +1,33 @@ +-----BEGIN CERTIFICATE----- +MIIFqTCCA5GgAwIBAgIBATANBgkqhkiG9w0BAQUFADBZMSAwHgYDVQQDExdQdWJs +aWMgVHJ1c3RCcmlkZ2UgVGVzdDEoMCYGA1UEChMfUHVibGljIHNlY3JldCBkbyBu +b3QgdHJ1c3QgdGhpczELMAkGA1UEBhMCREUwHhcNMTMwMTAxMDAwMDAwWhcNMTUx +MjMxMjM1OTU5WjBlMSwwKgYDVQQDEyNQdWJsaWMgVHJ1c3RCcmlkZ2UgY29kZXNp +Z25pbmcgdGVzdDEoMCYGA1UEChMfUHVibGljIHNlY3JldCBkbyBub3QgdHJ1c3Qg +dGhpczELMAkGA1UEBhMCREUwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC +AQDIz9IetAtdqJJ7aSfJcLmA9Mb4nxrqEJ5E6PMejDJZmmHNjyhCVp1qsLYmyC60 +m7qJ4OBENx0v2n5LiCUHJpJ4mzAklkWn1GffUkzWgQ2VHw5Nr44NWEwkUUa5/jT7 +Sxts2DWuaLz2r7oi6BUQpoRmQRPwwzFPONcCSw9iAvTU6oVI2jW1opEW3t10UwY3 +5/muryPsUz6y5VkBIc73VC0wByXoAruEPBBpMgOVw1+npOaJ1PL1XXQ/P6xziZo0 +Ab/tKvN6IpEHrNEGv1gScJt//pKKklvIyXm9UdIY9XpB6aauzthKpTFJXGYySlXx +bD1a5sq0i2sAK/p8RvErVWg3EfBlUrQryJxONPVqribczZIWcgKVEFfXjX1tQqiC +qRCgO4M6zhNIKLkAicp0DvYs8M4hIoPng98nqK6kSpfXR6Y4b9DU3yEktH7wGrwL +jKATVM2l2yTF17Pjxkr2tH0XWrChfS+oV6Qzm9JQ/vmLKz5piLKpt5SXuZny+j0Y +68ch709sVTuuPm4RAm5c5t0SCwEippClFpkZynYRsJVrjG9ZTrdvULxZao8GBzJx +Lb+tCaKP60BRoUuRfwGMKZbU6j6ujOCy5bZIoJaKgHgyAHXRuS4PIjY9K2BGM5vI +seA2GEdAJNmZPAQJE5rxkrsAH9n8QtmHucEqzCZVFcLuCwIDAQABo3AwbjAJBgNV +HRMEAjAAMB0GA1UdDgQWBBSMgUaKY3L65wH5M4il/gbHCeVm4TAfBgNVHSMEGDAW +gBTl/kZGRoa0cm82zW7CPn3yqk4MeTAOBgNVHQ8BAQEEBAMCAYAwEQYJYIZIAYb4 +QgEBBAQDAgAQMA0GCSqGSIb3DQEBBQUAA4ICAQAdmpf8k+ZKuhDvNwMCrf1JIZh3 +uJxlCHFke/ypsMT2E6p/GZpD/lLyRHbk7V5aEYdmBaK6Dem0KYhRuDclWscpQdXl +96wx1IDNueMkj5ZDmpBLFl/nqxlM9HfHo8YTE9dRgzJAR8+dFR8HyRSayKo+pz4L +FkNFT5Jtm9kKLIN+mSGKMBmpY4owfpeh7K6YyASoOHL9Zk8A0I7iZX8FB5KujrlG +WJahjSAyvLvy98XDCf9/SyX73F1ol5ycAb/du+G5VZFDEI8sv/7fIdTx/AUR30Ac +f3tqXZ4HwxWc0gofT0J2z/I4FZ/sT/1SNHReGNrG9GNn5bxjwpSXfc5A1bjhRfxd +x73xKEInjpgo6AXY7wfNk1V+2z7keVOpaDEZUOsd/x/C+L8FsUh2JJHZp/hKX6Co +AD///pxqNfvH5pPLUINC7VRUOTynUas7p9UvkPeJjqnWY6pmjeb4Fs6Z6vn0+Opy +HP1MjLL41a+U9VxuNb6SfRDoeT19pqK6ovT2gbc61OvTI0lE97ChC622rjnV0c/N +QYqkeTQG/IjPk0QFrYQxMqq6QKgds2nheYd4LyLGhk72pKWr28Hfj1ElcoTFFbWP +ndI+uZePkkCsVYNMXbIAIpqLb++1ftl+L+itqxTyq+0tPObIL3WG9rzBGz8X6WT0 +KIzi4KAn66e5/iWZng== +-----END CERTIFICATE-----
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ui/tests/data/codesign/codesigning_root.key Wed Jun 25 15:16:24 2014 +0200 @@ -0,0 +1,51 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIJKAIBAAKCAgEAzABSlmw303tsL/5PI71FuLst5AJN7p2/0kms0qEVDpACRzwa +DSiRrQj8QVK3msnYiRwfXfRmOticwu7QphNyVDZz5mzCU75puOMcB1G8eeAQJW8m +pD0kyJbEIMditSVhi1evjzyemW63dlf/NZ4BZBoDV+OYId47EtKvRD5DgC6D3dW7 +ndpxkPZVXRaEw9NUP53f4lxnxUMoCGRR7EKa/Juo2CLaz5t5vS+iRMG9XXnx0IMT +Fk3WeVSo6LfNKOiLfHXaznW9E2pRPyTJUvJ4eEDn587SZYAyQqZMy17NNCvUdRdz +2sGAGJQy61OgZsfwuqSRAgaaGfXizTm4WpOW0duHQ6ALRxIhO3SPJ+0mdkw65keL +CwXdMcSoEmD8gAh8l+sz2EBo1DFnJNyGwyLBYwXjeHIX0sn/GwGL77LSpb7/QD5T +FGmlQM/xBwjM9qYp/Wsie3WIGEJfTGJoXw7s0jzEV9R8gc+el0vV/Ukw2QNPLYrS +7PCROuvY6hSpeuMMG4cmlOS0MAziAUnff3CewAdq8vWgvfb5+UpJ8mIJBPhqS7qv +h7BwZfPfAd+7uGshAEIz4F0ncK43eMl0ECWu5R+B8RKmK21e8jfqW3/Tu1IQUv9t +BRq5za3BZ3GBkqJAs/B0s0pU5Z8eykB1c0TWGJOUNAL1CEMjKeHD6xeFUh0CAwEA +AQKCAgB8Pi4OYvZVHLQ1PqMgVyPhcE5wsV6ZVwX+otRYq7ZRWi+pBteu7+hZBEHt +3tznrsrsJm6MIE8qw8YliqEUpH9a/pbz3YU0z6E/80Gcy5EIgQgUZG+aU4rVh80H +UaeyP4P7A3puuDK3q5CcyNcr5oFeX+FtY7XB2sELo7kOzQT7SlkRgBx19RZ5fS1c +NlzBjzGeVR6HlFO29kGpar/iLmaKNptMl13AVyZ7rEkdqwkTpzM5FLtJODrJRmBg +66BNq+NX98c9OsPe0T+OP29Fz1rDknQq3/GP09XIddQLgD9l6NPKRHBQ6MyFK60f +WZ01O8xHP/b4zuCHsxNgfijjMUQGkDft+h959OiLZjYdmkl6PAosmCHkzro/p5Ch +VPY1Xvi7j1SRLY4Zq6GbK2Nv6OqDr4X4gwRDt/W5IbtE8Y9zls5shuk7wdcnSLBc +uZ3B8BbPhzNnRHWNBcglG7QlyPOq3IrI2f2GmL5AZcxeE2AMbIk8geyAPkTiYIKE +vpkPn4hozBvzL7VP7pNZn9Af8HG50Pj47zOraPfZkOw2iW+vFCtqIJdlwYZpsUq5 +8NIRTcndF7E4DMhJ9QOT7iOKsQABIpClpuT8Va+YIz8o1+wHrx/5wQMYStjBRElZ +VnV51ZK8x4xrXPiJQ6DvWO9WoXpHafz3f0hUCzfyy9Hf8iEUQQKCAQEA+hkv7XRB +sWGZIAE3F1FwvMxgzFa8fHoMmfQOM2HYypuTo0pJx2iq5zxiJMuh4ag60d+Ftl9L +K4xqtMDTekJBQTFhrk5sTEVaRiucNbsm/9uEvYTgrO7hJ3Can2YFbH5nzQ+V4y0v +ifd6ze6jhI+FTzLdCFDHxUiH66qRB4nJw/l0v9D8T0pXsiaG4pk2/hlw6MODIFvG +wWC4cqxTViTwVS26uuUTSBaamTjf8dchNRHqdG6bZF9sOtKL83RtkX5+FCPMVALZ +g7D3SeKU8uskMKNzpCx5OE6HsKEg4rbwdBXtphqyOHPkElIDoQxTp/23P7UDeAtA +pYM8FK5M7eHU9QKCAQEA0NCrIHl3O6krySkHAvcnDmI3N96F0c4WFTCD2okg8TU2 +qs/pM4s+LLt9Mtvoq2kYO4wja6Idgfy4INfyQbHaMhU4fPiEfFTSuHc/8Sj0dzzC +S6vNP4fTCqJGWDYms7NkD0iPk5oaNr3feH+W1DpMEUD7Wla5BxPLTM6orX7VJnYa +AWZnmOmFNO8e5ZbeEIhzPNuiA3He/+g6sWDL3kZPmBldmVpTnUoCNOuck6ANV11a +eQECVR/4qqvXv8wjzOh9gHjcq2Ey4Os4XlcgXLj6FoLdu90wPp3xDPodsLpkVPQ6 +vMQR0FFcfxlJPyx6O/p1FJP/Zgj3yUOiZu8i93APiQKCAQA5kf60XGSa3mqPMXhr +B7Y535oQr46n4Lhx3/o83bM3wGRV3E3rdy6QGBhHfBCBj2Yq1ZdECd+V4LbXcOO9 +au72gNWJeEf5rqU/Ld7Bh5lMoE2ICsRlSn/Nwl/1fViWRurCC2pnZwlgavV73gkK +BLedKYoz1dSGl1GicBr+bztgv1Weqg7KecSCH9hA5SABkf2ptwfCNR4leYw76Wst +k0c3dFVdnEm5+GoSB0OVuf3M55jewG9IxaZ2S+0nV4+5RDLlk+//DsDfTac+/Mdo +u7QS9i0yh4JH8dvOTujxB0eGkV2pNM/9qr+/b92h/uJq8z5xjcuEoKJ69yCnahAP +WkLZAoIBAHwRb4vk/7YABtcHvHXDmX4PVxWn7kTBORev8re2wE7wuiF1VO7eLbvw +TiwYwz6NO+utkSITeYrROCmzhOoJnUYim6SNGFKzJ1yY5fIIzm/GNv80/cdgkUEB +N+CTlB0zWiFGkKA3cJnT6OI0lM5WMPoTbQS5AEi3NxTUuR4UfNrUUxE/4g/Vt+LC +rM3m/Nw/5pBjQvjfAIt2VOEtTRQtHH+XmqhSJdoPrg35a9e+wg6FlgrNUbB4RYxK +e+8mgKLwBBmANkTRhKRkveI3zC+rbFRRvyMvAcpCl4WJWni11oUvc3LS4G6w2M9f +m8igSaQ3ZLcsVBQxAeCgge686T6xY1kCggEBALCKZxPafc3zyDMj9+MMgCiO1CnU +K3sEMN9qSNNTG/0XStImpX47mz0KlJyjeEJDhYIhxRv6vq+Dg3YR56i+OKJoiNhO +i9YYlXo7riFqmGT/aGYJjahnYSTzmWT1BJLoJNG3+WBMktQnWQcbsrq8K665lfTL +1lEbuAZOtQVg4f7FxgUHenB5k3GAXxSn7GB89ZsNCVgdepgOr5wxWGkRWwecczxG +qrynb2eOqjwAusy2tiKBaVfPiDszawYDUaLLX5b8a8+jp6NxalmruZ4/Hp/K7lHC +b+Gc1Gi08HWbFBDIihR+Our+Nm9l3VO8ijuZD6ruqN109SqKGT3GKkApPuM= +-----END RSA PRIVATE KEY-----
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ui/tests/data/codesign/codesigning_root.pem Wed Jun 25 15:16:24 2014 +0200 @@ -0,0 +1,32 @@ +-----BEGIN CERTIFICATE----- +MIIFgDCCA2igAwIBAgIBATANBgkqhkiG9w0BAQUFADBZMSAwHgYDVQQDExdQdWJs +aWMgVHJ1c3RCcmlkZ2UgVGVzdDEoMCYGA1UEChMfUHVibGljIHNlY3JldCBkbyBu +b3QgdHJ1c3QgdGhpczELMAkGA1UEBhMCREUwHhcNMTMwMTAxMDAwMDAwWhcNMTUx +MjMxMjM1OTU5WjBZMSAwHgYDVQQDExdQdWJsaWMgVHJ1c3RCcmlkZ2UgVGVzdDEo +MCYGA1UEChMfUHVibGljIHNlY3JldCBkbyBub3QgdHJ1c3QgdGhpczELMAkGA1UE +BhMCREUwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDMAFKWbDfTe2wv +/k8jvUW4uy3kAk3unb/SSazSoRUOkAJHPBoNKJGtCPxBUreaydiJHB9d9GY62JzC +7tCmE3JUNnPmbMJTvmm44xwHUbx54BAlbyakPSTIlsQgx2K1JWGLV6+PPJ6Zbrd2 +V/81ngFkGgNX45gh3jsS0q9EPkOALoPd1bud2nGQ9lVdFoTD01Q/nd/iXGfFQygI +ZFHsQpr8m6jYItrPm3m9L6JEwb1defHQgxMWTdZ5VKjot80o6It8ddrOdb0TalE/ +JMlS8nh4QOfnztJlgDJCpkzLXs00K9R1F3PawYAYlDLrU6Bmx/C6pJECBpoZ9eLN +Obhak5bR24dDoAtHEiE7dI8n7SZ2TDrmR4sLBd0xxKgSYPyACHyX6zPYQGjUMWck +3IbDIsFjBeN4chfSyf8bAYvvstKlvv9APlMUaaVAz/EHCMz2pin9ayJ7dYgYQl9M +YmhfDuzSPMRX1HyBz56XS9X9STDZA08titLs8JE669jqFKl64wwbhyaU5LQwDOIB +Sd9/cJ7AB2ry9aC99vn5SknyYgkE+GpLuq+HsHBl898B37u4ayEAQjPgXSdwrjd4 +yXQQJa7lH4HxEqYrbV7yN+pbf9O7UhBS/20FGrnNrcFncYGSokCz8HSzSlTlnx7K +QHVzRNYYk5Q0AvUIQyMp4cPrF4VSHQIDAQABo1MwUTAPBgNVHRMECDAGAQEBAgEA +MB0GA1UdDgQWBBTl/kZGRoa0cm82zW7CPn3yqk4MeTAfBgNVHSMEGDAWgBTl/kZG +Roa0cm82zW7CPn3yqk4MeTANBgkqhkiG9w0BAQUFAAOCAgEAocyJF10oZa0Y20Sj +WyiQruMGW/Ag6AhjFd8akZXG3UGUHVj209op3nR3nrWRGovh8ZsLp51aNtjNaAIT +vtYRMSPE/W1GO+iVWOG6RI/XMTPokdWy4QDSteczJbMy4WxupjKZ09ID0eS5uaWC +4MYZOenBEpcAKO8cL3hAnahrxFGcDYCIYDSWJ1zjBBZphIu9IPHN8tgxmLIiQ7Ii +A/wm1lsvS7vTTR9jyGttxQOcjpyWDkvjemSJ2qFgbOfzF7CrtDxQPihiGo0DEuaP +8FdZFuHU6WDRGoxFhTAkYWXQiPVqSclwvMM6tcQTQ9t25OW9iT2Ykcss4PSY2Kx3 +x/xut8HRV1ikL7ROi0I1QbraOji7ro+AczsOmJx7KU1HAdMSun1bAdCyf7IKb/NK +UdqmohyUOOnCH5CupmSP4p8Az3Es7viSd/7qO6g3e3byU0XNHvCR0DFA8PA0bwu9 +h4g7mN4tRwI+hDkhO2q9uDokDf+iMN4o4w4w8DFrVTrGT/+/1Xo3JGTFnJafZX1b +nivzImON66SBsFiepeQ2vqQWSYfVn8MtGxviWSMODDbiHqILwK30nY0K+q/0K+T/ +Pw9r8vcoARIFMaUhIg8yXyqaEdWLgSSCBKwakR/CWpCYicFAa+Fwqetdf7Umsv5N +lftfVWONowED2z1t1jEwH4TG8cw= +-----END CERTIFICATE-----
--- a/ui/tests/mainwindowtest.cpp Wed Jun 25 14:56:19 2014 +0200 +++ b/ui/tests/mainwindowtest.cpp Wed Jun 25 15:16:24 2014 +0200 @@ -23,10 +23,6 @@ emit closeCalled(); } -void MainWindowTest::testInvalidUpdate() { - // TODO -} - void MainWindowTest::testValidUpdate() { QSignalSpy closed(this, SIGNAL(closeCalled())); #ifdef Q_OS_WIN
--- a/ui/tests/mainwindowtest.h Wed Jun 25 14:56:19 2014 +0200 +++ b/ui/tests/mainwindowtest.h Wed Jun 25 15:16:24 2014 +0200 @@ -23,7 +23,6 @@ void closeApp(); private Q_SLOTS: - void testInvalidUpdate(); void testValidUpdate(); Q_SIGNALS:
--- a/ui/tests/windowsstoretest.cpp Wed Jun 25 14:56:19 2014 +0200 +++ b/ui/tests/windowsstoretest.cpp Wed Jun 25 15:16:24 2014 +0200 @@ -14,7 +14,7 @@ #include <QTest> void WindowsStoreTest::dumpContents() { - char pszNameString[256]; + wchar_t pszNameString[256]; PCCERT_CONTEXT pCert = NULL; qDebug() << "Currently in store: " ; while((pCert = CertEnumCertificatesInStore(testStore, pCert))) {