Merge branch 'feature/pc_identifiers' into develop
issues #2 #3 #14 #49
42个文件已修改
54个文件已添加
21 文件已重命名
9个文件已删除
| | |
| | | |
| | | #Visual studio files |
| | | .vs |
| | | /out |
| | | |
| | | # Compiled Static libraries |
| | | *.lai |
| | |
| | | projects/* |
| | | !projects/.gitkeep |
| | | |
| | | **/CMakeCache.txt |
| | | **/CMakeFiles |
| | | /CMakeSettings.json |
| | |
| | | - os: linux |
| | | dist: bionic |
| | | name: "Ubuntu 18.04 - Travis CI VM" |
| | | env: |
| | | - VIRTUAL_ENV=VM |
| | | addons: |
| | | apt: |
| | | packages: |
| | |
| | | - os: linux |
| | | dist: bionic |
| | | name: "Ubuntu 18.04 - Travis CI VM - Debug build" |
| | | env: |
| | | - VIRTUAL_ENV=VM |
| | | addons: |
| | | apt: |
| | | packages: |
| | |
| | | script: |
| | | - cmake --build . --target install |
| | | - ctest |
| | | - ctest -T memcheck |
| | | after_success: |
| | | # Create lcov report |
| | | - lcov --capture --directory . --output-file coverage.info |
| | |
| | | - lcov --list coverage.info # debug info |
| | | # Uploading report to CodeCov |
| | | - bash <(curl -s https://codecov.io/bash) -f coverage.info || echo "Codecov did not collect coverage reports" |
| | | |
| | | - os: linux |
| | | dist: bionic |
| | | name: "CentOS-7 Docker" |
| | |
| | | - docker commit centos8_toconfigure centos8_configured |
| | | script: |
| | | - docker run --name centos8_make -v `pwd`:/root/open-license-manager centos8_configured /bin/bash -c \ |
| | | "cd /root/open-license-manager/build && make && make install && VIRT_ENV=CONTAINER make test" |
| | | "cd /root/open-license-manager/build && make && make install && VIRTUAL_ENV=DOCKER make test" |
| | | - os: linux |
| | | dist: bionic |
| | | name: "Ubuntu 18.04 - MinGW cross-compile for Windows x64" |
| | |
| | | - libboost-system-dev |
| | | - libboost-thread-dev |
| | | - libboost-date-time-dev |
| | | - python3-pip |
| | | - doxygen |
| | | - graphviz |
| | | script: |
| | | - make docs |
| | | - pip3 install sphinx sphinx_rtd_theme breathe sphinx-markdown-tables recommonmark sphinx-rtd-theme |
| | | - make documentation |
| | | deploy: |
| | | provider: pages |
| | | skip_cleanup: true |
| | |
| | | keep_history: false |
| | | verbose: true |
| | | target_branch: "gh-pages" |
| | | local_dir: "build/html" |
| | | local_dir: "build/docs/sphinx" |
| | | on: |
| | | branch: develop |
| | | env: |
| | | - CTEST_OUTPUT_ON_FAILURE=1 |
| | | - CTEST_OUTPUT_ON_FAILURE=1 |
| | | before_script: |
| | | - cd build && cmake -DCMAKE_INSTALL_PREFIX=../../install .. |
| | | |
| | |
| | | ENDIF(NOT LCC_PROJECTS_BASE_DIR) |
| | | |
| | | cmake_policy(SET CMP0048 NEW) |
| | | #cmake_policy(SET CMP0091 NEW) |
| | | project (licensecc |
| | | VERSION 2.0.0 |
| | | DESCRIPTION "Copy protection and licensing library" |
| | | LANGUAGES C CXX) |
| | | LANGUAGES CXX) |
| | | |
| | | set(CMAKE_CXX_STANDARD 11) |
| | | set(CMAKE_CXX_STANDARD_REQUIRED ON) |
| | |
| | | SET(CMAKE_CROSSCOMPILING_EMULATOR "wine") |
| | | ENDIF() |
| | | |
| | | SET (OPENSSL_USE_STATIC_LIBS ON) |
| | | SET (OPENSSL_USE_STATIC_LIBS TRUE) |
| | | IF(${STATIC_RUNTIME}) |
| | | SET(OPENSSL_MSVC_STATIC_RT TRUE) |
| | | ENDIF(${STATIC_RUNTIME}) |
| | | find_package(OpenSSL COMPONENTS Crypto QUIET) |
| | | IF(OPENSSL_FOUND) |
| | | MESSAGE(STATUS "Found openssl version ${OPENSSL_VERSION}") |
| | | MESSAGE(STATUS "Found openssl version ${OPENSSL_VERSION} -licensecc") |
| | | ENDIF(OPENSSL_FOUND) |
| | | |
| | | if(UNIX) #this is true for all the linux systems but not for cross compiling "linux->windows" |
| | | IF(${STATIC_RUNTIME}) |
| | | set(CMAKE_EXE_LINKER_FLAGS "-static-libgcc -static-libstdc++ -static") |
| | | ENDIF(${STATIC_RUNTIME}) |
| | | IF(NOT OPENSSL_FOUND) |
| | | MESSAGE(SEND_ERROR "Openssl required in Linux, please install it or specify -DOPENSSL_ROOT") |
| | | ENDIF(NOT OPENSSL_FOUND) |
| | | |
| | | #Zlib required when openssl version < 1.0.1f (centos 7) |
| | | SET ( ZLIB_USE_STATIC_LIBS ON ) |
| | | find_package(ZLIB REQUIRED) |
| | | list(APPEND EXTERNAL_LIBS ${ZLIB_LIBRARIES}) |
| | | MESSAGE(STATUS "Found zlib version ${ZLIB_VERSION} ") |
| | | |
| | | find_package(Threads) |
| | | if(THREADS_HAVE_PTHREAD_ARG) |
| | |
| | | list(APPEND EXTERNAL_LIBS "${CMAKE_THREAD_LIBS_INIT}") |
| | | endif() |
| | | endif(THREADS_HAVE_PTHREAD_ARG) |
| | | |
| | | #Zlib required with old openssl version < 1.0.1f in centos 7 |
| | | IF(OPENSSL_VERSION VERSION_LESS_EQUAL 1.0.2) |
| | | SET ( ZLIB_USE_STATIC_LIBS ON ) |
| | | find_package(ZLIB REQUIRED) |
| | | list(APPEND EXTERNAL_LIBS ${ZLIB_LIBRARIES}) |
| | | MESSAGE(STATUS "Found zlib version ${ZLIB_VERSION_STRING} - licensecc") |
| | | ELSE(OPENSSL_VERSION VERSION_LESS_EQUAL 1.0.2) |
| | | MESSAGE(STATUS "openssl ${OPENSSL_VERSION} zlib not required - licensecc") |
| | | ENDIF(OPENSSL_VERSION VERSION_LESS_EQUAL 1.0.2) |
| | | |
| | | find_program( MEMORYCHECK_COMMAND valgrind ) |
| | | set( MEMORYCHECK_COMMAND_OPTIONS "--trace-children=yes --leak-check=full" ) |
| | | |
| | | if(USE_DBUS_IDENTIFIER) |
| | | FIND_PACKAGE(Dbus REQUIRED) |
| | | add_definitions(-DUSE_DBUS) |
| | | include_directories(${DBUS_INCLUDE_DIR}) |
| | | include_directories(${DBUS_ARCH_INCLUDE_DIR}) |
| | | list(APPEND EXTERNAL_LIBS ${DBUS_LIBRARIES}) |
| | | endif(USE_DBUS_IDENTIFIER) |
| | | set(main_lib_dest "lib/${PROJECT_NAME}") |
| | | else(UNIX) |
| | | IF(NOT OPENSSL_FOUND) |
| | |
| | | include(target_arch) |
| | | target_architecture( TARGET_ARCHITECTURE ) |
| | | message(STATUS "architecture detected: ${TARGET_ARCHITECTURE}") |
| | | |
| | | #cmake > 3.15 handle the /MD flag more nicely than this |
| | | if(${STATIC_RUNTIME}) |
| | | string(REPLACE "/MD" "/MT" CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}") |
| | | if(STATIC_RUNTIME) |
| | | message(STATUS "Static runtime ${STATIC_RUNTIME}") |
| | | string(REPLACE "/MD" "/MT" CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}") |
| | | string(REPLACE "/MDd" "/MTd" CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}") |
| | | string(REPLACE "/MDd" "/MTd" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}") |
| | | #list(APPEND CMAKE_CXX_FLAGS_DEBUG "/MTd") |
| | | SET(Boost_USE_STATIC_RUNTIME ON) |
| | | endif(${STATIC_RUNTIME}) |
| | | |
| | | endif(STATIC_RUNTIME) |
| | | add_definitions("/D _CRT_SECURE_NO_WARNINGS") |
| | | list(APPEND EXTERNAL_LIBS "bcrypt" "crypt32" "ws2_32" "iphlpapi") |
| | | else(MSVC) |
| | | if(MINGW) |
| | | list(APPEND EXTERNAL_LIBS "-lcrypt32 -lbcrypt -lws2_32 -liphlpapi") |
| | | SET(CMAKE_EXE_LINKER_FLAGS "-static") |
| | | if(MINGW) |
| | | list(APPEND EXTERNAL_LIBS "-lbcrypt" "-lcrypt32" "-lws2_32" "-liphlpapi") |
| | | SET(CMAKE_EXE_LINKER_FLAGS "-static -static-libstdc++") |
| | | endif(MINGW) |
| | | endif(MSVC) |
| | | set(main_lib_dest "${PROJECT_NAME}") |
| | |
| | | COMMENT "generating ${LCC_PROJECT_PUBLIC_KEY}" |
| | | USES_TERMINAL |
| | | ) |
| | | include_directories( ${LCC_INCLUDE_DIR} "${CMAKE_CURRENT_SOURCE_DIR}/include" ) |
| | | add_custom_target(project_initialize DEPENDS "${LCC_PROJECT_PUBLIC_KEY}" "${LCC_PROJECT_PRIVATE_KEY}") |
| | | include_directories( ${LCC_INCLUDE_DIR} ${CMAKE_BINARY_DIR} "${CMAKE_CURRENT_SOURCE_DIR}/include") |
| | | |
| | | message( STATUS "C compiler : " ${CMAKE_C_COMPILER}) |
| | | message( STATUS "C compiler flags : " ${CMAKE_C_FLAGS}) |
| | | message( STATUS "CXX compiler : " ${CMAKE_CXX_COMPILER}) |
| | | message( STATUS "CXX compiler flags: " ${CMAKE_CXX_FLAGS}) |
| | | message( STATUS "CXX compiler : " ${CMAKE_CXX_COMPILER}) |
| | | message( STATUS "CXX compiler flags : " ${CMAKE_CXX_FLAGS}) |
| | | message( STATUS "CXX compiler flags debug : " ${CMAKE_CXX_FLAGS_DEBUG}) |
| | | message( STATUS "CXX compiler flags release: " ${CMAKE_CXX_FLAGS_RELEASE}) |
| | | if(CMAKE_BUILD_TYPE) |
| | | message( STATUS "Build type : " ${CMAKE_BUILD_TYPE}) |
| | | message( STATUS "Build type : " ${CMAKE_BUILD_TYPE}) |
| | | endif(CMAKE_BUILD_TYPE) |
| | | message( STATUS "Install prefix : " ${CMAKE_INSTALL_PREFIX}) |
| | | message( STATUS "Project name : " ${LCC_PROJECT_NAME} ) |
| | | message( STATUS "Project base dir : " ${LCC_PROJECTS_BASE_DIR}/${LCC_PROJECT_NAME} ) |
| | | message( STATUS "Install prefix : " ${CMAKE_INSTALL_PREFIX}) |
| | | message( STATUS "Project name : " ${LCC_PROJECT_NAME} ) |
| | | message( STATUS "Project base dir : " ${LCC_PROJECTS_BASE_DIR}/${LCC_PROJECT_NAME} ) |
| | | |
| | | add_subdirectory(src) |
| | | |
| | |
| | | MARK_AS_ADVANCED(BUILDNAME) |
| | | add_subdirectory(test) |
| | | ENDIF(BUILD_TESTING) |
| | | add_subdirectory("src/inspector") |
| | | ELSE(Boost_FOUND) |
| | | message(WARNING "Boost not found, disabling tests") |
| | | ENDIF(Boost_FOUND) |
| | | |
| | | ################################# |
| | | # Documentation |
| | | ################################# |
| | | find_package(Doxygen COMPONENTS dot) |
| | | IF(Doxygen_FOUND) |
| | | find_package(Sphinx) |
| | | |
| | | IF(Doxygen_FOUND AND Sphinx_FOUND) |
| | | message(STATUS "Doxygen found, generating docs.") |
| | | SET(DOXYGEN_EXCLUDE_PATTERNS "*/library/ini/*;*/doc/resources/*") |
| | | SET(DOXYGEN_DISABLE_INDEX YES) |
| | | SET(DOXYGEN_GENERATE_TREEVIEW YES) |
| | | SET(DOXYGEN_GENERATE_XML YES) |
| | | SET(DOXYGEN_LAYOUT_FILE "${CMAKE_CURRENT_SOURCE_DIR}/doc/DoxygenLayout.xml") |
| | | doxygen_add_docs(docs doc src include/licensecc COMMENT "doxygen docs") |
| | | file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/doc/resources/" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/html") |
| | | ELSE(Doxygen_FOUND) |
| | | message(STATUS "Doxygen not found, not generating docs.") |
| | | ENDIF(Doxygen_FOUND) |
| | | #file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/doc/resources/" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/html") |
| | | |
| | | #file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/doc/sphinx/" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}") |
| | | set(SPHINX_SOURCE ${CMAKE_CURRENT_SOURCE_DIR}/doc) |
| | | set(SPHINX_BUILD ${CMAKE_CURRENT_BINARY_DIR}/docs/sphinx) |
| | | |
| | | add_custom_target(documentation |
| | | COMMAND |
| | | ${SPHINX_EXECUTABLE} -b html |
| | | ${SPHINX_SOURCE} ${SPHINX_BUILD} |
| | | -Dbreathe_projects.licensecc=${CMAKE_CURRENT_BINARY_DIR}/xml |
| | | WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} |
| | | COMMENT "Generating documentation with Sphinx") |
| | | add_dependencies(documentation docs) |
| | | |
| | | ELSE(Doxygen_FOUND AND Sphinx_FOUND) |
| | | message(STATUS "Doxygen or Sphynx not found, not generating docs.") |
| | | ENDIF(Doxygen_FOUND AND Sphinx_FOUND) |
| | | |
| | | |
| | | install(DIRECTORY ${LCC_INCLUDE_DIR} DESTINATION include/${PROJECT_NAME}) |
| | | install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include/ DESTINATION include) |
| | |
| | | |
| | | The following is a set of guidelines for contributing to Open License Manager and its packages, which are hosted in the [Open License Manager organization](https://github.com/open-license-manager) on GitHub. These are mostly guidelines, not rules. |
| | | |
| | | ## How to Contribute |
| | | ## How to contribute |
| | | |
| | | ### Interacting with the team |
| | | |
| | |
| | | - Very large pull requests with few comments, no corresponding issue explaining what's it about will probably be rejected. |
| | | - We understand that the project is still in beta stage, however we would like to discuss it with you before we take project changing decision. You can reach us on the [project forum](https://groups.google.com/forum/#!forum/licensecc). |
| | | - Even it it's in beta stage it's used ( _by some really courageous people!_ ) in production. We can't break current functionality, user established habits without documenting the change. |
| | | |
| | |
| | | [](https://codecov.io/gh/open-license-manager/open-license-manager) |
| | | [](http://github.com/open-license-manager/open-license-manager/issues) |
| | | |
| | | Protect the software you develop from unauthorized copies, |
| | | limit the usage in time, to a specific set of machines, or prevent the usage in |
| | | virtualized environments. It is an Open License Manager that helps to keep your |
| | | software closed :smirk: . A comprehensive [list of features](https://github.com/open-license-manager/open-license-manager/wiki/features), and their status is available in the project wiki. |
| | | Protect the software you develop from unauthorized copies, limit the usage in time, to a specific set of |
| | | machines, or prevent the usage in virtualized environments. It is an Open License Manager that helps to keep your |
| | | software closed :smirk: . Among other features if it runs on a "real hardware" it can generate a signature of that hardware and report if the signature doesn't match. |
| | | |
| | | A comprehensive [list of features](https://github.com/open-license-manager/open-license-manager/wiki/features), and their status is available in the project wiki. |
| | | |
| | | If you plan to use this library or part of it remember to show us your appreciation giving it a |
| | | <a class="github-button" href="https://github.com/open-license-manager/open-license-manager" data-icon="octicon-star" aria-label="Star open-license-manager/open-license-manager on GitHub">star</a> here on GitHub. |
| | | |
| | | ## License |
| | | The project is donated to the community. It comes with a very large freedom of use for everyone, and it will always be. |
| | | It uses a [BSD 3 clauses](https://opensource.org/licenses/BSD-3-Clause) licensing schema, that allows free modification and inclusion in commercial software. |
| | | |
| | | If you plan to use the project or part of it consider showing us your appreciation placing a star here on github. |
| | | ## Project Structure |
| | | The software is made by 2 main sub-components: |
| | | The software is made by 3 main sub-components: |
| | | - a C++ library with a nice C api, `licensecc` with minimal (or no) external dependencies (the part you have to integrate in your software) that is the project you're currently in. |
| | | - a license generator lcc-license-generator `lcc` for customizing the library and generate the licenses. |
| | | - a license debugger `lcc-inspector` to be sent to the final customer when there are licensing problems or for calculating the pc hash before issuing the license. |
| | | - a license generator (github project [lcc-license-generator](https://github.com/open-license-manager/lcc-license-generator)) `lcc` for customizing the library and generate the licenses. |
| | | |
| | | The following modules are planned... |
| | | - a license [backoffice](../../issues/7) in php (in order to handle multiple licenses). |
| | | - a license debugger to be sent to the final customer when there are licensing problems. |
| | | - a [log descriptor](../../issues/8) in order to decrypt logs generated by the license system. |
| | | |
| | | ## How to build |
| | | Below an overview of the basic build procedure, you can find detailed instructions for [linux](https://github.com/open-license-manager/open-license-manager/wiki/Build-the-library) or [windows](https://github.com/open-license-manager/open-license-manager/wiki/Build-the-library-windows) in the wiki. |
| | | |
New file |
| | |
| | | # - This module looks for Sphinx |
| | | # Find the Sphinx documentation generator |
| | | # |
| | | # This modules defines |
| | | # SPHINX_EXECUTABLE |
| | | # SPHINX_FOUND |
| | | find_program(SPHINX_EXECUTABLE |
| | | NAMES sphinx-build |
| | | PATHS |
| | | /usr/bin |
| | | /usr/local/bin |
| | | /opt/local/bin |
| | | ~/.local/bin |
| | | DOC "Sphinx documentation generator" |
| | | ) |
| | | |
| | | if( NOT SPHINX_EXECUTABLE ) |
| | | set(_Python_VERSIONS |
| | | 2.7 2.6 2.5 2.4 2.3 2.2 2.1 2.0 1.6 1.5 |
| | | ) |
| | | foreach( _version ${_Python_VERSIONS} ) |
| | | set( _sphinx_NAMES sphinx-build-${_version} ) |
| | | find_program( SPHINX_EXECUTABLE |
| | | NAMES ${_sphinx_NAMES} |
| | | PATHS |
| | | /usr/bin |
| | | /usr/local/bin |
| | | /opt/local/bin |
| | | ~/.local/bin |
| | | DOC "Sphinx documentation generator" |
| | | ) |
| | | endforeach() |
| | | endif() |
| | | |
| | | include(FindPackageHandleStandardArgs) |
| | | find_package_handle_standard_args(Sphinx DEFAULT_MSG SPHINX_EXECUTABLE) |
| | | mark_as_advanced(SPHINX_EXECUTABLE) |
| | | |
| | | function(Sphinx_add_target target_name builder conf source destination) |
| | | |
| | | add_custom_target(${target_name} ALL |
| | | COMMAND ${SPHINX_EXECUTABLE} -b ${builder} |
| | | -c ${conf} |
| | | ${source} |
| | | ${destination} |
| | | COMMENT "Generating sphinx documentation: ${builder}" |
| | | ) |
| | | |
| | | set_property(DIRECTORY |
| | | APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES ${destination} |
| | | ) |
| | | |
| | | endfunction() |
| | |
| | | set(CMAKE_C_COMPILER ${TOOLCHAIN_PREFIX}-gcc) |
| | | set(CMAKE_CXX_COMPILER ${TOOLCHAIN_PREFIX}-g++) |
| | | set(CMAKE_RC_COMPILER ${TOOLCHAIN_PREFIX}-windres) |
| | | set(CMAKE_CXX_LINK_EXECUTABLE ${TOOLCHAIN_PREFIX}-g++) |
| | | |
| | | # target environment on the build host system |
| | | # set 1st to dir with the cross compiler's C/C++ headers/libs |
| | | set(CMAKE_FIND_ROOT_PATH /usr/${TOOLCHAIN_PREFIX}) |
| | | |
| | | #if(CMAKE_CROSSCOMPILING) #cross compiling for linux... a crazy bug on my system |
| | | # link_directories(BEFORE /usr/lib/gcc/x86_64-w64-mingw32/7.3-win32) |
| | | #endif(CMAKE_CROSSCOMPILING) |
| | | # modify default behavior of FIND_XXX() commands to |
| | | # search for headers/libs in the target environment and |
| | | # search for programs in the build host environment |
File was renamed from doc/Development-And-Usage-Workflow.md |
| | |
| | | # Development and usage workflow |
| | | |
| | | Below a description of the planned development and usage process. Comments and progress are reported on [issue #42](https://github.com/open-license-manager/open-license-manager/issues/42) |
| | | |
| | |  |
| | |
| | | |
| | | ### Binary release contents |
| | | Binary release contains: |
| | | * open-license-manager executable (merge of the actual `license_generator` executable and `bootstrap`). |
| | | * open-license-manager executable (`lcc`). |
| | | * source code of the unconfigured library. |
| | | * source code of (part of) the tests. |
| | | |
| | |
| | | In this phase the library is configured, compiled (only for the tests sake), linked with a mock executable and tested together with the license generator. |
| | | |
| | | ## Initialize library |
| | | In this phase the signing keys are generated by open-license-manager executable (`olm`), and optionally the source code of the library may be modified or obfuscated. |
| | | In this phase the signing keys are generated by open-license-manager executable (`lcc`), and optionally the source code of the library may be modified or obfuscated. |
| | | |
| | | ### Test (2) |
| | | |
| | |
| | | * If we want to link the execution to a specific hardware we need to send the product to the client without a license (or a demo executable, with the sole intent to generate the machine identifier). |
| | | * If we just want to send a demo product with an expiry date we prepare a license without the machine identifier. |
| | | |
| | | # Build process |
| | | From the process described above, (strange to say) the license generator (`olm`) configures itself as a build |
| | | ## Build process |
| | | From the process described above, (strange to say) the license generator (`lcc`) configures itself as a build |
| | | dependency of the licensing library, thus it needs to be built first. |
File was renamed from doc/features.md |
| | |
| | | # General features: |
| | | # Features: |
| | | |
| | | ## features and their status |
| | | | Feature | Implementation status | |
| | | |--------------------------------------|:---------------------:| |
| | | | Trial license with expiry date | :heavy_check_mark: | |
| | |
| | | | Java/C# bindings | Planned | |
| | | | Floating/network licenses | Planned | |
| | | |
| | | ## Issue a "demo" license with only expiry date. |
| | | ### Issue a "demo" license with only expiry date. |
| | | Software editors often want to release a trial license that is not linked to a specified machine, but just limit the usage in time or to some other feature (number of cpu, process memory). |
| | | See [execution limits](Implemented/Planned execution limits) section. |
| | | |
| | | ## Licenses linked to "physical" hardware id |
| | | ### Licenses linked to "physical" hardware id |
| | | Link the software to a physical hardware (a pc). In this scenario the software editor wants his software to be executed on a specific piece of hardware. We suppose the operating system is installed "bare to metal" and we're able to calculate an identifier of that hardware. This isn't always true for virtualized environments for which alternative strategies must be planned [eg. floating licenses (not yet implemented)]. See the section on [hardware identifiers](hardware-identifiers) for a detailed discussion of the use cases. |
| | | |
| | | Depending on the situation there are are different kinds of hardware id that can be used. See [execution limits](Implemented/Planned execution limits) section. |
| | | |
| | | ## Virtual machine detection |
| | | ### Virtual machine detection |
| | | Detect if the software is running in a virtualized environment and (optionally) forbid the execution. This is useful if software editors want to prevent the execution in virtual machines (lxc/dockers...) and be able to compute a meaningful hardware id. |
| | | Another use case is the software is to be used only in a specific class of virtualized environments. For instance it was initially packaged as a docker image, the software editor don't want it to be "extracted" and placed elsewhere. |
| | | |
| | | ## License retrieval |
| | | ### License retrieval |
| | | Open License Manager, when integrated into a licensed software will find its license file based on many different strategies. |
| | | It can handle multiple licenses at the same time. See the wiki page about [license retrieval](license-retrieval) for details. |
| | | |
| | | ## Licensed software features (partially implemented) |
| | | ### Licensed software features (partially implemented) |
| | | A licensed software may be composed by many features (functions) each one activable independently. Licensing system tells the licensed software which features are enabled, and which features are disabled. |
| | | |
| | | ## License Management (planned) |
| | | It is necessary to keep track of the licenses that have been issued, of the clients, and their pc identifier. |
| | | ### License Management (planned) |
| | | It is necessary to keep track of the licenses that have been issued, of the clients, and their hardware identifier. |
| | | A web application is planned that will provide integration with payment systems to allow licensed software customers to buy licenses. |
| | | |
| | | ## Customizable execution limits (planned) |
| | | ### Customizable execution limits (planned) |
| | | It should be easy to add and implement your own "execution limit": that is require/forbid some feature in the application execution environment. |
| | | |
| | | ## Java/C# bindings (planned) |
| | | ### Java/C# bindings (planned) |
| | | The application should support bindings to java language. The library has to be compiled as a .dll for use with JNI or C# integration layer. This is especially challenging on the api side. |
| | | Since the api is public, and the library is packaged as a separate .dll/.so everybody can compile a version of it always returning LICENSE_OK easily defeating the license schema. |
| | | |
| | | ## Floating licenses (planned) |
| | | ### Floating licenses (planned) |
| | | Limit the execution of the licensed software to a certain number of instances per license. |
| | | This can be done in multiple ways: |
| | | * without a central server, using broadcast or scanning the local network to find peers. |
| | |
| | | |
| | | Status of this implementation is tracked in [issue #4](https://github.com/open-license-manager/open-license-manager/issues/4) |
| | | |
| | | # Implemented/Planned execution limits |
| | | ## Implemented/Planned execution limits |
| | | Open License Manager can limit execution of licensed software based on some criteria, called "execution limits". |
| | | Depending on the execution environment some criteria may not be applicable: |
| | | |
| | |
| | | | concurrent execution | Planned | Planned | Planned | Planned | |
| | | | licensed sw version | Planned | Planned | Planned | Planned | |
| | | |
| | | ## Date |
| | | ### Date |
| | | This is the most common limit set on a license, allow the software to expire after the defined date. |
| | | |
| | | ## Disk label/Disk id |
| | | ### Disk label/Disk id |
| | | It is possible to limit the execution to a computer that has a certain disk connected. |
| | | This kind of limitation doesn't make sense in linux containerized environments. |
| | | |
| | | ## Cpu Number/Machine memory |
| | | ### Cpu Number/Machine memory |
| | | Allow to restrict the execution only to a machine with the specified amount of cpu or memory or less. This is useful in virtualized environments, to create a licensed software demo version with limited performaces or with limited scalability. |
| | | |
| | | Status of this implementation is tracked in [issue #4](https://github.com/open-license-manager/open-license-manager/issues/4) |
| | | |
| | | ## Virtualization type |
| | | ### Virtualization type |
| | | Allow the execution of the licensed software only on some type of hardware or virtualized environment eg. only bare to metal, only in virtual machine, only in docker. |
| | | |
| | | ## Licensed software version |
| | | ### Licensed software version |
| | | A licensed software may declare a version (eg 1.0.0). A license may span multiple releases of the software e.g. allow version 1.1.1 but not 2.0.0. |
| | | |
| | | # |
New file |
| | |
| | | |
| | | |
| | | |
| | | Documentation |
| | | ================== |
| | | .. doxygennamespace:: license |
| | | :project: licensecc |
| | | :members: |
New file |
| | |
| | | #!/usr/bin/env python3 |
| | | # -*- coding: utf-8 -*- |
| | | # |
| | | # licensecc documentation build configuration file, created by |
| | | # sphinx-quickstart on Sat Mar 14 13:43:01 2020. |
| | | # |
| | | # This file is execfile()d with the current directory set to its |
| | | # containing dir. |
| | | # |
| | | # Note that not all possible configuration values are present in this |
| | | # autogenerated file. |
| | | # |
| | | # All configuration values have a default; values that are commented out |
| | | # serve to show the default. |
| | | |
| | | # If extensions (or modules to document with autodoc) are in another directory, |
| | | # add these directories to sys.path here. If the directory is relative to the |
| | | # documentation root, use os.path.abspath to make it absolute, like shown here. |
| | | # |
| | | # import os |
| | | # import sys |
| | | # sys.path.insert(0, os.path.abspath('.')) |
| | | |
| | | |
| | | # -- General configuration ------------------------------------------------ |
| | | |
| | | # If your documentation needs a minimal Sphinx version, state it here. |
| | | # |
| | | # needs_sphinx = '1.0' |
| | | |
| | | # Add any Sphinx extension module names here, as strings. They can be |
| | | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom |
| | | # ones. |
| | | extensions = ['sphinx.ext.todo', |
| | | 'sphinx.ext.githubpages', 'breathe', 'recommonmark', 'sphinx_markdown_tables', 'sphinx_rtd_theme' ] |
| | | |
| | | # Breathe Configuration |
| | | breathe_default_project = "licensecc" |
| | | |
| | | # Add any paths that contain templates here, relative to this directory. |
| | | templates_path = ['_templates'] |
| | | |
| | | # The suffix(es) of source filenames. |
| | | # You can specify multiple suffix as a list of string: |
| | | # |
| | | # source_suffix = ['.rst', '.md'] |
| | | source_suffix = ['.rst', '.md'] |
| | | |
| | | # The master toctree document. |
| | | master_doc = 'index' |
| | | |
| | | # General information about the project. |
| | | project = 'licensecc' |
| | | copyright = '2020, Open License Manager' |
| | | author = 'Open License Manager' |
| | | |
| | | # The version info for the project you're documenting, acts as replacement for |
| | | # |version| and |release|, also used in various other places throughout the |
| | | # built documents. |
| | | # |
| | | # The short X.Y version. |
| | | version = '2.0.0' |
| | | # The full version, including alpha/beta/rc tags. |
| | | release = '2.0.0' |
| | | |
| | | # The language for content autogenerated by Sphinx. Refer to documentation |
| | | # for a list of supported languages. |
| | | # |
| | | # This is also used if you do content translation via gettext catalogs. |
| | | # Usually you set "language" from the command line for these cases. |
| | | language = None |
| | | |
| | | # List of patterns, relative to source directory, that match files and |
| | | # directories to ignore when looking for source files. |
| | | # This patterns also effect to html_static_path and html_extra_path |
| | | exclude_patterns = [] |
| | | |
| | | # The name of the Pygments (syntax highlighting) style to use. |
| | | pygments_style = 'sphinx' |
| | | |
| | | # If true, `todo` and `todoList` produce output, else they produce nothing. |
| | | todo_include_todos = True |
| | | |
| | | |
| | | # -- Options for HTML output ---------------------------------------------- |
| | | |
| | | # The theme to use for HTML and HTML Help pages. See the documentation for |
| | | # a list of builtin themes. |
| | | # |
| | | html_theme = 'sphinx_rtd_theme' |
| | | |
| | | # Theme options are theme-specific and customize the look and feel of a theme |
| | | # further. For a list of options available for each theme, see the |
| | | # documentation. |
| | | # |
| | | html_theme_options = { |
| | | 'titles_only': False |
| | | } |
| | | |
| | | # Add any paths that contain custom static files (such as style sheets) here, |
| | | # relative to this directory. They are copied after the builtin static files, |
| | | # so a file named "default.css" will overwrite the builtin "default.css". |
| | | html_static_path = ['_static'] |
| | | |
| | | # Custom sidebar templates, must be a dictionary that maps document names |
| | | # to template names. |
| | | # |
| | | # This is required for the alabaster theme |
| | | # refs: http://alabaster.readthedocs.io/en/latest/installation.html#sidebars |
| | | #html_sidebars = { |
| | | # '**': [ |
| | | # 'relations.html', # needs 'show_related': True theme option to display |
| | | # 'searchbox.html', |
| | | # ] |
| | | #} |
| | | |
| | | |
| | | # -- Options for HTMLHelp output ------------------------------------------ |
| | | |
| | | # Output file base name for HTML help builder. |
| | | htmlhelp_basename = 'licenseccdoc' |
| | | |
| | | |
| | | # -- Options for LaTeX output --------------------------------------------- |
| | | |
| | | latex_elements = { |
| | | # The paper size ('letterpaper' or 'a4paper'). |
| | | # |
| | | # 'papersize': 'letterpaper', |
| | | |
| | | # The font size ('10pt', '11pt' or '12pt'). |
| | | # |
| | | # 'pointsize': '10pt', |
| | | |
| | | # Additional stuff for the LaTeX preamble. |
| | | # |
| | | # 'preamble': '', |
| | | |
| | | # Latex figure (float) alignment |
| | | # |
| | | # 'figure_align': 'htbp', |
| | | } |
| | | |
| | | # Grouping the document tree into LaTeX files. List of tuples |
| | | # (source start file, target name, title, |
| | | # author, documentclass [howto, manual, or own class]). |
| | | latex_documents = [ |
| | | (master_doc, 'licensecc.tex', 'licensecc Documentation', |
| | | 'Open License Manager', 'manual'), |
| | | ] |
| | | |
| | | |
| | | # -- Options for manual page output --------------------------------------- |
| | | |
| | | # One entry per manual page. List of tuples |
| | | # (source start file, name, description, authors, manual section). |
| | | man_pages = [ |
| | | (master_doc, 'licensecc', 'licensecc Documentation', |
| | | [author], 1) |
| | | ] |
| | | |
| | | |
| | | # -- Options for Texinfo output ------------------------------------------- |
| | | |
| | | # Grouping the document tree into Texinfo files. List of tuples |
| | | # (source start file, target name, title, author, |
| | | # dir menu entry, description, category) |
| | | texinfo_documents = [ |
| | | (master_doc, 'licensecc', 'licensecc Documentation', |
| | | author, 'licensecc', 'One line description of project.', |
| | | 'Miscellaneous'), |
| | | ] |
| | | |
| | | |
| | | |
File was renamed from doc/Build-the-library-windows.md |
| | |
| | | @ingroup group_02 |
| | | # Windows |
| | | |
| | | This page describes how to build the library. It's a good starting point if you just downloaded it and you want to start explore. |
| | | |
File was renamed from doc/Build-the-library.md |
| | |
| | | @ingroup group_01 |
| | | |
| | | # Linux |
| | | |
| | | ## Install prerequisites |
File was renamed from doc/Dependencies.md |
| | |
| | | # Dependencies |
| | | |
| | | This page describes the dependencies of open-license-manager and the supported build environments. |
| | | |
| | | Dependencies varies with the environment, if you're building the library for the first time we suggest you download or set up one of the supported environments to be sure not to incur in dependency/compiler errors (you can use virtual machines , docker or lxc/lxd technologies). |
File was renamed from doc/Development-Environment-Setup.md |
| | |
| | | |
| | | # Developer's environment setup |
| | | This guide is just an help in case you haven't decided your development environment or your development environment match ours. |
| | | We don't have any specific dependency on development tools, you can choose the one you prefer. Though if you want to contribute |
| | | you're required to format the code using `clang-format` before you submit the pull request. |
New file |
| | |
| | | |
| | | Welcome to licensecc's documentation. |
| | | ===================================== |
| | | |
| | | * :ref:`genindex` |
| | | * :ref:`modindex` |
| | | * :ref:`search` |
| | | |
| | | |
| | | .. toctree:: |
| | | :glob: |
| | | :maxdepth: 2 |
| | | :hidden: |
| | | :caption: Build the library: |
| | | |
| | | development/* |
| | | |
| | | .. toctree:: |
| | | :glob: |
| | | :maxdepth: 2 |
| | | :hidden: |
| | | :caption: Integrate and use: |
| | | |
| | | usage/* |
| | | |
| | | |
| | | .. toctree:: |
| | | :glob: |
| | | :maxdepth: 2 |
| | | :hidden: |
| | | :caption: API: |
| | | |
| | | api/* |
| | | |
| | | .. toctree:: |
| | | :glob: |
| | | :maxdepth: 2 |
| | | :hidden: |
| | | :caption: Analysis: |
| | | |
| | | analysis/* |
| | | |
| | | .. toctree:: |
| | | :glob: |
| | | :maxdepth: 2 |
| | | :hidden: |
| | | :caption: Miscellaneous: |
| | | |
| | | other/* |
| | | |
New file |
| | |
| | | # Credits |
| | | The following open source code has been used in OpenLicenseManager. |
| | | Thanks to every one of the authors of such projects. Without you open license manager would never have been completed. |
| | | |
| | | |
| | | ## isVM |
| | | Thanks for the great smbios parsing code. It saved me days. |
| | | |
| | | isvm : https://github.com/0of/isvm |
| | | |
| | | The MIT License (MIT) |
| | | |
| | | Copyright (c) 2015 Magnus |
| | | |
| | | Permission is hereby granted, free of charge, to any person obtaining a copy |
| | | of this software and associated documentation files (the "Software"), to deal |
| | | in the Software without restriction, including without limitation the rights |
| | | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
| | | copies of the Software, and to permit persons to whom the Software is |
| | | furnished to do so, subject to the following conditions: |
| | | |
| | | The above copyright notice and this permission notice shall be included in all |
| | | copies or substantial portions of the Software. |
| | | |
| | | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| | | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| | | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
| | | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| | | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
| | | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
| | | SOFTWARE. |
| | | |
| | | |
File was renamed from doc/QA.md |
| | |
| | | # Q&A |
| | | |
| | | ## Development |
| | | Development related questions. |
| | | |
File was renamed from doc/Basic-concepts.md |
| | |
| | | #Basic concepts and terminology |
| | | # Glossary |
| | | |
| | | ##Project |
| | | Some `common` word that recur into the documentation have a specific meaning. Below an explanation of the terms and concepts used. |
| | | |
| | | ## Project |
| | | A project corresponds to one application where the licensing system need to be integrated. |
| | | Each project has its own private key and its own folder where `licensecc` is compiled. |
| | | Currently we support only one project per (build) machine. This is especially true in Windows, where the private key has the same name for all the projects. |
| | | |
| | | ##Features |
| | | ## Features |
| | | Features let licensed application to selectively enable or disable functions in the application, features are part of the original license, they do not have hardware identifications, they only have validity date. |
| | | |
| | | |
| | | #Customizing the build |
| | |
| | | echo "Boost installed" |
| | | cd C:/local/boost |
| | | dir |
| | | ) else echo "Boost already installed" |
| | | ) else echo "Boost already installed" |
| | | |
| | | linux cross compile for windows openssl |
| | | |
| | | ./Configure no-zlib no-shared --prefix=$PWD/dist-win-64 --cross-compile-prefix=x86_64-w64-mingw32- mingw64 |
| | | /usr/local/bin/cmake -DCMAKE_TOOLCHAIN_FILE=../cmake/toolchain-ubuntu-mingw64.cmake -DCMAKE_INSTALL_PREFIX=../../install -DBOOST_ROOT=$PWD/../../boost_1_69_0/dist-win-x64/ -DOPENSSL_ROOT_DIR=$PWD/../../openssl-OpenSSL_1_1_1d/dist-win-64/ -DBoost_ARCHITECTURE="-x64" -DCMAKE_CXX_COMPILER_ARCHITECTURE_ID="x64" -DCMAKE_SH="CMAKE_SH-NOTFOUND" -DCMAKE_VERBOSE_MAKEFILE=ON -DLOGS_DISABLED=ON .. |
New file |
| | |
| | | /********************* physical_processors.cpp ***************************** |
| | | * Author: Agner Fog |
| | | * Date created: 2019-10-29 |
| | | * Last modified: 2019-11-25 |
| | | * Version: 1.02 beta |
| | | * Project: vector class library |
| | | * Description: Detect number of physical and logical processors on CPU chip. |
| | | * Compile for C++11 or later |
| | | * |
| | | * (c) Copyright 2019 Agner Fog. |
| | | * Apache License version 2.0 or later. |
| | | ******************************************************************************* |
| | | Some modern CPUs can run two threads in each CPU core when simultaneous |
| | | multithreading (SMT, called hyperthreading by Intel) is enabled. |
| | | |
| | | The number of physical processors is the number of CPU cores. |
| | | The number of logical processors is the same number multiplied by the number of |
| | | threads that can run simultaneously in each CPU core. |
| | | |
| | | Simultaneous multithreading will slow down performance when two CPU-intensive |
| | | threads running in the same physical processor (CPU core) are competing for the |
| | | same resources. Therefore, the optimal number of threads for CPU-intensive |
| | | tasks is most likely to be the number of physical processors. |
| | | |
| | | Tasks that are less CPU-intensive but limited by RAM access, disk access, |
| | | network, etc. may get an advantage by running as many threads as the number of |
| | | logical processors. This will be double the number of physical processors when |
| | | simultaneous multithreading is enabled. |
| | | |
| | | The physicalProcessors function detects the number of physical processors and |
| | | logical processors on an x86 computer. This is useful for determining the |
| | | optimal number of threads. |
| | | |
| | | |
| | | Note: There are several problems in detecting the number of physical processors: |
| | | |
| | | 1. The CPUID instruction on Intel CPUs will return a wrong number of logical |
| | | processors when SMT (hyperthreading) is disabled. It may be necessary to |
| | | compare the number of processors returned by the CPUID instruction with the |
| | | number of processors reported by the operating system to detect if SMT is |
| | | enabled (AMD processors do not have this problem). |
| | | |
| | | 2. It is necessary to rely on system functions to detect if there is more than |
| | | one CPU chip installed. It is assumed that the status of SMT is the same on |
| | | all CPU chips in a system. |
| | | |
| | | 3. The behavior of VIA processors is undocumented. |
| | | |
| | | 4. This function is not guaranteed to work on future CPUs. It may need updating |
| | | when new CPUs with different configurations or different CPUID functionality |
| | | appear. |
| | | ******************************************************************************/ |
| | | |
| | | #include <thread> // std::thread functions |
| | | |
| | | #ifdef _MSC_VER |
| | | #include <intrin.h> // __cpuidex intrinsic function available on microsoft compilers |
| | | #endif |
| | | |
| | | // Define interface to CPUID instruction. |
| | | // input: leaf = eax, subleaf = ecx |
| | | // output: output[0] = eax, output[1] = ebx, output[2] = ecx, output[3] = edx |
| | | static inline void cpuid(int output[4], int leaf, int subleaf = 0) { |
| | | #if defined(__GNUC__) || defined(__clang__) // use inline assembly, Gnu/AT&T syntax |
| | | int a, b, c, d; |
| | | __asm("cpuid" : "=a"(a), "=b"(b), "=c"(c), "=d"(d) : "a"(leaf), "c"(subleaf) : ); |
| | | output[0] = a; |
| | | output[1] = b; |
| | | output[2] = c; |
| | | output[3] = d; |
| | | |
| | | #elif defined (_MSC_VER) // Microsoft compiler, intrin.h included |
| | | __cpuidex(output, leaf, subleaf); // intrinsic function for CPUID |
| | | |
| | | #else // unknown platform. try inline assembly with masm/intel syntax |
| | | __asm { |
| | | mov eax, leaf |
| | | mov ecx, subleaf |
| | | cpuid; |
| | | mov esi, output |
| | | mov[esi], eax |
| | | mov[esi + 4], ebx |
| | | mov[esi + 8], ecx |
| | | mov[esi + 12], edx |
| | | } |
| | | #endif |
| | | } |
| | | |
| | | // Function prototype: |
| | | int physicalProcessors(int * logical_processors = 0); |
| | | |
| | | |
| | | // Find the number of physical and logical processors supported by CPU |
| | | // Parameter: |
| | | // logical_processors: an optional pointer to an integer that will receive the number of logical processors. |
| | | // Return value: number of physical processors |
| | | int physicalProcessors(int * logical_processors) { |
| | | int vendor = 0; // CPU vendor: 1 = Intel, 2 = AMD, 3 = VIA, 0 = other |
| | | int logicalProc = 1; // number of logical processor cores |
| | | int physicalProc = 1; // number of physical processor cores |
| | | int procPerCore = 1; // logical cores per physical core |
| | | bool hyperthreadingSupported = false; // CPU supports hyperthreading / simultaneous multithreading |
| | | int systemProcessors = std::thread::hardware_concurrency(); // number of processors reported by operating system |
| | | |
| | | int abcd[4] = { 0,0,0,0 }; // CPUID output |
| | | cpuid(abcd, 0); // CPUID function 0 |
| | | |
| | | int maxLeaf = abcd[0]; // maximum eax input for CPUID |
| | | if (abcd[2] == 0x6C65746E) { // last 4 chars of "GenuineIntel" |
| | | vendor = 1; |
| | | } |
| | | else if (abcd[2] == 0x444D4163) { // last 4 chars of "AuthenticAMD" |
| | | vendor = 2; |
| | | } |
| | | else if (abcd[2] == 0x736C7561) { // last 4 chars of "CentaurHauls" |
| | | vendor = 3; |
| | | } |
| | | |
| | | if (maxLeaf >= 1) { |
| | | cpuid(abcd, 1); |
| | | if (abcd[3] & (1 << 28)) { // hyperthreading supported |
| | | hyperthreadingSupported = true; |
| | | } |
| | | } |
| | | |
| | | if (vendor == 1) { |
| | | ////////////////// |
| | | // Intel // |
| | | ////////////////// |
| | | |
| | | int hyper = 0; // hyperthreading status: 0 = unknown, 1 = disabled, 2 = enabled |
| | | if (maxLeaf >= 0xB) { // leaf 0xB or 0x1F: Extended Topology Enumeration |
| | | int num = 0xB; |
| | | // if (maxLeaf >= 0x1F) num = 0x1F; |
| | | |
| | | for (int c = 0; c < 5; c++) { |
| | | cpuid(abcd, num, c); // enumeration level c |
| | | int type = (abcd[2] >> 8) & 0xFF;// enumeration type at level c |
| | | if (type == 1) { // SMT level |
| | | procPerCore = abcd[1] & 0xFFFF; |
| | | } |
| | | else if (type >= 2) { // core level |
| | | logicalProc = abcd[1] & 0xFFFF; |
| | | } |
| | | else if (type == 0) break; |
| | | // There are more types/levels to consider if we use num = 0x1F. We may need |
| | | // to fix this in the future if CPUs with more complex configurations appear |
| | | } |
| | | physicalProc = logicalProc / procPerCore; |
| | | |
| | | // The number of performance monitor registers depends on hyperthreading status |
| | | // on Intel CPUs with performance monitoring version 3 or 4 |
| | | cpuid(abcd, 0xA, 0); // performance monitor counters information |
| | | int perfVersion = abcd[0] & 0xFF; // performance monitoring version |
| | | int perfNum = (abcd[0] >> 8) & 0xFF; // number of performance monitoring registers |
| | | if (perfVersion == 3 || perfVersion == 4) { |
| | | if (perfNum == 4) { |
| | | hyper = 2; // 4 performance registers when hyperthreading enabled |
| | | } |
| | | else if (perfNum == 8) { // 8 performance registers when hyperthreading disabled |
| | | hyper = 1; |
| | | procPerCore = 1; |
| | | logicalProc = physicalProc; // reduce the number of logical processors when hyperthreading is disabled |
| | | } |
| | | // hyper remains 0 in all other cases, indicating unknown status |
| | | } |
| | | } |
| | | else if (maxLeaf >= 4) { // CPUID function 4: cache parameters and cores |
| | | cpuid(abcd, 4); |
| | | logicalProc = (abcd[0] >> 26) + 1; |
| | | if (hyperthreadingSupported) { |
| | | // number of logical processors per core is not known. Assume 2 if hyperthreading supported |
| | | procPerCore = 2; |
| | | } |
| | | physicalProc = logicalProc / procPerCore; |
| | | } |
| | | else { |
| | | // no information. Assume 1 processor |
| | | } |
| | | if (systemProcessors > logicalProc) { |
| | | // Multiple CPU chips. Assume that chips are identical with respect to hypethreading |
| | | physicalProc = systemProcessors * physicalProc / logicalProc; |
| | | logicalProc = systemProcessors; |
| | | } |
| | | else if (logicalProc > systemProcessors && systemProcessors > 0 && hyper == 0) { |
| | | // Hyperthreading is disabled |
| | | logicalProc = systemProcessors; |
| | | physicalProc = systemProcessors; |
| | | } |
| | | } |
| | | else if (vendor == 2) { |
| | | |
| | | ////////////////// |
| | | // AMD // |
| | | ////////////////// |
| | | |
| | | cpuid(abcd, 0x80000000); // AMD specific CPUID functions |
| | | int maxLeaf8 = abcd[0] & 0xFFFF; // maximum eax 0x8000.... input for CPUID |
| | | |
| | | if (maxLeaf8 >= 8) { |
| | | cpuid(abcd, 0x80000008); |
| | | logicalProc = (abcd[2] & 0xFF) + 1; |
| | | |
| | | if (maxLeaf8 >= 0x1E) { |
| | | cpuid(abcd, 0x8000001E); |
| | | procPerCore = ((abcd[1] >> 8) & 0x03) + 1; |
| | | // procPerCore = 2 if simultaneous multithreading is enabled, 1 if disabled |
| | | } |
| | | else { |
| | | if (hyperthreadingSupported) { |
| | | procPerCore = 2; |
| | | } |
| | | else { |
| | | procPerCore = 1; |
| | | } |
| | | } |
| | | physicalProc = logicalProc / procPerCore; |
| | | } |
| | | else if (hyperthreadingSupported) { |
| | | // number of logical processors per core is not known. Assume 2 if SMT supported |
| | | logicalProc = 2; |
| | | physicalProc = 1; |
| | | } |
| | | if (systemProcessors > logicalProc) { |
| | | // Multiple CPU chips. Assume that chips are identical with respect to SMT |
| | | physicalProc = systemProcessors * physicalProc / logicalProc; |
| | | logicalProc = systemProcessors; |
| | | } |
| | | } |
| | | else { |
| | | |
| | | ////////////////////////////// |
| | | // VIA or unknown CPU // |
| | | ////////////////////////////// |
| | | |
| | | // The behavior of VIA processors is undocumented! It is not known how to detect threads on a VIA processor |
| | | physicalProc = logicalProc = systemProcessors; |
| | | if (hyperthreadingSupported && physicalProc > 1) { |
| | | physicalProc /= 2; |
| | | } |
| | | } |
| | | if (logical_processors) { |
| | | // return logical_processors if pointer is not null |
| | | *logical_processors = logicalProc; |
| | | } |
| | | return physicalProc; |
| | | } |
| | | |
| | | /* Uncomment this for testing: |
| | | |
| | | #include <stdio.h> |
| | | |
| | | int main() { |
| | | |
| | | int logicalProc = 0; |
| | | int physicalProc = physicalProcessors(&logicalProc); |
| | | |
| | | printf("\nlogical processors: %i", logicalProc); |
| | | printf("\nphysical processors: %i", physicalProc); |
| | | printf("\nlogical processors per core: %i", logicalProc / physicalProc); |
| | | int sysproc = std::thread::hardware_concurrency(); |
| | | printf("\nsystem processors: %i", sysproc); |
| | | |
| | | return 0; |
| | | } |
| | | */ |
File was renamed from doc/Hardware-identifiers.md |
| | |
| | | # Hardware Identifiers |
| | | |
| | | ## Use cases |
| | | Linking the execution of a software to a. With the recent coming of virtualized environments the installation of software directly on the machine has been less and less. |
| | | Linking the execution of a software to a physical hardware (a pc). With the recent coming of virtualized environments |
| | | the installation of software directly on the machine has been less and less. |
| | | |
| | | OpenLicenseManager guess the environment where the user is trying to launch the software, and reports it to the software publisher when he is generating a license in a way that he can decide how to limit the usage on per license basis. |
| | | |
| | |
| | | This is straightforward case. If the software is executing on a physical hardware it is possible to identify the hardware by various parameters (cpu type/memory/disk label/mac address) |
| | | |
| | | ### Execution in a virtual machine |
| | | Generating a pc identifier on a virtual machine doesn't make much sense, since the vm can be copied as a whole elsewhere |
| | | Generating a hardware identifier on a virtual machine doesn't make much sense, since the vm can be copied as a whole elsewhere |
| | | and there are few ways to detect this without using an external license server. |
| | | |
| | | * Usually when the machine is copied the MAC address is changed. But sometimes it changes on its own. Software publishers may want to use this as a last resort to prevent the vm for being cloned. It has to be verified case by case. |
| | |
| | | |
| | | |
| | | If the licensed software specify the parameter |
| | | If the licensed software uses `STRATEGY_DEFAULT` and the strategy generates an unstable identifier it is possible to ask the user to set t |
| | | If the licensed software uses `STRATEGY_DEFAULT` and the strategy generates an unstable identifier it is possible to ask the user to |
| | | set the environemnt variable. |
File was renamed from doc/License-retrieval.md |
| | |
| | | # License retrieval |
| | | # Place the license file |
| | | |
| | | Open License Manager, when integrated into a licensed software can automatically find its license file (or multiple license files) based on: |
| | | |
| | | * An environment variable: |
File was renamed from doc/Integration.md |
| | |
| | | # Integrate license in your application |
| | | |
| | | This short guide explain how to integrate `open-license-manager` in your application. |
| | | |
| | | Working examples are provided in the [examples](https://github.com/open-license-manager/examples) project. |
| | |
| | | The file containing the public api is `include/licensecc/licensecc.h`. Functions in there are considered stable. |
| | | |
| | | |
| | | ### Print a pc identifier |
| | | ### Print a hardware identifier |
| | | |
| | | ```CPP |
| | | bool identify_pc(IDENTIFICATION_STRATEGY pc_id_method, char* identifier_out, size_t bufSize); |
File was renamed from doc/Issue-licenses.md |
| | |
| | | # Issue licenses |
| | | |
| | | The easiest way to issue licenses is to enter the project library and create the following project structure: |
| | | The projects folder can be anyware. We created one in `open-license-manager/projects` for your convenience (and for testing purposes). A default project<sup>1</sup> named `DEFAULT` has been created for you when you configured the project with cmake. |
| | |
| | | #define DllExport __declspec(dllexport) |
| | | #endif |
| | | |
| | | // define api structure sizes |
| | | #define PC_IDENTIFIER_SIZE 19 |
| | | #define PROPRIETARY_DATA_SIZE 16 |
| | | #define AUDIT_EVENT_NUM 5 |
| | | #define AUDIT_EVENT_PARAM2 255 |
| | | #define VERSION_SIZE 15 |
| | | #define PROJECT_NAME_SIZE 15 |
| | | #define EXPIRY_DATE_SIZE 10 |
| | | |
| | | #define ERROR_BUFFER_SIZE 256 |
| | | #include <licensecc_properties.h> |
| | | |
| | | typedef enum { |
| | | LICENSE_OK = 0, // OK |
| | |
| | | FILE_FORMAT_NOT_RECOGNIZED = 4, // license file has invalid format (not .ini file) |
| | | LICENSE_MALFORMED = 5, // some mandatory field are missing, or data can't be fully read. |
| | | PRODUCT_NOT_LICENSED = 6, // this product was not licensed |
| | | PRODUCT_EXPIRED = 7, |
| | | PRODUCT_EXPIRED = 7, //!< PRODUCT_EXPIRED |
| | | LICENSE_CORRUPTED = 8, // License signature didn't match with current license |
| | | IDENTIFIERS_MISMATCH = 9, // Calculated identifier and the one provided in license didn't match |
| | | |
| | | LICENSE_SPECIFIED = 100, // license location was specified |
| | | LICENSE_FOUND = 101, // License file has been found or license data has been located |
| | | PRODUCT_FOUND = 102, // License has been loaded and the declared product has been found |
| | | SIGNATURE_VERIFIED = 103 |
| | | } EVENT_TYPE; |
| | | SIGNATURE_VERIFIED = 103//!< SIGNATURE_VERIFIED |
| | | } LCC_EVENT_TYPE; |
| | | |
| | | typedef enum { |
| | | LOCAL, |
| | | REMOTE // remote licenses are not supported now. |
| | | } LICENSE_TYPE; |
| | | LCC_LOCAL, |
| | | LCC_REMOTE // remote licenses are not supported now. |
| | | } LCC_LICENSE_TYPE; |
| | | |
| | | typedef enum { SVRT_INFO, SVRT_WARN, SVRT_ERROR } SEVERITY; |
| | | typedef enum { SVRT_INFO, SVRT_WARN, SVRT_ERROR } LCC_SEVERITY; |
| | | |
| | | typedef struct { |
| | | SEVERITY severity; |
| | | EVENT_TYPE event_type; |
| | | LCC_SEVERITY severity; |
| | | LCC_EVENT_TYPE event_type; |
| | | /** |
| | | * License file name or location where the license is stored. |
| | | */ |
| | | char license_reference[MAX_PATH]; |
| | | char param2[AUDIT_EVENT_PARAM2 + 1]; |
| | | char param2[LCC_API_AUDIT_EVENT_PARAM2 + 1]; |
| | | } AuditEvent; |
| | | |
| | | typedef enum { |
| | | /** |
| | | * A list of absolute path separated by ';' containing the eventual location |
| | | * of the license files. Can be NULL. |
| | | */ |
| | | LICENSE_PATH, |
| | | /** |
| | | * The license is provided as plain data |
| | | */ |
| | | LICENSE_PLAIN_DATA, |
| | | /** |
| | | * The license is encoded |
| | | */ |
| | | LICENSE_ENCODED |
| | | } LCC_LICENSE_DATA_TYPE; |
| | | |
| | | /** |
| | | * This structure contains informations on the raw license data. Software authors |
| | |
| | | * license file location on its own. |
| | | */ |
| | | typedef struct { |
| | | /** |
| | | * A list of absolute path separated by ';' containing the eventual location |
| | | * of the license files. Can be NULL. |
| | | */ |
| | | const char *licenseFileLocation; |
| | | /** |
| | | * The application can provide the full license content through this string. |
| | | * It can be both in encoded form (base64) or in plain. It's optional. |
| | | */ |
| | | const char *licenseData; |
| | | LCC_LICENSE_DATA_TYPE license_data_type; |
| | | char licenseData[LCC_API_MAX_LICENSE_DATA_LENGTH]; |
| | | } LicenseLocation; |
| | | |
| | | /** |
| | | * Informations on the software requiring the license |
| | | */ |
| | | typedef struct { |
| | | char version[VERSION_SIZE + 1]; // software version in format xxxx.xxxx.xxxx |
| | | char project_name[PROJECT_NAME_SIZE + 1]; // name of the project (must correspond to the name in the license) |
| | | uint32_t magic; // reserved |
| | | char version[LCC_API_VERSION_LENGTH + 1]; // software version in format xxxx[.xxxx.xxxx] //TODO |
| | | char project_name[LCC_API_PROJECT_NAME_SIZE + 1]; // name of the project (must correspond to the name in the license) |
| | | /** |
| | | * this number passed in by the application must correspond to the magic number used when compiling the library. |
| | | * See cmake parameter -DLCC_PROJECT_MAGIC_NUM and licensecc_properties.h macro VERIFY_MAGIC |
| | | */ |
| | | unsigned int magic; |
| | | } CallerInformations; |
| | | |
| | | typedef struct { |
| | | /** |
| | | * Detailed reason of success/failure. Reasons for a failure can be |
| | | * multiple (for instance, license expired and signature not verified). |
| | | * Only the last AUDIT_EVENT_NUM are reported. |
| | | */ |
| | | AuditEvent status[AUDIT_EVENT_NUM]; |
| | | AuditEvent status[LCC_API_AUDIT_EVENT_NUM]; |
| | | /** |
| | | * Eventual expiration date of the software, |
| | | * can be '\0' if the software don't expire |
| | | * */ |
| | | char expiry_date[EXPIRY_DATE_SIZE + 1]; |
| | | char expiry_date[LCC_API_EXPIRY_DATE_SIZE + 1]; |
| | | unsigned int days_left; |
| | | bool has_expiry; |
| | | bool linked_to_pc; |
| | | LICENSE_TYPE license_type; // Local or Remote |
| | | LCC_LICENSE_TYPE license_type; // Local or Remote |
| | | /* A string of character inserted into the license understood |
| | | * by the calling application. |
| | | * '\0' if the application didn't specify one */ |
| | | char proprietary_data[PROPRIETARY_DATA_SIZE + 1]; |
| | | char proprietary_data[LCC_API_PROPRIETARY_DATA_SIZE + 1]; |
| | | int license_version; // license file version |
| | | } LicenseInfo; |
| | | |
| | | /** |
| | | * Enum to select a specific pc identification_strategy. DEFAULT Should be used |
| | | * in most cases. |
| | | */ |
| | | typedef enum { |
| | | STRATEGY_DEFAULT, |
| | | STRATEGY_ETHERNET, |
| | | STRATEGY_IP_ADDRESS, |
| | | STRATEGY_DISK_NUM, |
| | | STRATEGY_DISK_LABEL, |
| | | STRATEGY_PLATFORM_SPECIFIC, |
| | | STRATEGY_UNKNOWN |
| | | } IDENTIFICATION_STRATEGY; |
| | | |
| | | #ifdef __cplusplus |
| | | } |
| | |
| | | extern "C" { |
| | | #endif |
| | | |
| | | #include <licensecc_properties.h> |
| | | |
| | | #include "datatypes.h" |
| | | |
| | | /* |
| | | /** |
| | | * Method used to convert the LicenseInfo into a human readable |
| | | * representation. //not yet implemented |
| | | * representation. |
| | | */ |
| | | void print_error(char out_buffer[ERROR_BUFFER_SIZE], LicenseInfo* licenseInfo); |
| | | void print_error(char out_buffer[LCC_API_ERROR_BUFFER_SIZE], LicenseInfo* licenseInfo); |
| | | |
| | | /** |
| | | * This method calculates the pc identifier. The string need to be shown to the user and given back to the software |
| | | * This method calculates the hardware identifier. The string need to be shown to the user and given back to the software |
| | | * editor when issuing a license. |
| | | * pc_id_method = STRATEGY_DEFAULT usually works. |
| | | */ |
| | | bool identify_pc(IDENTIFICATION_STRATEGY pc_id_method, char* identifier_out, size_t* bufSize); |
| | | bool identify_pc(LCC_API_IDENTIFICATION_STRATEGY pc_id_method, char* identifier_out, size_t* bufSize); |
| | | |
| | | /** |
| | | * This method is used to request the use of one license for a product. |
| | |
| | | * @param license[out] optional, can be NULL, if set it will return extra informations about the license. |
| | | */ |
| | | |
| | | EVENT_TYPE acquire_license(const CallerInformations* callerInformation, const LicenseLocation* licenseLocation, |
| | | LCC_EVENT_TYPE acquire_license(const CallerInformations* callerInformation, const LicenseLocation* licenseLocation, |
| | | LicenseInfo* license_out); |
| | | |
| | | /** |
| | |
| | | * Should be called from time to time to confirm we're still using the |
| | | * license. |
| | | */ |
| | | EVENT_TYPE confirm_license(char* featureName, LicenseLocation* licenseLocation); |
| | | LCC_EVENT_TYPE confirm_license(char* featureName, LicenseLocation* licenseLocation); |
| | | /** |
| | | * Do nothing for now, useful for network licenses. |
| | | */ |
| | | EVENT_TYPE release_license(char* featureName, LicenseLocation licenseLocation); |
| | | LCC_EVENT_TYPE release_license(char* featureName, LicenseLocation licenseLocation); |
| | | |
| | | #ifdef __cplusplus |
| | | } |
| | |
| | | add_subdirectory("library") |
| | | IF (NOT LCC_PROJECT_MAGIC_NUM) |
| | | set(LCC_PROJECT_MAGIC_NUM 0) |
| | | ENDIF (NOT LCC_PROJECT_MAGIC_NUM) |
| | | |
| | | #for no reason overwrite it (maybe it's manually customized) |
| | | IF(NOT EXISTS "${LCC_INCLUDE_DIR}/licensecc_properties.h") |
| | | configure_file ("templates/licensecc_properties.h.in" |
| | | "${LCC_INCLUDE_DIR}/licensecc_properties.h") |
| | | ENDIF(NOT EXISTS "${LCC_INCLUDE_DIR}/licensecc_properties.h") |
| | | ENDIF(NOT EXISTS "${LCC_INCLUDE_DIR}/licensecc_properties.h") |
| | | |
| | | add_subdirectory("library") |
New file |
| | |
| | | |
| | | ADD_EXECUTABLE(inspector inspector.cpp ) |
| | | |
| | | target_link_libraries(inspector |
| | | licensecc_static |
| | | Boost::unit_test_framework |
| | | Boost::filesystem |
| | | Boost::system) |
New file |
| | |
| | | #include <iostream> |
| | | #include <map> |
| | | #include <unordered_map> |
| | | #include <licensecc/licensecc.h> |
| | | #include <fstream> |
| | | #include "../library/os/cpu_info.hpp" |
| | | #include "../library/os/execution_environment.hpp" |
| | | |
| | | using namespace std; |
| | | using namespace license::os; |
| | | |
| | | const map<int, string> stringByStrategyId = {{STRATEGY_DEFAULT, "DEFAULT"}, |
| | | {STRATEGY_ETHERNET, "MAC"}, |
| | | {STRATEGY_IP_ADDRESS, "IP"}, |
| | | {STRATEGY_DISK_NUM, "Disk1"}, |
| | | {STRATEGY_DISK_LABEL, "Disk2"}}; |
| | | |
| | | const unordered_map<int, string> descByVirtDetail = {{BARE_TO_METAL, "No virtualization"}, |
| | | {VMWARE, "Vmware"}, |
| | | {VIRTUALBOX, "Virtualbox"}, |
| | | {V_XEN, "XEN"}, |
| | | {KVM, "KVM"}, |
| | | {HV, "Microsoft Hypervisor"}, |
| | | {V_OTHER, "Other type of vm"}}; |
| | | |
| | | const unordered_map<int, string> descByVirt = { |
| | | {VIRTUALIZATION::NONE, "No virtualization"}, {VIRTUALIZATION::VM, "VM"}, {VIRTUALIZATION::CONTAINER, "Container"}}; |
| | | |
| | | const unordered_map<int, string> stringByEventType = { |
| | | {LICENSE_OK, "OK "}, |
| | | {LICENSE_FILE_NOT_FOUND, "license file not found "}, |
| | | {LICENSE_SERVER_NOT_FOUND, "license server can't be contacted "}, |
| | | {ENVIRONMENT_VARIABLE_NOT_DEFINED, "environment variable not defined "}, |
| | | {FILE_FORMAT_NOT_RECOGNIZED, "license file has invalid format (not .ini file) "}, |
| | | {LICENSE_MALFORMED, "some mandatory field are missing, or data can't be fully read. "}, |
| | | {PRODUCT_NOT_LICENSED, "this product was not licensed "}, |
| | | {PRODUCT_EXPIRED, "license expired "}, |
| | | {LICENSE_CORRUPTED, "license signature didn't match with current license "}, |
| | | {IDENTIFIERS_MISMATCH, "Calculated identifier and the one provided in license didn't match"}}; |
| | | |
| | | static LCC_EVENT_TYPE verifyLicense(const string& fname) { |
| | | LicenseInfo licenseInfo; |
| | | LicenseLocation licLocation = {LICENSE_PATH}; |
| | | std::copy(fname.begin(), fname.end(), licLocation.licenseData); |
| | | LCC_EVENT_TYPE result = acquire_license(nullptr, &licLocation, &licenseInfo); |
| | | if (result == LICENSE_OK) { |
| | | cout << "license OK" << endl; |
| | | } else { |
| | | cerr << stringByEventType.find(result)->second << endl; |
| | | } |
| | | |
| | | return result; |
| | | } |
| | | |
| | | int main(int argc, char* argv[]) { |
| | | license::os::CpuInfo cpu; |
| | | cout << "Cpu Vendor :" << cpu.vendor() << endl; |
| | | cout << "Cpu Brand :" << cpu.brand() << endl; |
| | | cout << "Cpu is hypervis.:" << cpu.cpu_virtual() << endl; |
| | | cout << "Cpu model :0x" << std::hex << ((long)cpu.model()) << std::dec << endl; |
| | | cout << "Virt. detail cpu:" << descByVirtDetail.find(cpu.virtualization_details())->second << endl <<endl; |
| | | ExecutionEnvironment execEnv; |
| | | cout << "Running in cloud:" << execEnv.is_cloud() << endl; |
| | | cout << "Docker :" << execEnv.is_docker() << endl; |
| | | cout << "other container :" << execEnv.is_container() << endl; |
| | | cout << "Virtualiz. class:" << descByVirt.find(execEnv.getVirtualization())->second << endl; |
| | | |
| | | cout << "Bios vendor :" << execEnv.bios_vendor() << endl; |
| | | cout << "Bios description:" << execEnv.bios_description() << endl; |
| | | cout << "System vendor :" << execEnv.sys_vendor() << endl <<endl; |
| | | |
| | | char hw_identifier[LCC_API_PC_IDENTIFIER_SIZE + 1]; |
| | | size_t bufSize = LCC_API_PC_IDENTIFIER_SIZE + 1; |
| | | for (const auto& x : stringByStrategyId) { |
| | | if (identify_pc(static_cast<LCC_API_IDENTIFICATION_STRATEGY>(x.first), hw_identifier, &bufSize)) { |
| | | std::cout << x.second << ':' << hw_identifier << std::endl; |
| | | } else { |
| | | std::cout << x.second << ": NA" << endl; |
| | | } |
| | | } |
| | | |
| | | if (argc == 2) { |
| | | const string fname(argv[1]); |
| | | ifstream license_file(fname); |
| | | if (license_file.good()) { |
| | | verifyLicense(fname); |
| | | } else { |
| | | cerr << "license file :" << fname << " not found." << endl; |
| | | } |
| | | } |
| | | } |
| | |
| | | add_subdirectory("base") |
| | | add_subdirectory("os") |
| | | add_subdirectory("locate") |
| | | add_subdirectory("hw_identifier") |
| | | |
| | | ADD_LIBRARY(licensecc_static STATIC |
| | | licensecc.cpp |
| | | LicenseReader.cpp |
| | | pc-identifiers.c |
| | | limits/license_verifier.cpp |
| | | ini/ConvertUTF.c |
| | | ini/ConvertUTF.cpp |
| | | $<TARGET_OBJECTS:hw_identifier> |
| | | $<TARGET_OBJECTS:locate> |
| | | $<TARGET_OBJECTS:os> |
| | | $<TARGET_OBJECTS:base> |
| | | ) |
| | | |
| | | add_subdirectory("locate") |
| | | add_subdirectory("os") |
| | | if(CODE_COVERAGE AND UNIX) |
| | | if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.13) |
| | | target_link_options(licensecc_static PUBLIC --coverage) |
| | | endif() |
| | | list(APPEND EXTERNAL_LIBS gcov) |
| | | endif(CODE_COVERAGE AND UNIX) |
| | | |
| | | define_property(TARGET PROPERTY WITH_OPENSSL BRIEF_DOCS "need openssl to compile" FULL_DOCS "ff") |
| | | IF(UNIX OR OPENSSL_FOUND) |
| | | target_compile_definitions(licensecc_static PUBLIC HAS_OPENSSL) |
| | | set_target_properties(licensecc_static PROPERTIES WITH_OPENSSL 1) |
| | | target_link_libraries(licensecc_static PUBLIC base OpenSSL::Crypto ${EXTERNAL_LIBS} ${CMAKE_DL_LIBS}) |
| | | target_link_libraries(licensecc_static PUBLIC OpenSSL::Crypto ${EXTERNAL_LIBS} ${CMAKE_DL_LIBS}) |
| | | ELSE(UNIX OR OPENSSL_FOUND) |
| | | set_target_properties(licensecc_static PROPERTIES WITH_OPENSSL 0) |
| | | target_link_libraries(licensecc_static PUBLIC base ${EXTERNAL_LIBS}) |
| | | target_link_libraries(licensecc_static PUBLIC ${EXTERNAL_LIBS}) |
| | | ENDIF(UNIX OR OPENSSL_FOUND) |
| | | |
| | | #set_property(TARGET licensecc_static PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>") |
| | | |
| | | target_include_directories(licensecc_static |
| | | INTERFACE |
| | | PUBLIC |
| | | $<INSTALL_INTERFACE:include> |
| | | $<INSTALL_INTERFACE:include/${PROJECT_NAME}/${LCC_PROJECT_NAME}> |
| | | $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../../include> |
| | | $<BUILD_INTERFACE:${LCC_INCLUDE_DIR}> |
| | | ) |
| | | |
| | | add_library(licensecc::licensecc_static ALIAS licensecc_static) |
| | |
| | | #include <stdlib.h> |
| | | #include <math.h> |
| | | |
| | | #include <public_key.h> |
| | | #include <licensecc_properties.h> |
| | | #include <licensecc/licensecc.h> |
| | | |
| | | #include "base/base.h" |
| | | #include "pc-identifiers.h" |
| | | #include "LicenseReader.hpp" |
| | | #include "base/StringUtils.h" |
| | | #include "base/logger.h" |
| | |
| | | FullLicenseInfo::FullLicenseInfo(const string &source, const string &product, const string &license_signature) |
| | | : source(source), |
| | | m_project(product), // |
| | | license_signature(license_signature) {} |
| | | license_signature(license_signature), |
| | | m_magic(0) {} |
| | | |
| | | LicenseReader::LicenseReader(const LicenseLocation *licenseLocation) : licenseLocation(licenseLocation) {} |
| | | |
| | |
| | | const std::string license_signature; |
| | | const std::string source; |
| | | const std::string m_project; |
| | | unsigned int m_magic; |
| | | std::map<std::string, std::string> m_limits; |
| | | |
| | | FullLicenseInfo(const std::string& source, const std::string& product, const std::string& license_signature); |
| | |
| | | ADD_LIBRARY(base STATIC |
| | | ADD_LIBRARY(base OBJECT |
| | | EventRegistry.cpp |
| | | StringUtils.cpp |
| | | FileUtils.cpp |
| | | logger.c |
| | | base64.c |
| | | file_utils.cpp |
| | | base64.cpp |
| | | logger.cpp |
| | | ) |
| | | |
| | | if(CODE_COVERAGE AND UNIX) |
| | |
| | | -g # generate debug info |
| | | --coverage # sets all required flags |
| | | ) |
| | | target_link_libraries(base PUBLIC gcov) |
| | | endif(CODE_COVERAGE AND UNIX) |
| | | |
| | | add_dependencies( base project_initialize ) |
| | | |
| | | install(TARGETS base EXPORT licensecc ARCHIVE DESTINATION lib/${PROJECT_NAME}/${LCC_PROJECT_NAME}) |
| | | |
| | |
| | | namespace license { |
| | | using namespace std; |
| | | |
| | | const map<EVENT_TYPE, int> PROGRESS_BY_EVENT_TYPE = { |
| | | const map<LCC_EVENT_TYPE, int> PROGRESS_BY_EVENT_TYPE = { |
| | | {LICENSE_SPECIFIED, 0}, {LICENSE_FOUND, 1}, {PRODUCT_FOUND, 2}, {SIGNATURE_VERIFIED, 3}, {LICENSE_OK, 4}}; |
| | | |
| | | EventRegistry::EventRegistry() { current_validation_step = -1; } |
| | |
| | | return result; |
| | | } |
| | | |
| | | void EventRegistry::addEvent(EVENT_TYPE event, const std::string &licenseLocationId) { |
| | | void EventRegistry::addEvent(LCC_EVENT_TYPE event, const std::string &licenseLocationId) { |
| | | addEvent(event, licenseLocationId.c_str(), nullptr); |
| | | } |
| | | |
| | | void EventRegistry::addEvent(EVENT_TYPE event, const char *licenseLocationId, const char *info) { |
| | | void EventRegistry::addEvent(LCC_EVENT_TYPE event, const char *licenseLocationId, const char *info) { |
| | | AuditEvent audit; |
| | | auto eventIterator = PROGRESS_BY_EVENT_TYPE.find(event); |
| | | bool successEvent = (eventIterator != PROGRESS_BY_EVENT_TYPE.end()); |
| | |
| | | * @return NULL if no failures are found. |
| | | */ |
| | | const AuditEvent *getLastFailure() const; |
| | | void addEvent(EVENT_TYPE event, const std::string &licenseLocationId); |
| | | void addEvent(EVENT_TYPE event, const char *licenseLocationId = nullptr, const char *info = nullptr); |
| | | void addEvent(LCC_EVENT_TYPE event, const std::string &licenseLocationId); |
| | | void addEvent(LCC_EVENT_TYPE event, const char *licenseLocationId = nullptr, const char *info = nullptr); |
| | | void exportLastEvents(AuditEvent *auditEvents, int nlogs); |
| | | }; |
| | | } // namespace license |
| | |
| | | ++it; |
| | | } |
| | | std::string::const_reverse_iterator rit = string_to_trim.rbegin(); |
| | | while (rit.base() != it && isspace(*rit)) { |
| | | while (rit.base() != it && (isspace(*rit) || *rit == 0)) { |
| | | ++rit; |
| | | } |
| | | return std::string(it, rit.base()); |
New file |
| | |
| | | #include <stdio.h>
|
| | | #include <stdlib.h>
|
| | | #include <algorithm>
|
| | |
|
| | | #include "base64.h"
|
| | | namespace license {
|
| | | using namespace std;
|
| | |
|
| | | const static char* b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
| | |
|
| | | // maps A=>0,B=>1..
|
| | | const static unsigned char unb64[] = {
|
| | | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 10
|
| | | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20
|
| | | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 30
|
| | | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 40
|
| | | 0, 0, 0, 62, 0, 0, 0, 63, 52, 53, // 50
|
| | | 54, 55, 56, 57, 58, 59, 60, 61, 0, 0, // 60
|
| | | 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, // 70
|
| | | 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, // 80
|
| | | 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, // 90
|
| | | 25, 0, 0, 0, 0, 0, 0, 26, 27, 28, // 100
|
| | | 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, // 110
|
| | | 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, // 120
|
| | | 49, 50, 51, 0, 0, 0, 0, 0, 0, 0, // 130
|
| | | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 140
|
| | | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 150
|
| | | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 160
|
| | | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 170
|
| | | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 180
|
| | | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 190
|
| | | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 200
|
| | | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 210
|
| | | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 220
|
| | | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 230
|
| | | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 240
|
| | | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 250
|
| | | 0, 0, 0, 0, 0, 0,
|
| | | }; // This array has 255 elements
|
| | |
|
| | | // review api
|
| | | void add_CR_if_needed(string& encodeBuffer, int lineLenght) {
|
| | | if (lineLenght > 0 && ((encodeBuffer.size() + 1) % lineLenght) == 0) {
|
| | | encodeBuffer += '\n';
|
| | | }
|
| | | }
|
| | |
|
| | | string base64(const void* binaryData, size_t len, int lineLenght) {
|
| | | const unsigned char* bin = (const unsigned char*)binaryData;
|
| | |
|
| | | int rc = 0; // result counter
|
| | | int byteNo; // I need this after the loop
|
| | |
|
| | | int modulusLen = len % 3;
|
| | | int pad = ((modulusLen & 1) << 1) + ((modulusLen & 2) >> 1); // 2 gives 1 and 1 gives 2, but 0 gives 0.
|
| | |
|
| | | const size_t flen = 4 * (len + pad) / 3;
|
| | | size_t totalLength = flen;
|
| | | if (lineLenght > 0) {
|
| | | totalLength += ((int)flen / lineLenght) + 3;
|
| | | }
|
| | |
|
| | | string encodeBuffer;
|
| | | encodeBuffer.reserve(totalLength);
|
| | |
|
| | | for (byteNo = 0; byteNo <= len - 3; byteNo += 3) {
|
| | | unsigned char BYTE0 = bin[byteNo];
|
| | | unsigned char BYTE1 = bin[byteNo + 1];
|
| | | unsigned char BYTE2 = bin[byteNo + 2];
|
| | |
|
| | | add_CR_if_needed(encodeBuffer, lineLenght);
|
| | | encodeBuffer += b64[BYTE0 >> 2];
|
| | | add_CR_if_needed(encodeBuffer, lineLenght);
|
| | | encodeBuffer += b64[((0x3 & BYTE0) << 4) + (BYTE1 >> 4)];
|
| | | add_CR_if_needed(encodeBuffer, lineLenght);
|
| | | encodeBuffer += b64[((0x0f & BYTE1) << 2) + (BYTE2 >> 6)];
|
| | | add_CR_if_needed(encodeBuffer, lineLenght);
|
| | | encodeBuffer += b64[0x3f & BYTE2];
|
| | | }
|
| | |
|
| | | if (pad == 2) {
|
| | | add_CR_if_needed(encodeBuffer, lineLenght);
|
| | | encodeBuffer += b64[bin[byteNo] >> 2];
|
| | | add_CR_if_needed(encodeBuffer, lineLenght);
|
| | | encodeBuffer += b64[(0x3 & bin[byteNo]) << 4];
|
| | | add_CR_if_needed(encodeBuffer, lineLenght);
|
| | | encodeBuffer += '=';
|
| | | add_CR_if_needed(encodeBuffer, lineLenght);
|
| | | encodeBuffer += '=';
|
| | | } else if (pad == 1) {
|
| | | add_CR_if_needed(encodeBuffer, lineLenght);
|
| | | encodeBuffer += b64[bin[byteNo] >> 2];
|
| | | add_CR_if_needed(encodeBuffer, lineLenght);
|
| | | encodeBuffer += b64[((0x3 & bin[byteNo]) << 4) + (bin[byteNo + 1] >> 4)];
|
| | | add_CR_if_needed(encodeBuffer, lineLenght);
|
| | | encodeBuffer += b64[(0x0f & bin[byteNo + 1]) << 2];
|
| | | add_CR_if_needed(encodeBuffer, lineLenght);
|
| | | encodeBuffer += '=';
|
| | | }
|
| | | if (lineLenght && encodeBuffer[encodeBuffer.length() - 1] != '\n') {
|
| | | encodeBuffer += '\n';
|
| | | }
|
| | | return encodeBuffer;
|
| | | }
|
| | |
|
| | | std::vector<uint8_t> unbase64(const std::string& base64_data) {
|
| | | string tmp_str(base64_data);
|
| | | tmp_str.erase(std::remove(tmp_str.begin(), tmp_str.end(), '\n'), tmp_str.end());
|
| | | const unsigned char* safeAsciiPtr = (const unsigned char*)tmp_str.c_str();
|
| | | std::vector<uint8_t> bin;
|
| | | int cb = 0;
|
| | | int charNo;
|
| | | int pad = 0;
|
| | | size_t len = tmp_str.size();
|
| | |
|
| | | if (len < 2) { // 2 accesses below would be OOB.
|
| | | // catch empty string, return NULL as result.
|
| | | puts("ERROR: You passed an invalid base64 string (too short). You get NULL back.");
|
| | | return bin;
|
| | | }
|
| | | if (safeAsciiPtr[len - 1] == '=') ++pad;
|
| | | if (safeAsciiPtr[len - 2] == '=') ++pad;
|
| | |
|
| | | size_t flen = 3 * len / 4 - pad;
|
| | | bin.reserve(flen);
|
| | |
|
| | | for (charNo = 0; charNo <= len - 4 - pad; charNo += 4) {
|
| | | int A = unb64[safeAsciiPtr[charNo]];
|
| | | int B = unb64[safeAsciiPtr[charNo + 1]];
|
| | | int C = unb64[safeAsciiPtr[charNo + 2]];
|
| | | int D = unb64[safeAsciiPtr[charNo + 3]];
|
| | |
|
| | | bin.push_back((A << 2) | (B >> 4));
|
| | | bin.push_back((B << 4) | (C >> 2));
|
| | | bin.push_back((C << 6) | (D));
|
| | | }
|
| | |
|
| | | if (pad == 1) {
|
| | | int A = unb64[safeAsciiPtr[charNo]];
|
| | | int B = unb64[safeAsciiPtr[charNo + 1]];
|
| | | int C = unb64[safeAsciiPtr[charNo + 2]];
|
| | | bin.push_back((A << 2) | (B >> 4));
|
| | | bin.push_back((B << 4) | (C >> 2));
|
| | | } else if (pad == 2) {
|
| | | int A = unb64[safeAsciiPtr[charNo]];
|
| | | int B = unb64[safeAsciiPtr[charNo + 1]];
|
| | | bin.push_back((A << 2) | (B >> 4));
|
| | | }
|
| | |
|
| | | return bin;
|
| | | }
|
| | |
|
| | | } // namespace license
|
| | |
| | | /* |
| | | |
| | | https://github.com/superwills/NibbleAndAHalf |
| | | base64.h -- Fast base64 encoding and decoding. |
| | | version 1.0.0, April 17, 2013 143a |
| | | |
| | | Copyright (C) 2013 William Sherif |
| | | |
| | | This software is provided 'as-is', without any express or implied |
| | | warranty. In no event will the authors be held liable for any damages |
| | | arising from the use of this software. |
| | | |
| | | Permission is granted to anyone to use this software for any purpose, |
| | | including commercial applications, and to alter it and redistribute it |
| | | freely, subject to the following restrictions: |
| | | |
| | | 1. The origin of this software must not be misrepresented; you must not |
| | | claim that you wrote the original software. If you use this software |
| | | in a product, an acknowledgment in the product documentation would be |
| | | appreciated but is not required. |
| | | 2. Altered source versions must be plainly marked as such, and must not be |
| | | misrepresented as being the original software. |
| | | 3. This notice may not be removed or altered from any source distribution. |
| | | |
| | | William Sherif |
| | | will.sherif@gmail.com |
| | | |
| | | YWxsIHlvdXIgYmFzZSBhcmUgYmVsb25nIHRvIHVz |
| | | |
| | | */ |
| | | #ifndef BASE64_H |
| | | #define BASE64_H |
| | | |
| | | #ifdef __cplusplus |
| | | extern "C" { |
| | | #include <string> |
| | | #include <vector> |
| | | |
| | | #if _WIN32 |
| | | #include <wtypes.h> |
| | | #endif |
| | | |
| | | unsigned char* unbase64(const char* ascii, int len, int *flen); |
| | | char* base64(const void* binaryData, int len, int *flen); |
| | | namespace license { |
| | | |
| | | #ifdef __cplusplus |
| | | } |
| | | #endif |
| | | std::vector<uint8_t> unbase64(const std::string& base64_data); |
| | | std::string base64(const void* binaryData, size_t len, int lineLenght = -1); |
| | | |
| | | } // namespace license |
| | | |
| | | #endif |
File was renamed from src/library/base/FileUtils.cpp |
| | |
| | | #include <iostream> |
| | | #include <algorithm> |
| | | |
| | | #include "FileUtils.hpp" |
| | | #include "file_utils.hpp" |
| | | |
| | | namespace license { |
| | | using namespace std; |
File was renamed from src/library/base/logger.c |
| | |
| | | #include <stdarg.h> |
| | | #include <time.h> |
| | | |
| | | #ifndef LOG_DISABLED |
| | | |
| | | #ifdef __unix__ |
| | | #include <unistd.h> |
| | | #define MAX_PATH 255 |
| | |
| | | logFile = NULL; |
| | | } |
| | | } |
| | | #endif |
| | |
| | | #ifndef logger_INCLUDED |
| | | #define logger_INCLUDED |
| | | #ifdef __cplusplus |
| | | extern "C" { |
| | | #endif |
| | | #define LOG_DISABLED 1 |
| | | |
| | | #ifndef LOG_DISABLED |
| | | #include <errno.h> |
| | | #include <string.h> |
| | | #ifdef __cplusplus |
| | | extern "C" { |
| | | #endif |
| | | |
| | | #define clean_errno() (errno == 0 ? "None" : strerror(errno)) |
| | | |
New file |
| | |
| | | add_library(hw_identifier OBJECT |
| | | hw_identifier_facade.cpp |
| | | default_strategy.cpp |
| | | ethernet.cpp |
| | | disk_strategy.cpp |
| | | identification_strategy.cpp |
| | | hw_identifier.cpp |
| | | ) |
| | | |
| | | if(CODE_COVERAGE AND UNIX) |
| | | target_compile_options(hw_identifier PUBLIC -O0 -g --coverage) |
| | | endif(CODE_COVERAGE AND UNIX) |
New file |
| | |
| | | /* |
| | | * default_strategy.cpp |
| | | * |
| | | * Created on: Jan 1, 2020 |
| | | * Author: devel |
| | | */ |
| | | |
| | | #include <vector> |
| | | #include "../os/execution_environment.hpp" |
| | | #include "default_strategy.hpp" |
| | | |
| | | using namespace std; |
| | | namespace license { |
| | | namespace hw_identifier { |
| | | |
| | | static vector<LCC_API_IDENTIFICATION_STRATEGY> available_strategies() { |
| | | os::ExecutionEnvironment exec; |
| | | os::VIRTUALIZATION virtualization = exec.getVirtualization(); |
| | | vector<LCC_API_IDENTIFICATION_STRATEGY> strategy_to_try; |
| | | if (virtualization == os::CONTAINER) { |
| | | if (exec.is_docker()) { |
| | | strategy_to_try = LCC_DOCKER_STRATEGIES; |
| | | } else { |
| | | strategy_to_try = LCC_LXC_STRATEGIES; |
| | | } |
| | | } else if (virtualization == os::VM) { |
| | | if (exec.is_cloud()) { |
| | | strategy_to_try = LCC_CLOUD_STRATEGIES; |
| | | } else { |
| | | strategy_to_try = LCC_VM_STRATEGIES; |
| | | } |
| | | } else { |
| | | strategy_to_try = LCC_BARE_TO_METAL_STRATEGIES; |
| | | } |
| | | return strategy_to_try; |
| | | } |
| | | |
| | | DefaultStrategy::DefaultStrategy() {} |
| | | |
| | | DefaultStrategy::~DefaultStrategy() {} |
| | | |
| | | LCC_API_IDENTIFICATION_STRATEGY DefaultStrategy::identification_strategy() const { return STRATEGY_DEFAULT; } |
| | | |
| | | FUNCTION_RETURN DefaultStrategy::identify_pc(HwIdentifier& pc_id) const { |
| | | vector<LCC_API_IDENTIFICATION_STRATEGY> strategy_to_try = available_strategies(); |
| | | FUNCTION_RETURN ret = FUNC_RET_NOT_AVAIL; |
| | | for (auto it : strategy_to_try) { |
| | | LCC_API_IDENTIFICATION_STRATEGY strat_to_try = it; |
| | | unique_ptr<IdentificationStrategy> strategy_ptr = IdentificationStrategy::get_strategy(strat_to_try); |
| | | ret = strategy_ptr->identify_pc(pc_id); |
| | | if (ret == FUNC_RET_OK) { |
| | | break; |
| | | } |
| | | } |
| | | return ret; |
| | | } |
| | | |
| | | std::vector<HwIdentifier> DefaultStrategy::alternative_ids() const { |
| | | vector<LCC_API_IDENTIFICATION_STRATEGY> strategy_to_try = available_strategies(); |
| | | vector<HwIdentifier> identifiers; |
| | | FUNCTION_RETURN ret = FUNC_RET_NOT_AVAIL; |
| | | for (auto it : strategy_to_try) { |
| | | LCC_API_IDENTIFICATION_STRATEGY strat_to_try = it; |
| | | unique_ptr<IdentificationStrategy> strategy_ptr = IdentificationStrategy::get_strategy(strat_to_try); |
| | | vector<HwIdentifier> alt_ids = strategy_ptr->alternative_ids(); |
| | | identifiers.insert(alt_ids.begin(), alt_ids.end(), identifiers.end()); |
| | | } |
| | | return identifiers; |
| | | } |
| | | |
| | | LCC_EVENT_TYPE DefaultStrategy::validate_identifier(const HwIdentifier& identifier) const { |
| | | // default strategy should always realize itself as a concrete strategy |
| | | return IDENTIFIERS_MISMATCH; |
| | | } |
| | | |
| | | } // namespace hw_identifier |
| | | } /* namespace license */ |
New file |
| | |
| | | /* |
| | | * default_strategy.hpp |
| | | * |
| | | * Created on: Jan 2, 2020 |
| | | * Author: devel |
| | | */ |
| | | |
| | | #ifndef SRC_LIBRARY_PC_IDENTIFIER_DEFAULT_STRATEGY_HPP_ |
| | | #define SRC_LIBRARY_PC_IDENTIFIER_DEFAULT_STRATEGY_HPP_ |
| | | #include "identification_strategy.hpp" |
| | | |
| | | namespace license { |
| | | namespace hw_identifier { |
| | | |
| | | class DefaultStrategy : public IdentificationStrategy { |
| | | public: |
| | | DefaultStrategy(); |
| | | virtual ~DefaultStrategy(); |
| | | virtual LCC_API_IDENTIFICATION_STRATEGY identification_strategy() const; |
| | | virtual FUNCTION_RETURN identify_pc(HwIdentifier &pc_id) const; |
| | | virtual std::vector<HwIdentifier> alternative_ids() const; |
| | | virtual LCC_EVENT_TYPE validate_identifier(const HwIdentifier &identifier) const; |
| | | }; |
| | | } // namespace hw_identifier |
| | | } /* namespace license */ |
| | | |
| | | #endif /* SRC_LIBRARY_PC_IDENTIFIER_DEFAULT_STRATEGY_HPP_ */ |
New file |
| | |
| | | /* |
| | | * disk_strategy.cpp |
| | | * |
| | | * Created on: Jan 14, 2020 |
| | | * Author: devel |
| | | */ |
| | | #include <string.h> |
| | | #include "../os/os.h" |
| | | #include "disk_strategy.hpp" |
| | | |
| | | using namespace std; |
| | | namespace license { |
| | | namespace hw_identifier { |
| | | |
| | | static FUNCTION_RETURN generate_disk_pc_id(vector<array<uint8_t, HW_IDENTIFIER_PROPRIETARY_DATA>> &v_disk_id, |
| | | bool use_id) { |
| | | size_t disk_num = 0; |
| | | size_t available_disk_info = 0; |
| | | FUNCTION_RETURN result_diskinfos; |
| | | |
| | | result_diskinfos = getDiskInfos(nullptr, &disk_num); |
| | | if (result_diskinfos != FUNC_RET_OK && result_diskinfos != FUNC_RET_BUFFER_TOO_SMALL) { |
| | | return result_diskinfos; |
| | | } |
| | | if (disk_num == 0) { |
| | | return FUNC_RET_NOT_AVAIL; |
| | | } |
| | | size_t mem = disk_num * sizeof(DiskInfo); |
| | | DiskInfo *diskInfos = (DiskInfo *)malloc(mem); |
| | | if (diskInfos == nullptr) { |
| | | return FUNC_RET_NOT_AVAIL; |
| | | } |
| | | memset(diskInfos, 0, mem); |
| | | result_diskinfos = getDiskInfos(diskInfos, &disk_num); |
| | | |
| | | if (result_diskinfos != FUNC_RET_OK) { |
| | | free(diskInfos); |
| | | return result_diskinfos; |
| | | } |
| | | for (unsigned int i = 0; i < disk_num; i++) { |
| | | char firstChar = use_id ? diskInfos[i].label[0] : diskInfos[i].disk_sn[0]; |
| | | available_disk_info += firstChar == 0 ? 0 : 1; |
| | | } |
| | | if (available_disk_info == 0) { |
| | | free(diskInfos); |
| | | return FUNC_RET_NOT_AVAIL; |
| | | } |
| | | v_disk_id.reserve(available_disk_info); |
| | | for (int j = 0; j < 2; j++) { |
| | | int preferred = (j == 0 ? 1 : 0); |
| | | for (unsigned int i = 0; i < disk_num; i++) { |
| | | array<uint8_t, HW_IDENTIFIER_PROPRIETARY_DATA> a_disk_id; |
| | | a_disk_id.fill(0); |
| | | if (use_id) { |
| | | if (diskInfos[i].disk_sn[0] != 0 && diskInfos[i].preferred == preferred) { |
| | | size_t size = min(a_disk_id.size(), sizeof(&diskInfos[i].disk_sn)); |
| | | memcpy(&a_disk_id[0], diskInfos[i].disk_sn, size); |
| | | v_disk_id.push_back(a_disk_id); |
| | | } |
| | | } else { |
| | | if (diskInfos[i].label[0] != 0 && diskInfos[i].preferred == preferred) { |
| | | strncpy((char *)&a_disk_id[0], diskInfos[i].label, a_disk_id.size() - 1); |
| | | v_disk_id.push_back(a_disk_id); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | free(diskInfos); |
| | | return FUNC_RET_OK; |
| | | } |
| | | |
| | | DiskStrategy::DiskStrategy(bool use_id) : m_use_id(use_id) {} |
| | | |
| | | DiskStrategy::~DiskStrategy() {} |
| | | |
| | | LCC_API_IDENTIFICATION_STRATEGY DiskStrategy::identification_strategy() const { |
| | | return m_use_id ? STRATEGY_DISK_NUM : STRATEGY_DISK_LABEL; |
| | | } |
| | | |
| | | std::vector<HwIdentifier> DiskStrategy::alternative_ids() const { |
| | | vector<array<uint8_t, HW_IDENTIFIER_PROPRIETARY_DATA>> data; |
| | | FUNCTION_RETURN result = generate_disk_pc_id(data, m_use_id); |
| | | vector<HwIdentifier> identifiers; |
| | | if (result == FUNC_RET_OK) { |
| | | identifiers.reserve(data.size()); |
| | | for (auto &it : data) { |
| | | HwIdentifier pc_id; |
| | | pc_id.set_identification_strategy(identification_strategy()); |
| | | pc_id.set_data(it); |
| | | identifiers.push_back(pc_id); |
| | | } |
| | | } |
| | | return identifiers; |
| | | } |
| | | |
| | | } // namespace hw_identifier |
| | | } /* namespace license */ |
New file |
| | |
| | | /* |
| | | * disk_strategy.hpp |
| | | * |
| | | * Created on: Jan 14, 2020 |
| | | * Author: devel |
| | | */ |
| | | |
| | | #ifndef SRC_LIBRARY_PC_IDENTIFIER_DISK_STRATEGY_HPP_ |
| | | #define SRC_LIBRARY_PC_IDENTIFIER_DISK_STRATEGY_HPP_ |
| | | |
| | | #include "identification_strategy.hpp" |
| | | |
| | | namespace license { |
| | | namespace hw_identifier { |
| | | |
| | | class DiskStrategy : public IdentificationStrategy { |
| | | private: |
| | | bool m_use_id; |
| | | public: |
| | | DiskStrategy(bool use_id); |
| | | virtual ~DiskStrategy(); |
| | | virtual LCC_API_IDENTIFICATION_STRATEGY identification_strategy() const; |
| | | virtual std::vector<HwIdentifier> alternative_ids() const; |
| | | }; |
| | | |
| | | } // namespace hw_identifier |
| | | } /* namespace license */ |
| | | |
| | | #endif /* SRC_LIBRARY_PC_IDENTIFIER_DISK_STRATEGY_HPP_ */ |
New file |
| | |
| | | /* |
| | | * ethernet.cpp |
| | | * |
| | | * Created on: Jan 11, 2020 |
| | | * Author: GC |
| | | */ |
| | | |
| | | #include <array> |
| | | #include <vector> |
| | | |
| | | #include <licensecc/datatypes.h> |
| | | #include <licensecc_properties.h> |
| | | #include "../base/base.h" |
| | | #include "../os/network.hpp" |
| | | #include "hw_identifier.hpp" |
| | | #include "ethernet.hpp" |
| | | |
| | | namespace license { |
| | | namespace hw_identifier { |
| | | using namespace std; |
| | | |
| | | static FUNCTION_RETURN generate_ethernet_pc_id(vector<array<uint8_t, HW_IDENTIFIER_PROPRIETARY_DATA>> &data, |
| | | const bool use_ip) { |
| | | vector<os::OsAdapterInfo> adapters; |
| | | |
| | | FUNCTION_RETURN result_adapterInfos = getAdapterInfos(adapters); |
| | | if (result_adapterInfos != FUNC_RET_OK) { |
| | | return result_adapterInfos; |
| | | } |
| | | if (adapters.size() == 0) { |
| | | return FUNC_RET_NOT_AVAIL; |
| | | } |
| | | |
| | | for (auto &it : adapters) { |
| | | unsigned int k, data_len; |
| | | array<uint8_t, HW_IDENTIFIER_PROPRIETARY_DATA> identifier; |
| | | data_len = use_ip ? sizeof(os::OsAdapterInfo::ipv4_address) : sizeof(os::OsAdapterInfo::mac_address); |
| | | |
| | | for (k = 0; k < HW_IDENTIFIER_PROPRIETARY_DATA; k++) { |
| | | if (k < data_len) { |
| | | identifier[k] = use_ip ? it.ipv4_address[k] : it.mac_address[k]; |
| | | } else { |
| | | identifier[k] = 42; |
| | | } |
| | | } |
| | | identifier[0] = identifier[0] & 0x1F; |
| | | data.push_back(identifier); |
| | | } |
| | | |
| | | return result_adapterInfos; |
| | | } |
| | | |
| | | Ethernet::Ethernet(bool useIp) : use_ip(useIp) {} |
| | | |
| | | Ethernet::~Ethernet() {} |
| | | |
| | | LCC_API_IDENTIFICATION_STRATEGY Ethernet::identification_strategy() const { |
| | | return use_ip ? STRATEGY_IP_ADDRESS : STRATEGY_ETHERNET; |
| | | } |
| | | |
| | | std::vector<HwIdentifier> Ethernet::alternative_ids() const { |
| | | vector<array<uint8_t, HW_IDENTIFIER_PROPRIETARY_DATA>> data; |
| | | FUNCTION_RETURN result = generate_ethernet_pc_id(data, use_ip); |
| | | vector<HwIdentifier> identifiers; |
| | | if (result == FUNC_RET_OK) { |
| | | identifiers.reserve(data.size()); |
| | | for (auto &it : data) { |
| | | HwIdentifier pc_id; |
| | | pc_id.set_identification_strategy(identification_strategy()); |
| | | pc_id.set_data(it); |
| | | identifiers.push_back(pc_id); |
| | | } |
| | | } |
| | | return identifiers; |
| | | } |
| | | |
| | | } // namespace hw_identifier |
| | | } /* namespace license */ |
New file |
| | |
| | | /* |
| | | * ethernet.hpp |
| | | * |
| | | * Created on: Jan 11, 2020 |
| | | * Author: devel |
| | | */ |
| | | |
| | | #ifndef SRC_LIBRARY_PC_IDENTIFIER_ETHERNET_HPP_ |
| | | #define SRC_LIBRARY_PC_IDENTIFIER_ETHERNET_HPP_ |
| | | |
| | | #include "identification_strategy.hpp" |
| | | |
| | | namespace license { |
| | | namespace hw_identifier { |
| | | |
| | | class Ethernet : public IdentificationStrategy { |
| | | private: |
| | | const bool use_ip; |
| | | public: |
| | | Ethernet(bool use_ip); |
| | | virtual ~Ethernet(); |
| | | virtual LCC_API_IDENTIFICATION_STRATEGY identification_strategy() const; |
| | | virtual std::vector<HwIdentifier> alternative_ids() const; |
| | | }; |
| | | |
| | | } // namespace hw_identifier |
| | | } /* namespace license */ |
| | | |
| | | #endif /* SRC_LIBRARY_PC_IDENTIFIER_ETHERNET_HPP_ */ |
New file |
| | |
| | | /* |
| | | * hw_identifier.cpp |
| | | * |
| | | * Created on: Dec 22, 2019 |
| | | * Author: GC |
| | | */ |
| | | |
| | | #include <algorithm> |
| | | #include "hw_identifier.hpp" |
| | | #include "../base/base64.h" |
| | | |
| | | namespace license { |
| | | namespace hw_identifier { |
| | | |
| | | using namespace std; |
| | | |
| | | HwIdentifier::HwIdentifier() {} |
| | | |
| | | HwIdentifier::HwIdentifier(const std::string& param) { |
| | | string tmp_str(param); // throw away const |
| | | std::replace(tmp_str.begin(), tmp_str.end(), '-', '\n'); |
| | | vector<uint8_t> decoded = unbase64(tmp_str); |
| | | if (decoded.size() != HW_IDENTIFIER_PROPRIETARY_DATA + 1) { |
| | | cerr << decoded.size(); |
| | | throw logic_error("wrong identifier size " + param); |
| | | } |
| | | std::copy_n(decoded.begin(), HW_IDENTIFIER_PROPRIETARY_DATA + 1, m_data.begin()); |
| | | } |
| | | |
| | | HwIdentifier::~HwIdentifier() {} |
| | | |
| | | HwIdentifier::HwIdentifier(const HwIdentifier& other) : m_data(other.m_data) {} |
| | | |
| | | void HwIdentifier::set_identification_strategy(LCC_API_IDENTIFICATION_STRATEGY strategy) { |
| | | if (strategy == STRATEGY_NONE || strategy == STRATEGY_DEFAULT) { |
| | | throw logic_error("Only known strategies are permitted"); |
| | | } |
| | | uint8_t stratMov = (strategy << 5); |
| | | m_data[1] = (m_data[1] & 0x1F) | stratMov; |
| | | } |
| | | |
| | | void HwIdentifier::set_use_environment_var(bool use_env_var) { |
| | | if (use_env_var) { |
| | | m_data[0] = m_data[0] | 0x40; |
| | | } else { |
| | | m_data[0] = m_data[0] & ~0x40; |
| | | } |
| | | } |
| | | |
| | | void HwIdentifier::set_virtual_environment(os::VIRTUALIZATION virt) { |
| | | // 110000 0x30 |
| | | m_data[0] = (m_data[0] & ~0x30) | virt << 4; |
| | | } |
| | | |
| | | void HwIdentifier::set_virtualization(os::VIRTUALIZATION_DETAIL virtualization_detail) { |
| | | m_data[0] = (m_data[0] & ~0x0F) | virtualization_detail; |
| | | } |
| | | |
| | | void HwIdentifier::set_cloud_provider(os::CLOUD_PROVIDER cloud_provider) { |
| | | m_data[0] = (m_data[0] & ~0x0F) | cloud_provider | 0x08; |
| | | } |
| | | |
| | | void HwIdentifier::set_data(const std::array<uint8_t, HW_IDENTIFIER_PROPRIETARY_DATA>& data) { |
| | | m_data[1] = (m_data[1] & (~0x1f)) | (data[0] & 0x1f); |
| | | for (int i = 1; i < HW_IDENTIFIER_PROPRIETARY_DATA; i++) { |
| | | m_data[i + 1] = data[i]; |
| | | } |
| | | } |
| | | |
| | | std::string HwIdentifier::print() const { |
| | | string result = base64(m_data.data(), m_data.size(), 5); |
| | | std::replace(result.begin(), result.end(), '\n', '-'); |
| | | return result.substr(0, result.size() - 1); |
| | | } |
| | | |
| | | LCC_API_IDENTIFICATION_STRATEGY HwIdentifier::get_identification_strategy() const { |
| | | uint8_t stratMov = m_data[1] >> 5; |
| | | return static_cast<LCC_API_IDENTIFICATION_STRATEGY>(stratMov); |
| | | } |
| | | |
| | | bool HwIdentifier::data_match(const std::array<uint8_t, HW_IDENTIFIER_PROPRIETARY_DATA>& data) const { |
| | | bool equals = true; |
| | | for (int i = 0; i < HW_IDENTIFIER_PROPRIETARY_DATA && equals; i++) { |
| | | equals = (i == 0) ? ((data[i] & 0x1f) == (m_data[i + 1] & 0x1f)) : (data[i] == m_data[i + 1]); |
| | | } |
| | | return equals; |
| | | } |
| | | |
| | | bool operator==(const HwIdentifier& lhs, const HwIdentifier& rhs) { |
| | | bool equals = lhs.get_identification_strategy() == rhs.get_identification_strategy(); |
| | | for (int i = 0; i < HW_IDENTIFIER_PROPRIETARY_DATA && equals; i++) { |
| | | equals = (i == 0) ? ((rhs.m_data[i + 1] & 0x1f) == (lhs.m_data[i + 1] & 0x1f)) |
| | | : (lhs.m_data[i + 1] == rhs.m_data[i + 1]); |
| | | } |
| | | return equals; |
| | | } |
| | | |
| | | } // namespace hw_identifier |
| | | } /* namespace license */ |
New file |
| | |
| | | /* |
| | | * hw_identifier.h |
| | | * |
| | | * Created on: Dec 22, 2019 |
| | | * Author: GC |
| | | */ |
| | | |
| | | #ifndef SRC_LIBRARY_PC_IDENTIFIER_PC_IDENTIFIER_HPP_ |
| | | #define SRC_LIBRARY_PC_IDENTIFIER_PC_IDENTIFIER_HPP_ |
| | | |
| | | #include <array> |
| | | #include <iostream> |
| | | #include <string> |
| | | |
| | | #include <licensecc_properties.h> |
| | | #include "../../../include/licensecc/datatypes.h" |
| | | #include "../os/execution_environment.hpp" |
| | | #include "../os/cpu_info.hpp" |
| | | |
| | | namespace license { |
| | | namespace hw_identifier { |
| | | |
| | | #define HW_IDENTIFIER_PROPRIETARY_DATA 8 |
| | | |
| | | /** |
| | | * data[0] |
| | | * bit 7 = 0 if pc id is being generated 1 if it is coming from an issued license. |
| | | * |
| | | * if bit 7 = 0 |
| | | * bit 6 = environment variable was used to generate pc_id |
| | | * bit 5-4 = execution environment information (0=BARE_TO_METAL,1=VM,2=CONTAINER) |
| | | * bit 3 = 0 on premise vm 1 = cloud |
| | | * if on premise vm bits 2-1-0 are virtualization technology |
| | | * if cloud vm bits 2-1-0 identify cloud provider |
| | | * |
| | | * if bit 7 = 1 hardware identifier is used to enable some flag that we don't want to show openly in the license |
| | | * bit 6 = 1 enable magic file/registry key |
| | | * ---- |
| | | * data[1] bit 7-6-5 define identification strategy. |
| | | * data[1] bits 4-0, data[2-8] are hardware identifier proprietary strategy data. |
| | | */ |
| | | |
| | | class HwIdentifier { |
| | | private: |
| | | std::array<uint8_t, HW_IDENTIFIER_PROPRIETARY_DATA + 1> m_data = {}; |
| | | friend bool operator==(const HwIdentifier &lhs, const HwIdentifier &rhs); |
| | | |
| | | public: |
| | | HwIdentifier(); |
| | | HwIdentifier(const std::string ¶m); |
| | | virtual ~HwIdentifier(); |
| | | HwIdentifier(const HwIdentifier &other); |
| | | void set_identification_strategy(LCC_API_IDENTIFICATION_STRATEGY strategy); |
| | | LCC_API_IDENTIFICATION_STRATEGY get_identification_strategy() const; |
| | | void set_use_environment_var(bool use_env_var); |
| | | void set_virtual_environment(os::VIRTUALIZATION virtualization); |
| | | void set_virtualization(os::VIRTUALIZATION_DETAIL virtualization_detail); |
| | | void set_cloud_provider(os::CLOUD_PROVIDER cloud_provider); |
| | | void set_data(const std::array<uint8_t, HW_IDENTIFIER_PROPRIETARY_DATA> &data); |
| | | bool data_match(const std::array<uint8_t, HW_IDENTIFIER_PROPRIETARY_DATA> &data) const; |
| | | std::string print() const; |
| | | friend std::ostream &operator<<(std::ostream &output, const HwIdentifier &d) { |
| | | output << d.print(); |
| | | return output; |
| | | }; |
| | | }; |
| | | |
| | | |
| | | } // namespace hw_identifier |
| | | } /* namespace license */ |
| | | |
| | | #endif /* SRC_LIBRARY_PC_IDENTIFIER_PC_IDENTIFIER_HPP_ */ |
New file |
| | |
| | | /* |
| | | * hw_identifier_facade.cpp |
| | | * |
| | | * Created on: Dec 26, 2019 |
| | | * Author: devel |
| | | */ |
| | | |
| | | #include "hw_identifier_facade.hpp" |
| | | |
| | | #include <cstdlib> |
| | | #include <stdexcept> |
| | | |
| | | #include "../base/base.h" |
| | | #include "../base/logger.h" |
| | | #include "../os/cpu_info.hpp" |
| | | #include "../os/execution_environment.hpp" |
| | | #include "identification_strategy.hpp" |
| | | #include "hw_identifier.hpp" |
| | | |
| | | namespace license { |
| | | namespace hw_identifier { |
| | | |
| | | using namespace std; |
| | | |
| | | LCC_EVENT_TYPE HwIdentifierFacade::validate_pc_signature(const std::string& str_code) { |
| | | HwIdentifier pc_id(str_code); |
| | | LCC_API_IDENTIFICATION_STRATEGY id_strategy = pc_id.get_identification_strategy(); |
| | | LCC_EVENT_TYPE result = IDENTIFIERS_MISMATCH; |
| | | try { |
| | | unique_ptr<IdentificationStrategy> strategy = IdentificationStrategy::get_strategy(id_strategy); |
| | | result = strategy->validate_identifier(pc_id); |
| | | } catch (logic_error& e) { |
| | | LOG_ERROR("Error validating identifier %s: %s", str_code.c_str(), e.what()); |
| | | } |
| | | return result; |
| | | } |
| | | |
| | | std::string HwIdentifierFacade::generate_user_pc_signature(LCC_API_IDENTIFICATION_STRATEGY strategy) { |
| | | bool use_env_var = false; |
| | | vector<LCC_API_IDENTIFICATION_STRATEGY> strategies_to_try; |
| | | if (strategy == STRATEGY_DEFAULT) { |
| | | char* env_var_value = getenv(LCC_IDENTIFICATION_STRATEGY_ENV_VAR); |
| | | if (env_var_value != nullptr && env_var_value[0] != '\0') { |
| | | int strategy_int = atoi(env_var_value); |
| | | if (strategy_int < 0 || strategy_int > 3) { |
| | | LOG_WARN("unknown " LCC_IDENTIFICATION_STRATEGY_ENV_VAR " %s", env_var_value); |
| | | } else { |
| | | strategy = (LCC_API_IDENTIFICATION_STRATEGY)strategy_int; |
| | | use_env_var = true; |
| | | } |
| | | } |
| | | } |
| | | |
| | | unique_ptr<IdentificationStrategy> strategy_ptr = IdentificationStrategy::get_strategy(strategy); |
| | | HwIdentifier pc_id; |
| | | FUNCTION_RETURN result = strategy_ptr->identify_pc(pc_id); |
| | | if (result != FUNC_RET_OK) { |
| | | throw logic_error("strategy " + to_string(strategy_ptr->identification_strategy()) + " failed"); |
| | | } |
| | | os::ExecutionEnvironment exec; |
| | | os::VIRTUALIZATION virtualization = exec.getVirtualization(); |
| | | pc_id.set_virtual_environment(virtualization); |
| | | pc_id.set_use_environment_var(use_env_var); |
| | | if (virtualization != os::NONE) { |
| | | bool isCloud = exec.is_cloud(); |
| | | if (isCloud) { |
| | | pc_id.set_cloud_provider(exec.getCloudProvider()); |
| | | } else { |
| | | os::CpuInfo cpu; |
| | | pc_id.set_virtualization(cpu.virtualization_details()); |
| | | } |
| | | } |
| | | return pc_id.print(); |
| | | } |
| | | |
| | | } // namespace hw_identifier |
| | | } /* namespace license */ |
New file |
| | |
| | | /* |
| | | * hw_identifier_facade.hpp |
| | | * |
| | | * Created on: Dec 26, 2019 |
| | | * Author: devel |
| | | */ |
| | | |
| | | #ifndef SRC_LIBRARY_PC_IDENTIFIER_HW_IDENTIFIER_FACADE_HPP_ |
| | | #define SRC_LIBRARY_PC_IDENTIFIER_HW_IDENTIFIER_FACADE_HPP_ |
| | | #include "hw_identifier_facade.hpp" |
| | | |
| | | #include <string> |
| | | #include <unordered_map> |
| | | #include <licensecc/datatypes.h> |
| | | #include "identification_strategy.hpp" |
| | | |
| | | namespace license { |
| | | namespace hw_identifier { |
| | | |
| | | class HwIdentifierFacade { |
| | | private: |
| | | HwIdentifierFacade(){}; |
| | | virtual ~HwIdentifierFacade(){}; |
| | | public: |
| | | static LCC_EVENT_TYPE validate_pc_signature(const std::string& str_code); |
| | | /** |
| | | * |
| | | * @throws logic_error if pc_identifier can't be generated. |
| | | * @param strategy |
| | | * @return |
| | | */ |
| | | static std::string generate_user_pc_signature(LCC_API_IDENTIFICATION_STRATEGY strategy); |
| | | }; |
| | | |
| | | } // namespace hw_identifier |
| | | } /* namespace license */ |
| | | |
| | | #endif /* SRC_LIBRARY_PC_IDENTIFIER_HW_IDENTIFIER_FACADE_HPP_ */ |
New file |
| | |
| | | #include <array> |
| | | #include "identification_strategy.hpp" |
| | | #include "default_strategy.hpp" |
| | | #include "ethernet.hpp" |
| | | #include "disk_strategy.hpp" |
| | | namespace license { |
| | | namespace hw_identifier { |
| | | |
| | | using namespace std; |
| | | LCC_EVENT_TYPE IdentificationStrategy::validate_identifier(const HwIdentifier& identifier) const { |
| | | LCC_EVENT_TYPE result = IDENTIFIERS_MISMATCH; |
| | | |
| | | if (identifier.get_identification_strategy() == identification_strategy()) { |
| | | const vector<HwIdentifier> available_ids = alternative_ids(); |
| | | for (const auto& it : available_ids) { |
| | | if (it == identifier) { |
| | | result = LICENSE_OK; |
| | | break; |
| | | } |
| | | } |
| | | } |
| | | return result; |
| | | } |
| | | |
| | | FUNCTION_RETURN IdentificationStrategy::identify_pc(HwIdentifier& pc_id) const { |
| | | vector<array<uint8_t, HW_IDENTIFIER_PROPRIETARY_DATA>> data; |
| | | const vector<HwIdentifier> available_ids = alternative_ids(); |
| | | FUNCTION_RETURN result = FUNC_RET_NOT_AVAIL; |
| | | if (available_ids.size() > 0) { |
| | | pc_id = available_ids[0]; |
| | | result = FUNC_RET_OK; |
| | | } |
| | | return result; |
| | | } |
| | | |
| | | std::unique_ptr<IdentificationStrategy> IdentificationStrategy::get_strategy(LCC_API_IDENTIFICATION_STRATEGY strategy) { |
| | | unique_ptr<IdentificationStrategy> result; |
| | | switch (strategy) { |
| | | case STRATEGY_DEFAULT: |
| | | result = unique_ptr<IdentificationStrategy>(dynamic_cast<IdentificationStrategy*>(new DefaultStrategy())); |
| | | break; |
| | | case STRATEGY_ETHERNET: |
| | | result = unique_ptr<IdentificationStrategy>(dynamic_cast<IdentificationStrategy*>(new Ethernet(false))); |
| | | break; |
| | | case STRATEGY_IP_ADDRESS: |
| | | result = unique_ptr<IdentificationStrategy>(dynamic_cast<IdentificationStrategy*>(new Ethernet(true))); |
| | | break; |
| | | case STRATEGY_DISK_NUM: |
| | | result = unique_ptr<IdentificationStrategy>(dynamic_cast<IdentificationStrategy*>(new DiskStrategy(true))); |
| | | break; |
| | | case STRATEGY_DISK_LABEL: |
| | | result = unique_ptr<IdentificationStrategy>(dynamic_cast<IdentificationStrategy*>(new DiskStrategy(false))); |
| | | break; |
| | | default: |
| | | throw logic_error("strategy not supported"); |
| | | } |
| | | return result; |
| | | } |
| | | } // namespace hw_identifier |
| | | } // namespace license |
New file |
| | |
| | | /* |
| | | * identification_strategy.hpp |
| | | * |
| | | * Created on: Jan 1, 2020 |
| | | * Author: devel |
| | | */ |
| | | |
| | | #ifndef SRC_LIBRARY_PC_IDENTIFIER_IDENTIFICATION_STRATEGY_HPP_ |
| | | #define SRC_LIBRARY_PC_IDENTIFIER_IDENTIFICATION_STRATEGY_HPP_ |
| | | |
| | | #include <licensecc/datatypes.h> |
| | | #include <licensecc_properties.h> |
| | | #include <vector> |
| | | #include <memory> |
| | | #include "../base/base.h" |
| | | #include "hw_identifier.hpp" |
| | | |
| | | namespace license { |
| | | namespace hw_identifier { |
| | | |
| | | class IdentificationStrategy { |
| | | protected: |
| | | IdentificationStrategy(){}; |
| | | |
| | | public: |
| | | virtual ~IdentificationStrategy(){}; |
| | | virtual LCC_API_IDENTIFICATION_STRATEGY identification_strategy() const = 0; |
| | | virtual FUNCTION_RETURN identify_pc(HwIdentifier& identifier_out) const; |
| | | virtual std::vector<HwIdentifier> alternative_ids() const = 0; |
| | | virtual LCC_EVENT_TYPE validate_identifier(const HwIdentifier& identifier_in) const; |
| | | |
| | | /** |
| | | * Factory method to create an instance of IdentificationStrategy |
| | | * @param strategy |
| | | * @return |
| | | */ |
| | | static std::unique_ptr<IdentificationStrategy> get_strategy(LCC_API_IDENTIFICATION_STRATEGY strategy); |
| | | }; |
| | | |
| | | } // namespace hw_identifier |
| | | } /* namespace license */ |
| | | |
| | | #endif /* SRC_LIBRARY_PC_IDENTIFIER_IDENTIFICATION_STRATEGY_HPP_ */ |
| | |
| | | #include <licensecc/licensecc.h> |
| | | #include <licensecc_properties.h> |
| | | |
| | | #include "base/logger.h" |
| | | #include "hw_identifier/hw_identifier_facade.hpp" |
| | | #include "limits/license_verifier.hpp" |
| | | #include "base/StringUtils.h" |
| | | #include "LicenseReader.hpp" |
| | | #include "pc-identifiers.h" |
| | | |
| | | using namespace std; |
| | | |
| | | void print_error(char out_buffer[ERROR_BUFFER_SIZE], LicenseInfo* licenseInfo) {} |
| | | |
| | | bool identify_pc(IDENTIFICATION_STRATEGY pc_id_method, char* chbuffer, size_t* bufSize) { |
| | | FUNCTION_RETURN result = FUNC_RET_BUFFER_TOO_SMALL; |
| | | if (*bufSize > sizeof(PcSignature)) { |
| | | PcSignature identifier_out; |
| | | result = generate_user_pc_signature(identifier_out, pc_id_method); |
| | | strncpy(chbuffer, identifier_out, *bufSize); |
| | | void print_error(char out_buffer[LCC_API_ERROR_BUFFER_SIZE], LicenseInfo* licenseInfo) {} |
| | | |
| | | bool identify_pc(LCC_API_IDENTIFICATION_STRATEGY pc_id_method, char* chbuffer, size_t* bufSize) { |
| | | bool result = false; |
| | | if (*bufSize > LCC_API_PC_IDENTIFIER_SIZE && chbuffer != nullptr) { |
| | | try { |
| | | string pc_id = license::hw_identifier::HwIdentifierFacade::generate_user_pc_signature(pc_id_method); |
| | | strncpy(chbuffer, pc_id.c_str(), *bufSize); |
| | | result = true; |
| | | } catch (const std::exception& ex) { |
| | | LOG_ERROR("Error calculating hw_identifier: %s", ex.what()); |
| | | #ifdef _DEBUG |
| | | cout |
| | | << "Error occurred: " << ex.what() << std::endl; |
| | | #endif |
| | | } |
| | | } else { |
| | | *bufSize = sizeof(PcSignature) + 1; |
| | | *bufSize = LCC_API_PC_IDENTIFIER_SIZE + 1; |
| | | } |
| | | return result == FUNC_RET_OK; |
| | | return result; |
| | | } |
| | | |
| | | static void mergeLicenses(const vector<LicenseInfo>& licenses, LicenseInfo* license_out) { |
| | |
| | | } |
| | | } |
| | | |
| | | EVENT_TYPE acquire_license(const CallerInformations* callerInformation, const LicenseLocation* licenseLocation, |
| | | LicenseInfo* license_out) { |
| | | LCC_EVENT_TYPE acquire_license(const CallerInformations* callerInformation, |
| | | const LicenseLocation* licenseLocation, LicenseInfo* license_out) { |
| | | const license::LicenseReader lr = license::LicenseReader(licenseLocation); |
| | | vector<license::FullLicenseInfo> licenses; |
| | | string project; |
| | |
| | | project = string(LCC_PROJECT_NAME); |
| | | } |
| | | license::EventRegistry er = lr.readLicenses(string(project), licenses); |
| | | EVENT_TYPE result; |
| | | LCC_EVENT_TYPE result; |
| | | if (licenses.size() > 0) { |
| | | vector<LicenseInfo> licenses_with_errors; |
| | | vector<LicenseInfo> licenses_ok; |
| | | license::LicenseVerifier verifier(er); |
| | | for (auto it = licenses.begin(); it != licenses.end(); it++) { |
| | | FUNCTION_RETURN signatureValid = verifier.verify_signature(*it); |
| | | for (auto full_lic_info_it = licenses.begin(); full_lic_info_it != licenses.end(); full_lic_info_it++) { |
| | | if (callerInformation != nullptr) { |
| | | full_lic_info_it->m_magic = callerInformation->magic; |
| | | } |
| | | const FUNCTION_RETURN signatureValid = verifier.verify_signature(*full_lic_info_it); |
| | | LicenseInfo licInfo = verifier.toLicenseInfo(*full_lic_info_it); |
| | | if (signatureValid == FUNC_RET_OK) { |
| | | if (verifier.verify_limits(*it) == FUNC_RET_OK) { |
| | | licenses_ok.push_back(verifier.toLicenseInfo(*it)); |
| | | if (verifier.verify_limits(*full_lic_info_it) == FUNC_RET_OK) { |
| | | licenses_ok.push_back(licInfo); |
| | | } else { |
| | | licenses_with_errors.push_back(verifier.toLicenseInfo(*it)); |
| | | licenses_with_errors.push_back(licInfo); |
| | | } |
| | | } else { |
| | | licenses_with_errors.push_back(verifier.toLicenseInfo(*it)); |
| | | licenses_with_errors.push_back(licInfo); |
| | | } |
| | | } |
| | | if (licenses_ok.size() > 0) { |
| | |
| | | #endif |
| | | |
| | | if (license_out != nullptr) { |
| | | er.exportLastEvents(license_out->status, AUDIT_EVENT_NUM); |
| | | er.exportLastEvents(license_out->status, LCC_API_AUDIT_EVENT_NUM); |
| | | } |
| | | return result; |
| | | } |
| | | |
| | | EVENT_TYPE confirm_license(char* product, LicenseLocation licenseLocation) { return LICENSE_OK; } |
| | | LCC_EVENT_TYPE confirm_license(char* product, LicenseLocation licenseLocation) { return LICENSE_OK; } |
| | | |
| | | EVENT_TYPE release_license(char* product, LicenseLocation licenseLocation) { return LICENSE_OK; } |
| | | LCC_EVENT_TYPE release_license(char* product, LicenseLocation licenseLocation) { return LICENSE_OK; } |
| | | |
| | |
| | | */ |
| | | #include <cmath> |
| | | #include <algorithm> |
| | | #include <licensecc_properties.h> |
| | | |
| | | #include "license_verifier.hpp" |
| | | #include "../os/signature_verifier.h" |
| | | #include "../base/StringUtils.h" |
| | | #include "../pc-identifiers.h" |
| | | #include "../os/signature_verifier.hpp" |
| | | #include "../hw_identifier/hw_identifier_facade.hpp" |
| | | |
| | | namespace license { |
| | | using namespace std; |
| | |
| | | FUNCTION_RETURN LicenseVerifier::verify_signature(const FullLicenseInfo& licInfo) { |
| | | const string licInfoData(licInfo.printForSign()); |
| | | |
| | | FUNCTION_RETURN ret = license::verify_signature(licInfoData, licInfo.license_signature); |
| | | FUNCTION_RETURN ret = license::os::verify_signature(licInfoData, licInfo.license_signature); |
| | | |
| | | if (ret == FUNC_RET_OK) { |
| | | m_event_registry.addEvent(SIGNATURE_VERIFIED, licInfo.source); |
| | |
| | | } |
| | | |
| | | // TODO: split in different classes |
| | | FUNCTION_RETURN LicenseVerifier::verify_limits(const FullLicenseInfo& licInfo) { |
| | | bool is_valid = true; |
| | | FUNCTION_RETURN LicenseVerifier::verify_limits(const FullLicenseInfo& lic_info) { |
| | | bool is_valid = LCC_VERIFY_MAGIC; |
| | | if (!is_valid) { |
| | | m_event_registry.addEvent(LICENSE_CORRUPTED, lic_info.source.c_str()); |
| | | } |
| | | const time_t now = time(nullptr); |
| | | auto expiry = licInfo.m_limits.find(PARAM_EXPIRY_DATE); |
| | | if (expiry != licInfo.m_limits.end()) { |
| | | auto expiry = lic_info.m_limits.find(PARAM_EXPIRY_DATE); |
| | | if (is_valid && expiry != lic_info.m_limits.end()) { |
| | | if (seconds_from_epoch(expiry->second) < now) { |
| | | /* |
| | | eventRegistryOut.addEvent(PRODUCT_EXPIRED, source.c_str(), |
| | | string("Expired on: " + this->to_date).c_str());*/ |
| | | m_event_registry.addEvent(PRODUCT_EXPIRED, licInfo.source.c_str(), ("Expired " + expiry->second).c_str()); |
| | | m_event_registry.addEvent(PRODUCT_EXPIRED, lic_info.source.c_str(), ("Expired " + expiry->second).c_str()); |
| | | is_valid = false; |
| | | } |
| | | } |
| | | auto start_date = licInfo.m_limits.find(PARAM_BEGIN_DATE); |
| | | if (is_valid && start_date != licInfo.m_limits.end()) { |
| | | const auto start_date = lic_info.m_limits.find(PARAM_BEGIN_DATE); |
| | | if (is_valid && start_date != lic_info.m_limits.end()) { |
| | | if (seconds_from_epoch(start_date->second) > now) { |
| | | /*eventRegistryOut.addEvent(PRODUCT_EXPIRED, source.c_str(), |
| | | string("Valid from " + this->from_date).c_str());*/ |
| | | m_event_registry.addEvent(PRODUCT_EXPIRED, licInfo.source.c_str(), |
| | | m_event_registry.addEvent(PRODUCT_EXPIRED, lic_info.source.c_str(), |
| | | ("Valid from " + start_date->second).c_str()); |
| | | is_valid = false; |
| | | } |
| | | } |
| | | auto client_sig = licInfo.m_limits.find(PARAM_CLIENT_SIGNATURE); |
| | | if (is_valid && client_sig != licInfo.m_limits.end()) { |
| | | PcSignature str_code; |
| | | strncpy(str_code, client_sig->second.c_str(), sizeof(str_code) - 1); |
| | | const EVENT_TYPE event = validate_pc_signature(str_code); |
| | | m_event_registry.addEvent(event, licInfo.source); |
| | | const auto client_sig = lic_info.m_limits.find(PARAM_CLIENT_SIGNATURE); |
| | | if (is_valid && client_sig != lic_info.m_limits.end()) { |
| | | const LCC_EVENT_TYPE event = hw_identifier::HwIdentifierFacade::validate_pc_signature(client_sig->second); |
| | | m_event_registry.addEvent(event, lic_info.source); |
| | | is_valid = is_valid && (event == LICENSE_OK); |
| | | } |
| | | return is_valid ? FUNC_RET_OK : FUNC_RET_ERROR; |
| | |
| | | |
| | | LicenseInfo LicenseVerifier::toLicenseInfo(const FullLicenseInfo& fullLicInfo) const { |
| | | LicenseInfo info; |
| | | info.license_type = LOCAL; |
| | | info.license_type = LCC_LOCAL; |
| | | |
| | | auto expiry = fullLicInfo.m_limits.find(PARAM_EXPIRY_DATE); |
| | | const auto expiry = fullLicInfo.m_limits.find(PARAM_EXPIRY_DATE); |
| | | if (expiry != fullLicInfo.m_limits.end()) { |
| | | strncpy(info.expiry_date, expiry->second.c_str(), sizeof(info.expiry_date)); |
| | | info.has_expiry = true; |
| | |
| | | info.expiry_date[0] = '\0'; |
| | | } |
| | | |
| | | auto start_date = fullLicInfo.m_limits.find(PARAM_BEGIN_DATE); |
| | | const auto start_date = fullLicInfo.m_limits.find(PARAM_BEGIN_DATE); |
| | | if (start_date != fullLicInfo.m_limits.end()) { |
| | | } |
| | | |
| | | auto client_sig = fullLicInfo.m_limits.find(PARAM_CLIENT_SIGNATURE); |
| | | const auto client_sig = fullLicInfo.m_limits.find(PARAM_CLIENT_SIGNATURE); |
| | | info.linked_to_pc = (client_sig != fullLicInfo.m_limits.end()); |
| | | |
| | | auto proprietary_data = fullLicInfo.m_limits.find(PARAM_EXTRA_DATA); |
| | | const auto proprietary_data = fullLicInfo.m_limits.find(PARAM_EXTRA_DATA); |
| | | if (proprietary_data != fullLicInfo.m_limits.end()) { |
| | | strncpy(info.proprietary_data, proprietary_data->second.c_str(), PROPRIETARY_DATA_SIZE); |
| | | strncpy(info.proprietary_data, proprietary_data->second.c_str(), LCC_API_PROPRIETARY_DATA_SIZE); |
| | | } |
| | | return info; |
| | | } |
| | |
| | | #include "../base/logger.h" |
| | | #include "../base/base.h" |
| | | #include "../base/EventRegistry.h" |
| | | #include "../base/FileUtils.hpp" |
| | | #include "../os/os.h" |
| | | #include "ApplicationFolder.hpp" |
| | | #include "../base/file_utils.hpp" |
| | | |
| | | namespace license { |
| | | namespace locate { |
| | |
| | | const FUNCTION_RETURN fret = getModuleName(fname); |
| | | if (fret == FUNC_RET_OK) { |
| | | const string module_name = remove_extension(fname); |
| | | const string temptativeLicense = string(module_name) + LICENSE_FILE_EXTENSION; |
| | | const string temptativeLicense = string(module_name) + LCC_LICENSE_FILE_EXTENSION; |
| | | ifstream f(temptativeLicense.c_str()); |
| | | if (f.good()) { |
| | | diskFiles.push_back(temptativeLicense); |
| | |
| | | target_sources(licensecc_static PRIVATE |
| | | ${CMAKE_CURRENT_SOURCE_DIR}/ApplicationFolder.cpp |
| | | ${CMAKE_CURRENT_SOURCE_DIR}/EnvironmentVarLocation.cpp |
| | | ${CMAKE_CURRENT_SOURCE_DIR}/EnvironmentVarData.cpp |
| | | ${CMAKE_CURRENT_SOURCE_DIR}/ExternalDefinition.cpp |
| | | ${CMAKE_CURRENT_SOURCE_DIR}/LocatorStrategy.cpp |
| | | ${CMAKE_CURRENT_SOURCE_DIR}/LocatorFactory.cpp |
| | | add_library(locate OBJECT |
| | | ApplicationFolder.cpp |
| | | EnvironmentVarLocation.cpp |
| | | EnvironmentVarData.cpp |
| | | ExternalDefinition.cpp |
| | | LocatorStrategy.cpp |
| | | LocatorFactory.cpp |
| | | ) |
| | | |
| | | target_include_directories(locate PRIVATE |
| | | $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../../include> |
| | | $<BUILD_INTERFACE:${LCC_INCLUDE_DIR}> |
| | | ) |
| | | |
| | | if(CODE_COVERAGE AND UNIX) |
| | | target_compile_options(locate PUBLIC -O0 -g --coverage) |
| | | endif(CODE_COVERAGE AND UNIX) |
| | |
| | | |
| | | const vector<string> EnvironmentVarData::license_locations(EventRegistry &eventRegistry) { |
| | | vector<string> diskFiles; |
| | | char *env_var_value = getenv(LICENSE_DATA_ENV_VAR); |
| | | char *env_var_value = getenv(LCC_LICENSE_DATA_ENV_VAR); |
| | | if (env_var_value != nullptr && env_var_value[0] != '\0') { |
| | | eventRegistry.addEvent(LICENSE_SPECIFIED, LICENSE_LOCATION_ENV_VAR); |
| | | eventRegistry.addEvent(LICENSE_SPECIFIED, LCC_LICENSE_LOCATION_ENV_VAR); |
| | | FILE_FORMAT licenseFormat = identify_format(env_var_value); |
| | | if (licenseFormat == UNKNOWN) { |
| | | eventRegistry.addEvent(LICENSE_MALFORMED, LICENSE_LOCATION_ENV_VAR); |
| | | eventRegistry.addEvent(LICENSE_MALFORMED, LCC_LICENSE_LOCATION_ENV_VAR); |
| | | } else { |
| | | diskFiles.push_back(LICENSE_LOCATION_ENV_VAR); |
| | | diskFiles.push_back(LCC_LICENSE_LOCATION_ENV_VAR); |
| | | isBase64 = (licenseFormat == BASE64); |
| | | } |
| | | } else { |
| | | eventRegistry.addEvent(ENVIRONMENT_VARIABLE_NOT_DEFINED, LICENSE_LOCATION_ENV_VAR); |
| | | eventRegistry.addEvent(ENVIRONMENT_VARIABLE_NOT_DEFINED, LCC_LICENSE_LOCATION_ENV_VAR); |
| | | } |
| | | return diskFiles; |
| | | } |
| | | |
| | | const std::string EnvironmentVarData::retrieve_license_content(const std::string &licenseLocation) const { |
| | | string tmpVal = getenv(LICENSE_LOCATION_ENV_VAR); |
| | | string env_val = getenv(LCC_LICENSE_LOCATION_ENV_VAR); |
| | | if (isBase64) { |
| | | int flen = 0; |
| | | unsigned char *raw = unbase64(tmpVal.c_str(), tmpVal.length(), &flen); |
| | | string str = string(reinterpret_cast<char *>(raw)); |
| | | free(raw); |
| | | vector<uint8_t> data = unbase64(env_val); |
| | | string str = string(reinterpret_cast<char *>(data.data())); |
| | | return str; |
| | | } |
| | | return tmpVal; |
| | | return env_val; |
| | | } |
| | | |
| | | } // namespace locate |
| | |
| | | |
| | | #include <licensecc_properties.h> |
| | | |
| | | #include "../base/FileUtils.hpp" |
| | | #include "../base/StringUtils.h" |
| | | #include "EnvironmentVarLocation.hpp" |
| | | #include "../base/file_utils.hpp" |
| | | |
| | | namespace license { |
| | | namespace locate { |
| | |
| | | const vector<string> EnvironmentVarLocation::license_locations(EventRegistry &eventRegistry) { |
| | | vector<string> licenseFileFoundWithEnvVariable; |
| | | |
| | | const string varName(LICENSE_LOCATION_ENV_VAR); |
| | | const string varName(LCC_LICENSE_LOCATION_ENV_VAR); |
| | | if (varName.length() > 0) { |
| | | // var name is defined in header files. |
| | | char *env_var_value = getenv(LICENSE_LOCATION_ENV_VAR); |
| | | char *env_var_value = getenv(LCC_LICENSE_LOCATION_ENV_VAR); |
| | | if (env_var_value != nullptr && env_var_value[0] != '\0') { |
| | | const vector<string> declared_positions = license::split_string(string(env_var_value), ';'); |
| | | licenseFileFoundWithEnvVariable = |
| | | license::filter_existing_files(declared_positions, eventRegistry, LICENSE_LOCATION_ENV_VAR); |
| | | license::filter_existing_files(declared_positions, eventRegistry, LCC_LICENSE_LOCATION_ENV_VAR); |
| | | } else { |
| | | eventRegistry.addEvent(ENVIRONMENT_VARIABLE_NOT_DEFINED); |
| | | } |
| | |
| | | #include <cstring> |
| | | #include <string> |
| | | #include <vector> |
| | | |
| | | #include <stdexcept> |
| | | #include <licensecc/datatypes.h> |
| | | |
| | | #include "../base/base64.h" |
| | | #include "../base/EventRegistry.h" |
| | | #include "../base/FileUtils.hpp" |
| | | #include "../base/StringUtils.h" |
| | | |
| | | #include "ExternalDefinition.hpp" |
| | | #include "../base/file_utils.hpp" |
| | | |
| | | namespace license { |
| | | namespace locate { |
| | | using namespace std; |
| | | using namespace std; |
| | | |
| | | ExternalDefinition::ExternalDefinition(const LicenseLocation *location) : |
| | | LocatorStrategy("ExternalDefinition"), m_location(location) { |
| | | } |
| | | ExternalDefinition::ExternalDefinition(const LicenseLocation *location) |
| | | : LocatorStrategy("ExternalDefinition"), m_location(location) {} |
| | | |
| | | ExternalDefinition::~ExternalDefinition() { |
| | | } |
| | | ExternalDefinition::~ExternalDefinition() {} |
| | | |
| | | const std::vector<std::string> ExternalDefinition::license_locations( |
| | | EventRegistry &eventRegistry) { |
| | | const std::vector<std::string> ExternalDefinition::license_locations(EventRegistry &eventRegistry) { |
| | | vector<string> existing_pos; |
| | | if (m_location->licenseData != nullptr |
| | | && m_location->licenseData[0] != '\0') { |
| | | if (m_location->licenseData[0] != '\0') { |
| | | eventRegistry.addEvent(LICENSE_SPECIFIED, get_strategy_name()); |
| | | FILE_FORMAT licenseFormat = identify_format(m_location->licenseData); |
| | | |
| | | if (licenseFormat == UNKNOWN) { |
| | | eventRegistry.addEvent(LICENSE_MALFORMED, get_strategy_name()); |
| | | } else { |
| | | existing_pos.push_back(get_strategy_name()); |
| | | licenseDataIsBase64 = (licenseFormat == BASE64); |
| | | switch (m_location->license_data_type) { |
| | | case LICENSE_PATH: { |
| | | string licData(m_location->licenseData, mstrnlen_s(m_location->licenseData, LCC_API_MAX_LICENSE_DATA_LENGTH)); |
| | | const vector<string> declared_positions = license::split_string(licData, ';'); |
| | | existing_pos = |
| | | license::filter_existing_files(declared_positions, eventRegistry, get_strategy_name().c_str()); |
| | | } break; |
| | | case LICENSE_ENCODED: |
| | | case LICENSE_PLAIN_DATA: |
| | | existing_pos.push_back(get_strategy_name()); |
| | | break; |
| | | default: |
| | | throw logic_error("license type not supported "); |
| | | } |
| | | } |
| | | if (m_location->licenseFileLocation != nullptr |
| | | && strlen(m_location->licenseFileLocation) > 0) { |
| | | const vector<string> declared_positions = license::split_string( |
| | | m_location->licenseFileLocation, ';'); |
| | | existing_pos = license::filter_existing_files(declared_positions, |
| | | eventRegistry, get_strategy_name().c_str()); |
| | | } |
| | | return existing_pos; |
| | | } |
| | | |
| | | const std::string ExternalDefinition::retrieve_license_content( |
| | | const std::string &licenseLocation) const { |
| | | const std::string ExternalDefinition::retrieve_license_content(const std::string &licenseLocation) const { |
| | | if (licenseLocation == get_strategy_name()) { |
| | | if (licenseDataIsBase64) { |
| | | int flen = 0; |
| | | unsigned char *raw = unbase64(m_location->licenseData, |
| | | strlen(m_location->licenseData), &flen); |
| | | string str = string(reinterpret_cast<char*>(raw)); |
| | | free(raw); |
| | | string licData(m_location->licenseData, mstrnlen_s(m_location->licenseData, LCC_API_MAX_LICENSE_DATA_LENGTH)); |
| | | if (m_location->license_data_type == LICENSE_ENCODED) { |
| | | // FIXME what if license is wrong |
| | | vector<uint8_t> raw = unbase64(licData); |
| | | string str = string(reinterpret_cast<char *>(raw.data())); |
| | | return str; |
| | | } else { |
| | | return m_location->licenseData; |
| | | return licData; |
| | | } |
| | | } else { |
| | | return LocatorStrategy::retrieve_license_content(licenseLocation); |
| | |
| | | class ExternalDefinition: public LocatorStrategy { |
| | | private: |
| | | const LicenseLocation* m_location; |
| | | bool licenseDataIsBase64 = false; |
| | | public: |
| | | ExternalDefinition(const LicenseLocation* location); |
| | | virtual const std::vector<std::string> license_locations(EventRegistry& eventRegistry); |
| | | virtual const std::string retrieve_license_content(const std::string &licenseLocation) const; |
| | | const virtual std::vector<std::string> license_locations(EventRegistry& eventRegistry); |
| | | const virtual std::string retrieve_license_content(const std::string& licenseLocation) const; |
| | | virtual ~ExternalDefinition(); |
| | | }; |
| | | |
| | |
| | | |
| | | #include <licensecc_properties.h> |
| | | |
| | | #include "../base/FileUtils.hpp" |
| | | #include "LocatorStrategy.hpp" |
| | | #include "../base/file_utils.hpp" |
| | | |
| | | namespace license { |
| | | namespace locate { |
| | | using namespace std; |
| | | |
| | | const string LocatorStrategy::retrieve_license_content(const string &licenseLocation) const { |
| | | return get_file_contents(licenseLocation.c_str(), MAX_LICENSE_LENGTH); |
| | | return get_file_contents(licenseLocation.c_str(), LCC_API_MAX_LICENSE_DATA_LENGTH); |
| | | } |
| | | |
| | | } // namespace locate |
| | |
| | | IF(UNIX OR OPENSSL_FOUND) |
| | | IF(UNIX) |
| | | target_sources(licensecc_static PRIVATE |
| | | ${CMAKE_CURRENT_SOURCE_DIR}/openssl/signature_verifier.cpp |
| | | ${CMAKE_CURRENT_SOURCE_DIR}/os-linux.c |
| | | ${CMAKE_CURRENT_SOURCE_DIR}/network_id.c) |
| | | add_library(os OBJECT |
| | | openssl/signature_verifier.cpp |
| | | execution_environment_common.cpp |
| | | linux/execution_environment.cpp |
| | | cpu_info_common.cpp |
| | | linux/cpu_info.cpp |
| | | linux/network.cpp |
| | | linux/os_linux.cpp) |
| | | ELSE(UNIX) |
| | | target_sources(licensecc_static PRIVATE |
| | | ${CMAKE_CURRENT_SOURCE_DIR}/openssl/signature_verifier.cpp |
| | | ${CMAKE_CURRENT_SOURCE_DIR}/os-win.c) |
| | | #windows and openssl |
| | | add_library(os OBJECT |
| | | cpu_info_common.cpp windows/cpu_info.cpp |
| | | openssl/signature_verifier.cpp |
| | | execution_environment_common.cpp windows/execution_environment.cpp |
| | | windows/isvm/Native.cpp |
| | | windows/isvm/BIOSReader.cpp |
| | | windows/os_win.cpp |
| | | windows/network.cpp) |
| | | ENDIF(UNIX) |
| | | target_include_directories(os PUBLIC ${OPENSSL_INCLUDE_DIR}) |
| | | ELSE(UNIX OR OPENSSL_FOUND) |
| | | target_sources(licensecc_static PRIVATE |
| | | ${CMAKE_CURRENT_SOURCE_DIR}/windows/signature_verifier.cpp |
| | | ${CMAKE_CURRENT_SOURCE_DIR}/os-win.c) |
| | | #windows no openssl |
| | | add_library(os OBJECT |
| | | cpu_info_common.cpp |
| | | windows/cpu_info.cpp |
| | | windows/signature_verifier.cpp |
| | | execution_environment_common.cpp windows/execution_environment.cpp |
| | | windows/isvm/Native.cpp |
| | | windows/isvm/BIOSReader.cpp |
| | | windows/os_win.cpp |
| | | windows/network.cpp) |
| | | ENDIF(UNIX OR OPENSSL_FOUND) |
| | | |
| | | #dependency of signature_verifier.cpp |
| | | add_dependencies( os project_initialize ) |
| | | |
| | | if(CODE_COVERAGE AND UNIX) |
| | | target_compile_options(os PUBLIC -O0 -g --coverage) |
| | | endif(CODE_COVERAGE AND UNIX) |
New file |
| | |
| | | /* |
| | | * cpu_info.h |
| | | * |
| | | * Created on: Dec 14, 2019 |
| | | * Author: devel |
| | | */ |
| | | |
| | | #ifndef SRC_LIBRARY_OS_CPU_INFO_H_ |
| | | #define SRC_LIBRARY_OS_CPU_INFO_H_ |
| | | #include <string> |
| | | namespace license { |
| | | namespace os { |
| | | typedef enum { BARE_TO_METAL, VMWARE, VIRTUALBOX, V_XEN, KVM, HV, V_OTHER } VIRTUALIZATION_DETAIL; |
| | | |
| | | /** |
| | | * Cpu informations |
| | | */ |
| | | class CpuInfo { |
| | | private: |
| | | bool is_hypervisor_set() const; |
| | | const std::string m_vendor; |
| | | const std::string m_brand; |
| | | public: |
| | | CpuInfo(); |
| | | virtual ~CpuInfo(); |
| | | /** |
| | | * Detect Virtual machine using hypervisor bit or the cpu vendor name. |
| | | * @return true if the cpu is detected to be a virtual cpu |
| | | */ |
| | | bool cpu_virtual() const; |
| | | uint32_t model() const; |
| | | const std::string& vendor() const { return m_vendor; } |
| | | const std::string& brand() const { return m_brand; } |
| | | VIRTUALIZATION_DETAIL virtualization_details() const; |
| | | }; |
| | | |
| | | } // namespace os |
| | | } // namespace license |
| | | #endif /* SRC_LIBRARY_OS_CPU_INFO_H_ */ |
New file |
| | |
| | | /* |
| | | * cpu_info_common.cpp |
| | | * |
| | | * Created on: Jan 19, 2020 |
| | | * Author: GC |
| | | */ |
| | | #include <unordered_map> |
| | | #include "cpu_info.hpp" |
| | | |
| | | namespace license { |
| | | namespace os { |
| | | using namespace std; |
| | | |
| | | const unordered_map<string, VIRTUALIZATION_DETAIL> virtual_cpu_names{ |
| | | {"bhyve bhyve ", V_OTHER}, {"KVMKVMKVM", KVM}, {"Microsoft Hv", HV}, |
| | | {" lrpepyh vr", HV}, {"prl hyperv ", V_OTHER}, {"VMwareVMware", VMWARE}, |
| | | {"XenVMMXenVMM", V_XEN}, {"ACRNACRNACRN", V_OTHER}, {"VBoxVBoxVBox", VIRTUALBOX}}; |
| | | |
| | | /** |
| | | * Detect Virtual machine using hypervisor bit. |
| | | * @return true if the cpu hypervisor bit is set to 1 |
| | | */ |
| | | bool CpuInfo::cpu_virtual() const { |
| | | bool is_virtual = is_hypervisor_set(); |
| | | if (!is_virtual) { |
| | | string cpu_vendor = vendor(); |
| | | auto it = virtual_cpu_names.find(cpu_vendor); |
| | | is_virtual = (it != virtual_cpu_names.end()); |
| | | } |
| | | return is_virtual; |
| | | } |
| | | |
| | | VIRTUALIZATION_DETAIL CpuInfo::virtualization_details() const { |
| | | string cpu_vendor = vendor(); |
| | | auto it = virtual_cpu_names.find(cpu_vendor); |
| | | VIRTUALIZATION_DETAIL result = BARE_TO_METAL; |
| | | if (it != virtual_cpu_names.end()) { |
| | | result = it->second; |
| | | } else if (is_hypervisor_set()) { |
| | | result = (VIRTUALIZATION_DETAIL)V_OTHER; |
| | | } |
| | | return result; |
| | | } |
| | | } // namespace os |
| | | } // namespace license |
New file |
| | |
| | | /* |
| | | * virtualization.hpp |
| | | * |
| | | * Created on: Dec 15, 2019 |
| | | * Author: GC |
| | | */ |
| | | |
| | | #ifndef SRC_LIBRARY_OS_VIRTUALIZATION_HPP_ |
| | | #define SRC_LIBRARY_OS_VIRTUALIZATION_HPP_ |
| | | |
| | | #include <string> |
| | | |
| | | namespace license { |
| | | namespace os { |
| | | |
| | | /* |
| | | * windows bios sometimes reports vm names add execution environment detection from bios |
| | | const char *vmVendors[] = { |
| | | "VMware", "Microsoft Corporation", "Virtual Machine", "innotek GmbH", "PowerVM", "Bochs", "KVM"}; |
| | | */ |
| | | |
| | | typedef enum { NONE, CONTAINER, VM } VIRTUALIZATION; |
| | | |
| | | typedef enum { |
| | | PROV_UNKNOWN, |
| | | ON_PREMISE, |
| | | GOOGLE_CLOUD, |
| | | AZURE_CLOUD, |
| | | AWS, |
| | | /** |
| | | * "/sys/class/dmi/id/bios_vendor" SeaBIOS |
| | | * "/sys/class/dmi/id/sys_vendor" Alibaba Cloud |
| | | * modalias |
| | | * "dmi:bvnSeaBIOS:bvrrel-1.7.5-0-ge51488c-20140602_164612-nilsson.home.kraxel.org:bd04/01/2014:svnAlibabaCloud:pnAlibabaCloudECS:pvrpc-i440fx-2.1:cvnAlibabaCloud:ct1:cvrpc-i440fx-2.1:" |
| | | */ |
| | | ALI_CLOUD |
| | | } CLOUD_PROVIDER; |
| | | |
| | | class ExecutionEnvironment { |
| | | private: |
| | | std::string m_sys_vendor; |
| | | std::string m_bios_vendor; |
| | | std::string m_bios_description; |
| | | |
| | | public: |
| | | ExecutionEnvironment(); |
| | | ~ExecutionEnvironment(){}; |
| | | VIRTUALIZATION getVirtualization() const; |
| | | bool is_cloud() const; |
| | | bool is_docker() const; |
| | | // detect if it's a kind of container technology (docker or lxc) |
| | | bool is_container() const; |
| | | CLOUD_PROVIDER getCloudProvider() const; |
| | | const std::string& bios_vendor() const { return m_bios_vendor; }; |
| | | const std::string& sys_vendor() const { return m_sys_vendor; }; |
| | | const std::string& bios_description() const { return m_bios_description; }; |
| | | // VIRTUALIZATION_DETAIL getVirtualizationDetail() const; //as reported by the bios |
| | | }; |
| | | |
| | | } // namespace os |
| | | } // namespace license |
| | | |
| | | #endif /* SRC_LIBRARY_OS_VIRTUALIZATION_HPP_ */ |
New file |
| | |
| | | /* |
| | | * |
| | | * Created on: Feb 23, 2020 |
| | | * Author: GC |
| | | */ |
| | | |
| | | #include <stdio.h> |
| | | #include <string.h> |
| | | #include <unordered_map> |
| | | #include <array> |
| | | |
| | | #include "../base/base.h" |
| | | #include "cpu_info.hpp" |
| | | #include "execution_environment.hpp" |
| | | |
| | | namespace license { |
| | | namespace os { |
| | | using namespace std; |
| | | |
| | | VIRTUALIZATION ExecutionEnvironment::getVirtualization() const { |
| | | VIRTUALIZATION result; |
| | | CpuInfo cpuInfo; |
| | | bool isContainer = is_container(); |
| | | if (isContainer) { |
| | | result = CONTAINER; |
| | | } else if (cpuInfo.cpu_virtual() || is_cloud()) { |
| | | result = VM; |
| | | } else { |
| | | result = NONE; |
| | | } |
| | | return result; |
| | | } |
| | | |
| | | bool ExecutionEnvironment::is_cloud() const { |
| | | CLOUD_PROVIDER prov = getCloudProvider(); |
| | | return prov != ON_PREMISE && prov != PROV_UNKNOWN; |
| | | } |
| | | |
| | | // TODO test and azure |
| | | CLOUD_PROVIDER ExecutionEnvironment::getCloudProvider() const { |
| | | CLOUD_PROVIDER result = PROV_UNKNOWN; |
| | | if (m_bios_description.size() > 0 || m_bios_vendor.size() > 0 || m_sys_vendor.size() > 0) { |
| | | if (m_bios_vendor.find("SEABIOS") != string::npos || m_bios_description.find("ALIBABA") != string::npos || |
| | | m_sys_vendor.find("ALIBABA") != string::npos) { |
| | | result = ALI_CLOUD; |
| | | } else if (m_sys_vendor.find("GOOGLE") != string::npos || m_bios_description.find("GOOGLE") != string::npos) { |
| | | result = GOOGLE_CLOUD; |
| | | } else if (m_bios_vendor.find("AWS") != string::npos || m_bios_description.find("AMAZON") != string::npos || |
| | | m_sys_vendor.find("AWS") != string::npos) { |
| | | result = AWS; |
| | | } else if (m_bios_description.find("HP-COMPAQ") != string::npos || m_bios_description.find("ASUS") || |
| | | m_bios_description.find("DELL")) { |
| | | result = ON_PREMISE; |
| | | } |
| | | } |
| | | return result; |
| | | } |
| | | } // namespace os |
| | | } // namespace license |
New file |
| | |
| | | /* |
| | | * cpu_info.cpp |
| | | * |
| | | * Created on: Dec 14, 2019 |
| | | * Author: devel |
| | | */ |
| | | |
| | | #include <cpuid.h> |
| | | #include <string> |
| | | #include <unordered_set> |
| | | #include <memory.h> |
| | | #include "../cpu_info.hpp" |
| | | |
| | | namespace license { |
| | | namespace os { |
| | | using namespace std; |
| | | |
| | | struct CPUVendorID { |
| | | unsigned int ebx; |
| | | unsigned int edx; |
| | | unsigned int ecx; |
| | | |
| | | string toString() const { return string(reinterpret_cast<const char *>(this), 12); } |
| | | }; |
| | | |
| | | static string get_cpu_vendor() { |
| | | unsigned int level = 0, eax = 0, ebx = 0, ecx = 0, edx = 0; |
| | | // hypervisor flag false, try to get the vendor name, see if it's a virtual cpu |
| | | __get_cpuid(level, &eax, &ebx, &ecx, &edx); |
| | | CPUVendorID vendorID{.ebx = ebx, .edx = edx, .ecx = ecx}; |
| | | return vendorID.toString(); |
| | | } |
| | | |
| | | // https://en.wikipedia.org/wiki/CPUID |
| | | static string get_cpu_brand() { |
| | | string result; |
| | | uint32_t brand[0x10]; |
| | | |
| | | if (!__get_cpuid_max(0x80000004, NULL)) { |
| | | result = "NA"; |
| | | } else { |
| | | memset(brand, 0, sizeof(brand)); |
| | | __get_cpuid(0x80000002, brand + 0x0, brand + 0x1, brand + 0x2, brand + 0x3); |
| | | __get_cpuid(0x80000003, brand + 0x4, brand + 0x5, brand + 0x6, brand + 0x7); |
| | | __get_cpuid(0x80000004, brand + 0x8, brand + 0x9, brand + 0xa, brand + 0xb); |
| | | result = string(reinterpret_cast<char *>(brand)); |
| | | } |
| | | return result; |
| | | } |
| | | |
| | | CpuInfo::CpuInfo() : m_vendor(get_cpu_vendor()), m_brand(get_cpu_brand()) {} |
| | | |
| | | CpuInfo::~CpuInfo() {} |
| | | /** |
| | | * Detect Virtual machine using hypervisor bit. |
| | | * @return true if the cpu hypervisor bit is set to 1 |
| | | */ |
| | | bool CpuInfo::is_hypervisor_set() const { |
| | | unsigned int level = 1, eax = 0, ebx = 0, ecx = 0, edx = 0; |
| | | __get_cpuid(level, &eax, &ebx, &ecx, &edx); |
| | | |
| | | bool is_virtual = (((ecx >> 31) & 1) == 1); // hypervisor flag |
| | | return is_virtual; |
| | | } |
| | | |
| | | uint32_t CpuInfo::model() const { |
| | | unsigned int level = 1, eax = 0, ebx = 0, ecx = 0, edx = 0; |
| | | __get_cpuid(level, &eax, &ebx, &ecx, &edx); |
| | | // ax bits 0-3 stepping,4-7 model,8-11 family id,12-13 processor type |
| | | // 14-15 reserved, 16-19 extended model, 20-27 extended family, 27-31 reserved |
| | | // bx bits 0-7 brand index |
| | | return (eax & 0x3FFF) | (eax & 0x3FF8000) >> 2 | (ebx & 0xff) << 24; |
| | | } |
| | | |
| | | } // namespace os |
| | | } /* namespace license */ |
New file |
| | |
| | | /* |
| | | * virtualization.cpp |
| | | * |
| | | * Created on: Dec 15, 2019 |
| | | * Author: GC |
| | | */ |
| | | #include <paths.h> |
| | | #include <sys/stat.h> |
| | | #include <unistd.h> |
| | | #include <fstream> |
| | | #include <iostream> |
| | | #include <stdio.h> |
| | | #include <string.h> |
| | | #include <dirent.h> |
| | | #include <sys/utsname.h> |
| | | |
| | | #include "../../base/base.h" |
| | | #include "../cpu_info.hpp" |
| | | #include "../execution_environment.hpp" |
| | | #include "../../base/file_utils.hpp" |
| | | #include "../../base/StringUtils.h" |
| | | |
| | | namespace license { |
| | | namespace os { |
| | | using namespace std; |
| | | |
| | | // 0=NO 1=Docker/2=Lxc |
| | | static int checkContainerProc() { |
| | | // in docer /proc/self/cgroups contains the "docker" or "lxc" string |
| | | // https://stackoverflow.com/questions/23513045/how-to-check-if-a-process-is-running-inside-docker-container |
| | | char path[MAX_PATH] = {0}; |
| | | char proc_path[MAX_PATH], pidStr[64]; |
| | | pid_t pid = getpid(); |
| | | sprintf(pidStr, "%d", pid); |
| | | strcpy(proc_path, "/proc/"); |
| | | strcat(proc_path, pidStr); |
| | | strcat(proc_path, "/cgroup"); |
| | | |
| | | FILE *fp; |
| | | char *line = NULL; |
| | | size_t len = 0; |
| | | ssize_t read; |
| | | int result = 0; |
| | | |
| | | fp = fopen(proc_path, "r"); |
| | | if (fp == NULL) { |
| | | return 0; |
| | | } |
| | | |
| | | while ((read = getline(&line, &len, fp)) != -1 && result == 0) { |
| | | // line[len]=0; |
| | | // printf("Retrieved line of length %zu:\n", read); |
| | | // printf("%s", line); |
| | | if (strstr(line, "docker") != NULL) { |
| | | result = 1; |
| | | } |
| | | if (strstr(line, "lxc") != NULL) { |
| | | result = 2; |
| | | } |
| | | } |
| | | |
| | | fclose(fp); |
| | | if (line) free(line); |
| | | return result; |
| | | } |
| | | |
| | | // 0=NO 1=Docker/2=Lxc |
| | | static int checkSystemdContainer() { |
| | | ifstream systemd_container("/var/run/systemd/container"); |
| | | int result = 0; |
| | | if (systemd_container.good()) { |
| | | result = 1; |
| | | for (string line; getline(systemd_container, line);) { |
| | | if (line.find("docker") != string::npos) { |
| | | result = 1; |
| | | break; |
| | | } else if (line.find("lxc") != string::npos) { |
| | | result = 2; |
| | | break; |
| | | } |
| | | } |
| | | } |
| | | return result; |
| | | } |
| | | |
| | | ExecutionEnvironment::ExecutionEnvironment() { |
| | | try { |
| | | m_bios_vendor = toupper_copy(trim_copy(get_file_contents("/sys/class/dmi/id/sys_vendor", 256))); |
| | | |
| | | } catch (...) { |
| | | } |
| | | try { |
| | | m_bios_description = toupper_copy(trim_copy(get_file_contents("/sys/class/dmi/id/modalias", 256))); |
| | | char last_char = m_bios_description[m_bios_description.length() - 1]; |
| | | if (last_char == '\r' || last_char == '\n') { |
| | | m_bios_description = m_bios_description.erase(m_bios_description.length() - 1); |
| | | } |
| | | } catch (...) { |
| | | } |
| | | try { |
| | | m_sys_vendor = get_file_contents("/sys/class/dmi/id/sys_vendor", 256); |
| | | char last_char = m_sys_vendor[m_sys_vendor.length() - 2]; |
| | | if (last_char == '\r' || last_char == '\n') { |
| | | m_sys_vendor = m_sys_vendor.erase(m_sys_vendor.length() - 1); |
| | | } |
| | | } catch (...) { |
| | | } |
| | | } |
| | | |
| | | bool ExecutionEnvironment::is_container() const { return (checkContainerProc() != 0 || checkSystemdContainer() != 0); } |
| | | |
| | | bool ExecutionEnvironment::is_docker() const { return (checkContainerProc() == 1 || checkSystemdContainer() == 1); } |
| | | |
| | | } // namespace os |
| | | } // namespace license |
New file |
| | |
| | | /** |
| | | * @file network_id.c |
| | | * @date 16 Sep 2014 |
| | | * @brief File containing network interface detection functions for Linux. |
| | | * |
| | | * The only public function of this module is #getAdapterInfos(OsAdapterInfo *, |
| | | * size_t *), other functions are either static or inline. |
| | | * |
| | | * Responsibility of this module is to fill OsAdapterInfo structures, in a |
| | | * predictable way (skip "lo" interfaces, |
| | | * @TODO: place physical interfaces in front in a repeatable order: "eth", "wlan","ib" |
| | | * and other interfaces later, first the one with a a specified mac address, then |
| | | * the ones with only an ip.) |
| | | */ |
| | | |
| | | #ifndef _GNU_SOURCE |
| | | #define _GNU_SOURCE /* To get defns of NI_MAXSERV and NI_MAXHOST */ |
| | | #endif |
| | | #include <arpa/inet.h> |
| | | #include <sys/socket.h> |
| | | #include <net/if.h> |
| | | #include <netdb.h> |
| | | #include <ifaddrs.h> |
| | | #include <linux/if_link.h> |
| | | #include <netpacket/packet.h> |
| | | #include <stdio.h> |
| | | #include <unordered_map> |
| | | #include <string.h> |
| | | #include <memory.h> |
| | | |
| | | #include "../../base/StringUtils.h" |
| | | #include "../../base/logger.h" |
| | | #include "../network.hpp" |
| | | |
| | | namespace license { |
| | | namespace os { |
| | | using namespace std; |
| | | |
| | | |
| | | /** |
| | | * |
| | | * @param adapterInfos |
| | | * @param adapter_info_size |
| | | * @return |
| | | */ |
| | | FUNCTION_RETURN getAdapterInfos(vector<OsAdapterInfo> &adapterInfos) { |
| | | unordered_map<string, OsAdapterInfo> adapterByName; |
| | | |
| | | FUNCTION_RETURN f_return = FUNC_RET_OK; |
| | | struct ifaddrs *ifaddr, *ifa; |
| | | int family, n = 0; |
| | | unsigned int if_num, if_max; |
| | | |
| | | if (getifaddrs(&ifaddr) == -1) { |
| | | LOG_WARN("getifaddrs failed == -1"); |
| | | return FUNC_RET_ERROR; |
| | | } |
| | | |
| | | for (ifa = ifaddr, n = 0, if_num = 0; ifa != NULL; ifa = ifa->ifa_next, n++) { |
| | | if (ifa->ifa_addr == NULL || (ifa->ifa_flags & IFF_LOOPBACK) != 0) { |
| | | continue; |
| | | } |
| | | string if_name(ifa->ifa_name, mstrnlen_s(ifa->ifa_name, NI_MAXHOST)); |
| | | // if_name_position = ifname_position(ifnames, ifa->ifa_name, if_num); |
| | | // interface name not seen en advance |
| | | OsAdapterInfo *currentAdapter; |
| | | // FIXME not working |
| | | if (adapterByName.find(if_name) == adapterByName.end()) { |
| | | OsAdapterInfo newAdapter; |
| | | memset(&newAdapter, 0, sizeof(OsAdapterInfo)); |
| | | strncpy(&newAdapter.description[0], ifa->ifa_name, NI_MAXHOST); |
| | | adapterByName[if_name] = newAdapter; |
| | | } |
| | | auto it = adapterByName.find(if_name); |
| | | currentAdapter = &it->second; |
| | | family = ifa->ifa_addr->sa_family; |
| | | /* Display interface name and family (including symbolic |
| | | form of the latter for the common families) */ |
| | | #ifdef _DEBUG |
| | | printf("%-8s %s (%d)\n", ifa->ifa_name, |
| | | (family == AF_PACKET) ? "AF_PACKET" |
| | | : (family == AF_INET) ? "AF_INET" : (family == AF_INET6) ? "AF_INET6" : "???", |
| | | family); |
| | | #endif |
| | | /* For an AF_INET* interface address, display the address |
| | | * || family == AF_INET6*/ |
| | | if (family == AF_INET) { |
| | | struct sockaddr_in *s1 = (struct sockaddr_in *)ifa->ifa_addr; |
| | | in_addr_t iaddr = s1->sin_addr.s_addr; |
| | | currentAdapter->ipv4_address[0] = (iaddr & 0x000000ff); |
| | | currentAdapter->ipv4_address[1] = (iaddr & 0x0000ff00) >> 8; |
| | | currentAdapter->ipv4_address[2] = (iaddr & 0x00ff0000) >> 16; |
| | | currentAdapter->ipv4_address[3] = (iaddr & 0xff000000) >> 24; |
| | | |
| | | } else if (family == AF_PACKET && ifa->ifa_data != NULL) { |
| | | struct sockaddr_ll *s1 = (struct sockaddr_ll *)ifa->ifa_addr; |
| | | int i; |
| | | for (i = 0; i < 6; i++) { |
| | | currentAdapter->mac_address[i] = s1->sll_addr[i]; |
| | | #ifdef _DEBUG |
| | | printf("%02x:", s1->sll_addr[i]); |
| | | #endif |
| | | } |
| | | #ifdef _DEBUG |
| | | printf("\t %s\n", ifa->ifa_name); |
| | | #endif |
| | | } |
| | | } |
| | | freeifaddrs(ifaddr); |
| | | |
| | | // FIXME sort by eth , enps, wlan |
| | | if (adapterByName.size() == 0) { |
| | | f_return = FUNC_RET_NOT_AVAIL; |
| | | } else { |
| | | f_return = FUNC_RET_OK; |
| | | adapterInfos.reserve(adapterByName.size()); |
| | | for (auto &it : adapterByName) { |
| | | adapterInfos.push_back(it.second); |
| | | } |
| | | } |
| | | return f_return; |
| | | } |
| | | |
| | | } // namespace os |
| | | } // namespace license |
File was renamed from src/library/os/os-linux.c |
| | |
| | | #include <paths.h> |
| | | #include <sys/stat.h> |
| | | #include "os.h" |
| | | #include "../base/logger.h" |
| | | #include <openssl/pem.h> |
| | | #include <openssl/err.h> |
| | | #include <stdio.h> |
| | | #include "../os.h" |
| | | #include "../../base/logger.h" |
| | | |
| | | #include <mntent.h> |
| | | #include <dirent.h> |
| | |
| | | if (strcmp(ent->mnt_dir, "/") == 0) { |
| | | strcpy(tmpDrives[drive_found].label, "root"); |
| | | LOG_DEBUG("drive %s set to preferred\n", ent->mnt_fsname); |
| | | tmpDrives[drive_found].preferred = true; |
| | | tmpDrives[drive_found].preferred = 1; |
| | | } else { |
| | | tmpDrives[drive_found].preferred = 0; |
| | | } |
| | | } |
| | | } |
| | |
| | | } else { |
| | | result = FUNC_RET_BUFFER_TOO_SMALL; |
| | | } |
| | | /* |
| | | FILE *mounts = fopen(_PATH_MOUNTED, "r"); |
| | | if (mounts == NULL) { |
| | | return ERROR; |
| | | } |
| | | |
| | | while (fscanf(mounts, "%64s %64s %64s %1024[^\n]", device, name, type, |
| | | discard) != EOF) { |
| | | if (stat(device, &mount_stat) != 0) |
| | | continue; |
| | | if (filename_stat.st_dev == mount_stat.st_rdev) { |
| | | fprintf(stderr, "device: %s; name: %s; type: %s\n", device, name, |
| | | type); |
| | | } |
| | | } |
| | | */ |
| | | free(statDrives); |
| | | return result; |
| | | } |
| | | |
| | | void os_initialize() {} |
| | | |
| | | static void _getCpuid(unsigned int *p, unsigned int ax) { |
| | | __asm __volatile( |
| | |
| | | return FUNC_RET_OK; |
| | | } |
| | | |
| | | // 0=NO 1=Docker/Lxc |
| | | static int checkContainerProc() { |
| | | // in docer /proc/self/cgroups contains the "docker" or "lxc" string |
| | | // https://stackoverflow.com/questions/23513045/how-to-check-if-a-process-is-running-inside-docker-container |
| | | char path[MAX_PATH] = {0}; |
| | | char proc_path[MAX_PATH], pidStr[64]; |
| | | pid_t pid = getpid(); |
| | | sprintf(pidStr, "%d", pid); |
| | | strcpy(proc_path, "/proc/"); |
| | | strcat(proc_path, pidStr); |
| | | strcat(proc_path, "/cgroup"); |
| | | |
| | | FILE *fp; |
| | | char *line = NULL; |
| | | size_t len = 0; |
| | | ssize_t read; |
| | | int result = 0; |
| | | |
| | | fp = fopen(proc_path, "r"); |
| | | if (fp == NULL) { |
| | | return 0; |
| | | } |
| | | |
| | | while ((read = getline(&line, &len, fp)) != -1 && result == 0) { |
| | | // line[len]=0; |
| | | // printf("Retrieved line of length %zu:\n", read); |
| | | // printf("%s", line); |
| | | if (strstr(line, "docker") != NULL || strstr(line, "lxc") != NULL) { |
| | | result = 1; |
| | | } |
| | | } |
| | | |
| | | fclose(fp); |
| | | if (line) free(line); |
| | | return result; |
| | | } |
| | | |
| | | // 0=NO 1=Docker/Lxc |
| | | static int checkLXC() { return (access("/var/run/systemd/container", F_OK) == 0) ? 1 : 0; } |
| | | |
| | | VIRTUALIZATION getVirtualization() { |
| | | VIRTUALIZATION result = NONE; |
| | | int isContainer = checkContainerProc(); |
| | | if (isContainer == 1) { |
| | | result = CONTAINER; |
| | | } else if (checkLXC()) { |
| | | result = CONTAINER; |
| | | } |
| | | return result; |
| | | |
| | | // http://www.ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html |
| | | // |
| | | // bool rc = true; |
| | | /*__asm__ ( |
| | | "push %edx\n" |
| | | "push %ecx\n" |
| | | "push %ebx\n" |
| | | "mov %eax, 'VMXh'\n" |
| | | "mov %ebx, 0\n" // any value but not the MAGIC VALUE |
| | | "mov %ecx, 10\n"// get VMWare version |
| | | "mov %edx, 'VX'\n"// port number |
| | | "in %eax, dx\n"// read port on return EAX returns the VERSION |
| | | "cmp %ebx, 'VMXh'\n"// is it a reply from VMWare? |
| | | "setz [rc] \n"// set return value |
| | | "pop %ebx \n" |
| | | "pop %ecx \n" |
| | | "pop %edx \n" |
| | | );*/ |
| | | |
| | | // systemd-detect-virt |
| | | return NONE; |
| | | } |
| | | |
| | | FUNCTION_RETURN getMachineName(unsigned char identifier[6]) { |
| | | static struct utsname u; |
New file |
| | |
| | | /* |
| | | * network.hpp |
| | | * |
| | | * Created on: Feb 8, 2020 |
| | | * Author: devel |
| | | */ |
| | | |
| | | #ifndef SRC_LIBRARY_OS_NETWORK_HPP_ |
| | | #define SRC_LIBRARY_OS_NETWORK_HPP_ |
| | | #include <stdlib.h> |
| | | #include <vector> |
| | | |
| | | #include "../base/base.h" |
| | | |
| | | namespace license { |
| | | namespace os { |
| | | |
| | | typedef enum { IFACE_TYPE_ETHERNET, IFACE_TYPE_WIRELESS } IFACE_TYPE; |
| | | |
| | | typedef struct { |
| | | int id; |
| | | char description[1024]; |
| | | unsigned char mac_address[8]; |
| | | unsigned char ipv4_address[4]; |
| | | IFACE_TYPE type; |
| | | } OsAdapterInfo; |
| | | |
| | | FUNCTION_RETURN getAdapterInfos(std::vector<OsAdapterInfo>& adapterInfos); |
| | | |
| | | } // namespace os |
| | | } // namespace license |
| | | #endif /* SRC_LIBRARY_OS_NETWORK_HPP_ */ |
| | |
| | | #include <stdlib.h> |
| | | #include <errno.h> |
| | | |
| | | #ifdef _WIN32 |
| | | #include <windows.h> |
| | | #endif |
| | | //#ifdef _WIN32 |
| | | //#include <windows.h> |
| | | //#endif |
| | | |
| | | #include <public_key.h> |
| | | |
| | | #include "../signature_verifier.h" |
| | | #include "../signature_verifier.hpp" |
| | | #include "../../base/logger.h" |
| | | |
| | | namespace license { |
| | | #include "../../base/logger.h" |
| | | namespace os { |
| | | |
| | | static void free_resources(EVP_PKEY* pkey, EVP_MD_CTX* mdctx) { |
| | | if (pkey) { |
| | |
| | | free_resources(pkey, mdctx); |
| | | return result; |
| | | } |
| | | |
| | | } // namespace os |
| | | } /* namespace license */ |
| | |
| | | extern "C" { |
| | | #endif |
| | | |
| | | #include "../base/base.h" |
| | | #include <stddef.h> |
| | | #include <string.h> |
| | | #include <ctype.h> |
| | | #include <sys/types.h> |
| | | //definition of size_t |
| | | // definition of size_t |
| | | #include <stdlib.h> |
| | | #ifdef __unix__ |
| | | #include <unistd.h> |
| | | #include <stdbool.h> |
| | | #endif |
| | | |
| | | typedef enum { |
| | | NONE, CONTAINER, VM |
| | | } VIRTUALIZATION; |
| | | |
| | | typedef enum { |
| | | IFACE_TYPE_ETHERNET, IFACE_TYPE_WIRELESS |
| | | } IFACE_TYPE; |
| | | #include "../base/base.h" |
| | | |
| | | typedef struct { |
| | | int id; |
| | | char description[1024]; |
| | | unsigned char mac_address[8]; |
| | | unsigned char ipv4_address[4]; |
| | | IFACE_TYPE type; |
| | | } OsAdapterInfo; |
| | | |
| | | typedef struct { |
| | | int id; |
| | | char device[255]; |
| | | char device[MAX_PATH]; |
| | | unsigned char disk_sn[8]; |
| | | char label[255]; |
| | | bool preferred; |
| | | int preferred; |
| | | } DiskInfo; |
| | | |
| | | FUNCTION_RETURN getAdapterInfos(OsAdapterInfo * adapterInfos, |
| | | size_t * adapter_info_size); |
| | | FUNCTION_RETURN getDiskInfos(DiskInfo * diskInfos, size_t * disk_info_size); |
| | | FUNCTION_RETURN getDiskInfos(DiskInfo* diskInfos, size_t* disk_info_size); |
| | | FUNCTION_RETURN getUserHomePath(char[MAX_PATH]); |
| | | FUNCTION_RETURN getModuleName(char buffer[MAX_PATH]); |
| | | FUNCTION_RETURN getCpuId(unsigned char identifier[6]); |
| | | FUNCTION_RETURN getMachineName(unsigned char identifier[6]); |
| | | /** |
| | | * Get an identifier of the machine in an os specific way. |
| | |
| | | * @return |
| | | */ |
| | | FUNCTION_RETURN getOsSpecificIdentifier(unsigned char identifier[6]); |
| | | VIRTUALIZATION getVirtualization(); |
| | | void os_initialize(); |
| | | |
| | | // FUNCTION_RETURN verifySignature(const char* stringToVerify, const char* signatureB64); |
| | | |
| | | #ifdef _WIN32 |
| | | #define SETENV(VAR,VAL) _putenv_s(VAR, VAL); |
| | | #define UNSETENV(P) _putenv_s(P, ""); |
| | | #define SETENV(VAR, VAL) _putenv_s(VAR, VAL); |
| | | #define UNSETENV(P) _putenv_s(P, ""); |
| | | #else |
| | | #define SETENV(VAR,VAL) setenv(VAR, VAL, 1); |
| | | #define UNSETENV(P) unsetenv(P); |
| | | #define SETENV(VAR, VAL) setenv(VAR, VAL, 1); |
| | | #define UNSETENV(P) unsetenv(P); |
| | | #endif |
| | | |
| | | #ifdef __cplusplus |
File was renamed from src/library/os/signature_verifier.h |
| | |
| | | #include "../base/base.h" |
| | | |
| | | namespace license { |
| | | |
| | | namespace os { |
| | | FUNCTION_RETURN verify_signature(const std::string& stringToVerify, const std::string& signatureB64); |
| | | |
| | | } |
| | | } /* namespace license */ |
| | | |
| | | #endif /* SRC_LIBRARY_OS_VERIFIER_HPP_ */ |
New file |
| | |
| | | /* |
| | | * cpu_info.cpp |
| | | * |
| | | * Created on: Dec 14, 2019 |
| | | * Author: devel |
| | | */ |
| | | |
| | | |
| | | #include <intrin.h> |
| | | #include <string> |
| | | #include <unordered_set> |
| | | #include "../cpu_info.hpp" |
| | | |
| | | namespace license { |
| | | namespace os { |
| | | using namespace std; |
| | | |
| | | static string get_cpu_vendor() { |
| | | // hypervisor flag false, try to get the vendor name, see if it's a virtual cpu |
| | | int cpui[4] = {0}; |
| | | __cpuidex(cpui, 0x0, 0x0); |
| | | |
| | | char vendor[13]; |
| | | memset(vendor, 0, sizeof(vendor)); |
| | | *reinterpret_cast<int *>(vendor) = cpui[1]; |
| | | *reinterpret_cast<int *>(vendor + 4) = cpui[3]; |
| | | *reinterpret_cast<int *>(vendor + 8) = cpui[2]; |
| | | return string(vendor, 12); |
| | | } |
| | | |
| | | static string get_cpu_brand() { |
| | | int cpui[4] = {0}; |
| | | __cpuid(cpui, 0x80000000); |
| | | int maxSupported = cpui[0]; |
| | | |
| | | char brand[0x41]; |
| | | memset(brand, 0, sizeof(brand)); |
| | | string result; |
| | | if (maxSupported >= 0x80000004) { |
| | | int instruction = 0x80000002; |
| | | for (int i = 0; i <= 2; ++i) { |
| | | __cpuidex(cpui, instruction + i, 0); |
| | | memcpy(&brand[i * sizeof(cpui)], cpui, sizeof(cpui)); |
| | | } |
| | | result = string(brand); |
| | | } else { |
| | | result = "NA"; |
| | | } |
| | | |
| | | return result; |
| | | } |
| | | |
| | | CpuInfo::CpuInfo() : m_vendor(get_cpu_vendor()), m_brand(get_cpu_brand()) {} |
| | | |
| | | CpuInfo::~CpuInfo() {} |
| | | /** |
| | | * Detect Virtual machine using hypervisor bit. |
| | | * @return true if the cpu hypervisor bit is set to 1 |
| | | */ |
| | | bool CpuInfo::is_hypervisor_set() const { |
| | | int cpui[4] = {0}; |
| | | __cpuid(cpui, 0x1); |
| | | |
| | | return ((cpui[2] >> 31) & 1); |
| | | } |
| | | |
| | | uint32_t CpuInfo::model() const { |
| | | int cpui[4] = {0}; |
| | | __cpuid(cpui, 0x1); |
| | | // ax bits 0-3 stepping,4-7 model,8-11 family id,12-13 processor type |
| | | // 14-15 reserved, 16-19 extended model, 20-27 extended family, 27-31 reserved |
| | | // bx bits 0-7 brand index |
| | | return (cpui[0] & 0x3FFF) | (cpui[0] & 0x3FF8000) >> 2 | (cpui[1] & 0xff) << 24; |
| | | } |
| | | |
| | | |
| | | } // namespace os |
| | | } /* namespace license */ |
New file |
| | |
| | | /* |
| | | * virtualization.cpp |
| | | * |
| | | * Created on: Dec 15, 2019 |
| | | * Author: GC |
| | | */ |
| | | #include <windows.h> |
| | | #include <sys/stat.h> |
| | | #include <fstream> |
| | | #include <iostream> |
| | | #include <stdio.h> |
| | | #include <string> |
| | | |
| | | #include "isvm/BIOSReader.h" |
| | | #include "isvm/Native.h" |
| | | #include "../../base/base.h" |
| | | #include "../../base/StringUtils.h" |
| | | #include "../cpu_info.hpp" |
| | | #include "../execution_environment.hpp" |
| | | |
| | | namespace license { |
| | | namespace os { |
| | | using namespace std; |
| | | |
| | | ExecutionEnvironment::ExecutionEnvironment() { |
| | | if (InitEntryPoints()) { |
| | | BIOSReader reader; |
| | | SystemInformation info = reader.readSystemInfo(); |
| | | m_sys_vendor = toupper_copy(info.Manufacturer); |
| | | m_bios_vendor = toupper_copy(info.ProductName); |
| | | m_bios_description = toupper_copy(info.SysVersion) + toupper_copy(info.family); |
| | | } |
| | | } |
| | | |
| | | #define MAX_UNITS 20 |
| | | int wine_container() { |
| | | DWORD fileMaxLen; |
| | | size_t ndrives = 0; |
| | | DWORD fileFlags; |
| | | char volName[MAX_PATH], fileSysName[MAX_PATH]; |
| | | DWORD volSerial = 0; |
| | | const DWORD dwSize = MAX_PATH; |
| | | char szLogicalDrives[MAX_PATH] = {0}; |
| | | |
| | | int result = 0; |
| | | const DWORD dwResult = GetLogicalDriveStrings(dwSize, szLogicalDrives); |
| | | |
| | | if (dwResult > 0 && dwResult <= MAX_PATH) { |
| | | char* szSingleDrive = szLogicalDrives; |
| | | while (*szSingleDrive && ndrives < MAX_UNITS) { |
| | | // get the next drive |
| | | UINT driveType = GetDriveType(szSingleDrive); |
| | | if (driveType == DRIVE_FIXED) { |
| | | string name = szSingleDrive + string("/var/run/systemd/container"); |
| | | try { |
| | | ifstream systemd_container(name); |
| | | if (systemd_container.good()) { |
| | | result = 1; |
| | | for (string line; getline(systemd_container, line);) { |
| | | if (line.find("docker") != string::npos) { |
| | | result = 1; |
| | | break; |
| | | } else if (line.find("lxc") != string::npos) { |
| | | result = 2; |
| | | break; |
| | | } |
| | | } |
| | | } |
| | | } catch (...) { |
| | | //no problem,we're just guessing |
| | | } |
| | | } |
| | | } |
| | | } |
| | | return result; |
| | | } |
| | | |
| | | bool ExecutionEnvironment::is_docker() const { |
| | | // let's check we're not in linux under wine ;) ... |
| | | //int cont = wine_container(); |
| | | return false; |
| | | } |
| | | //TODO |
| | | bool ExecutionEnvironment::is_container() const { return is_docker(); } |
| | | } // namespace os |
| | | } // namespace license |
New file |
| | |
| | | #include "BIOSReader.h" |
| | | |
| | | #include <cstdint> |
| | | |
| | | #include "Native.h" |
| | | |
| | | struct smbios_structure_header { |
| | | uint8_t type; |
| | | uint8_t length; |
| | | uint16_t handle; |
| | | }; |
| | | |
| | | // |
| | | // System information |
| | | // |
| | | struct smbios_type_1 { |
| | | struct smbios_structure_header header; |
| | | uint8_t manufacturer_str; |
| | | uint8_t product_name_str; |
| | | uint8_t version_str; |
| | | uint8_t serial_number_str; |
| | | uint8_t uuid[16]; |
| | | uint8_t wake_up_type; |
| | | uint8_t sku_number_str; |
| | | uint8_t family_str; |
| | | }; |
| | | |
| | | #define _TYPE_COUNT1 6 |
| | | |
| | | #define _CONCATE(x, y) x##y |
| | | #define CONCATE(x, y) _CONCATE(x, y) |
| | | #define TYPE_COUNT(t) CONCATE(_TYPE_COUNT, t) |
| | | |
| | | // |
| | | // Windows |
| | | // |
| | | #include <windows.h> |
| | | #include <tchar.h> |
| | | |
| | | int8_t *parse_smbiod_content(int8_t *addr, int8_t **indexes, int32_t *count) { |
| | | //! ignore 0 |
| | | int8_t parsed_count = 0; |
| | | int8_t *raw_addr = addr; |
| | | |
| | | //! first one |
| | | if (indexes) *indexes = raw_addr; |
| | | |
| | | bool reach_terminal = false; |
| | | |
| | | while (true) { |
| | | if (0 == *raw_addr++) { |
| | | if (reach_terminal) |
| | | break; |
| | | else { |
| | | ++parsed_count; |
| | | |
| | | if (count && parsed_count < *count) { |
| | | if (indexes) *(indexes + parsed_count) = raw_addr; |
| | | } |
| | | |
| | | reach_terminal = true; |
| | | } |
| | | } else { |
| | | reach_terminal = false; |
| | | continue; |
| | | } |
| | | } |
| | | |
| | | if (count) *count = parsed_count; |
| | | |
| | | return raw_addr; |
| | | } |
| | | |
| | | void read_smbios_type_1(int8_t *addr, SystemInformation *info) { |
| | | smbios_type_1 *t1 = (smbios_type_1 *)addr; |
| | | |
| | | int32_t offset = ((0x0F) & (t1->header.length >> 4)) * 16 + (t1->header.length & 0x0F); |
| | | |
| | | int8_t *string_addr[TYPE_COUNT(1)] = {0}; |
| | | |
| | | int32_t count = TYPE_COUNT(1); |
| | | parse_smbiod_content((int8_t *)t1 + offset, string_addr, &count); |
| | | |
| | | if (0 != t1->manufacturer_str) |
| | | info->Manufacturer = (std::string::traits_type::char_type *)string_addr[t1->manufacturer_str - 1]; |
| | | |
| | | if (0 != t1->product_name_str) |
| | | info->ProductName = (std::string::traits_type::char_type *)string_addr[t1->product_name_str - 1]; |
| | | |
| | | if (0 != t1->serial_number_str) |
| | | info->SerialNum = (std::string::traits_type::char_type *)string_addr[t1->serial_number_str - 1]; |
| | | |
| | | if (0 != t1->version_str) |
| | | info->SysVersion = (std::string::traits_type::char_type *)string_addr[t1->version_str - 1]; |
| | | |
| | | if (0 != t1->family_str) info->family = (std::string::traits_type::char_type *)string_addr[t1->family_str - 1]; |
| | | } |
| | | |
| | | SystemInformation BIOSReader::readSystemInfo() { |
| | | SystemInformation info; |
| | | |
| | | uint32_t size = 0; |
| | | RawSMBIOSData *data = (RawSMBIOSData *)(LocateSMBIOS(&size)); |
| | | |
| | | if (NULL == data || 0 == size) return info; |
| | | |
| | | smbios_structure_header *header = (smbios_structure_header *)(data->SMBIOSTableData); |
| | | |
| | | while (NULL != header) { |
| | | if (1 == header->type) { |
| | | read_smbios_type_1((int8_t *)header, &info); |
| | | header = NULL; //! stop |
| | | } else { |
| | | int32_t offset = ((0x0F) & (header->length >> 4)) * 16 + (header->length & 0x0F); |
| | | header = (smbios_structure_header *)parse_smbiod_content((int8_t *)header + offset, NULL, NULL); |
| | | } |
| | | } |
| | | |
| | | free(data); |
| | | return info; |
| | | } |
New file |
| | |
| | | #ifndef BIOSREADER_H |
| | | #define BIOSREADER_H |
| | | |
| | | #include <string> |
| | | |
| | | class SystemInformation |
| | | { |
| | | public: |
| | | std::string Manufacturer; |
| | | std::string ProductName; |
| | | std::string SysVersion; |
| | | std::string SerialNum; |
| | | std::string family; |
| | | }; |
| | | |
| | | class BIOSReader |
| | | { |
| | | public: |
| | | SystemInformation readSystemInfo(); |
| | | }; |
| | | |
| | | #endif |
New file |
| | |
| | | #include "Native.h" |
| | | |
| | | #include <tchar.h> |
| | | |
| | | typedef LARGE_INTEGER PHYSICAL_ADDRESS, *PPHYSICAL_ADDRESS; // windbgkd |
| | | |
| | | typedef LONG NTSTATUS; |
| | | #define NT_SUCCESS(Status) ((NTSTATUS)(Status) >= 0) |
| | | |
| | | typedef struct _UNICODE_STRING |
| | | { |
| | | USHORT Length; |
| | | USHORT MaximumLength; |
| | | #ifdef MIDL_PASS |
| | | [size_is(MaximumLength / 2), length_is((Length) / 2)] USHORT * Buffer; |
| | | #else // MIDL_PASS |
| | | PWSTR Buffer; |
| | | #endif // MIDL_PASS |
| | | } UNICODE_STRING; |
| | | typedef UNICODE_STRING *PUNICODE_STRING; |
| | | |
| | | typedef enum _SECTION_INHERIT |
| | | { |
| | | ViewShare = 1, |
| | | ViewUnmap = 2 |
| | | } SECTION_INHERIT; |
| | | |
| | | #define OBJ_INHERIT 0x00000002L |
| | | #define OBJ_PERMANENT 0x00000010L |
| | | #define OBJ_EXCLUSIVE 0x00000020L |
| | | #define OBJ_CASE_INSENSITIVE 0x00000040L |
| | | #define OBJ_OPENIF 0x00000080L |
| | | #define OBJ_OPENLINK 0x00000100L |
| | | #define OBJ_VALID_ATTRIBUTES 0x000001F2L |
| | | |
| | | static bool bIsWindowsXPLater = false; |
| | | static DWORD dwPageSize = 0; |
| | | |
| | | #ifdef _UNICODE |
| | | #define GetVersionExProc "GetVersionExW" |
| | | #else |
| | | #define GetVersionExProc "GetVersionExA" |
| | | #endif |
| | | |
| | | typedef struct _OBJECT_ATTRIBUTES |
| | | { |
| | | ULONG Length; |
| | | HANDLE RootDirectory; |
| | | PUNICODE_STRING ObjectName; |
| | | ULONG Attributes; |
| | | PVOID SecurityDescriptor; // Points to type SECURITY_DESCRIPTOR |
| | | PVOID SecurityQualityOfService; // Points to type SECURITY_QUALITY_OF_SERVICE |
| | | } OBJECT_ATTRIBUTES; |
| | | typedef OBJECT_ATTRIBUTES *POBJECT_ATTRIBUTES; |
| | | |
| | | typedef struct SMBIOSEntryPoint |
| | | { |
| | | char EntryPointString[4]; |
| | | uint8_t Checksum; |
| | | uint8_t Length; |
| | | uint8_t MajorVersion; |
| | | uint8_t MinorVersion; |
| | | uint16_t MaxStructureSize; |
| | | uint8_t EntryPointRevision; |
| | | char FormattedArea[5]; |
| | | char EntryPointString2[5]; |
| | | uint8_t Checksum2; |
| | | uint16_t TableLength; |
| | | uint32_t TableAddress; |
| | | uint16_t NumberOfStructures; |
| | | uint8_t BCDRevision; |
| | | } SMBIOSEntryPoint, *PSMBIOSEntryPoint; |
| | | |
| | | #define InitializeObjectAttributes( p, n, a, r, s ) { \ |
| | | (p)->Length = sizeof(OBJECT_ATTRIBUTES); \ |
| | | (p)->RootDirectory = r; \ |
| | | (p)->Attributes = a; \ |
| | | (p)->ObjectName = n; \ |
| | | (p)->SecurityDescriptor = s; \ |
| | | (p)->SecurityQualityOfService = NULL; \ |
| | | } |
| | | |
| | | NTSTATUS(WINAPI *NtUnmapViewOfSection)( |
| | | IN HANDLE ProcessHandle, |
| | | IN PVOID BaseAddress |
| | | ); |
| | | |
| | | NTSTATUS(WINAPI *NtOpenSection)( |
| | | OUT PHANDLE SectionHandle, |
| | | IN ACCESS_MASK DesiredAccess, |
| | | IN POBJECT_ATTRIBUTES ObjectAttributes |
| | | ); |
| | | |
| | | NTSTATUS(WINAPI *NtMapViewOfSection)( |
| | | IN HANDLE SectionHandle, |
| | | IN HANDLE ProcessHandle, |
| | | IN OUT PVOID *BaseAddress, |
| | | IN ULONG ZeroBits, |
| | | IN ULONG CommitSize, |
| | | IN OUT PLARGE_INTEGER SectionOffset, /* optional */ |
| | | IN OUT PULONG ViewSize, |
| | | IN SECTION_INHERIT InheritDisposition, |
| | | IN ULONG AllocationType, |
| | | IN ULONG Protect |
| | | ); |
| | | |
| | | VOID(WINAPI *RtlInitUnicodeString)( |
| | | IN OUT PUNICODE_STRING DestinationString, |
| | | IN PCWSTR SourceString |
| | | ); |
| | | |
| | | ULONG(WINAPI *RtlNtStatusToDosError) ( |
| | | IN NTSTATUS Status |
| | | ); |
| | | |
| | | UINT(WINAPI *Win32GetSystemFirmwareTable)( |
| | | _In_ DWORD FirmwareTableProviderSignature, |
| | | _In_ DWORD FirmwareTableID, |
| | | _Out_writes_bytes_to_opt_(BufferSize, return) PVOID pFirmwareTableBuffer, |
| | | _In_ DWORD BufferSize); |
| | | |
| | | BOOL(WINAPI *Win32GetVersionEx)( |
| | | _Inout_ LPOSVERSIONINFO lpVersionInfo |
| | | ); |
| | | |
| | | VOID(WINAPI *Win32GetSystemInfo)( |
| | | _Out_ LPSYSTEM_INFO lpSystemInfo |
| | | ); |
| | | |
| | | BOOL(WINAPI *Win32VirtualProtect)( |
| | | _In_ LPVOID lpAddress, |
| | | _In_ SIZE_T dwSize, |
| | | _In_ DWORD flNewProtect, |
| | | _Out_ PDWORD lpflOldProtect |
| | | ); |
| | | |
| | | //---------------------------------------------------------------------- |
| | | // |
| | | // PrintError |
| | | // |
| | | // Formats an error message for the last error |
| | | // |
| | | // Mark Russinovich |
| | | // Systems Internals |
| | | // http://www.sysinternals.com |
| | | //---------------------------------------------------------------------- |
| | | void PrintError(char *message, NTSTATUS status) |
| | | { |
| | | char *errMsg; |
| | | |
| | | FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, |
| | | NULL, RtlNtStatusToDosError(status), |
| | | MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), |
| | | (LPTSTR)&errMsg, 0, NULL); |
| | | LocalFree(errMsg); |
| | | } |
| | | |
| | | //-------------------------------------------------------- |
| | | // |
| | | // UnmapPhysicalMemory |
| | | // |
| | | |
| | | // Maps a view of a section. |
| | | // |
| | | // Mark Russinovich |
| | | // Systems Internals |
| | | // http://www.sysinternals.com |
| | | //-------------------------------------------------------- |
| | | static VOID UnmapPhysicalMemory(PVOID Address) |
| | | { |
| | | NTSTATUS status; |
| | | |
| | | status = NtUnmapViewOfSection((HANDLE)-1, Address); |
| | | if (!NT_SUCCESS(status)) |
| | | { |
| | | PrintError("Unable to unmap view", status); |
| | | } |
| | | } |
| | | |
| | | |
| | | //-------------------------------------------------------- |
| | | // |
| | | // MapPhysicalMemory |
| | | // |
| | | // Maps a view of a section. |
| | | // |
| | | // Mark Russinovich |
| | | // Systems Internals |
| | | // http://www.sysinternals.com |
| | | //-------------------------------------------------------- |
| | | static BOOLEAN MapPhysicalMemory(HANDLE PhysicalMemory, |
| | | PVOID Address, PDWORD Length, |
| | | PVOID *VirtualAddress) |
| | | { |
| | | NTSTATUS ntStatus; |
| | | PHYSICAL_ADDRESS viewBase; |
| | | char error[256]; |
| | | |
| | | viewBase.QuadPart = (ULONGLONG)(Address); |
| | | ntStatus = NtMapViewOfSection(PhysicalMemory, |
| | | (HANDLE)-1, |
| | | VirtualAddress, |
| | | 0L, *Length, |
| | | &viewBase, |
| | | Length, |
| | | ViewShare, |
| | | 0, |
| | | PAGE_READONLY); |
| | | |
| | | if (!NT_SUCCESS(ntStatus)) { |
| | | |
| | | PrintError(error, ntStatus); |
| | | return FALSE; |
| | | } |
| | | |
| | | return TRUE; |
| | | } |
| | | |
| | | |
| | | //-------------------------------------------------------- |
| | | // |
| | | // OpensPhysicalMemory |
| | | // |
| | | // This function opens the physical memory device. It |
| | | // uses the native API since |
| | | // |
| | | // Mark Russinovich |
| | | // Systems Internals |
| | | // http://www.sysinternals.com |
| | | //-------------------------------------------------------- |
| | | static HANDLE OpenPhysicalMemory() |
| | | { |
| | | NTSTATUS status; |
| | | HANDLE physmem; |
| | | UNICODE_STRING physmemString; |
| | | OBJECT_ATTRIBUTES attributes; |
| | | WCHAR physmemName[] = L"\\device\\physicalmemory"; |
| | | |
| | | RtlInitUnicodeString(&physmemString, physmemName); |
| | | |
| | | InitializeObjectAttributes(&attributes, &physmemString, |
| | | OBJ_CASE_INSENSITIVE, NULL, NULL); |
| | | status = NtOpenSection(&physmem, SECTION_MAP_READ, &attributes); |
| | | |
| | | if (!NT_SUCCESS(status)) |
| | | { |
| | | PrintError("Could not open \\device\\physicalmemory", status); |
| | | return NULL; |
| | | } |
| | | |
| | | return physmem; |
| | | } |
| | | |
| | | static PVOID MapPhysicalMemoryWithBase(HANDLE hPhyHandle, PVOID pBase, PDWORD pLen, PVOID *pVirtualBase) |
| | | { |
| | | DWORD dwOffset = (ULONGLONG)pBase % dwPageSize; |
| | | DWORD dwLen = *pLen + dwOffset; |
| | | |
| | | PVOID pVAddr = NULL; |
| | | |
| | | if (MapPhysicalMemory(hPhyHandle, pBase, &dwLen, &pVAddr)) |
| | | { |
| | | *pVirtualBase = pVAddr; |
| | | *pLen = dwLen; |
| | | |
| | | return (PBYTE)pVAddr + dwOffset; |
| | | } |
| | | else |
| | | { |
| | | return NULL; |
| | | } |
| | | } |
| | | |
| | | bool InitEntryPoints() |
| | | { |
| | | Win32GetVersionEx = decltype(Win32GetVersionEx)(GetProcAddress(::GetModuleHandle(_T("kernel32.dll")), GetVersionExProc)); |
| | | if (!Win32GetVersionEx) |
| | | return false; |
| | | |
| | | Win32GetSystemInfo = decltype(Win32GetSystemInfo)(GetProcAddress(::GetModuleHandle(_T("kernel32.dll")), "GetSystemInfo")); |
| | | if (!Win32GetSystemInfo) |
| | | return false; |
| | | |
| | | OSVERSIONINFO osvi; |
| | | ZeroMemory(&osvi, sizeof(OSVERSIONINFO)); |
| | | osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); |
| | | |
| | | if (!Win32GetVersionEx(&osvi)) |
| | | return false; |
| | | |
| | | bIsWindowsXPLater = ((osvi.dwMajorVersion > 5) || ((osvi.dwMajorVersion == 5) && (osvi.dwMinorVersion > 1))); |
| | | |
| | | SYSTEM_INFO sysinfo; |
| | | ::ZeroMemory(&sysinfo, sizeof (SYSTEM_INFO)); |
| | | Win32GetSystemInfo(&sysinfo); |
| | | |
| | | dwPageSize = sysinfo.dwPageSize; |
| | | |
| | | if (bIsWindowsXPLater) |
| | | { |
| | | Win32GetSystemFirmwareTable = decltype(Win32GetSystemFirmwareTable)(GetProcAddress(GetModuleHandle(_T("kernel32.dll")), "GetSystemFirmwareTable")); |
| | | if (!Win32GetSystemFirmwareTable) |
| | | return false; |
| | | } |
| | | else |
| | | { |
| | | Win32VirtualProtect = decltype(Win32VirtualProtect)(GetProcAddress(GetModuleHandle(_T("kernel32.dll")), "VirtualProtect")); |
| | | if (!Win32VirtualProtect) |
| | | return false; |
| | | |
| | | RtlInitUnicodeString = (decltype(RtlInitUnicodeString))(GetProcAddress(GetModuleHandle(_T("ntdll.dll")), "RtlInitUnicodeString")); |
| | | if (!RtlInitUnicodeString) |
| | | return false; |
| | | |
| | | NtUnmapViewOfSection = (decltype(NtUnmapViewOfSection))(GetProcAddress(GetModuleHandle(_T("ntdll.dll")), "NtUnmapViewOfSection")); |
| | | if (!NtUnmapViewOfSection) |
| | | return false; |
| | | |
| | | NtOpenSection = (decltype(NtOpenSection))(GetProcAddress(GetModuleHandle(_T("ntdll.dll")), "NtOpenSection")); |
| | | if (!NtOpenSection) |
| | | return false; |
| | | |
| | | NtMapViewOfSection = (decltype(NtMapViewOfSection))(GetProcAddress(GetModuleHandle(_T("ntdll.dll")), "NtMapViewOfSection")); |
| | | if (!NtMapViewOfSection) |
| | | return false; |
| | | |
| | | RtlNtStatusToDosError = (decltype(RtlNtStatusToDosError))(GetProcAddress(GetModuleHandle(_T("ntdll.dll")), "RtlNtStatusToDosError")); |
| | | if (!NtMapViewOfSection) |
| | | return false; |
| | | } |
| | | |
| | | return true; |
| | | } |
| | | |
| | | void *LocateSMBIOS(uint32_t *smbios_size) { |
| | | void *buf = NULL; |
| | | const DWORD tableSignature = ('R' << 24) | ('S' << 16) | ('M' << 8) | 'B'; |
| | | |
| | | if (bIsWindowsXPLater) |
| | | { |
| | | uint32_t size = 0; |
| | | size = Win32GetSystemFirmwareTable(tableSignature, 0, buf, size); |
| | | if (0 == size) |
| | | { |
| | | return NULL; |
| | | } |
| | | |
| | | buf = malloc(size); |
| | | if (buf) |
| | | { |
| | | if (0 == Win32GetSystemFirmwareTable(tableSignature, 0, buf, size)) |
| | | { |
| | | free(buf); |
| | | buf = NULL; |
| | | } |
| | | else |
| | | { |
| | | *smbios_size = size; |
| | | } |
| | | } |
| | | } |
| | | else |
| | | { |
| | | HANDLE hPhysMem = OpenPhysicalMemory(); |
| | | if (NULL == hPhysMem) |
| | | return NULL; |
| | | |
| | | DWORD dwReadLen = 0x10000; |
| | | DWORD dwActualLen = dwReadLen; |
| | | PVOID pBaseVAddr = NULL; |
| | | PVOID pVAddr = MapPhysicalMemoryWithBase(hPhysMem, (PVOID)0xF0000, &dwActualLen, &pBaseVAddr); |
| | | if (!pVAddr) |
| | | { |
| | | ::CloseHandle(hPhysMem); |
| | | return NULL; |
| | | } |
| | | |
| | | DWORD dwReadOffset = 0; |
| | | |
| | | PBYTE pbVAddr = (PBYTE)pVAddr; |
| | | PBYTE pbGuardVAddr = pbVAddr + dwReadLen; |
| | | |
| | | while (pbVAddr < pbGuardVAddr) |
| | | { |
| | | if (pbVAddr[0] == '_' && pbVAddr[1] == 'S' && pbVAddr[2] == 'M' && pbVAddr[3] == '_') |
| | | { |
| | | break; |
| | | } |
| | | |
| | | pbVAddr += 16; |
| | | } |
| | | |
| | | //! no SMBIOS found |
| | | if (pbVAddr >= pbGuardVAddr) |
| | | { |
| | | UnmapPhysicalMemory(pVAddr); |
| | | ::CloseHandle(hPhysMem); |
| | | |
| | | return NULL; |
| | | } |
| | | |
| | | PSMBIOSEntryPoint pEntryPoint = (PSMBIOSEntryPoint)pbVAddr; |
| | | |
| | | RawSMBIOSData *pData = (RawSMBIOSData *)::malloc(pEntryPoint->TableLength + sizeof(RawSMBIOSData)); |
| | | PVOID pTableBaseVAddr = NULL; |
| | | if (NULL != pData) |
| | | { |
| | | DWORD dwTableLen = pEntryPoint->TableLength; |
| | | PVOID pTableVAddr = MapPhysicalMemoryWithBase(hPhysMem, (PVOID)pEntryPoint->TableAddress, &dwTableLen, &pTableBaseVAddr); |
| | | if (!pTableVAddr) |
| | | { |
| | | UnmapPhysicalMemory(pBaseVAddr); |
| | | ::CloseHandle(hPhysMem); |
| | | return NULL; |
| | | } |
| | | |
| | | pData->Used20CallingMethod = 0; |
| | | pData->DmiRevision = 0; |
| | | pData->SMBIOSMajorVersion = pEntryPoint->MajorVersion; |
| | | pData->SMBIOSMinorVersion = pEntryPoint->MinorVersion; |
| | | pData->Length = pEntryPoint->TableLength; |
| | | |
| | | ::memcpy(pData->SMBIOSTableData, (PVOID)pTableVAddr, pEntryPoint->TableLength); |
| | | *smbios_size = pEntryPoint->TableLength; |
| | | } |
| | | |
| | | if (NULL != pTableBaseVAddr) |
| | | UnmapPhysicalMemory(pTableBaseVAddr); |
| | | if (NULL != pBaseVAddr) |
| | | UnmapPhysicalMemory(pBaseVAddr); |
| | | |
| | | ::CloseHandle(hPhysMem); |
| | | |
| | | buf = pData; |
| | | } |
| | | |
| | | return buf; |
| | | } |
New file |
| | |
| | | #pragma once |
| | | |
| | | #include <stdint.h> |
| | | #include <windows.h> |
| | | |
| | | struct RawSMBIOSData |
| | | { |
| | | BYTE Used20CallingMethod; |
| | | BYTE SMBIOSMajorVersion; |
| | | BYTE SMBIOSMinorVersion; |
| | | BYTE DmiRevision; |
| | | DWORD Length; |
| | | BYTE SMBIOSTableData[]; |
| | | }; |
| | | |
| | | bool InitEntryPoints(); |
| | | void *LocateSMBIOS(uint32_t *smbios_size); |
| | | |
New file |
| | |
| | | #include "intrin.h" |
| | | |
| | | #include <iostream> |
| | | #include "BIOSReader.h" |
| | | #include "Native.h" |
| | | |
| | | int _tmain(int argc, _TCHAR* argv[]) |
| | | { |
| | | int cpui[4] = { 0 }; |
| | | __cpuid(cpui, 0x1); |
| | | |
| | | if ((cpui[2] >> 31) & 1) |
| | | { |
| | | std::cout << "Inside virual machine!"; |
| | | return 1; |
| | | } |
| | | |
| | | if (InitEntryPoints()) |
| | | { |
| | | BIOSReader reader; |
| | | SystemInformation info = reader.readSystemInfo(); |
| | | |
| | | const char *vmVendors[] = |
| | | { |
| | | "VMware", "Microsoft Corporation", "Virtual Machine", "innotek GmbH", "PowerVM", "Bochs", "KVM" |
| | | }; |
| | | |
| | | const int count = _countof(vmVendors); |
| | | for (int i = 0; i != count; ++i) |
| | | { |
| | | const char *vendor = vmVendors[i]; |
| | | |
| | | if (std::string::npos != info.Manufacturer.find(vendor) || |
| | | std::string::npos != info.ProductName.find(vendor) || |
| | | std::string::npos != info.SerialNum.find(vendor)) |
| | | { |
| | | std::cout << "Inside virual machine!"; |
| | | return 1; |
| | | } |
| | | } |
| | | } |
| | | else |
| | | { |
| | | return -1; |
| | | } |
| | | |
| | | std::cout << "Inside host machine!"; |
| | | |
| | | return 0; |
| | | } |
| | | |
New file |
| | |
| | | /** |
| | | * @file network_id.c |
| | | * @date 16 Sep 2014 |
| | | * @brief File containing network interface detection functions for Windows. |
| | | * |
| | | * The only public function of this module is #getAdapterInfos(OsAdapterInfo *, |
| | | * size_t *), other functions are either static or inline. |
| | | * |
| | | * Responsibility of this module is to fill OsAdapterInfo structures, in a predictable way (skip loopback/vpn interfaces) |
| | | */ |
| | | |
| | | #ifdef _MSC_VER |
| | | #include <Windows.h> |
| | | #endif |
| | | #include <iphlpapi.h> |
| | | #include <unordered_map> |
| | | #include <stdio.h> |
| | | //#pragma comment(lib, "IPHLPAPI.lib") |
| | | |
| | | #include "../../base/StringUtils.h" |
| | | #include "../../base/logger.h" |
| | | #include "../network.hpp" |
| | | |
| | | namespace license { |
| | | namespace os { |
| | | using namespace std; |
| | | |
| | | static int translate(char ipStringIn[16], unsigned char ipv4[4]) { |
| | | size_t index = 0; |
| | | |
| | | char *str2 = ipStringIn; /* save the pointer */ |
| | | while (*str2) { |
| | | if (isdigit((unsigned char)*str2)) { |
| | | ipv4[index] *= 10; |
| | | ipv4[index] += *str2 - '0'; |
| | | } else { |
| | | index++; |
| | | } |
| | | str2++; |
| | | } |
| | | return 0; |
| | | } |
| | | /** |
| | | * |
| | | * @param adapterInfos |
| | | * @param adapter_info_size |
| | | * @return |
| | | */ |
| | | FUNCTION_RETURN getAdapterInfos(vector<OsAdapterInfo> &adapterInfos) { |
| | | unordered_map<string, OsAdapterInfo> adapterByName; |
| | | FUNCTION_RETURN f_return = FUNC_RET_OK; |
| | | DWORD dwStatus; |
| | | int adapter_info_size; |
| | | PIP_ADAPTER_INFO pAdapterInfo; |
| | | DWORD dwBufLen = sizeof(IP_ADAPTER_INFO); |
| | | |
| | | unsigned int i = 3; |
| | | do { |
| | | pAdapterInfo = (PIP_ADAPTER_INFO)malloc(dwBufLen); |
| | | dwStatus = GetAdaptersInfo( // Call GetAdapterInfo |
| | | pAdapterInfo, // [out] buffer to receive data |
| | | &dwBufLen // [in] size of receive data buffer |
| | | ); |
| | | if (dwStatus != NO_ERROR && pAdapterInfo != nullptr) { |
| | | free(pAdapterInfo); |
| | | pAdapterInfo = nullptr; |
| | | } |
| | | } while (dwStatus == ERROR_BUFFER_OVERFLOW && i-- > 0); |
| | | |
| | | if (dwStatus == ERROR_BUFFER_OVERFLOW) { |
| | | return FUNC_RET_ERROR; |
| | | } |
| | | |
| | | adapter_info_size = dwBufLen / sizeof(IP_ADAPTER_INFO); |
| | | if (adapter_info_size == 0) { |
| | | return FUNC_RET_NOT_AVAIL; |
| | | } |
| | | |
| | | PIP_ADAPTER_INFO pAdapter = pAdapterInfo; |
| | | i = 0; |
| | | FUNCTION_RETURN result = FUNC_RET_OK; |
| | | while (pAdapter) { |
| | | OsAdapterInfo ai = {}; |
| | | strncpy(ai.description, pAdapter->Description, |
| | | min((int)sizeof(ai.description), MAX_ADAPTER_DESCRIPTION_LENGTH)); |
| | | memcpy(ai.mac_address, pAdapter->Address, 8); |
| | | translate(pAdapter->IpAddressList.IpAddress.String, ai.ipv4_address); |
| | | ai.type = IFACE_TYPE_ETHERNET; |
| | | i++; |
| | | pAdapter = pAdapter->Next; |
| | | if (i == adapter_info_size) { |
| | | result = FUNC_RET_BUFFER_TOO_SMALL; |
| | | break; |
| | | } |
| | | adapterByName[string(ai.description)] = ai; |
| | | } |
| | | free(pAdapterInfo); |
| | | |
| | | // FIXME sort by eth , enps, wlan |
| | | if (adapterByName.size() == 0) { |
| | | f_return = FUNC_RET_NOT_AVAIL; |
| | | } else { |
| | | f_return = FUNC_RET_OK; |
| | | adapterInfos.reserve(adapterByName.size()); |
| | | for (auto &it : adapterByName) { |
| | | adapterInfos.push_back(it.second); |
| | | } |
| | | } |
| | | return f_return; |
| | | } |
| | | |
| | | } // namespace os |
| | | } // namespace license |
New file |
| | |
| | | #define NOMINMAX |
| | | #include <windows.h> |
| | | #include <algorithm> |
| | | #include <licensecc/datatypes.h> |
| | | #include <iphlpapi.h> |
| | | #include <stdio.h> |
| | | |
| | | #include "../../base/logger.h" |
| | | #include "../os.h" |
| | | using namespace std; |
| | | |
| | | FUNCTION_RETURN getMachineName(unsigned char identifier[6]) { |
| | | FUNCTION_RETURN result = FUNC_RET_ERROR; |
| | | char buffer[MAX_COMPUTERNAME_LENGTH + 1]; |
| | | int bufsize = MAX_COMPUTERNAME_LENGTH + 1; |
| | | const BOOL cmpName = GetComputerName(buffer, (unsigned long*)&bufsize); |
| | | if (cmpName) { |
| | | strncpy((char*)identifier, buffer, 6); |
| | | result = FUNC_RET_OK; |
| | | } |
| | | return result; |
| | | } |
| | | |
| | | //http://www.ok-soft-gmbh.com/ForStackOverflow/EnumMassStorage.c |
| | | //http://stackoverflow.com/questions/3098696/same-code-returns-diffrent-result-on-windows7-32-bit-system |
| | | #define MAX_UNITS 30 |
| | | //bug check return with diskinfos == null func_ret_ok |
| | | FUNCTION_RETURN getDiskInfos(DiskInfo * diskInfos, size_t * disk_info_size) { |
| | | DWORD fileMaxLen; |
| | | size_t ndrives = 0; |
| | | DWORD fileFlags; |
| | | char volName[MAX_PATH], fileSysName[MAX_PATH]; |
| | | DWORD volSerial = 0; |
| | | const DWORD dwSize = MAX_PATH; |
| | | char szLogicalDrives[MAX_PATH] = { 0 }; |
| | | |
| | | |
| | | FUNCTION_RETURN return_value = FUNC_RET_NOT_AVAIL; |
| | | const DWORD dwResult = GetLogicalDriveStrings(dwSize, szLogicalDrives); |
| | | |
| | | if (dwResult > 0 && dwResult <= MAX_PATH) { |
| | | return_value = FUNC_RET_OK; |
| | | char* szSingleDrive = szLogicalDrives; |
| | | while (*szSingleDrive && ndrives < MAX_UNITS) { |
| | | |
| | | // get the next drive |
| | | UINT driveType = GetDriveType(szSingleDrive); |
| | | if (driveType == DRIVE_FIXED) { |
| | | BOOL success = GetVolumeInformation(szSingleDrive, volName, MAX_PATH, |
| | | &volSerial, &fileMaxLen, &fileFlags, fileSysName, |
| | | MAX_PATH); |
| | | if (success) { |
| | | LOG_INFO("drive : %s", szSingleDrive); |
| | | LOG_INFO("Volume Name : %s", volName); |
| | | LOG_INFO("Volume Serial : 0x%x", volSerial); |
| | | LOG_DEBUG("Max file length : %d", fileMaxLen); |
| | | LOG_DEBUG("Filesystem : %s", fileSysName); |
| | | if (diskInfos != NULL) { |
| | | if (ndrives < (int)*disk_info_size) { |
| | | diskInfos[ndrives].id = (int)ndrives; |
| | | strncpy(diskInfos[ndrives].device, volName, |
| | | min(std::size_t{MAX_PATH}, sizeof(volName)) - 1); |
| | | strncpy(diskInfos[ndrives].label, fileSysName, |
| | | min(sizeof(diskInfos[ndrives].label), sizeof(fileSysName)) - 1); |
| | | memcpy(diskInfos[ndrives].disk_sn, &volSerial, sizeof(DWORD)); |
| | | diskInfos[ndrives].preferred = (szSingleDrive[0] == 'C'); |
| | | } else { |
| | | return_value = FUNC_RET_BUFFER_TOO_SMALL; |
| | | } |
| | | } |
| | | ndrives++; |
| | | } else { |
| | | LOG_WARN("Unable to retrieve information of '%s'", szSingleDrive); |
| | | } |
| | | } else { |
| | | LOG_INFO("This volume is not fixed : %s, type: %d", szSingleDrive); |
| | | } |
| | | szSingleDrive += strlen(szSingleDrive) + 1; |
| | | } |
| | | } |
| | | if (diskInfos == NULL || *disk_info_size == 0) { |
| | | if (ndrives > 0) { |
| | | return_value = FUNC_RET_OK; |
| | | } else { |
| | | return_value = FUNC_RET_NOT_AVAIL; |
| | | LOG_INFO("No fixed drive was detected"); |
| | | } |
| | | *disk_info_size = ndrives; |
| | | } else { |
| | | *disk_info_size = min(ndrives, *disk_info_size); |
| | | } |
| | | return return_value; |
| | | } |
| | | |
| | | |
| | | FUNCTION_RETURN getModuleName(char buffer[MAX_PATH]) { |
| | | FUNCTION_RETURN result = FUNC_RET_OK; |
| | | const DWORD wres = GetModuleFileName(NULL, buffer, MAX_PATH); |
| | | if (wres == 0) { |
| | | result = FUNC_RET_ERROR; |
| | | } |
| | | return result; |
| | | } |
| | | |
| | |
| | | #include <wincrypt.h> |
| | | #include <iphlpapi.h> |
| | | #include <windows.h> |
| | | #pragma comment(lib, "bcrypt.lib") |
| | | //#pragma comment(lib, "bcrypt.lib") |
| | | |
| | | #include <public_key.h> |
| | | #include "../../base/logger.h" |
| | | #include "../../base/base64.h" |
| | | #include "../signature_verifier.h" |
| | | #include "../signature_verifier.hpp" |
| | | |
| | | #define RSA_KEY_BITLEN 1024 |
| | | |
| | | namespace license { |
| | | namespace os { |
| | | using namespace std; |
| | | #define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0) |
| | | |
| | |
| | | DWORD status; |
| | | FUNCTION_RETURN result = FUNC_RET_ERROR; |
| | | PBYTE pbSignature = nullptr; |
| | | DWORD dwSigLen; |
| | | BYTE* sigBlob = nullptr; |
| | | BCRYPT_ALG_HANDLE hSignAlg = nullptr; |
| | | |
| | | // FIXME!! |
| | | sigBlob = unbase64(signatureBuffer.c_str(), (int)signatureBuffer.size(), (int*)&dwSigLen); |
| | | vector<uint8_t> signatureBlob = unbase64(signatureBuffer); |
| | | DWORD dwSigLen = (DWORD) signatureBlob.size(); |
| | | BYTE* sigBlob = &signatureBlob[0]; |
| | | |
| | | if (NT_SUCCESS(status = BCryptOpenAlgorithmProvider(&hSignAlg, BCRYPT_RSA_ALGORITHM, NULL, 0))) { |
| | | if ((result = readPublicKey(hSignAlg, &phKey)) == FUNC_RET_OK) { |
| | |
| | | } else { |
| | | LOG_DEBUG("Error reading public key"); |
| | | } |
| | | } else { |
| | | } |
| | | else { |
| | | result = FUNC_RET_NOT_AVAIL; |
| | | #ifdef _DEBUG |
| | | formatError(status, "error opening RSA provider"); |
| | |
| | | if (hSignAlg != nullptr) { |
| | | BCryptCloseAlgorithmProvider(hSignAlg, 0); |
| | | } |
| | | if (sigBlob) { |
| | | free(sigBlob); |
| | | } |
| | | //if (sigBlob) { |
| | | // free(sigBlob); |
| | | //} |
| | | return result; |
| | | } |
| | | |
| | |
| | | } |
| | | return result; |
| | | } |
| | | |
| | | } // namespace os |
| | | } /* namespace license */ |
| | |
| | | #ifndef BUILD_PROPERTIES_H_ |
| | | #define BUILD_PROPERTIES_H_ |
| | | |
| | | /** |
| | | * This file contains all the properties that are customizable on on a per-project basis eg: |
| | | * 1) api parameter sizes |
| | | * 2) |
| | | * |
| | | * It is safe to place the values that your project need to customize here, since each project get its own copy of this |
| | | * file. |
| | | */ |
| | | |
| | | #define LCC_PROJECT_NAME "@LCC_PROJECT_NAME@" |
| | | |
| | | //License retrieval configuration |
| | | #define FIND_LICENSE_NEAR_MODULE true |
| | | #define FIND_LICENSE_WITH_ENV_VAR false |
| | | |
| | | #define LICENSE_FILE_EXTENSION ".lic" |
| | | #define LICENSE_LOCATION_ENV_VAR "LICENSE_LOCATION" |
| | | #define LICENSE_DATA_ENV_VAR "LICENSE_DATA" |
| | | /** |
| | | * License file name extension |
| | | */ |
| | | #define LCC_LICENSE_FILE_EXTENSION ".lic" |
| | | #define LCC_LICENSE_LOCATION_ENV_VAR "LICENSE_LOCATION" |
| | | #define LCC_LICENSE_DATA_ENV_VAR "LICENSE_DATA" |
| | | /** |
| | | * Environment variable that if defined will change the identification strategy used to generate the hardware identifier. |
| | | * If a client has an unstable pc-identifier use this variable to generate one. |
| | | * Valid values are integers defined in `LCC_IDENTIFICATION_STRATEGY` enum. |
| | | */ |
| | | #define LCC_IDENTIFICATION_STRATEGY_ENV_VAR "IDENTIFICATION_STRATEGY" |
| | | |
| | | //Internal data structures limits |
| | | #define MAX_LICENSE_LENGTH 256*1024 |
| | | /** |
| | | * Enum to select a specific pc identification_strategy. DEFAULT Should be used in most cases. |
| | | */ |
| | | typedef enum { |
| | | STRATEGY_DEFAULT = -1, |
| | | STRATEGY_ETHERNET = 0, |
| | | STRATEGY_IP_ADDRESS = 1, |
| | | STRATEGY_DISK_NUM = 2, |
| | | STRATEGY_DISK_LABEL = 3, |
| | | STRATEGY_MEMORY_CPU_SIZE = 4, |
| | | STRATEGY_HOST_NAME = 5, |
| | | STRATEGY_NONE = -2 |
| | | } LCC_API_IDENTIFICATION_STRATEGY; |
| | | |
| | | //strategies used for each virtual environment. |
| | | #define LCC_BARE_TO_METAL_STRATEGIES { STRATEGY_ETHERNET, STRATEGY_DISK_LABEL, STRATEGY_NONE } |
| | | #define LCC_VM_STRATEGIES { STRATEGY_ETHERNET, STRATEGY_NONE } |
| | | #define LCC_LXC_STRATEGIES { STRATEGY_ETHERNET, STRATEGY_NONE } |
| | | #define LCC_DOCKER_STRATEGIES { STRATEGY_NONE } |
| | | #define LCC_CLOUD_STRATEGIES { STRATEGY_NONE } |
| | | |
| | | //Api structure limits |
| | | /** |
| | | * Maximum size of a license file or base64 data |
| | | */ |
| | | #define LCC_API_MAX_LICENSE_DATA_LENGTH 1024 * 4 |
| | | |
| | | // define api structure sizes |
| | | #define LCC_API_PC_IDENTIFIER_SIZE 19 |
| | | #define LCC_API_PROPRIETARY_DATA_SIZE 16 |
| | | #define LCC_API_AUDIT_EVENT_NUM 5 |
| | | #define LCC_API_AUDIT_EVENT_PARAM2 255 |
| | | #define LCC_API_VERSION_LENGTH 15 |
| | | #define LCC_API_PROJECT_NAME_SIZE 15 |
| | | #define LCC_API_EXPIRY_DATE_SIZE 10 |
| | | #define LCC_API_ERROR_BUFFER_SIZE 256 |
| | | |
| | | /** |
| | | This definition allows to specify a custom expression to verify the magic number passed in by the api. |
| | | */ |
| | | #define LCC_VERIFY_MAGIC (lic_info.m_magic == @LCC_PROJECT_MAGIC_NUM@) |
| | | |
| | | #endif |
| | |
| | | #if we're here boost has been found |
| | | add_definitions(-DBOOST_ALL_NO_LIB) #Disable Boost Microsoft magic, all dependencies are handled by cmake |
| | | add_definitions(-DBOOST_LIB_DIAGNOSTIC) #Check it is really disabled |
| | | include_directories(${Boost_INCLUDE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) |
| | | link_directories ( ${Boost_LIBRARY_DIR} ) |
| | | |
| | | configure_file ( |
| | | "${CMAKE_CURRENT_SOURCE_DIR}/../src/templates/licensecc_properties_test.h.in" |
| | |
| | | file(GENERATE OUTPUT "${CMAKE_BINARY_DIR}/include/$<CONFIG>/licensecc_properties_test.h" |
| | | INPUT "${CMAKE_BINARY_DIR}/licensecc_properties_test.h.tmp") |
| | | include_directories ( ${CMAKE_BINARY_DIR}/include/$<CONFIG> ) |
| | | |
| | | |
| | | add_subdirectory(library) |
| | | add_subdirectory(functional) |
New file |
| | |
| | | /* |
| | | * IdentificationStrategy_test.cpp |
| | | * |
| | | * Created on: Jan 1, 2020 |
| | | * Author: devel |
| | | */ |
| | | |
| | | #include "identification_strategy.hpp" |
| | | |
| | | namespace license {} /* namespace license */ |
New file |
| | |
| | | /* |
| | | * default_strategy_test.cpp |
| | | * |
| | | * Created on: Jan 2, 2020 |
| | | * Author: devel |
| | | */ |
| | | |
| | | #include "default_strategy.hpp" |
| | | |
| | | namespace license {} /* namespace license */ |
| | |
| | | generate-license.cpp |
| | | ) |
| | | |
| | | target_link_libraries( |
| | | license_generator_snippet |
| | | target_link_libraries( license_generator_snippet |
| | | Boost::unit_test_framework |
| | | Boost::filesystem |
| | | Boost::system |
| | | ) |
| | | |
| | | add_executable( |
| | | test_standard_license |
| | | add_executable( test_standard_license |
| | | standard-license_test.cpp |
| | | ) |
| | | |
| | | target_link_libraries( |
| | | test_standard_license |
| | | target_link_libraries( test_standard_license |
| | | licensecc_static |
| | | license_generator_snippet |
| | | Boost::unit_test_framework |
| | |
| | | Boost::system |
| | | ) |
| | | |
| | | add_executable( |
| | | test_date |
| | | add_executable( test_date |
| | | date_test.cpp |
| | | ) |
| | | |
| | | target_link_libraries( |
| | | test_date |
| | | target_link_libraries( test_date |
| | | licensecc_static |
| | | license_generator_snippet |
| | | Boost::unit_test_framework |
| | |
| | | Boost::system |
| | | ) |
| | | |
| | | add_executable( |
| | | test_signature_verifier |
| | | add_executable( test_signature_verifier |
| | | signature_verifier_test.cpp |
| | | ) |
| | | |
| | |
| | | ) |
| | | |
| | | |
| | | add_executable( |
| | | test_volid |
| | | volid_test.cpp |
| | | ) |
| | | add_executable(test_it_hw_identifier hw_identifier_it_test.cpp) |
| | | |
| | | target_link_libraries( |
| | | test_volid |
| | | licensecc_static |
| | | target_link_libraries(test_it_hw_identifier |
| | | license_generator_snippet |
| | | licensecc_static |
| | | Boost::unit_test_framework |
| | | Boost::filesystem |
| | | Boost::system |
| | | ) |
| | | |
| | | add_executable(test_crack crack_test.cpp) |
| | | |
| | | target_link_libraries( test_crack |
| | | license_generator_snippet |
| | | licensecc_static |
| | | Boost::unit_test_framework |
| | | Boost::filesystem |
| | | Boost::system |
| | | ) |
| | | |
| | | ADD_TEST(NAME test_crack COMMAND test_crack WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) |
| | | ADD_TEST(NAME test_date COMMAND test_date WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) |
| | | ADD_TEST(NAME test_it_hw_identifier COMMAND test_it_hw_identifier WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) |
| | | ADD_TEST(NAME test_standard_license COMMAND test_standard_license WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) |
| | | ADD_TEST(NAME test_signature_verifier COMMAND test_signature_verifier WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) |
| | | ADD_TEST(NAME test_volid COMMAND test_volid WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) |
| | | |
| | | |
New file |
| | |
| | | |
| | | #define BOOST_TEST_MODULE standard_license_test |
| | | |
| | | #include <boost/test/unit_test.hpp> |
| | | #include <boost/filesystem.hpp> |
| | | |
| | | #include <licensecc/licensecc.h> |
| | | #include <licensecc_properties_test.h> |
| | | #include <licensecc_properties.h> |
| | | #include <iostream> |
| | | #include "../../src/library/ini/SimpleIni.h" |
| | | #include "generate-license.h" |
| | | #include "../../src/library/base/file_utils.hpp" |
| | | |
| | | namespace license { |
| | | namespace test { |
| | | namespace fs = boost::filesystem; |
| | | using namespace license; |
| | | using namespace std; |
| | | |
| | | /** |
| | | * Test a generic license, passing a bad license number trough the api. |
| | | * see projects/DEFAULT/include/licensecc/DEFAULT/licensecc_properties.h (magic should be 0) |
| | | */ |
| | | BOOST_AUTO_TEST_CASE(test_bad_magic_number) { |
| | | const vector<string> extraArgs; |
| | | const string licLocation = generate_license("standard_license", extraArgs); |
| | | /* */ |
| | | LicenseInfo license; |
| | | LicenseLocation location = {LICENSE_PATH}; |
| | | std::copy(licLocation.begin(), licLocation.end(), location.licenseData); |
| | | // magic should be 0 for this build... |
| | | CallerInformations callInfo{{0}, {0}, 42}; |
| | | const LCC_EVENT_TYPE result = acquire_license(&callInfo, &location, &license); |
| | | BOOST_CHECK_EQUAL(result, LICENSE_CORRUPTED); |
| | | } |
| | | |
| | | } // namespace test |
| | | } // namespace license |
| | |
| | | const string licLocation = generate_license("not_expired.lic", extraArgs); |
| | | /* */ |
| | | LicenseInfo license; |
| | | LicenseLocation licenseLocation; |
| | | licenseLocation.licenseFileLocation = licLocation.c_str(); |
| | | licenseLocation.licenseData = ""; |
| | | const EVENT_TYPE result = acquire_license(nullptr, &licenseLocation, &license); |
| | | LicenseLocation location = {LICENSE_PATH}; |
| | | std::copy(licLocation.begin(), licLocation.end(), location.licenseData); |
| | | |
| | | const LCC_EVENT_TYPE result = acquire_license(nullptr, &location, &license); |
| | | BOOST_CHECK_EQUAL(result, LICENSE_OK); |
| | | BOOST_CHECK_EQUAL(license.has_expiry, true); |
| | | BOOST_CHECK_EQUAL(license.linked_to_pc, false); |
| | | BOOST_CHECK_GT(license.days_left, 0); |
| | | BOOST_CHECK_GT(license.days_left, (unsigned int)0); |
| | | } |
| | | |
| | | BOOST_AUTO_TEST_CASE(license_expired) { |
| | |
| | | const string licLocation = generate_license("expired", extraArgs); |
| | | /* */ |
| | | LicenseInfo license; |
| | | LicenseLocation licenseLocation; |
| | | licenseLocation.licenseFileLocation = licLocation.c_str(); |
| | | licenseLocation.licenseData = nullptr; |
| | | LicenseLocation location = {LICENSE_PATH}; |
| | | std::copy(licLocation.begin(), licLocation.end(), location.licenseData); |
| | | BOOST_TEST_MESSAGE("before acquire license"); |
| | | const EVENT_TYPE result = acquire_license(nullptr, &licenseLocation, &license); |
| | | const LCC_EVENT_TYPE result = acquire_license(nullptr, &location, &license); |
| | | BOOST_CHECK_EQUAL(result, PRODUCT_EXPIRED); |
| | | BOOST_CHECK_EQUAL(license.has_expiry, true); |
| | | BOOST_CHECK_EQUAL(license.linked_to_pc, false); |
| | |
| | | |
| | | namespace fs = boost::filesystem; |
| | | using namespace std; |
| | | |
| | | namespace license { |
| | | namespace test { |
| | | |
| | | string generate_license(const string& license_name, const vector<string>& other_args) { |
| | | fs::path lcc_exe(LCC_EXE); |
| | | BOOST_REQUIRE_MESSAGE(fs::is_regular_file(lcc_exe), "License generator not found: " LCC_EXE); |
New file |
| | |
| | | #define BOOST_TEST_MODULE integration_test_hw_identifier |
| | | |
| | | #include <boost/test/unit_test.hpp> |
| | | #include <fstream> |
| | | #include <iostream> |
| | | #include <stdio.h> |
| | | #include <cstring> |
| | | #include <boost/filesystem.hpp> |
| | | #include <licensecc_properties.h> |
| | | #include <licensecc_properties_test.h> |
| | | |
| | | #include <licensecc/licensecc.h> |
| | | #include "../../src/library/ini/SimpleIni.h" |
| | | #include "../../src/library/hw_identifier/hw_identifier_facade.hpp" |
| | | #include "../../src/library/os/os.h" |
| | | #include "../../src/library/os/network.hpp" |
| | | #include "generate-license.h" |
| | | |
| | | |
| | | namespace license { |
| | | namespace test { |
| | | namespace fs = boost::filesystem; |
| | | using namespace std; |
| | | using namespace hw_identifier; |
| | | |
| | | /** |
| | | * If the current pc has at least one disk generate a hardware identifier using disk, generate a license, verify the license |
| | | * is OK |
| | | */ |
| | | |
| | | static void generate_and_verify_license(LCC_API_IDENTIFICATION_STRATEGY strategy, const string& lic_fname) { |
| | | BOOST_TEST_CHECKPOINT("Before generate"); |
| | | const string identifier_out = HwIdentifierFacade::generate_user_pc_signature(strategy); |
| | | BOOST_TEST_CHECKPOINT("After generate signature"); |
| | | cout << "Identifier:" << identifier_out << endl; |
| | | vector<string> extraArgs; |
| | | extraArgs.push_back("-s"); |
| | | extraArgs.push_back(identifier_out); |
| | | BOOST_TEST_CHECKPOINT("Before generate license"); |
| | | const string licLocation = generate_license(lic_fname, extraArgs); |
| | | LicenseInfo license; |
| | | LicenseLocation location = {LICENSE_PATH}; |
| | | std::copy(licLocation.begin(), licLocation.end(), location.licenseData); |
| | | const LCC_EVENT_TYPE result = acquire_license(nullptr, &location, &license); |
| | | BOOST_CHECK_EQUAL(result, LICENSE_OK); |
| | | BOOST_CHECK_EQUAL(license.has_expiry, false); |
| | | BOOST_CHECK_EQUAL(license.linked_to_pc, true); |
| | | } |
| | | |
| | | BOOST_AUTO_TEST_CASE(volid_lic_file) { |
| | | HwIdentifier identifier_out; |
| | | size_t disk_num; |
| | | FUNCTION_RETURN result_diskinfos = getDiskInfos(nullptr, &disk_num); |
| | | if ((result_diskinfos == FUNC_RET_BUFFER_TOO_SMALL || result_diskinfos == FUNC_RET_OK) && disk_num > 0) { |
| | | generate_and_verify_license(LCC_API_IDENTIFICATION_STRATEGY::STRATEGY_DISK_NUM, "volid_lic_file"); |
| | | } else { |
| | | BOOST_TEST_MESSAGE("No disk found skipping testing disk hardware identifier"); |
| | | } |
| | | } |
| | | |
| | | BOOST_AUTO_TEST_CASE(volume_name_lic_file) { |
| | | HwIdentifier identifier_out; |
| | | size_t disk_num; |
| | | FUNCTION_RETURN result_diskinfos = getDiskInfos(nullptr, &disk_num); |
| | | if ((result_diskinfos == FUNC_RET_BUFFER_TOO_SMALL || result_diskinfos == FUNC_RET_OK) && disk_num > 0) { |
| | | generate_and_verify_license(LCC_API_IDENTIFICATION_STRATEGY::STRATEGY_DISK_LABEL, "volume_name_lic_file"); |
| | | } else { |
| | | BOOST_TEST_MESSAGE("No disk found skipping testing volume name disk hardware identifier"); |
| | | } |
| | | } |
| | | |
| | | BOOST_AUTO_TEST_CASE(strategy_mac_address) { |
| | | vector<os::OsAdapterInfo> adapters; |
| | | FUNCTION_RETURN result_adapterInfos = os::getAdapterInfos(adapters); |
| | | if ((result_adapterInfos == FUNC_RET_BUFFER_TOO_SMALL || result_adapterInfos == FUNC_RET_OK) && |
| | | adapters.size() > 0) { |
| | | generate_and_verify_license(LCC_API_IDENTIFICATION_STRATEGY::STRATEGY_ETHERNET, "strategy_mac_address"); |
| | | } else { |
| | | BOOST_TEST_MESSAGE("No ethernet adapter found skipping testing mac address hardware identifier"); |
| | | } |
| | | } |
| | | |
| | | BOOST_AUTO_TEST_CASE(strategy_ip_address) { |
| | | vector<os::OsAdapterInfo> adapters; |
| | | FUNCTION_RETURN result_adapterInfos = os::getAdapterInfos(adapters); |
| | | if ((result_adapterInfos == FUNC_RET_BUFFER_TOO_SMALL || result_adapterInfos == FUNC_RET_OK) && |
| | | adapters.size() > 0) { |
| | | generate_and_verify_license(LCC_API_IDENTIFICATION_STRATEGY::STRATEGY_IP_ADDRESS, "strategy_ip_address"); |
| | | } else { |
| | | BOOST_TEST_MESSAGE("No ethernet adapter found skipping testing ip hardware identifier"); |
| | | } |
| | | } |
| | | |
| | | } // namespace test |
| | | } // namespace license |
| | |
| | | |
| | | /* |
| | | * LicenseVerifier_test.cpp |
| | | * |
| | |
| | | #include <licensecc_properties_test.h> |
| | | #include <licensecc_properties.h> |
| | | |
| | | #include "../../src/library/os/signature_verifier.h" |
| | | #include "../../src/library/os/signature_verifier.hpp" |
| | | #include "generate-license.h" |
| | | |
| | | namespace license { |
| | |
| | | const string test_data("test_data"); |
| | | const string signature = sign_data(test_data, string("verify_signature")); |
| | | |
| | | FUNCTION_RETURN result = license::verify_signature(test_data, signature); |
| | | FUNCTION_RETURN result = license::os::verify_signature(test_data, signature); |
| | | BOOST_CHECK_MESSAGE(result == FUNC_RET_OK, "signature verified"); |
| | | } |
| | | |
| | |
| | | const string test_data("test_data"); |
| | | const string signature = sign_data(test_data, string("verify_signature")); |
| | | |
| | | FUNCTION_RETURN result = license::verify_signature(string("other data"), signature); |
| | | FUNCTION_RETURN result = license::os::verify_signature(string("other data"), signature); |
| | | BOOST_CHECK_MESSAGE(result == FUNC_RET_ERROR, "signature NOT verified"); |
| | | } |
| | | |
| | |
| | | const string test_data("test_data"); |
| | | string signature = sign_data(test_data, string("verify_signature")); |
| | | signature[2] = signature[2] + 1; |
| | | FUNCTION_RETURN result = license::verify_signature(test_data, signature); |
| | | FUNCTION_RETURN result = license::os::verify_signature(test_data, signature); |
| | | BOOST_CHECK_MESSAGE(result == FUNC_RET_ERROR, "signature NOT verified"); |
| | | } |
| | | |
| | |
| | | |
| | | #define BOOST_TEST_MODULE test_standard_license |
| | | |
| | | #include <boost/test/unit_test.hpp> |
| | |
| | | |
| | | #include "../../src/library/ini/SimpleIni.h" |
| | | #include "generate-license.h" |
| | | #include "../../src/library/base/FileUtils.hpp" |
| | | #include "../../src/library/base/file_utils.hpp" |
| | | |
| | | using namespace std; |
| | | namespace fs = boost::filesystem; |
| | | |
| | | namespace license { |
| | | namespace test { |
| | | namespace fs = boost::filesystem; |
| | | using namespace license; |
| | | using namespace std; |
| | | |
| | | /** |
| | | * Test a generic license with no expiry neither client id. |
| | | * Test a generic license with no expiry neither client id. The license is read from file |
| | | */ |
| | | BOOST_AUTO_TEST_CASE(test_generic_license) { |
| | | BOOST_AUTO_TEST_CASE(test_generic_license_read_file) { |
| | | const vector<string> extraArgs; |
| | | const string licLocation = generate_license("standard_license", extraArgs); |
| | | /* */ |
| | | LicenseInfo license; |
| | | LicenseLocation licenseLocation; |
| | | licenseLocation.licenseFileLocation = licLocation.c_str(); |
| | | licenseLocation.licenseData = nullptr; |
| | | const EVENT_TYPE result = acquire_license(nullptr, &licenseLocation, &license); |
| | | LicenseLocation location = {LICENSE_PATH}; |
| | | std::copy(licLocation.begin(), licLocation.end(), location.licenseData); |
| | | const LCC_EVENT_TYPE result = acquire_license(nullptr, &location, &license); |
| | | BOOST_CHECK_EQUAL(result, LICENSE_OK); |
| | | BOOST_CHECK_EQUAL(license.has_expiry, false); |
| | | BOOST_CHECK_EQUAL(license.linked_to_pc, false); |
| | | } |
| | | |
| | | /** |
| | | * Test a generic license with no expiry neither client id. The license is passed in trhough the licenseData structure. |
| | | */ |
| | | BOOST_AUTO_TEST_CASE(test_read_license_data) { |
| | | const vector<string> extraArgs; |
| | | const fs::path licLocation = fs::path(generate_license("standard_license1", extraArgs)); |
| | | const string licLocationStr = licLocation.string(); |
| | | string license_data = get_file_contents(licLocationStr.c_str(), 65536); |
| | | LicenseInfo license; |
| | | LicenseLocation location = {LICENSE_PLAIN_DATA}; |
| | | std::copy(license_data.begin(), license_data.end(), location.licenseData); |
| | | const LCC_EVENT_TYPE result = acquire_license(nullptr, &location, &license); |
| | | BOOST_CHECK_EQUAL(result, LICENSE_OK); |
| | | BOOST_CHECK_EQUAL(license.has_expiry, false); |
| | | BOOST_CHECK_EQUAL(license.linked_to_pc, false); |
| | |
| | | // BOOST_CHECK_EQUAL(license.linked_to_pc, false); |
| | | //} |
| | | // |
| | | // BOOST_AUTO_TEST_CASE( pc_identifier ) { |
| | | // const string licLocation(PROJECT_TEST_TEMP_DIR "/pc_identifier.lic"); |
| | | // BOOST_AUTO_TEST_CASE( hw_identifier ) { |
| | | // const string licLocation(PROJECT_TEST_TEMP_DIR "/hw_identifier.lic"); |
| | | // const vector<string> extraArgs = { "-s", "Jaaa-aaaa-MG9F-ZhB1" }; |
| | | // generate_license(licLocation, extraArgs); |
| | | // |
| | |
| | | add_executable( |
| | | test_license_reader |
| | | add_executable( test_license_reader |
| | | LicenseReader_test.cpp |
| | | ) |
| | | |
| | | target_link_libraries( |
| | | test_license_reader |
| | | target_link_libraries( test_license_reader |
| | | licensecc_static |
| | | Boost::unit_test_framework |
| | | Boost::filesystem |
| | | Boost::system |
| | | ) |
| | | |
| | | ADD_TEST(NAME test_license_reader COMMAND test_license_reader) |
| | | |
| | | IF(WIN32) |
| | | #test windows |
| | | ELSE(WIN32) |
| | | add_executable( |
| | | test_os_linux |
| | | Os_Linux_test.cpp |
| | | os_linux_test.cpp |
| | | ) |
| | | |
| | | target_link_libraries( |
| | |
| | | |
| | | ### LicenseLocator tests |
| | | add_executable( |
| | | test_license_locator |
| | | LicenseLocator_test.cpp |
| | | test_license_locator |
| | | LicenseLocator_test.cpp |
| | | ) |
| | | |
| | | target_link_libraries( |
| | |
| | | Boost::system |
| | | ) |
| | | |
| | | ADD_TEST(NAME test_license_locator COMMAND test_license_locator) |
| | | |
| | | ### LicenseLocator tests |
| | | add_executable( |
| | | test_event_registry |
| | | EventRegistry_test.cpp |
| | | $<TARGET_OBJECTS:base> |
| | | ) |
| | | |
| | | target_link_libraries( |
| | | test_event_registry |
| | | base |
| | | Boost::unit_test_framework |
| | | Boost::filesystem |
| | | Boost::system |
| | | ) |
| | | |
| | | if(CODE_COVERAGE AND UNIX) |
| | | target_link_libraries(test_event_registry gcov) |
| | | endif(CODE_COVERAGE AND UNIX) |
| | | |
| | | ADD_TEST(NAME test_license_reader COMMAND test_license_reader) |
| | | ADD_TEST(NAME test_license_locator COMMAND test_license_locator) |
| | | ADD_TEST(NAME test_event_registry COMMAND test_event_registry) |
| | | |
| | | ADD_SUBDIRECTORY(os) |
| | | ADD_SUBDIRECTORY(hw_identifier) |
| | |
| | | #define BOOST_TEST_MODULE "test_license_locator" |
| | | #define __STDC_WANT_LIB_EXT1__ 1 |
| | | #include <string.h> |
| | | |
| | | #include <iostream> |
| | | #include <iterator> |
| | | #include <cstdio> |
| | | #include <fstream> |
| | | #include <string> |
| | | #include <vector> |
| | | #include <boost/filesystem.hpp> |
| | | #include <boost/optional.hpp> |
| | |
| | | |
| | | BOOST_AUTO_TEST_CASE(external_definition) { |
| | | // an application can define multiple license locations separated by ';' |
| | | const char *applicationDefinedString = MOCK_LICENSE ";/this/one/doesnt/exist"; |
| | | string applicationDefinedString = MOCK_LICENSE ";/this/one/doesnt/exist"; |
| | | |
| | | // read test license |
| | | std::ifstream src(MOCK_LICENSE, std::ios::binary); |
| | | std::string referenceContent((std::istreambuf_iterator<char>(src)), std::istreambuf_iterator<char>()); |
| | | license::EventRegistry registry; |
| | | const LicenseLocation licLocation = {applicationDefinedString, nullptr}; |
| | | LicenseLocation licLocation = {LICENSE_PATH}; |
| | | std::copy(applicationDefinedString.begin(), applicationDefinedString.end(), licLocation.licenseData); |
| | | ExternalDefinition externalDefinition(&licLocation); |
| | | vector<string> licenseInfos = externalDefinition.license_locations(registry); |
| | | BOOST_CHECK(registry.isGood()); |
| | |
| | | * The license file doesn't exist. Check that the locator reports the right error |
| | | */ |
| | | BOOST_AUTO_TEST_CASE(external_definition_not_found) { |
| | | const char *applicationDefinedString = PROJECT_TEST_SRC_DIR "/this/file/doesnt/exist"; |
| | | string applicationDefinedString = PROJECT_TEST_SRC_DIR "/this/file/doesnt/exist"; |
| | | license::EventRegistry registry; |
| | | const LicenseLocation licLocation = {applicationDefinedString, nullptr}; |
| | | LicenseLocation licLocation = {LICENSE_PATH}; |
| | | std::copy(applicationDefinedString.begin(), applicationDefinedString.end(), licLocation.licenseData); |
| | | ExternalDefinition externalDefinition(&licLocation); |
| | | vector<string> licenseInfos = externalDefinition.license_locations(registry); |
| | | |
| | |
| | | // an application can define multiple license locations separated by ';' |
| | | const char *environment_variable_value = MOCK_LICENSE ";/this/one/doesnt/exist"; |
| | | #ifdef _WIN32 |
| | | _putenv_s(LICENSE_LOCATION_ENV_VAR, environment_variable_value); |
| | | _putenv_s(LCC_LICENSE_LOCATION_ENV_VAR, environment_variable_value); |
| | | #else |
| | | setenv(LICENSE_LOCATION_ENV_VAR, environment_variable_value, 1); |
| | | setenv(LCC_LICENSE_LOCATION_ENV_VAR, environment_variable_value, 1); |
| | | #endif |
| | | // read test license |
| | | std::ifstream src(MOCK_LICENSE, std::ios::binary); |
| | |
| | | BOOST_CHECK_MESSAGE(string(MOCK_LICENSE).compare(currentLocation) == 0, "file found at expected location"); |
| | | string licenseRealContent = envVarLocationStrategy.retrieve_license_content(currentLocation); |
| | | BOOST_CHECK_MESSAGE(referenceContent.compare(licenseRealContent) == 0, "File content is same"); |
| | | UNSETENV(LICENSE_LOCATION_ENV_VAR); |
| | | UNSETENV(LCC_LICENSE_LOCATION_ENV_VAR); |
| | | } |
| | | |
| | | /** |
| | |
| | | */ |
| | | BOOST_AUTO_TEST_CASE(environment_var_location_not_found) { |
| | | const char *environment_variable_value = PROJECT_TEST_SRC_DIR "/this/file/doesnt/exist"; |
| | | SETENV(LICENSE_LOCATION_ENV_VAR, environment_variable_value); |
| | | SETENV(LCC_LICENSE_LOCATION_ENV_VAR, environment_variable_value); |
| | | |
| | | license::EventRegistry registry; |
| | | EnvironmentVarLocation envVarLocationStrategy; |
| | |
| | | BOOST_REQUIRE_MESSAGE(!registry.isGood(), "Error detected"); |
| | | BOOST_CHECK_EQUAL(0, licenseInfos.size()); |
| | | BOOST_CHECK_MESSAGE(registry.getLastFailure()->event_type == LICENSE_FILE_NOT_FOUND, "Error detected"); |
| | | UNSETENV(LICENSE_LOCATION_ENV_VAR); |
| | | UNSETENV(LCC_LICENSE_LOCATION_ENV_VAR); |
| | | } |
| | | |
| | | /** |
| | | * The license file doesn't exist. Check that the locator reports the right error |
| | | */ |
| | | BOOST_AUTO_TEST_CASE(environment_var_location_not_defined) { |
| | | UNSETENV(LICENSE_LOCATION_ENV_VAR); |
| | | UNSETENV(LCC_LICENSE_LOCATION_ENV_VAR); |
| | | license::EventRegistry registry; |
| | | EnvironmentVarLocation environmentVarLocation; |
| | | vector<string> licenseInfos = environmentVarLocation.license_locations(registry); |
| | |
| | | #define BOOST_TEST_MODULE "test_license_reader" |
| | | #define __STDC_WANT_LIB_EXT1__ 1 |
| | | |
| | | #include <string> |
| | | |
| | | #include <boost/test/unit_test.hpp> |
| | | #include <iostream> |
| | |
| | | * Read license at application provided location |
| | | */ |
| | | BOOST_AUTO_TEST_CASE(read_single_file) { |
| | | const char *licLocation = PROJECT_TEST_SRC_DIR "/library/test_reader.ini"; |
| | | string location = PROJECT_TEST_SRC_DIR "/library/test_reader.ini"; |
| | | |
| | | const LicenseLocation location = {licLocation, nullptr}; |
| | | LicenseReader licenseReader(&location); |
| | | LicenseLocation licLocation = {LICENSE_PATH}; |
| | | std::copy(location.begin(), location.end(), licLocation.licenseData); |
| | | LicenseReader licenseReader(&licLocation); |
| | | vector<FullLicenseInfo> licenseInfos; |
| | | const EventRegistry registry = licenseReader.readLicenses("PrODUCT", licenseInfos); |
| | | BOOST_CHECK(registry.isGood()); |
| | |
| | | * Test the error return if the product code is not found in the license |
| | | */ |
| | | BOOST_AUTO_TEST_CASE(product_not_licensed) { |
| | | const char *licLocation = PROJECT_TEST_SRC_DIR "/library/test_reader.ini"; |
| | | const LicenseLocation location = {licLocation, nullptr}; |
| | | LicenseReader licenseReader(&location); |
| | | string location = PROJECT_TEST_SRC_DIR "/library/test_reader.ini"; |
| | | LicenseLocation licLocation = {LICENSE_PATH}; |
| | | std::copy(location.begin(), location.end(), licLocation.licenseData); |
| | | LicenseReader licenseReader(&licLocation); |
| | | vector<FullLicenseInfo> licenseInfos; |
| | | const EventRegistry registry = licenseReader.readLicenses("PRODUCT-NOT", licenseInfos); |
| | | BOOST_CHECK(!registry.isGood()); |
| | |
| | | * Test the error code if the license file is specified but doesn't exists |
| | | */ |
| | | BOOST_AUTO_TEST_CASE(file_not_found) { |
| | | const char *licLocation = PROJECT_TEST_SRC_DIR "/library/not_found.ini"; |
| | | string licLocation = PROJECT_TEST_SRC_DIR "/library/not_found.ini"; |
| | | |
| | | locate::LocatorFactory::find_license_near_module(false); |
| | | locate::LocatorFactory::find_license_with_env_var(false); |
| | | const LicenseLocation location = {licLocation, nullptr}; |
| | | LicenseLocation location = {LICENSE_PATH}; |
| | | std::copy(licLocation.begin(), licLocation.end(), location.licenseData); |
| | | LicenseReader licenseReader(&location); |
| | | vector<FullLicenseInfo> licenseInfos; |
| | | const EventRegistry registry = licenseReader.readLicenses("PRODUCT", licenseInfos); |
| | |
| | | * Test the error code if the license default environment variable isn't specified |
| | | */ |
| | | BOOST_AUTO_TEST_CASE(env_var_not_defined) { |
| | | UNSETENV(LICENSE_LOCATION_ENV_VAR); |
| | | const LicenseLocation location = {nullptr, nullptr}; |
| | | UNSETENV(LCC_LICENSE_LOCATION_ENV_VAR); |
| | | locate::LocatorFactory::find_license_near_module(false); |
| | | locate::LocatorFactory::find_license_with_env_var(true); |
| | | LicenseReader licenseReader(&location); |
| | | LicenseReader licenseReader(nullptr); |
| | | vector<FullLicenseInfo> licenseInfos; |
| | | const EventRegistry registry = licenseReader.readLicenses("PRODUCT", licenseInfos); |
| | | BOOST_CHECK(!registry.isGood()); |
| | |
| | | */ |
| | | BOOST_AUTO_TEST_CASE(env_var_point_to_wrong_file) { |
| | | const char *environment_variable_value = PROJECT_TEST_SRC_DIR "/this/file/doesnt/exist"; |
| | | SETENV(LICENSE_LOCATION_ENV_VAR, environment_variable_value) |
| | | SETENV(LCC_LICENSE_LOCATION_ENV_VAR, environment_variable_value) |
| | | locate::LocatorFactory::find_license_near_module(false); |
| | | locate::LocatorFactory::find_license_with_env_var(true); |
| | | |
| | | const LicenseLocation location = {nullptr, nullptr}; |
| | | LicenseReader licenseReader(&location); |
| | | LicenseReader licenseReader(nullptr); |
| | | vector<FullLicenseInfo> licenseInfos; |
| | | const EventRegistry registry = licenseReader.readLicenses("PRODUCT", licenseInfos); |
| | | cout << registry << endl; |
| | |
| | | BOOST_CHECK_EQUAL(0, licenseInfos.size()); |
| | | BOOST_ASSERT(registry.getLastFailure() != NULL); |
| | | BOOST_CHECK_EQUAL(LICENSE_FILE_NOT_FOUND, registry.getLastFailure()->event_type); |
| | | UNSETENV(LICENSE_LOCATION_ENV_VAR); |
| | | UNSETENV(LCC_LICENSE_LOCATION_ENV_VAR); |
| | | } |
| | | } // namespace test |
| | | } // namespace license |
New file |
| | |
| | | add_executable( test_hw_identifier |
| | | hw_identifier_test.cpp |
| | | ) |
| | | |
| | | target_link_libraries( test_hw_identifier |
| | | licensecc_static |
| | | Boost::unit_test_framework |
| | | Boost::filesystem |
| | | Boost::system |
| | | ) |
| | | |
| | | if(CODE_COVERAGE AND UNIX) |
| | | target_compile_options(test_hw_identifier PUBLIC -O0 -g --coverage) |
| | | endif(CODE_COVERAGE AND UNIX) |
| | | |
| | | ADD_TEST(NAME test_hw_identifier COMMAND test_hw_identifier) |
New file |
| | |
| | | /* |
| | | * default_strategy_test.cpp |
| | | * |
| | | * Created on: Jan 2, 2020 |
| | | * Author: devel |
| | | */ |
| | | |
| | | #include "default_strategy.hpp" |
| | | |
| | | namespace license {} /* namespace license */ |
New file |
| | |
| | | /* |
| | | * ethernet_test.cpp |
| | | * |
| | | * Created on: Jan 11, 2020 |
| | | * Author: devel |
| | | */ |
| | | |
| | | #include "ethernet.hpp" |
| | | |
| | | namespace license {} /* namespace license */ |
New file |
| | |
| | | /* |
| | | * hw_identifier_facade_test.cpp |
| | | * |
| | | * Created on: Dec 26, 2019 |
| | | * Author: devel |
| | | */ |
| | | |
| | | #include "../../../src/library/hw_identifier/hw_identifier_facade.hpp" |
| | | |
| | | namespace license { |
| | | /* |
| | | * Test identifier stability: |
| | | * 1) generate the pc-identifier |
| | | * 2) save it to disk |
| | | * 3) every time check that the identifier can still be verified. |
| | | */ |
| | | static void generate_reference_file(const string &idfileLocation, LCC_API_IDENTIFICATION_STRATEGY strategies[], |
| | | int num_strategies) { |
| | | ofstream idfile(idfileLocation); |
| | | PcSignature identifier_out; |
| | | for (int i = 0; i < num_strategies; i++) { |
| | | FUNCTION_RETURN generate_ok = generate_user_pc_signature(identifier_out, strategies[i]); |
| | | if (generate_ok != FUNC_RET_OK) { |
| | | BOOST_ERROR("Generating identifier for strategy " << strategies[i] << " failed with: " << generate_ok); |
| | | idfile << "0000-0000-0000-0000" << endl; |
| | | BOOST_ASSERT(generate_ok == FUNC_RET_OK); |
| | | } else |
| | | idfile << identifier_out << endl; |
| | | } |
| | | idfile.close(); |
| | | } |
| | | |
| | | BOOST_AUTO_TEST_CASE(generated_identifiers_stability) { |
| | | const string idfileLocation(PROJECT_TEST_TEMP_DIR "/identifiers_file"); |
| | | std::vector<LCC_API_IDENTIFICATION_STRATEGY> strategies; |
| | | size_t disk_num; |
| | | getDiskInfos(NULL, &disk_num); |
| | | if (disk_num > 0) { |
| | | strategies = {STRATEGY_DEFAULT, STRATEGY_DISK_NUM, STRATEGY_DISK_LABEL}; |
| | | } else { |
| | | BOOST_TEST_CHECKPOINT("if no disk default strategy fails see #49"); |
| | | // strategies = { DEFAULT }; |
| | | strategies = {}; |
| | | } |
| | | size_t adapters; |
| | | getAdapterInfos(nullptr, &adapters); |
| | | if (adapters > 0) { |
| | | strategies.push_back(STRATEGY_ETHERNET); |
| | | } |
| | | |
| | | size_t num_strategies = strategies.size(); |
| | | if (num_strategies == 0) { |
| | | // see issue #49 can't use default |
| | | return; |
| | | } |
| | | std::ifstream test_idfile_exist(idfileLocation); |
| | | if (!test_idfile_exist.good()) { |
| | | generate_reference_file(idfileLocation, strategies.data(), strategies.size()); |
| | | } else { |
| | | std::istream_iterator<string> start(test_idfile_exist), end; |
| | | std::vector<string> reference_signatures(start, end); |
| | | test_idfile_exist.close(); |
| | | if (reference_signatures.size() != num_strategies || |
| | | std::find(reference_signatures.begin(), reference_signatures.end(), "0000-0000-0000-0000") != |
| | | reference_signatures.end()) |
| | | generate_reference_file(idfileLocation, strategies.data(), num_strategies); |
| | | } |
| | | std::ifstream is(idfileLocation); |
| | | std::istream_iterator<string> start(is), end; |
| | | std::vector<string> reference_signatures(start, end); |
| | | BOOST_TEST_CHECKPOINT("Generating current signatures and comparing with past"); |
| | | for (int i = 0; i < num_strategies; i++) { |
| | | PcSignature generated_identifier; |
| | | FUNCTION_RETURN generate_ok = generate_user_pc_signature(generated_identifier, strategies[i]); |
| | | BOOST_ASSERT(generate_ok == FUNCTION_RETURN::FUNC_RET_OK); |
| | | if (generate_ok != FUNC_RET_OK) { |
| | | BOOST_ERROR("Generating identifier for strategy " << strategies[i] << " failed with: " << generate_ok); |
| | | continue; |
| | | } |
| | | if (reference_signatures[i] != generated_identifier) { |
| | | string message = string("pc signature compare fail: strategy: ") + |
| | | to_string(static_cast<long long>(strategies[i])) + " generated: [" + generated_identifier + |
| | | "] reference: [" + reference_signatures[i] + "]"; |
| | | BOOST_ERROR(message); |
| | | } |
| | | } |
| | | BOOST_TEST_CHECKPOINT("Verifying signatures"); |
| | | for (int j = 0; j < 100; j++) { |
| | | for (unsigned int i = 0; i < reference_signatures.size(); i++) { |
| | | if (reference_signatures[i] == "0000-0000-0000-0000") continue; |
| | | PcSignature pcsig; |
| | | strncpy(pcsig, reference_signatures[i].c_str(), sizeof(PcSignature) - 1); |
| | | LCC_EVENT_TYPE val_result = validate_pc_signature(pcsig); |
| | | BOOST_TEST_CHECKPOINT("Verifying signature: "); |
| | | BOOST_CHECK_EQUAL(val_result, LICENSE_OK); |
| | | } |
| | | } |
| | | } |
| | | |
| | | } /* namespace license */ |
New file |
| | |
| | | /* |
| | | * Test on class HwIdentifier |
| | | * |
| | | * Created on: Dec 26, 2019 |
| | | * Author: devel |
| | | */ |
| | | |
| | | #define BOOST_TEST_MODULE test_hw_identifier |
| | | |
| | | #include <boost/test/unit_test.hpp> |
| | | #include <fstream> |
| | | #include <iostream> |
| | | #include <stdio.h> |
| | | #include <cstring> |
| | | #include <boost/filesystem.hpp> |
| | | #include <licensecc_properties.h> |
| | | #include <licensecc_properties_test.h> |
| | | |
| | | #include <licensecc/licensecc.h> |
| | | #include "../../../src/library/hw_identifier/hw_identifier.hpp" |
| | | |
| | | namespace license { |
| | | namespace test { |
| | | using namespace std; |
| | | using namespace license::hw_identifier; |
| | | |
| | | /** |
| | | * Test get and set and compare hardware identifier data |
| | | */ |
| | | BOOST_AUTO_TEST_CASE(set_and_compare_data) { |
| | | array<uint8_t, HW_IDENTIFIER_PROPRIETARY_DATA> data = {0xFF, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42}; |
| | | HwIdentifier pc_id; |
| | | pc_id.set_data(data); |
| | | data[0] = data[0] & 0x1f; |
| | | BOOST_CHECK_MESSAGE(pc_id.data_match(data), "Data match"); |
| | | } |
| | | /** |
| | | * Test get and set and compare hardware identifier data |
| | | */ |
| | | BOOST_AUTO_TEST_CASE(compare_wrong_data) { |
| | | array<uint8_t, HW_IDENTIFIER_PROPRIETARY_DATA> data = {0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42}; |
| | | HwIdentifier pc_id; |
| | | pc_id.set_data(data); |
| | | data[4] = 0; |
| | | BOOST_CHECK_MESSAGE(!pc_id.data_match(data), "Data shouldn't match"); |
| | | } |
| | | |
| | | /** |
| | | * Print a hardware identifier and read it from the same string, check the data matches |
| | | */ |
| | | BOOST_AUTO_TEST_CASE(print_and_read) { |
| | | array<uint8_t, HW_IDENTIFIER_PROPRIETARY_DATA> data = {0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42}; |
| | | HwIdentifier pc_id; |
| | | pc_id.set_data(data); |
| | | pc_id.set_identification_strategy(LCC_API_IDENTIFICATION_STRATEGY::STRATEGY_ETHERNET); |
| | | string pc_id_str = pc_id.print(); |
| | | cout << pc_id_str << endl; |
| | | const HwIdentifier id2(pc_id_str); |
| | | BOOST_CHECK_MESSAGE(id2.get_identification_strategy() == LCC_API_IDENTIFICATION_STRATEGY::STRATEGY_ETHERNET, |
| | | "Strategy decoded correctly"); |
| | | BOOST_CHECK_MESSAGE(id2.data_match(data), "Data deserialized correctly"); |
| | | } |
| | | |
| | | } // namespace test |
| | | } // namespace license |
New file |
| | |
| | | add_executable( test_network |
| | | network_test.cpp |
| | | ) |
| | | |
| | | target_link_libraries( test_network |
| | | licensecc_static |
| | | Boost::unit_test_framework |
| | | Boost::filesystem |
| | | Boost::system |
| | | ) |
| | | |
| | | ADD_TEST(NAME test_network COMMAND test_network) |
| | | |
| | | add_executable( test_execution_environment |
| | | execution_environment_test.cpp |
| | | ) |
| | | |
| | | target_link_libraries( test_execution_environment |
| | | licensecc_static |
| | | Boost::unit_test_framework |
| | | Boost::filesystem |
| | | Boost::system |
| | | ) |
| | | |
| | | ADD_TEST(NAME test_execution_environment COMMAND test_execution_environment) |
| | | if(CODE_COVERAGE AND UNIX) |
| | | target_compile_options(test_network PUBLIC -O0 -g --coverage) |
| | | target_compile_options(test_execution_environment PUBLIC -O0 -g --coverage) |
| | | endif(CODE_COVERAGE AND UNIX) |
New file |
| | |
| | | /* |
| | | * cpu_info_test.cpp |
| | | * |
| | | * Created on: Dec 19, 2019 |
| | | * Author: devel |
| | | */ |
| | | |
| | | #include "cpu_info.hpp" |
| | | |
| | | namespace license {} /* namespace license */ |
New file |
| | |
| | | #define BOOST_TEST_MODULE network_test |
| | | #include <string> |
| | | #include <iostream> |
| | | #include <boost/test/unit_test.hpp> |
| | | |
| | | #include <licensecc_properties.h> |
| | | #include <licensecc_properties_test.h> |
| | | #include "../../../src/library/base/StringUtils.h" |
| | | #include "../../../src/library/os/network.hpp" |
| | | #include "../../../src/library/os/execution_environment.hpp" |
| | | |
| | | namespace license { |
| | | namespace os { |
| | | namespace test { |
| | | |
| | | using namespace license::os; |
| | | using namespace std; |
| | | |
| | | // To test if virtualization is detected correctly define an env variable VIRT_ENV |
| | | // otherwise the test is skipped |
| | | BOOST_AUTO_TEST_CASE(test_virtualization) { |
| | | const char *env = getenv("VIRTUAL_ENV"); |
| | | os::ExecutionEnvironment exec_env; |
| | | bool docker = false; |
| | | if (env != nullptr) { |
| | | os::VIRTUALIZATION virt = exec_env.getVirtualization(); |
| | | if (strcmp(env, "CONTAINER") == 0 || (docker = (strcmp(env, "DOCKER") == 0))) { |
| | | BOOST_CHECK_MESSAGE(virt == VIRTUALIZATION::CONTAINER, "container detected"); |
| | | BOOST_CHECK_MESSAGE(exec_env.is_container(), "container detected"); |
| | | if (docker) { |
| | | BOOST_CHECK_MESSAGE(exec_env.is_docker(), "docker detected"); |
| | | } |
| | | } else if (strcmp(env, "VM") == 0) { |
| | | BOOST_CHECK_MESSAGE(virt == VIRTUALIZATION::VM, "VM detected"); |
| | | BOOST_CHECK_MESSAGE(!exec_env.is_container(), "VM is not a container"); |
| | | BOOST_CHECK_MESSAGE(!exec_env.is_docker(), "VM is not a docker"); |
| | | } else if (strcmp(env, "NONE") == 0) { |
| | | BOOST_CHECK_EQUAL(virt, VIRTUALIZATION::NONE); |
| | | BOOST_CHECK_MESSAGE(!exec_env.is_container(), "not a container"); |
| | | BOOST_CHECK_MESSAGE(!exec_env.is_docker(), "not a docker"); |
| | | } else { |
| | | BOOST_FAIL(string("value ") + env + " not supported: VM,DOCKER,CONTAINER,NONE"); |
| | | } |
| | | } |
| | | } |
| | | } // namespace test |
| | | } // namespace os |
| | | } // namespace license |
New file |
| | |
| | | #define BOOST_TEST_MODULE network_test |
| | | #include <string> |
| | | #include <iostream> |
| | | #include <boost/test/unit_test.hpp> |
| | | |
| | | #include <licensecc_properties.h> |
| | | #include <licensecc_properties_test.h> |
| | | #include "../../../src/library/base/StringUtils.h" |
| | | #include "../../../src/library/os/network.hpp" |
| | | #include "../../../src/library/os/execution_environment.hpp" |
| | | |
| | | namespace license { |
| | | namespace os { |
| | | namespace test { |
| | | |
| | | using namespace license::os; |
| | | using namespace std; |
| | | |
| | | BOOST_AUTO_TEST_CASE(read_network_adapters) { |
| | | std::vector<license::os::OsAdapterInfo> adapters; |
| | | // we can suppose every test environment other than docker has at least one network interface (it's hard to |
| | | // download this source code) |
| | | FUNCTION_RETURN result = getAdapterInfos(adapters); |
| | | ExecutionEnvironment exec_env; |
| | | if (result != FUNC_RET_OK && exec_env.is_docker()) { |
| | | BOOST_TEST_MESSAGE("detected docker environment, not having network interfaces is normal here"); |
| | | return; |
| | | } |
| | | BOOST_CHECK_EQUAL(result, FUNC_RET_OK); |
| | | for (auto& it : adapters) { |
| | | cout << "Interface found: " << string(it.description) << endl; |
| | | BOOST_CHECK_GT(strlen(it.description), 0); |
| | | // lo mac address is always 0 but it has ip |
| | | // other interfaces may not be connected |
| | | if (string(it.description) == "lo") { |
| | | BOOST_FAIL("loopback adapters shouldn't appear"); |
| | | } else { |
| | | // check mac address are not all zero |
| | | bool mac_is_0 = true; |
| | | for (int j = 0; j < 6; j++) { |
| | | mac_is_0 = mac_is_0 || (it.mac_address[j] != 0); |
| | | } |
| | | BOOST_CHECK_MESSAGE(mac_is_0, "Mac address for interface " << it.description << " is 0"); |
| | | } |
| | | } |
| | | } |
| | | |
| | | } // namespace test |
| | | } // namespace os |
| | | } // namespace license |
New file |
| | |
| | | #define BOOST_TEST_MODULE os_linux_test |
| | | #include <string> |
| | | #include <iostream> |
| | | #include <boost/test/unit_test.hpp> |
| | | |
| | | #include <licensecc_properties.h> |
| | | #include <licensecc_properties_test.h> |
| | | #include "../../src/library/base/StringUtils.h" |
| | | #include "../../src/library/os/os.h" |
| | | #include "../../src/library/os/execution_environment.hpp" |
| | | |
| | | namespace license { |
| | | namespace test { |
| | | using namespace std; |
| | | using namespace os; |
| | | |
| | | BOOST_AUTO_TEST_CASE(read_disk_id) { |
| | | os::ExecutionEnvironment exec_env; |
| | | os::VIRTUALIZATION virt = exec_env.getVirtualization(); |
| | | if (virt == VIRTUALIZATION::NONE || virt == VIRTUALIZATION::VM) { |
| | | DiskInfo *diskInfos = NULL; |
| | | size_t disk_info_size = 0; |
| | | FUNCTION_RETURN result = getDiskInfos(NULL, &disk_info_size); |
| | | BOOST_CHECK_EQUAL(result, FUNC_RET_OK); |
| | | BOOST_CHECK_GT(disk_info_size, 0); |
| | | diskInfos = (DiskInfo *)malloc(sizeof(DiskInfo) * disk_info_size); |
| | | result = getDiskInfos(diskInfos, &disk_info_size); |
| | | BOOST_CHECK_EQUAL(result, FUNC_RET_OK); |
| | | BOOST_CHECK_GT(mstrnlen_s(diskInfos[0].device, sizeof(diskInfos[0].device)), 0); |
| | | BOOST_CHECK_GT(mstrnlen_s(diskInfos[0].label, sizeof diskInfos[0].label), 0); |
| | | BOOST_CHECK_GT(diskInfos[0].disk_sn[0], 0); |
| | | free(diskInfos); |
| | | } else if (virt == VIRTUALIZATION::CONTAINER) { |
| | | // docker or lxc diskInfo is not meaningful |
| | | DiskInfo *diskInfos = NULL; |
| | | size_t disk_info_size = 0; |
| | | FUNCTION_RETURN result = getDiskInfos(NULL, &disk_info_size); |
| | | BOOST_CHECK_EQUAL(result, FUNC_RET_NOT_AVAIL); |
| | | } |
| | | } |
| | | |
| | | } // namespace test |
| | | } // namespace license |