# HG changeset patch # User Andre Heinecke # Date 1392824474 0 # Node ID f4f957c58e0ab8111773b265f9e63b3410f6c87f # Parent c12825a651eda016448587020faa0b4798509bfd Move listuitol and add cert pinning with a test certificate diff -r c12825a651ed -r f4f957c58e0a CMakeLists.txt --- a/CMakeLists.txt Wed Feb 19 14:22:26 2014 +0000 +++ b/CMakeLists.txt Wed Feb 19 15:41:14 2014 +0000 @@ -23,14 +23,16 @@ ${CMAKE_SOURCE_DIR}/ui/downloader.cpp ${CMAKE_SOURCE_DIR}/ui/downloader_win.cpp ${CMAKE_SOURCE_DIR}/ui/downloader_linux.cpp - ${CMAKE_SOURCE_DIR}/ui/listutil.c + ${CMAKE_SOURCE_DIR}/cinst/listutil.c + ${CMAKE_SOURCE_DIR}/ui/main.cpp ) # Seperated to make it easier to include the sources in tests -set(M13UI_MAIN ui/main.cpp) +set(M13UI_MAIN ) set(M13UI_RESOURCES - ui/icons.qrc + ${CMAKE_SOURCE_DIR}/ui/icons.qrc + ${CMAKE_SOURCE_DIR}/ui/certs.qrc ) # Warn level to be used for privileged parts @@ -98,6 +100,7 @@ if (FLAWFINDER_PATH) add_custom_target(flawfinder COMMENT "FlawFinder" VERBATIM COMMAND ${FLAWFINDER_PATH} ${CMAKE_SOURCE_DIR}/ui + ${CMAKE_SOURCE_DIR}/cinst ) add_dependencies(static_check flawfinder) endif (FLAWFINDER_PATH) diff -r c12825a651ed -r f4f957c58e0a cinst/listutil.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cinst/listutil.c Wed Feb 19 15:41:14 2014 +0000 @@ -0,0 +1,138 @@ +#include "listutil.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_FILESIZE_KB 1024 + +void handle_errno() +{ + printf("Error: %s \n", strerror(errno)); +} + +list_status_t readList(const char *fileName, char **data, size_t *size) +{ + int fd = -1; + struct stat fileStat; + int rc = 0; + ssize_t bRead = 0; + + memset(&fileStat, 0, sizeof(fileStat)); + + list_status_t retval = UnknownError; + + fd = open(fileName, O_RDONLY); + if (fd == -1) { + handle_errno(); + retval = StatFailed; + goto cleanup; + } + + rc = fstat(fd, &fileStat); + if (rc < 0) { + printf ("Stat failed with rc: %i\n", rc); + retval = StatFailed; + goto cleanup; + } + + // Check the size of the file + if (!fileStat.st_size) { + printf("Size zero\n"); + retval = StatFailed; + goto cleanup; + } + + if (fileStat.st_size / 1024 > MAX_FILESIZE_KB && + fileStat.st_size > 0) { + printf("File too large\n"); + retval = TooLarge; + goto cleanup; + } + + *size = (size_t) fileStat.st_size; + + *data = (char*) malloc(*size); + + if (*data == NULL) { + printf("Malloc failed\n"); + retval = UnknownError; + goto cleanup; + } + + bRead = read(fd, *data, *size); + + if (bRead < 0 || (size_t) bRead != *size) { + printf("Read failed\n"); + if (bRead == -1) { + handle_errno(); + } + retval = UnknownError; + *size = 0; + if (*data) { + free(*data); + printf("Nulling data\n"); + *data = NULL; + } + goto cleanup; + } + + retval = UnknownValidity; +cleanup: + + if (fd && fd != -1) { + close(fd); + fd = -1; + } + + return retval; +} + +list_status_t readAndVerifyList(const char *fileName, char **data, size_t *size) +{ +// int validSig = 0; + char * signature = NULL; + + list_status_t retval = UnknownError; + *data = NULL; + *size = 0; + + retval = readList(fileName, data, size); + + if (retval != UnknownValidity) { + printf ("Readlist failed\n"); + return retval; + } + + if (!data || !*size) { + // should not have happend if readList works as specified + return UnknownError; + } + + signature = *data; + + if (*signature != 'S') { + printf("Does not start with S\n"); + retval = InvalidFormat; + goto cleanup; + } + +// TODO VERIFIY +retval = Valid; + +// Maybe check if all bytes are < 127 and > 0 + +cleanup: + if (retval != Valid && *data) { + free(*data); + *data = NULL; + *size = 0; + } + return retval; +} + diff -r c12825a651ed -r f4f957c58e0a cinst/listutil.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cinst/listutil.h Wed Feb 19 15:41:14 2014 +0000 @@ -0,0 +1,48 @@ +#ifndef LISTUTIL_H +#define LISTUTIL_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +/** + * @file listutil.h + * @brief Functions to work with the certificate list. + */ + +/** + * @brief Status of the List Operations + */ +typedef enum { + UnknownValidity = 0, // Not yet parsed + 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 + StatFailed = 5, // Could not stat the file + ReadFailed = 6, // Could not read the file + IncompatibleVersion = 7, // The Format Version does not match + Valid = 8 // List is valid +} list_status_t; + +/** + * @brief Obtain the complete and verified Certificate list. + * + * This checks if the file fileName is a valid certificate + * list signed by the key specified in pubkey.h + * + * The caller has to free data. + * + * @param[in] fileName Name of the file (UTF-8 encoded). + * @param[out] data Newly allocated pointer to the file content. + * @param[out] size Size in Bytes of the file content. + * + * @return status of the operation. + */ +list_status_t readAndVerifyList(const char *fileName, char **data, size_t *size); +#ifdef __cplusplus +} +#endif +#endif diff -r c12825a651ed -r f4f957c58e0a tests/CMakeLists.txt --- a/tests/CMakeLists.txt Wed Feb 19 14:22:26 2014 +0000 +++ b/tests/CMakeLists.txt Wed Feb 19 15:41:14 2014 +0000 @@ -4,10 +4,10 @@ find_package(Qt5Test) -macro(add_m13_test _source) +macro(add_m13_test _source _additional_sources) set(_test ${_source}) get_filename_component(_name ${_source} NAME_WE) - add_executable(${_name} ${_test} ${M13UI_SOURCES}) + add_executable(${_name} ${_test} ${_additional_sources}) add_test(m13-${_name} ${_name}) target_link_libraries(${_name} Qt5::Test Qt5::Widgets ${EXTRA_STATIC_LIBS}) endmacro() @@ -15,5 +15,5 @@ # Add the current source dir to the definition # so that it can be used in file names in the tests. add_definitions(-DSOURCE_DIR="${CMAKE_CURRENT_SOURCE_DIR}") -add_m13_test(certlistparsertest.cpp) +add_m13_test(certlistparsertest.cpp "${CMAKE_SOURCE_DIR}/cinst/listutil.c;${CMAKE_SOURCE_DIR}/ui/certificatelist.cpp") diff -r c12825a651ed -r f4f957c58e0a ui/certificatelist.h --- a/ui/certificatelist.h Wed Feb 19 14:22:26 2014 +0000 +++ b/ui/certificatelist.h Wed Feb 19 15:41:14 2014 +0000 @@ -18,7 +18,7 @@ #include #include -#include "listutil.h" +#include "../cinst/listutil.h" class CertificateList : public QObject { diff -r c12825a651ed -r f4f957c58e0a ui/certificates/kolab.org.der Binary file ui/certificates/kolab.org.der has changed diff -r c12825a651ed -r f4f957c58e0a ui/certs.qrc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ui/certs.qrc Wed Feb 19 15:41:14 2014 +0000 @@ -0,0 +1,5 @@ + + + certificates/kolab.org.der + + diff -r c12825a651ed -r f4f957c58e0a ui/downloader.cpp --- a/ui/downloader.cpp Wed Feb 19 14:22:26 2014 +0000 +++ b/ui/downloader.cpp Wed Feb 19 15:41:14 2014 +0000 @@ -22,7 +22,7 @@ mLastModList(newestList) { if (certificate.isEmpty()) { - QFile certResource(":certificates/https"); + QFile certResource(":certs/kolab.org"); certResource.open(QFile::ReadOnly); mCert = certResource.readAll(); certResource.close(); diff -r c12825a651ed -r f4f957c58e0a ui/downloader_win.cpp --- a/ui/downloader_win.cpp Wed Feb 19 14:22:26 2014 +0000 +++ b/ui/downloader_win.cpp Wed Feb 19 15:41:14 2014 +0000 @@ -214,6 +214,7 @@ if (!retval) { DEBUG << "Certificate is not the same as the pinned one!" << "Base64 cert: " << serverCert.toBase64(); + emit error("Invalid certificate", InvalidCertificate); } CertFreeCertificateContext(certContext); @@ -258,7 +259,7 @@ if (!verifyCertificate(hRequest)) { DEBUG << "Certificate verification failed"; - // TODO error out + goto cleanup; } if (!(WinHttpQueryHeaders(hRequest, @@ -327,7 +328,7 @@ if (!verifyCertificate(hRequest)) { DEBUG << "Certificate verification failed"; - // TODO error out + goto cleanup; } diff -r c12825a651ed -r f4f957c58e0a ui/listutil.c --- a/ui/listutil.c Wed Feb 19 14:22:26 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,138 +0,0 @@ -#include "listutil.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -#define MAX_FILESIZE_KB 1024 - -void handle_errno() -{ - printf("Error: %s \n", strerror(errno)); -} - -list_status_t readList(const char *fileName, char **data, size_t *size) -{ - int fd = -1; - struct stat fileStat; - int rc = 0; - ssize_t bRead = 0; - - memset(&fileStat, 0, sizeof(fileStat)); - - list_status_t retval = UnknownError; - - fd = open(fileName, O_RDONLY); - if (fd == -1) { - handle_errno(); - retval = StatFailed; - goto cleanup; - } - - rc = fstat(fd, &fileStat); - if (rc < 0) { - printf ("Stat failed with rc: %i\n", rc); - retval = StatFailed; - goto cleanup; - } - - // Check the size of the file - if (!fileStat.st_size) { - printf("Size zero\n"); - retval = StatFailed; - goto cleanup; - } - - if (fileStat.st_size / 1024 > MAX_FILESIZE_KB && - fileStat.st_size > 0) { - printf("File too large\n"); - retval = TooLarge; - goto cleanup; - } - - *size = (size_t) fileStat.st_size; - - *data = (char*) malloc(*size); - - if (*data == NULL) { - printf("Malloc failed\n"); - retval = UnknownError; - goto cleanup; - } - - bRead = read(fd, *data, *size); - - if (bRead < 0 || (size_t) bRead != *size) { - printf("Read failed\n"); - if (bRead == -1) { - handle_errno(); - } - retval = UnknownError; - *size = 0; - if (*data) { - free(*data); - printf("Nulling data\n"); - *data = NULL; - } - goto cleanup; - } - - retval = UnknownValidity; -cleanup: - - if (fd && fd != -1) { - close(fd); - fd = -1; - } - - return retval; -} - -list_status_t readAndVerifyList(const char *fileName, char **data, size_t *size) -{ -// int validSig = 0; - char * signature = NULL; - - list_status_t retval = UnknownError; - *data = NULL; - *size = 0; - - retval = readList(fileName, data, size); - - if (retval != UnknownValidity) { - printf ("Readlist failed\n"); - return retval; - } - - if (!data || !*size) { - // should not have happend if readList works as specified - return UnknownError; - } - - signature = *data; - - if (*signature != 'S') { - printf("Does not start with S\n"); - retval = InvalidFormat; - goto cleanup; - } - -// TODO VERIFIY -retval = Valid; - -// Maybe check if all bytes are < 127 and > 0 - -cleanup: - if (retval != Valid && *data) { - free(*data); - *data = NULL; - *size = 0; - } - return retval; -} - diff -r c12825a651ed -r f4f957c58e0a ui/listutil.h --- a/ui/listutil.h Wed Feb 19 14:22:26 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,48 +0,0 @@ -#ifndef LISTUTIL_H -#define LISTUTIL_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -/** - * @file listutil.h - * @brief Functions to work with the certificate list. - */ - -/** - * @brief Status of the List Operations - */ -typedef enum { - UnknownValidity = 0, // Not yet parsed - 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 - StatFailed = 5, // Could not stat the file - ReadFailed = 6, // Could not read the file - IncompatibleVersion = 7, // The Format Version does not match - Valid = 8 // List is valid -} list_status_t; - -/** - * @brief Obtain the complete and verified Certificate list. - * - * This checks if the file fileName is a valid certificate - * list signed by the key specified in pubkey.h - * - * The caller has to free data. - * - * @param[in] fileName Name of the file (UTF-8 encoded). - * @param[out] data Newly allocated pointer to the file content. - * @param[out] size Size in Bytes of the file content. - * - * @return status of the operation. - */ -list_status_t readAndVerifyList(const char *fileName, char **data, size_t *size); -#ifdef __cplusplus -} -#endif -#endif