diff --git a/.gitignore b/.gitignore index de4157bf..bb074a5e 100644 --- a/.gitignore +++ b/.gitignore @@ -25,9 +25,12 @@ .DS_Store .idea + /ide_plugins/vs/vs2012/CoatiPlugin/CoatiPlugin/bin /ide_plugins/vs/vs2012/CoatiPlugin/CoatiPlugin/obj +.clang_complete + *.coatidb /deployment/windows/CoatiSetup/CoatiSetup/Debug @@ -48,5 +51,6 @@ /deployment/windows/CoatiSetup/SetupRemoveCacheFiles/obj/ *.sqlite +*.pch *.swp .clang_complete \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index f8a3ba04..7f39b0a8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -44,9 +44,9 @@ project(${PROJECT_NAME}) if (UNIX) if ("${CMAKE_BUILD_TYPE}" STREQUAL "Release") - find_package(LLVM REQUIRED PATHS "$ENV{CLANG_DIR}/build_release/share/llvm/cmake") + find_package(LLVM REQUIRED PATHS "$ENV{CLANG_DIR}/build_release/share/llvm/cmake" NO_DEFAULT_PATH) else() - find_package(LLVM REQUIRED PATHS "$ENV{CLANG_DIR}/build_debug/share/llvm/cmake") + find_package(LLVM REQUIRED PATHS "$ENV{CLANG_DIR}/build_debug/share/llvm/cmake" NO_DEFAULT_PATH) endif() else() find_package(LLVM REQUIRED PATHS "$ENV{CLANG_DIR}/build/share/llvm/cmake") @@ -72,6 +72,38 @@ find_package(Boost 1.59 COMPONENTS system filesystem date_time REQUIRED) add_definitions(-DEIGEN_MPL2_ONLY) set(EIGEN_ROOT $ENV{EIGEN_DIR}) +# Botan ------------------------------------------------------------------------- + +include(cmake/BotanConfig.cmake) + +set(BOTAN_ROOT ${BOTAN_DIR}) + +FIND_PACKAGE ( Threads REQUIRED ) + +add_library(BOTAN STATIC ${BOTAN_ROOT}/botan_all.cpp) + +target_link_libraries(BOTAN ${CMAKE_THREAD_LIBS_INIT}) +target_compile_options(BOTAN PUBLIC "-pthread") + +set_property( + TARGET BOTAN + PROPERTY INCLUDE_DIRECTORIES + "${BOTAN_ROOT}" +) + +# set(BOTAN_MODULES "base,ecdsa,emsa1,passhash9,rng,rsa,egd,emsa_pssr,emsa_pkcs1,x509,aes,dev_random") + +# ExternalProject_Add(BOTAN +# PREFIX $ENV{COATI_DEPEND_DIR}/botan +# GIT_REPOSITORY https://github.com/randombit/botan.git/ +# GIT_TAG 1.11.23 +# CONFIGURE_COMMAND ./configure.py --gen-amalgamation --minimized-build --enable-modules=${BOTAN_MODULES} + +# ) + +# license/key generator and license class include +add_subdirectory(src/gen) + # Lib -------------------------------------------------------------------------- set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin/lib) @@ -108,6 +140,7 @@ target_include_directories(${LIB_PROJECT_NAME} SYSTEM ${Boost_INCLUDE_DIRS} ${EIGEN_ROOT} "${CMAKE_SOURCE_DIR}/src/external" + "${BOTAN_ROOT}" ) target_link_libraries(${LIB_PROJECT_NAME} ${Boost_LIBRARIES}) @@ -246,7 +279,8 @@ if (WIN32) "// remains consistent on all systems.\n" "IDI_ICON1 ICON \"${CMAKE_SOURCE_DIR}/build/coati.ico\"\n" ) - add_executable(${APP_PROJECT_NAME} ${APP_FILES} ${CMAKE_SOURCE_DIR}/build/Coati.rc) + + add_executable(${APP_PROJECT_NAME} ${APP_FILES} ${CLANG_FILES} ${GEN_FILES} ${CMAKE_SOURCE_DIR}/build/Coati.rc ${CMAKE_SOURCE_DIR}/build/src/app/version.h) # hide the console when running a release build. set_target_properties(${APP_PROJECT_NAME} PROPERTIES LINK_FLAGS_DEBUG "/SUBSYSTEM:CONSOLE") @@ -255,14 +289,13 @@ if (WIN32) set_target_properties(${APP_PROJECT_NAME} PROPERTIES COMPILE_DEFINITIONS_RELWITHDEBINFO "_CONSOLE") set_target_properties(${APP_PROJECT_NAME} PROPERTIES LINK_FLAGS_RELEASE "/ENTRY:\"mainCRTStartup\" /SUBSYSTEM:WINDOWS") set_target_properties(${APP_PROJECT_NAME} PROPERTIES LINK_FLAGS_MINSIZEREL "/SUBSYSTEM:WINDOWS") - else () - add_executable(${APP_PROJECT_NAME} ${APP_FILES}) + add_executable(${APP_PROJECT_NAME} ${APP_FILES} ${GEN_FILES} ${CMAKE_SOURCE_DIR}/build/src/app/version.h) endif () create_source_groups(${APP_FILES}) -target_link_libraries(${APP_PROJECT_NAME} ${LIB_GUI_PROJECT_NAME} ${LIB_PARSER_PROJECT_NAME} ${LIB_PROJECT_NAME} ) +target_link_libraries(${APP_PROJECT_NAME} ${LIB_GUI_PROJECT_NAME} ${LIB_PARSER_PROJECT_NAME} ${LIB_PROJECT_NAME} BOTAN) set_property( TARGET ${APP_PROJECT_NAME} @@ -272,6 +305,9 @@ set_property( "${CMAKE_SOURCE_DIR}/src/lib_gui" "${CMAKE_SOURCE_DIR}/src/lib_parser" "${CMAKE_SOURCE_DIR}/build/src/lib_gui" + "${CMAKE_SOURCE_DIR}/src/gen" + "${CMAKE_SOURCE_DIR}/build/src/app" + "${BOTAN_ROOT}" ) target_include_directories(${APP_PROJECT_NAME} SYSTEM @@ -340,6 +376,15 @@ target_include_directories(${TRIAL_PROJECT_NAME} SYSTEM PUBLIC ${Boost_INCLUDE_DIRS} ) +# configure public key for the coati version +include(cmake/publicKey.cmake) + +#configure the versioning file +configure_file( + ${CMAKE_SOURCE_DIR}/src/app/version.h.in + ${CMAKE_SOURCE_DIR}/build/src/app/version.h +) + # Use the Widgets module from Qt 5. qt5_use_modules(${TRIAL_PROJECT_NAME} Widgets) qt5_use_modules(${TRIAL_PROJECT_NAME} Network) @@ -394,6 +439,46 @@ if (APPLE) endif () +# Key/LicenseGenerator -------------------------------------------------------- + +set(BOOST_ROOT $ENV{BOOST_159_DIR}) +set(Boost_USE_STATIC_LIBS ON) +set(Boost_USE_STATIC_RUNTIME ON) +Set(Boost_NO_SYSTEM_PATHS ON) + +find_package(Boost 1.59 COMPONENTS system program_options filesystem REQUIRED) + +set(GEN_PROJECT_NAME "${PROJECT_NAME}_keygen") + +create_source_groups(${GEN_FILES}) + +if (UNIX) + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin/gen/${CMAKE_BUILD_TYPE}) +else () + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin/gen/) +endif () + +add_executable(${GEN_PROJECT_NAME} "${CMAKE_SOURCE_DIR}/src/gen/gen.cpp" ${GEN_FILES}) + +set_target_properties( + ${GEN_PROJECT_NAME} + PROPERTIES + DEBUG_OUTPUT_NAME ${GEN_PROJECT_NAME}_d + RELEASE_OUTPUT_NAME ${GEN_PROJECT_NAME} +) + +set_property( + TARGET ${GEN_PROJECT_NAME} + PROPERTY INCLUDE_DIRECTORIES + "${CMAKE_SOURCE_DIR}/src/gen" +) + +target_include_directories(${GEN_PROJECT_NAME} SYSTEM + PUBLIC "${BOTAN_ROOT}" +) + +target_link_libraries(${GEN_PROJECT_NAME} BOTAN ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES} ) + # CxxTest ---------------------------------------------------------------------- if (UNIX) @@ -410,11 +495,11 @@ set(TESTGEN_FILE ${CMAKE_CURRENT_BINARY_DIR}/test_main.cpp) find_package(PythonInterp REQUIRED) -add_executable (${TEST_PROJECT_NAME} ${TESTGEN_FILE} ${TEST_FILES}) +add_executable (${TEST_PROJECT_NAME} ${TESTGEN_FILE} ${TEST_FILES} ${GEN_FILES}) create_source_groups(${TEST_FILES}) -target_link_libraries(${TEST_PROJECT_NAME} ${LIB_PARSER_PROJECT_NAME} ${LIB_PROJECT_NAME}) +target_link_libraries(${TEST_PROJECT_NAME} ${LIB_PARSER_PROJECT_NAME} ${LIB_PROJECT_NAME} BOTAN) find_package(CxxTest) if (CXXTEST_FOUND) @@ -423,6 +508,8 @@ if (CXXTEST_FOUND) PROPERTY INCLUDE_DIRECTORIES "${CMAKE_SOURCE_DIR}/src/lib" "${CMAKE_SOURCE_DIR}/src/lib_parser" + "${CMAKE_SOURCE_DIR}/src/gen" + "${BOTAN_ROOT}" "${CXXTEST_INCLUDE_DIR}" "${CMAKE_SOURCE_DIR}/src/external" ${Boost_INCLUDE_DIRS} @@ -460,7 +547,6 @@ elseif (UNIX) endif () - # Visual Leak Detector --------------------------------------------------------- if (WIN32) diff --git a/bin/test/data/GeneratorTestSuite/private-v2.pem b/bin/test/data/GeneratorTestSuite/private-v2.pem new file mode 100644 index 00000000..a36e4153 --- /dev/null +++ b/bin/test/data/GeneratorTestSuite/private-v2.pem @@ -0,0 +1,30 @@ +-----BEGIN ENCRYPTED PRIVATE KEY----- +MIIFNTBfBgkqhkiG9w0BBQ0wUjAxBgkqhkiG9w0BBQwwJAQMd9+hjJsW/c+J80nH +AgMDDUACASAwDAYIKoZIhvcNAgkFADAdBglghkgBZQMEASoEEO7nm7S9FQLRqEHu +Ru0PecYEggTQ+mGSNkbOzZYW2/2R8AJmyX20h4tZNwhM1fQgyWexaf8UxHfmPgI8 +Qm38NCO+NC2z+T5R7NFx2CO0MuSFoDu6bQL9fcNRnUqIQIrTTVWkSUyxpGmvee6x +h/AoTPOvGJ9WATojWCZSQH8CgNyBndMgKLurUB9tAty8vKPDuVucwcMFfPVR3wNt +em8s6e6tfq8fA7pg6yEWLyOHJYQE9UWM5hWw+kkBnZz/955QiC1bOmKB7ovlVt+Z +V0h2nFIAnyEwI6xgq/CpcK7K/i6+qW3KFgEFUBMr7Yfk1tLpezDWqR1JzJaQM6Vr +IykzWBnFFW9gjzgHxiaMdvjqkXgrI4oK8PK+YnmgEHJmLodXImx8hWGQwFoExpun +mrUg1swPumJjhAcJcaiEEy61qjcvYB3j3vpfk9DwU4g9LN0Ya9oohuKlU74w1OT8 +RlwyWvyDL7P8BP3yPaUhljl7vHlNCKnJCQVbhkQcGM8TXtzglrF4joL0+3PTHNZg +U05uYnJWNTRJmzxfTFIpHzqE+wCXoV0GbvaQ5ZSLIYRnm5cXCRCxnuf6RybIZp5a +R9VzUGHbxNAcMyqYr5prcuZz/wCBxdiusndNqfTHyBMetTehR55igDRD8LcEuNxB +KX1dmMj+kpuYXN7S/BBarFCxTQm3IWCi8sH2JUxBDJfZ6KxNrX3++7n9REe48cil +mjxccZgYAf0rh10/3s8nD2MbezWig/bUMdlCszqMdy6tDz0g2xff22P/OIOXF5ip +uLxegXWcBR9MKErzEJlTWN1evKc8BubmcdxeF/8aZVBDJh1GfQ8wYdYpKBVpCP1k +d9H5n4OgsviZYnyLm2mBoK1oTm1rwTTa0U1/Hro9nb/n5gHQixU9er17U6jbuISU +2SPCGzpYsXMuIf2/pGFO1CVkz2hCroqiryEp5tHI43uKl0R3N0+NmuICNEqxxZsf +hHmdZXh3o5LoTVUEf+WQPHSoiBzir7A1KmIH0huCW53N7NpQ9PKUwY2E0uj69hzz +XLmR63mHKvZc5tqIwhRs+dhiSuE5/UWfn6wpRDebSCD8/u9tC8ORSbXK7TB8fHRu +EahsvbsXMmO6kVe1NU2TiDVsBm3XiBTN+AurK5uPVSEPFBGZPUlNVGC9Z/wIpuOT +jinUN6eOfY/Le+30BsH31bMAF0ND8m/CypJu1ZJ2mzIklDLp5qGoZMPcnrumd/MR +6yptqp9eKBvlf5Ilbm5OnSzc7l7Vjlh5cN1wkcOxTgovFye7At0DEOd5vSh9xkfD +2WbRk0XJEF7HvDT3ncKcpsAMPQxC3vK1s7Giz51zgeqSl5HPrbXowqiiEOUGBI8G +TWOI/vVtCxzNa8XZtqVtJ8ybe+hpbhU0oER+dmzLv1VckxIMVcjtLZa6iRqdG3gm +NWGOWgJ5WMglhjW3AQGkG2fp4FIgiPhS+yZmdk1Z7l39PI9Oj7KSFg1flgo4cxQX +1rm+hBUcuNYJQrE+Np/5G/XDwQyHduycTdKZsD/SAaV1xgt00jetYiX8tNLLzCAf +PEeEbcPr5RbTALZurK+M8ZGnRPWXIH6BAn1ThYRvrccSpROtfM6NrMLKdGDzh+pA +HSYsFvk2F6lifYsjDogamCr+JYvND0SsysFj+wWBNzBxwlP+kzU6H7k= +-----END ENCRYPTED PRIVATE KEY----- diff --git a/cmake/BotanConfig.cmake b/cmake/BotanConfig.cmake new file mode 100644 index 00000000..b1e79a01 --- /dev/null +++ b/cmake/BotanConfig.cmake @@ -0,0 +1,45 @@ +SET(BOTAN_URL https://github.com/randombit/botan.git/) +SET(BOTAN_VERSION 1.11.23) +SET(BOTAN_MODULES "base,ecdsa,emsa1,passhash9,rng,rsa,egd,emsa_pssr,emsa_pkcs1,x509,aes,dev_random") + +SET(BOTAN_DIR $ENV{COATI_DEPEND_DIR}/botan) + +find_package(Git) + +if(Git_FOUND) +else() + message(ERROR "git not found: git not in path") +endif() + +if(EXISTS $ENV{COATI_DEPEND_DIR}) +else() + message(ERROR "coati dependency directory does not exist") +endif() + +if(EXISTS ${BOTAN_DIR}) +else() + execute_process( + COMMAND ${GIT_EXECUTABLE} clone ${BOTAN_URL} + WORKING_DIRECTORY $ENV{COATI_DEPEND_DIR} + ) +endif() + +execute_process( + COMMAND ${GIT_EXECUTABLE} checkout ${BOTAN_VERSION} + WORKING_DIRECTORY ${BOTAN_DIR} +) + +# system specific botan modules +if(UNIX) + +elseif(MSVC) + +endif() + +execute_process( + COMMAND ./configure.py --gen-amalgamation --minimized-build --enable-modules=${BOTAN_MODULES} + WORKING_DIRECTORY ${BOTAN_DIR} +) + +#linux +#./configure.py --gen-amalgamation --minimized-build --enable-modules=base,ecdsa,emsa1,passhash9,rng,rsa,egd,dev_random,emsa_pssr,emsa_pkcs1,x509,aes diff --git a/cmake/CLANGConfig.cmake b/cmake/CLANGConfig.cmake index 141dd1bd..3a7b12e4 100644 --- a/cmake/CLANGConfig.cmake +++ b/cmake/CLANGConfig.cmake @@ -8,7 +8,6 @@ else() set(CLANG_BUILD_PATH "$ENV{CLANG_DIR}/build") endif() - execute_process( COMMAND ${CLANG_BUILD_PATH}/bin/llvm-config --cxxflags OUTPUT_VARIABLE CLANG_DEFINITIONS diff --git a/cmake/PublicKey.h.in b/cmake/PublicKey.h.in new file mode 100644 index 00000000..304f90c1 --- /dev/null +++ b/cmake/PublicKey.h.in @@ -0,0 +1,10 @@ +#ifndef PUBLIC_KEY_H +#define PUBLIC_KEY_H + +// This File(PublicKey.h) is generated with CMake + +#include + +static const std::string PublicKey = "@KEY@"; + +#endif //PUBLIC_KEY_H diff --git a/cmake/licenses.cmake b/cmake/licenses.cmake index d733666b..7256099b 100644 --- a/cmake/licenses.cmake +++ b/cmake/licenses.cmake @@ -26,6 +26,7 @@ AddLicense("Boost" "http://www.boost.org" "${LICENSEFOLDER}/boost_LICENSE.TXT" f AddLicense("TinyXMl" "http://www.grinninglizard.com/tinyxml2/" "${LICENSEFOLDER}/tinyxml_LICENSE.TXT" false) AddLicense("CppSQLite" "http://www.codeproject.com/Articles/6343/CppSQLite-C-Wrapper-for-SQLite" "${LICENSEFOLDER}/CppSQLite_LICENSE.TXT" false) AddLicense("Eigen" "http://eigen.tuxfamily.org" "${LICENSEFOLDER}/eigen_LICENSE.TXT" false) +AddLicense("Botan" "http://botan.randombit.net/" "${LICENSEFOLDER}/botan_LICENSE.TXT" true) set(LICENSE_ARRAY "${LICENSE_ARRAY}\n") diff --git a/cmake/publicKey.cmake b/cmake/publicKey.cmake new file mode 100644 index 00000000..6110a437 --- /dev/null +++ b/cmake/publicKey.cmake @@ -0,0 +1,22 @@ +# searching for public key file of the Coati version in setup/RSA_keys +# if found the file will be put into a const string into the PubicKeh.h file + +string(REGEX REPLACE "^([0-9]+)\\..*" "\\1" VERSION_MAJOR "${GIT_VERSION_NUMBER}") +message(STATUS "Get Public Key for Coati version: ${VERSION_MAJOR}") + +set(pubKeyFile "${CMAKE_SOURCE_DIR}/setup/RSA_keys/public-${VERSION_MAJOR}.pem") +# message(STATUS "file: ${pubKeyFile}") + +if(EXISTS ${pubKeyFile}) + file(READ ${pubKeyFile} KEY) + STRING(REGEX REPLACE "\"" "\\\\\"" KEY "${KEY}") + STRING(REGEX REPLACE "\n" "\\\\n\"\n\t\"" KEY "${KEY}") + # message(STATUS "key: ${KEY}") +else() + message(WARNING "public keyfile for this version of Coati") +endif() + +configure_file( + ${CMAKE_SOURCE_DIR}/cmake/PublicKey.h.in + ${CMAKE_SOURCE_DIR}/build/src/app/PublicKey.h +) \ No newline at end of file diff --git a/script/build.sh b/script/build.sh index e178658f..bb78826c 100755 --- a/script/build.sh +++ b/script/build.sh @@ -16,6 +16,10 @@ then elif [ "$2" = "trial" ] then ninja -C build/Release Coati_trial && cd bin/app && Release/Coati_trial + elif [ "$2" = "keygen" ] + then + #echo "release keygen" + ninja -C build/Release Coati_keygen && cd bin/gen && Release/Coati_keygen else #echo "release app" ninja -C build/Release Coati && cd bin/app && Release/Coati @@ -29,6 +33,10 @@ then elif [ "$2" = "trial" ] then ninja -C build/Debug Coati_trial && cd bin/app && Debug/Coati_trial + elif [ "$2" = "keygen" ] + then + #echo "debug keygen" + ninja -C build/Debug Coati_keygen && cd bin/gen && Debug/Coati_keygen_d else #echo "debug app" ninja -C build/Debug Coati && cd bin/app && Debug/Coati diff --git a/script/setup.sh b/script/setup.sh index dcb29e2a..b6dfe8f1 100755 --- a/script/setup.sh +++ b/script/setup.sh @@ -32,6 +32,8 @@ echo -e $INFO "create build folders" mkdir -p build mkdir -p bin/app/Debug mkdir -p bin/app/Release +mkdir -p bin/gen/Debug +mkdir -p bin/gen/Release mkdir -p bin/lib/Debug mkdir -p bin/lib/Release mkdir -p bin/test/Debug diff --git a/setup/3rdPartyLicenses/botan_LICENSE.TXT b/setup/3rdPartyLicenses/botan_LICENSE.TXT new file mode 100644 index 00000000..02dcb0b6 --- /dev/null +++ b/setup/3rdPartyLicenses/botan_LICENSE.TXT @@ -0,0 +1,47 @@ +Copyright (C) 1999-2013,2014,2015 Jack Lloyd + 2001 Peter J Jones + 2004-2007 Justin Karneges + 2004 Vaclav Ovsik + 2005 Matthew Gregan + 2005-2006 Matt Johnston + 2006 Luca Piccarreta + 2007 Yves Jerschow + 2007-2008 FlexSecure GmbH + 2007-2008 Technische Universitat Darmstadt + 2007-2008,2010,2014 Falko Strenzke + 2007-2008 Martin Doering + 2007 Manuel Hartl + 2007 Christoph Ludwig + 2007 Patrick Sona + 2008 Copyright Projet SECRET, INRIA, Rocquencourt + 2008 Bhaskar Biswas and Nicolas Sendrier + 2008 Google Inc. + 2010 Olivier de Gaalon + 2012 Vojtech Kral + 2012-2014 Markus Wanner + 2013 Joel Low + 2014 cryptosource GmbH + 2014 Andrew Moon +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions, and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. diff --git a/setup/RSA_keys/private-0.pem b/setup/RSA_keys/private-0.pem new file mode 100644 index 00000000..8aa49ba5 --- /dev/null +++ b/setup/RSA_keys/private-0.pem @@ -0,0 +1,30 @@ +-----BEGIN ENCRYPTED PRIVATE KEY----- +MIIFNTBfBgkqhkiG9w0BBQ0wUjAxBgkqhkiG9w0BBQwwJAQMDAB5IuntKywoJmry +AgMDDUACASAwDAYIKoZIhvcNAgkFADAdBglghkgBZQMEASoEEA7JwOuCMu6xUJ+c +0NBKZZsEggTQC82I8AHltLbPCAIkTZoJv68aOV/cVXDcxZ7Mn1hOiob7nO4RuteW +mwTX3JZFd7Jlw5h706xAdRjbSsJXGgTMXECciqrfZ9c21+tYbKV4JpPBQMEhTLpa +IXUTWonQ9wh7vis3bcwBPaRCsfDtYaz872vDpf1X5BVOppoffKCiKFi2y5C+e3HG +CPcg+BTgZg+SRJB9yvSDqdDO5/s9Y6+otePt4Gr+wSOJRwYkdZ67f9uq4BaFcw2z +wIRKA0C1oClu7TAo5onjv1rvw/66migcMHRw1zjIk6oQv44caJvqca1eM9dniZo7 +ccbq11PWpeBdKvEkAWuW1PoI7uuLQNdzs3UDO7LJttWwVNAKtO3o8LOL8x9Q7Jns +tvQqUrf0VNB8eBfmsD2I3zVMu2X4rNEDYlAbrL3f1vNkt949ib4eG7+lo3wrCt6J +6UFA791HGVJUvFI0NHdtT32+LdKyTJ+bIlz663LkNU2+mBs6UL7qe6XIBoXCNcg8 ++VDKDDVSIyckSVxV7WuGeX9n3igRuvt88T2pCVlY+HEBWDgFoXxc5vx8LdD9EVaQ +OAmuXABLNTqUTCGms9KAa3WJ/QW6++NAt4uf+37LKzM9zyUrDZMTs5M2ZJ/otwgK +ZqIbDcVyfsX79ATs0UeJ7bdrMduXuKhFIVsjlJCGXlyKa7h+JmEpPkqnELGiThvi +hvWogpYt6S6/ofw13MAAgkDqgsfhUGH8tmPu8ufYQn2QQTjB7y1X+s+DUPBUYlic +Ds29YvGMp3wesMFppfwygtGtBFxxs7zvuz3aq9Putu1xC9q3dtHOPdxZYyLvz/aJ +F6BfOqk3NP0a6/S9TphgxE9CqYz2RIqRQg91IbPPrEiC8Sm3fLgX0fO1kfVN7x0E +Pg5+3M56UVflcWLsIcjDVYK4EId4XLHBTjFn8xhkEj56UJQsjb9fFbdQQBBI5pWM +G2nxoGdHD/GCOjZi2f393OMIDFbfoIaoz4L4osIFYaIg4sMrIy2oUOEwnqyLEVf2 +tQ58ysC7SDVZza4jai5QXuTCHyMcHYf9BxuzIHEViquI0y19QvlMW17effUctfow +8a0sqCYr0KczggsaOR9BdAgHpSeoCM7SxkQd+j55iX/w7Det8JUvHoCSHRPwM0ar +QiAncEtdKYyU/vz25feTh/crDH1OB4umZIatPVJFr7samb1McocSI5/AxQ5YSkRT +BYyFj6Yi5D0jgmob4+t96Ub0UnWinXk+V6CeTEzgSE6/FYlEb+PqibWAhDfEWG+7 +0oG58ajt2vOzbGytDE9RV48HzLoUoWEaNDoa51viuJhpSmRii4CrBj+ENvber2GR +qOM7bMcmicqUvegN9cB+9ZiIzWVePVvI/1NRvypqjXJVE99AD3GyRd5fuC0Vo4VQ +xdaZuk6ysWBldUcFVUCDzr32FWaxKe6cGZbjRtS/u6rDJ8DEJzvm7FcgcLj80qrd +mGrAMUafAfe+FrHSiMits/pUjzwiZqjsQeVIlULUgxQGeLVoERV7InkooBqxVOpI +R63O9zMjEZgkf7yhD8nOrw1fLO08D/eOud2yL5EhXUMWQmjnmBYDog/M1IRu13ba +L4qeddYh0cgHID8DjhjaY+g8VKiikgRO0d59xAkzHrMk4MS1l27xOz8= +-----END ENCRYPTED PRIVATE KEY----- diff --git a/setup/RSA_keys/public-0.pem b/setup/RSA_keys/public-0.pem new file mode 100644 index 00000000..c22aa858 --- /dev/null +++ b/setup/RSA_keys/public-0.pem @@ -0,0 +1,9 @@ +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsop6ceQNJeWYjourIu2Z +QydUFJwm3kwqXvoAiYP+NeLEyR9OET0eBRwowKDbFzdfDyCXcfJAbsRBoQ1he8Bw +dXcGZqs+QNcnoBz0Vl/uaxOXpVSN5RYj6wo0IFQ/nrR+gMTmzHut8ohtXI4n4a0C +7OVMfwoR2uJyLMLTQiHekEsLvraMnRcS5FbqIq2yUuVYCfGvU3Y2xo1jsvIkko7W +uF/Lw7LFCeruZ1hRYDLGa/HnKepdLhGXoh7lDQuagsUg510PVRGru4G50ATqKVTa +IwcvWNeF0BWjC78uBIhk5G65ZI/HRsS4MQvu3UwrTvtp6d9tTNOT9wixpfD1UtBr +qwIDAQAB +-----END PUBLIC KEY----- diff --git a/src/gen/CMakeLists.txt b/src/gen/CMakeLists.txt new file mode 100644 index 00000000..ee8e407e --- /dev/null +++ b/src/gen/CMakeLists.txt @@ -0,0 +1,8 @@ +add_files( + GEN_FILES + + Generator.cpp + Generator.h + License.cpp + License.h +) diff --git a/src/gen/Generator.cpp b/src/gen/Generator.cpp new file mode 100644 index 00000000..19e69984 --- /dev/null +++ b/src/gen/Generator.cpp @@ -0,0 +1,155 @@ +#include "Generator.h" + +#include +#include +#include + +#include "botan_all.h" +#include "boost/filesystem.hpp" + +#include "License.h" + +Generator::Generator(std::string version) + : m_version(version) +{ +} + +Generator::~Generator() +{ +} + +void Generator::generateKeys() +{ + m_privateKey = std::make_shared(m_rng, 2048); +} + +std::string Generator::getPrivateKeyFilename() +{ + if(m_privateKeyFile.empty()) + { + return "private-" + m_version + KEY_FILEENDING; + } + return m_privateKeyFile; +} + +std::string Generator::getPublicKeyFilename() +{ + if(m_publicKeyFile.empty()) + { + return "public-" + m_version + KEY_FILEENDING; + } + return m_publicKeyFile; +} + +void Generator::setVersion(std::string version) +{ + if(!version.empty()) + { + m_version = version; + } +} + +std::string Generator::encodeLicense(std::string user) +{ + License license; + + //load private key + std::string filename = getPrivateKeyFilename(); + std::shared_ptr privateKey( + Botan::PKCS8::load_key(filename, m_rng, PRIVATE_KEY_PASSWORD)); + Botan::RSA_PrivateKey *rsaKey = dynamic_cast(privateKey.get()); + if (!rsaKey) { + std::cout << "The key is not a RSA key" << std::endl; + } + + license.create(user, m_version, rsaKey); + license.writeToFile("license.txt"); + license.print(); + + return license.getLicenseString(); +} + +bool Generator::verifyLicense(std::string filename) +{ + License license; + license.loadFromFile(filename); + license.setVersion(m_version); + license.loadPublicKeyFromFile(getPublicKeyFilename()); + return license.isValid(); +} + +void Generator::setCustomPrivateKeyFile(std::string file) +{ + if(!file.empty()) + { + m_privateKeyFile = file; + } +} + +void Generator::setCustomPublicKeyFile(std::string file) +{ + if(!file.empty()) + { + m_publicKeyFile = file; + } +} + +std::string Generator::getPublicKeyPEMFileAsString() +{ + return Botan::X509::PEM_encode(*m_privateKey); +} + +std::string Generator::getPrivateKeyPEMFileAsString() +{ + return Botan::PKCS8::PEM_encode(*m_privateKey, m_rng, PRIVATE_KEY_PASSWORD); +} + +void Generator::writeKeysToFiles() +{ + //public key + std::string filename = getPublicKeyFilename(); + std::cout << "publickey filename: " << filename << std::endl; + std::ofstream pub(filename); + pub << getPublicKeyPEMFileAsString(); + std::cout << "public key created" << std::endl; + // private key + filename = getPrivateKeyFilename(); + std::cout << "publickey filename: " << filename << std::endl; + std::ofstream priv(filename); + priv << getPrivateKeyPEMFileAsString(); + std::cout << "private key created" << std::endl; +} + +bool Generator::loadPrivateKeyFromFile() +{ + boost::filesystem::exists(getPrivateKeyFilename()); + Botan::Private_Key* privateKey = Botan::PKCS8::load_key(getPrivateKeyFilename(), m_rng, PRIVATE_KEY_PASSWORD); + Botan::RSA_PrivateKey *rsaKey = dynamic_cast(privateKey); + if (!rsaKey) { + std::cout << "The key is not a RSA key" << std::endl; + return false; + } + m_privateKey = std::shared_ptr(rsaKey); + + return true; +} + +bool Generator::loadPrivateKeyFromString(std::string key) +{ + Botan::DataSource_Memory in(key); + Botan::Private_Key* privateKey= Botan::PKCS8::load_key(in, m_rng, PRIVATE_KEY_PASSWORD); + Botan::RSA_PrivateKey *rsaKey = dynamic_cast(privateKey); + if (!rsaKey) { + std::cout << "The key is not a RSA key" << std::endl; + return false; + } + m_privateKey = std::shared_ptr(rsaKey); + + return true; +} + +Botan::RSA_PrivateKey *Generator::getPrivateKey() const +{ + return m_privateKey.get(); +} + diff --git a/src/gen/Generator.h b/src/gen/Generator.h new file mode 100644 index 00000000..6e3fe8af --- /dev/null +++ b/src/gen/Generator.h @@ -0,0 +1,48 @@ +#ifndef KEYGEN_H +#define KEYGEN_H + +#include + +#include "botan_all.h" + +class Generator +{ +public: + Generator(std::string version = "x"); + ~Generator(); + + std::string encodeLicense(std::string message); + bool verifyLicense(std::string filename = "license.txt"); + void generateKeys(); + void writeKeysToFiles(); + void setVersion(std::string version); + void setCustomPrivateKeyFile(std::string file); + void setCustomPublicKeyFile(std::string file); + + std::string getPublicKeyPEMFileAsString(); + std::string getPrivateKeyPEMFileAsString(); + bool loadPrivateKeyFromFile(); + bool loadPrivateKeyFromString(std::string key); + + void PrintLicense(); + + Botan::RSA_PrivateKey* getPrivateKey() const; + +private: + std::string getPrivateKeyFilename(); + std::string getPublicKeyFilename(); + + //Botan + Botan::AutoSeeded_RNG m_rng; + + std::string m_version; + std::string m_privateKeyFile; + std::string m_publicKeyFile; + std::string m_license; + std::shared_ptr m_privateKey; + + const std::string PRIVATE_KEY_PASSWORD = "BA#jk5vbklAiKL9K3k$"; + const std::string KEY_FILEENDING = ".pem"; +}; + +#endif // KEYGEN_H diff --git a/src/gen/License.cpp b/src/gen/License.cpp new file mode 100644 index 00000000..05dda2e8 --- /dev/null +++ b/src/gen/License.cpp @@ -0,0 +1,319 @@ +#include "License.h" + +#include +#include +#include +#include + +// #include "botan/pubkey.h" +// #include "botan/base64.h" +// #include "botan/passhash9.h" + +#include "boost/filesystem.hpp" + +// #ifdef BOTAN_HAS_RSA +// #include "botan/rsa.h" +// #endif + +License::License() +{ +} + +License::~License() +{ +} + +std::string License::getHashLine() +{ + return lines[4]; +} + +std::string License::getMessage() +{ + std::string message = ""; + for(int i = 1; i < 5; ++i) + { + message += lines[i]; + } + return message; +} + +std::string License::getSignature() +{ + std::string signatue = ""; + for(int i = 5; i < 12; ++i) + { + signatue += lines[i]; + } + return signatue; +} + +std::string License::getVersionLine() +{ + return lines[3]; +} + +void License::create(std::string user, std::string version, Botan::RSA_PrivateKey* privateKey, unsigned int type) +{ + m_version = version; + createMessage(user, version, type); + + //encode message + Botan::PK_Signer signer(*privateKey, "EMSA4(SHA-256)"); + Botan::DataSource_Memory in(getMessage()); + Botan::byte buf[4096] = {0}; + while (size_t got = in.read(buf, sizeof(buf))) { + signer.update(buf, got); + } + std::string signature = Botan::base64_encode(signer.signature(m_rng)); + addSignature(signature); +} + +void License::createMessage(std::string user, std::string version, unsigned int type) +{ + lines.clear(); + lines.push_back(BEGIN_LICENSE); + lines.push_back(user); + std::string typestring; + switch(type) + { + case 0: + default: + typestring = "Single User License"; + + }; + lines.push_back(typestring); + std::string versionstring = "Coati " + getVersion(); + lines.push_back(versionstring); + std::string pass9 = Botan::generate_passhash9(versionstring, m_rng); + lines.push_back(pass9); +} + +void License::writeToFile(std::string filename) +{ + std::ofstream licenseFile(filename); + for(std::string line : lines) + { + licenseFile << line << std::endl; + } +} + +bool License::loadFromString(std::string licenseText) +{ + lines.clear(); + std::istringstream license(licenseText); + return load(license); +} + +bool License::load(std::istream& stream) +{ + lines.clear(); + std::string line; + if(!getline(stream, line, '\n')) + { + return false; + } + if(line.compare(BEGIN_LICENSE) ) + { + std::cout << "No License Header" << std::endl; + lines.push_back(BEGIN_LICENSE); + } + else + { + lines.push_back(line); + if(!getline(stream, line)) + { + return false; + } + } + lines.push_back(line); + + for(int i = 0; i < 2; ++i) + { + if(!getline(stream, line)) + { + return false; + } + lines.push_back(line); + } + if(!getline(stream, line)) + { + return false; + } + lines.push_back(line); + + //get signature + std::string signature = ""; + for(int i = 0; i < 7; ++i) + { + if(!getline(stream, line)) + { + return false; + } + signature += line; + lines.push_back(line); + } + + //check License ending + getline(stream, line); + if(line.compare(END_LICENSE)) + { + std::cout << "No License Footer" << std::endl; + lines.push_back(END_LICENSE); + } + else + { + lines.push_back(line); + } + return true; +} + + +bool License::loadFromFile(std::string filename) +{ + lines.clear(); + std::ifstream sigfile(filename); + return load(sigfile); +} + +void License::print() +{ + std::cout << getLicenseString(); +} + +std::string License::getOwnerLine() +{ + return lines[1]; +} + +std::string License::getLicenseTypeLine() +{ + return lines[2]; +} + +void License::addSignature(std::string signature) +{ + if(lines.size() > 5) + { + std::cout << "signature already there" << std::endl; + return; + } + if (!signature.size()) { + std::cout << "signature is empty." << std::endl; + return; + } + std::stringstream ss; + for (size_t i = 0; i < signature.size(); i++) { + if(i % 55 == 0 && i != 0) + { + lines.push_back(ss.str()); + ss.str(""); + } + ss << signature[i]; + } + lines.push_back(ss.str()); + lines.push_back(END_LICENSE); +} + +bool License::isValid() +{ + if(!m_publicKey) + { + std::cout << "No public key loaded" << std::endl; + return false; + } + if(Botan::check_passhash9("Coati "+ getVersion(), getHashLine())) + { + std::cout << "Hash from Coati "+ getVersion() + " confirmed" << std::endl; + } + + Botan::secure_vector sig = Botan::base64_decode(getSignature()); + + Botan::PK_Verifier verifier(*m_publicKey.get(), "EMSA4(SHA-256)"); + + Botan::DataSource_Memory in(getMessage()); + Botan::byte buf[4096] = {0}; + while(size_t got = in.read(buf, sizeof(buf))) + { + verifier.update(buf, got); + } + + const bool ok = verifier.check_signature(sig); + return ok; +} + +std::string License::getPublicKeyFilename() +{ + if(m_publicKeyFilename.empty()) + { + return "public-" + getVersion() + KEY_FILEENDING; + } + return m_publicKeyFilename; +} + +std::string License::getVersion() { + if(m_version.empty()) + { + return "x"; + } + return m_version; +} + +bool License::loadPublicKeyFromFile(std::string filename) +{ + if (!filename.empty()) { + m_publicKeyFilename = filename; + } + if(boost::filesystem::exists(getPublicKeyFilename())) + { + Botan::RSA_PublicKey *rsaPublicKey = dynamic_cast(Botan::X509::load_key(getPublicKeyFilename())); + if (!rsaPublicKey) { + std::cout << "The loaded key is not a RSA key" << std::endl; + return false; + } + m_publicKey = std::shared_ptr(rsaPublicKey); + return true; + } + return false; +} + +bool License::loadPublicKeyFromString(std::string publicKey) +{ + Botan::DataSource_Memory in(publicKey); + Botan::RSA_PublicKey *rsaPublicKey = dynamic_cast(Botan::X509::load_key(in)); + if (!rsaPublicKey) { + std::cout << "The loaded key is not a RSA key" << std::endl; + return false; + } + m_publicKey = std::shared_ptr(rsaPublicKey); + return true; +} + + +void License::setVersion(const std::string& version) +{ + if(!version.empty()) + { + m_version = version; + } +} + +std::string License::getLicenseString() +{ + std::stringstream license; + for(std::string line : lines) + { + license << line << std::endl; + } + return license.str(); +} + +bool License::checkLocation(const std::string& location, const std::string& hash) +{ + return Botan::check_passhash9(location, hash); +} + +std::string License::hashLocation(const std::string& location) +{ + return Botan::generate_passhash9(location, m_rng); +} diff --git a/src/gen/License.h b/src/gen/License.h new file mode 100644 index 00000000..fecb83e2 --- /dev/null +++ b/src/gen/License.h @@ -0,0 +1,66 @@ +#ifndef COATI_LICENSE_H +#define COATI_LICENSE_H + +#include +#include + +//#include "botan/botan.h" +#include "botan_all.h" + +#ifdef BOTAN_HAS_RSA +//#include "botan/rsa.h" +#endif + +class License { +public: + enum LicenseType + { + LICENSETYPE_SINGLEUSER = 0, + }; + License(); + ~License(); + + std::string getHashLine(); + std::string getMessage(); + std::string getSignature(); + std::string getVersionLine(); + std::string getOwnerLine(); + std::string getLicenseTypeLine(); + + std::string getPublicKeyFilename(); + std::string getVersion(); + + void create(std::string user, std::string version, Botan::RSA_PrivateKey* privateKey, unsigned int type = 0); + + std::string getLicenseString(); + + void writeToFile(std::string filename); + bool load(std::istream& stream); + bool loadFromString(std::string licenseText); + bool loadFromFile(std::string filename); + + bool loadPublicKeyFromFile(std::string); + bool loadPublicKeyFromString(std::string); + + void setVersion(const std::string&); + bool isValid(); + + void print(); + + std::string hashLocation(const std::string&); + bool checkLocation(const std::string&, const std::string&); +private: + void createMessage(std::string user, std::string version, unsigned int type = 0); + void addSignature(std::string); + std::string m_version; + std::string m_publicKeyFilename; + std::shared_ptr m_publicKey; + std::vector lines; + Botan::AutoSeeded_RNG m_rng; + + const std::string KEY_FILEENDING = ".pem"; + const std::string BEGIN_LICENSE = "-----BEGIN LICENSE-----"; + const std::string END_LICENSE = "-----END LICENSE-----"; +}; + +#endif //COATI_LICENSE_H diff --git a/src/gen/gen.cpp b/src/gen/gen.cpp new file mode 100644 index 00000000..7e462e6f --- /dev/null +++ b/src/gen/gen.cpp @@ -0,0 +1,93 @@ +#include +#include +#include +#include + +#include "boost/program_options.hpp" + +#include "Generator.h" + +namespace po = boost::program_options; + +bool process_command_line(int argc, char** argv) +{ + try + { + std::string user; + std::string version; + std::string privateKey; + std::string publicKey; + std::string license; + po::options_description desc("Coati Generator"); + + desc.add_options() + ("help,h", "Print this help message") + ("key,k", "Generate the private and public key") + ("generate,g", po::value(&user), "Generate a License, USERNAME as value") + ("check,c", "Validate a License") + ("version,v", po::value(&version), "Versionnumber of Coati") + ("public-file", po::value(&publicKey), "Custom public key file") + ("private-file", po::value(&privateKey), "Custom private key file") + ("license-file", po::value(&license), "Custom license") + ; + po::variables_map vm; + + po::store(po::parse_command_line(argc,argv,desc), vm); + po::notify(vm); + + Generator keygen(version); + + if(vm.count("help")) + { + std::cout << desc << std::endl; + return 1; + } + + if (vm.count("key")) + { + keygen.generateKeys(); + keygen.writeKeysToFiles(); + } + + if (vm.count("public-file")) + { + keygen.setCustomPublicKeyFile(publicKey); + } + + if (vm.count("private-file")) + { + keygen.setCustomPrivateKeyFile(privateKey); + } + + if(vm.count("generate")) + { +// std::cout << "generate License" << std::endl; + keygen.encodeLicense(user); + + } + + if(vm.count("check")) + { + if(keygen.verifyLicense()) + { + std::cout << "License valid" << std::endl; + } + else + { + std::cout << "License not valid" << std::endl; + } + } + } + catch(std::exception& e) + { + std::cout << "Exception caught: " << e.what() << std::endl; + return false; + } + return true; +} + +int main(int argc, char *argv[]) { + process_command_line(argc, argv); + + return 0; +} diff --git a/src/lib/Application.cpp b/src/lib/Application.cpp index 5614caab..dfc88aee 100644 --- a/src/lib/Application.cpp +++ b/src/lib/Application.cpp @@ -22,7 +22,6 @@ std::shared_ptr Application::create( const Version& version, ViewFactory* viewFactory, NetworkFactory* networkFactory ){ Version::setApplicationVersion(version); - loadSettings(); std::shared_ptr ptr(new Application()); diff --git a/src/lib/settings/ApplicationSettings.cpp b/src/lib/settings/ApplicationSettings.cpp index 82a5bd83..3811220c 100644 --- a/src/lib/settings/ApplicationSettings.cpp +++ b/src/lib/settings/ApplicationSettings.cpp @@ -160,3 +160,23 @@ int ApplicationSettings::getControlsMouseForwardButton() const { return getValue("controls/mouse_forward_button", 0x10); } + +std::string ApplicationSettings::getLicenseString() const +{ + return getValue("application/license/license:", ""); +} + +std::string ApplicationSettings::getLicenseCheck() const +{ + return getValue("application/license/check", ""); +} + +void ApplicationSettings::setLicenseString(const std::string& licenseString) +{ + setValue("application/license/license", licenseString); +} + +void ApplicationSettings::setLicenseCheck(const std::string& hash) +{ + setValue("application/license/check", hash); +} diff --git a/src/lib/settings/ApplicationSettings.h b/src/lib/settings/ApplicationSettings.h index d1264188..9bff9c34 100644 --- a/src/lib/settings/ApplicationSettings.h +++ b/src/lib/settings/ApplicationSettings.h @@ -63,6 +63,13 @@ public: int getControlsMouseBackButton() const; int getControlsMouseForwardButton() const; + // license + std::string getLicenseString() const; + void setLicenseString(const std::string& licenseString); + + std::string getLicenseCheck() const; + void setLicenseCheck(const std::string& hash); + private: ApplicationSettings(); ApplicationSettings(const ApplicationSettings&); diff --git a/src/lib_gui/CMakeLists.txt b/src/lib_gui/CMakeLists.txt index e717ed66..8acd35ef 100644 --- a/src/lib_gui/CMakeLists.txt +++ b/src/lib_gui/CMakeLists.txt @@ -107,6 +107,8 @@ add_files( qt/window/QtAboutLicense.h qt/window/QtApplicationSettingsScreen.cpp qt/window/QtApplicationSettingsScreen.h + qt/window/QtLicense.cpp + qt/window/QtLicense.h qt/window/QtMainWindow.cpp qt/window/QtMainWindow.h qt/window/QtProjectSetupScreen.cpp diff --git a/src/lib_gui/qt/window/QtAbout.cpp b/src/lib_gui/qt/window/QtAbout.cpp index 88eabf67..3a2ed98c 100644 --- a/src/lib_gui/qt/window/QtAbout.cpp +++ b/src/lib_gui/qt/window/QtAbout.cpp @@ -95,12 +95,7 @@ void QtAbout::setup() closeButton->setObjectName("closeButton"); closeButton->move(320, 20); - connect(closeButton, SIGNAL(clicked()), this, SLOT(handleCloseButtonPress())); -} - -void QtAbout::handleCloseButtonPress() -{ - emit finished(); + connect(closeButton, SIGNAL(clicked()), this, SLOT(handleUpdateButtonPress())); } void QtAbout::handleCancelButtonPress() @@ -109,4 +104,5 @@ void QtAbout::handleCancelButtonPress() void QtAbout::handleUpdateButtonPress() { + emit finished(); } diff --git a/src/lib_gui/qt/window/QtAbout.h b/src/lib_gui/qt/window/QtAbout.h index d30c4d1a..c059469e 100644 --- a/src/lib_gui/qt/window/QtAbout.h +++ b/src/lib_gui/qt/window/QtAbout.h @@ -18,8 +18,6 @@ public: virtual void setup() override; private slots: - void handleCloseButtonPress(); - void handleCancelButtonPress(); void handleUpdateButtonPress(); }; diff --git a/src/lib_gui/qt/window/QtLicense.cpp b/src/lib_gui/qt/window/QtLicense.cpp new file mode 100644 index 00000000..38bfc83b --- /dev/null +++ b/src/lib_gui/qt/window/QtLicense.cpp @@ -0,0 +1,83 @@ +#include "qt/window/QtLicense.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "License.h" +#include "PublicKey.h" + +#include "settings/ApplicationSettings.h" +#include "utility/logging/logging.h" +#include "utility/file/FilePath.h" + +QtLicense::QtLicense(QWidget *parent) + : QtSettingsWindow(parent) +{ + raise(); +} + +QSize QtLicense::sizeHint() const +{ + return QSize(600,600); +} + +void QtLicense::setup() +{ + setupForm(); + + updateTitle("Enter License"); + updateDoneButton("Ok"); +} + +void QtLicense::populateForm(QFormLayout* layout) +{ + QLabel* licenseName = new QLabel(); + licenseName->setText( QString::fromLatin1("Enter License:")); + QFont _font = licenseName->font(); + _font.setPixelSize(36); + licenseName->setFont(_font); + layout->addWidget(licenseName); + + m_licenseText = new QTextEdit(); + m_licenseText->setMinimumHeight(300); + layout->addWidget(m_licenseText); +} + +void QtLicense::handleCancelButtonPress() +{ + emit canceled(); +} + +void QtLicense::handleUpdateButtonPress() +{ + License license; + bool isLoaded = license.loadFromString(m_licenseText->toPlainText().toStdString()); + if(!isLoaded) + { + LOG_WARNING("Failed Loading License"); + return; + } + license.loadPublicKeyFromString(PublicKey); + license.print(); + + if(license.isValid()) + { + ApplicationSettings::getInstance()->setLicenseString(license.getLicenseString()); + FilePath p(""); + ApplicationSettings::getInstance()->setLicenseCheck(license.hashLocation(p.absolute().str())); + ApplicationSettings::getInstance()->save(); + LOG_WARNING("License saved"); + } + else + { + LOG_WARNING("License is not valid"); + } + emit finished(); + +} + diff --git a/src/lib_gui/qt/window/QtLicense.h b/src/lib_gui/qt/window/QtLicense.h new file mode 100644 index 00000000..875b2fb9 --- /dev/null +++ b/src/lib_gui/qt/window/QtLicense.h @@ -0,0 +1,35 @@ +#ifndef QT_LICENSE_H +#define QT_LICENSE_H + +#include +#include +#include + +#include "qt/window/QtSettingsWindow.h" + +class QtLicense + : public QtSettingsWindow +{ + Q_OBJECT + +public: + QtLicense(QWidget* parent = 0); + QSize sizeHint() const Q_DECL_OVERRIDE; + + virtual void setup() override; +protected: + virtual void populateForm(QFormLayout* layout) override; + +private slots: + void handleCancelButtonPress(); + void handleUpdateButtonPress(); + +private: + QPushButton* m_cancelButton; + QPushButton* m_updateButton; + + QTextEdit* m_licenseText; + +}; + +#endif //QT_LICENSE_H diff --git a/src/lib_gui/qt/window/QtMainWindow.cpp b/src/lib_gui/qt/window/QtMainWindow.cpp index 31b21bbb..969dc091 100644 --- a/src/lib_gui/qt/window/QtMainWindow.cpp +++ b/src/lib_gui/qt/window/QtMainWindow.cpp @@ -338,6 +338,20 @@ void QtMainWindow::showLicenses() pushWindow(m_licenseWindow.get()); } +void QtMainWindow::enterLicense() +{ + if (!m_enterLicenseWindow) + { + m_enterLicenseWindow = std::make_shared(this); + m_enterLicenseWindow->setup(); + + connect(m_enterLicenseWindow.get(), SIGNAL(finished()), this, SLOT(popWindow())); + connect(m_enterLicenseWindow.get(), SIGNAL(canceled()), this, SLOT(popWindow())); + } + + pushWindow(m_enterLicenseWindow) +} + void QtMainWindow::showStartScreen() { if (!m_startScreen) @@ -625,10 +639,11 @@ void QtMainWindow::setupHelpMenu() menu->addAction(tr("&About"), this, SLOT(about())); menu->addAction(tr("Licences"), this, SLOT(showLicenses())); + if(!isTrial()) { + menu->addAction(tr("Enter License..."), this, SLOT(enterLicense())); menu->addAction(tr("Preferences..."), this, SLOT(openSettings())); - //Todo: Enter License Window } } diff --git a/src/lib_gui/qt/window/QtMainWindow.h b/src/lib_gui/qt/window/QtMainWindow.h index 18ecc3a1..f4685865 100644 --- a/src/lib_gui/qt/window/QtMainWindow.h +++ b/src/lib_gui/qt/window/QtMainWindow.h @@ -13,6 +13,7 @@ #include "qt/window/QtProjectSetupScreen.h" #include "qt/window/QtAboutLicense.h" #include "qt/window/QtAbout.h" +#include "qt/window/QtLicense.h" class QDockWidget; class View; @@ -94,6 +95,7 @@ public slots: void about(); void openSettings(); void showLicenses(); + void enterLicense(); void showStartScreen(); void newProject(); @@ -109,7 +111,6 @@ public slots: void saveProject(); void saveAsProject(); - void undo(); void redo(); void zoomIn(); @@ -161,6 +162,7 @@ private: std::shared_ptr m_newProjectDialog; std::shared_ptr m_licenseWindow; std::shared_ptr m_aboutWindow; + std::shared_ptr m_enterLicenseWindow; std::vector m_windowStack; diff --git a/src/test/CMakeLists.txt b/src/test/CMakeLists.txt index 810fc94a..fa7bf16f 100644 --- a/src/test/CMakeLists.txt +++ b/src/test/CMakeLists.txt @@ -16,6 +16,7 @@ add_files( FileManagerTestSuite.h FilePathTestSuite.h FileSystemTestSuite.h + GeneratorTestSuite.h GraphTestSuite.h LogManagerTestSuite.h MatrixBaseTestSuite.h diff --git a/src/test/GeneratorTestSuite.h b/src/test/GeneratorTestSuite.h new file mode 100644 index 00000000..c246d7ef --- /dev/null +++ b/src/test/GeneratorTestSuite.h @@ -0,0 +1,99 @@ +#include "cxxtest/TestSuite.h" + +#include "utility/text/TextAccess.h" + +#include "License.h" +#include "Generator.h" + +#include "botan_all.h" + +class GeneratorTestSuite : public CxxTest::TestSuite +{ +public: + + void test_create_Keys_with_Version_and_check() + { + Generator generator("v0"); + generator.generateKeys(); + + std::string privateKey = generator.getPrivateKeyPEMFileAsString(); + std::string publicKey = generator.getPublicKeyPEMFileAsString(); + + TS_ASSERT_EQUALS(privateKey.size(), 1886); + TS_ASSERT_EQUALS(publicKey.size(), 451); + } + + void test_load_private_Key_from_file() + { + Generator generator("v2"); + generator.setCustomPrivateKeyFile("./data/GeneratorTestSuite/private-v2.pem"); + bool ok = generator.loadPrivateKeyFromFile(); + + TS_ASSERT(ok); + } + + void test_load_private_key_from_string() + { + Generator generator("v0"); + bool ok = generator.loadPrivateKeyFromString(m_privateKey); + + TS_ASSERT(ok); + } + + void test_create_license_and_validate() + { + Generator generator("v2"); + generator.generateKeys(); + + generator.loadPrivateKeyFromString(generator.getPrivateKeyPEMFileAsString()); + License license; + license.create("TestUser", "v2", generator.getPrivateKey()); + license.loadPublicKeyFromString(generator.getPublicKeyPEMFileAsString()); + + TS_ASSERT_EQUALS(license.getOwnerLine(), "TestUser"); + TS_ASSERT_EQUALS(license.getLicenseTypeLine(), "Single User License"); + TS_ASSERT_EQUALS(license.getVersion(), "v2"); + TS_ASSERT(license.isValid()); + } + +private: + std::string m_privateKey = "-----BEGIN ENCRYPTED PRIVATE KEY-----\n" + "MIIFNTBfBgkqhkiG9w0BBQ0wUjAxBgkqhkiG9w0BBQwwJAQMWEDuADurEQ4T8kJO\n" + "AgMDDUACASAwDAYIKoZIhvcNAgkFADAdBglghkgBZQMEASoEEGNDHYI3xozW5JBg\n" + "pOLkhIMEggTQPwClVPQbk+AVqOAXndQqCs0Ad+eihbekCHt5zkRrYl6JbLq9fvfs\n" + "kGgn1j7xtFZflcZimlLaao8pLWybJfa3xGSJnlYrJsGVMlmKJw/ee3fZG7y4/Tgo\n" + "FytAIP51He4YAZ+4fOXyOoAT0+k2DBekZHeMADX7eXVpCLQXuoQpECvf2IPd/de4\n" + "QKS12FRTd7Hkq7DwYs5D7aBizftcsB6FDqwKvvrheglMHfMt3/ChV8u3F8Zuqnh5\n" + "S1NVl2b8geAnYWLEfN/V8SDu00heVHq+z2CIQrvonsTwN1c9ppgMC7/udcr4GEKU\n" + "kqn/2h1sVRdlCxHf9p2nKRdOUXbSgQi16dKnEim3j3QCLVeNeX5Z6Tkb5pJA397i\n" + "mbL0ihdUvbVcPMG9Rh8NONY+MkE4NKye+NHzWjsd+egaeA79qy/Xd4cJRG7GFy68\n" + "pBWhf/xNpkhXJNV+O/KLszZG6f/UNDPJHovTp47aetD2/EqasvuYkPpapfYuqiZh\n" + "3vtNlgL1uNIN/TjoSaut5+ifJonJnQBrMQdWLTN6I8/lZFfxZB4jLkHffLS/zTA+\n" + "tPLxBcfZiec9dJDmuJ+P55D/3E+p6CL++yw15cgBNPFHrvfatikHvQXkRJl03S6Q\n" + "FvrBmbjWKwT+iSZAvJrdkCeFO53CYA3tJ23GtG9pxBHP+VFyJSBu7MukjcCEMSbU\n" + "HduNcsIIo8/p/X/CXYxJGYIfbrqz0n4z0QkZvCtyJoexoqqjTGclWoN3//j8lenL\n" + "SbrPCwLEn1coGr6rx97LHDBjdR1WouWeGkQOyMF/dC70p4QyE3Ru0cbhsjAWeo7P\n" + "HpGgQHJllJBFM9OkymRD32NnTCtr5Vu6epfiAsi16rfg1j1H9f0hnPbfULx+Q2WM\n" + "sCzuUbKUcjRNXOhwDxQXGVrMXEjRzJKmqy2kpMFX/v38iKfqIx+pHMOs+/+ESwwp\n" + "frKZ2mUwa7DdDv6fZwPUPtZk/6HyqiDoJcoiN05IxdPt6SXGPsseQWcwTdiHhDX2\n" + "3YsTJK0O/CAf/ouqWQiZMAifTZtalTArTvTtlTE7TpAT3I0OmwNG/nI1v/orHBbZ\n" + "M7sa9mlBDMzE4rTHIYMOttNKLxkXRChjgO2JfFDLxscSMw8wsrbGTbKh7VGFgg7Q\n" + "Tj6KAGPiU7WbaXiIhO4adgYp3Bpbo15BhhO5bdaYzxBjOhYw1ShLEgBOC7MsOt3N\n" + "8oChFJB1Gls5+RU6Ef27az+RE6uSumToT1HKgYDYX1TN68WWjT7Pa0lUMtZ4Bv1f\n" + "rXMH8igPXg62kzh/hjnEtl8y2+ySAs7RnZ0vUywaKcI0Tu5tqJSLtXSfJKAPmmzE\n" + "QYsg70kpufXccznTYvLSbM99FIbC6s+cSkJ43Ku4dwbEal+9FfqK639i2X9hdsLc\n" + "bYXIb0Fguo2IbWruBeSIc8lukOKCOVjanVZhfOCev8ye/Wz+SS8zbEixWZMzMCzC\n" + "if4dF/CUHnJK32IVlqKr9XGEe8ympqwMqN0eOdJn8IB+BQGCcaF6805D3R/OG4FU\n" + "hedhIvg1cODtoi8ri41Pz7o1x9Ia0zZr7oxhQuSgHiTfRfFN0xhCFZ+sIfGNpgUs\n" + "54IZGQlI0nQHOK8h2NI0wp3uo+fDEjjVIjQxINOSBa5awSReBpBUW2I=\n" + "-----END ENCRYPTED PRIVATE KEY-----"; + std::string m_publicKey = "-----BEGIN PUBLIC KEY-----\n" + "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAugYah7LOU0ssdSnyDA8h\n" + "nOeW2lwE+NmZGxIKnqZKYNePY7Tg0c1pI0lfgJ2WYtxbubDFNDYk6bJF6mFg3jjN\n" + "gCdocj6pyyibIISbRst+gl/1FwI8vbIkfkJBoZtftO5mKVBbO5mmrxm32fDQs1vo\n" + "zgVxcWx3LXW87pzdQQYRACdkLSxPd+ADs+KNv6UxlOEvucDaenX3ckl3HdcWruL8\n" + "xdYoM7z/C+PRShSGvY3wB7Y6A5IcdBmzsTR6xayCmTzzW83dmFzjCX5DSOJLHxq7\n" + "+Fs26xZU83P1boX7eg4TjMViTxJwsCCW/2wfsZAoF0cSYCxhrkSdMHroH7Edz1PM\n" + "fwIDAQAB\n" + "-----END PUBLIC KEY-----\n"; +};