diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml index 4ba4323..c031f70 100644 --- a/.github/workflows/cmake-multi-platform.yml +++ b/.github/workflows/cmake-multi-platform.yml @@ -54,30 +54,13 @@ jobs: - name: Set Env shell: bash run: | - echo "VCPKG_ROOT=${VCPKG_INSTALLATION_ROOT}" >> "$GITHUB_ENV" echo "BUILD_OUTPUT_DIR=${{ github.workspace }}/build" >> "$GITHUB_ENV" - - name: Fetch VCPKG Cache (Windows) - id: fetch-vcpkg-cache + - name: VCPKG Install (Windows) if: runner.os == 'Windows' - uses: actions/cache/restore@v4 + uses: ./.github/workflows/windows-vcpkg with: - key: ${{ runner.os }}-${{ matrix.build_type }}-${{ hashFiles('vcpkg.json') }} - path: ${{ env.VCPKG_ROOT }} - - - name: Install OpenSSL (Windows) - if: runner.os == 'Windows' - shell: powershell - run: | - echo "CMAKE_TOOLCHAIN_FILE=${env:VCPKG_ROOT}\scripts\buildsystems\vcpkg.cmake" | Out-File -FilePath $env:GITHUB_ENV -Append - vcpkg install - - - name: Always Save VCPKG Cache (Windows) - if: always() && runner.os == 'Windows' && steps.fetch-vcpkg-cache.outputs.cache-hit != 'true' - uses: actions/cache/save@v4 - with: - key: ${{ steps.fetch-vcpkg-cache.outputs.cache-primary-key }} - path: ${{ env.VCPKG_ROOT }} + key: ${{ runner.os }}-${{ matrix.build_type }} - name: Configure CMake # Configure CMake in a 'build' subdirectory. diff --git a/.github/workflows/code_scanning.yml b/.github/workflows/code_scanning.yml index 7c3199a..38971df 100644 --- a/.github/workflows/code_scanning.yml +++ b/.github/workflows/code_scanning.yml @@ -30,7 +30,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@v2 + uses: github/codeql-action/init@v3 with: languages: 'c-cpp' # If you wish to specify custom queries, you can do so here or in a config file. @@ -44,20 +44,10 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, Go, Java, or Swift). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@v2 - - # â„šī¸ Command-line programs to run using the OS shell. - # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun - - # If the Autobuild fails above, remove it and uncomment the following three lines. - # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance. - - # - run: | - # echo "Run, Build Application using script" - # ./location_of_script_within_repo/buildscript.sh + uses: github/codeql-action/autobuild@v3 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v2 + uses: github/codeql-action/analyze@v3 with: category: "/language:c-cpp" @@ -73,53 +63,66 @@ jobs: uses: actions/checkout@v3 - name: flawfinder_scan - uses: david-a-wheeler/flawfinder@8e4a779ad59dbfaee5da586aa9210853b701959c + uses: david-a-wheeler/flawfinder@2.0.19 with: arguments: '--sarif ./' output: 'flawfinder_results.sarif' - name: Upload analysis results to GitHub Security tab - uses: github/codeql-action/upload-sarif@v2 + uses: github/codeql-action/upload-sarif@v3 with: sarif_file: ${{github.workspace}}/flawfinder_results.sarif - # microsoft-analyze: - # permissions: - # contents: read # for actions/checkout to fetch code - # security-events: write # for github/codeql-action/upload-sarif to upload SARIF results - # actions: read # only required for a private repository by github/codeql-action/upload-sarif to get the Action run status - # name: Microsoft Analyze - # runs-on: windows-latest - - # steps: - # - name: Checkout repository - # uses: actions/checkout@v3 - - # - name: Configure CMake - # run: cmake -B ./build - - # # Build is not required unless generated source files are used - # # - name: Build CMake - # # run: cmake --build ./build - - # - name: Initialize MSVC Code Analysis - # uses: microsoft/msvc-code-analysis-action@04825f6d9e00f87422d6bf04e1a38b1f3ed60d99 - # # Provide a unique ID to access the sarif output path - # id: run-analysis - # with: - # cmakeBuildDirectory: ${{ env.build }} - # # Ruleset file that will determine what checks will be run - # ruleset: NativeRecommendedRules.ruleset - - # # Upload SARIF file to GitHub Code Scanning Alerts - # - name: Upload SARIF to GitHub - # uses: github/codeql-action/upload-sarif@v2 - # with: - # sarif_file: ${{ steps.run-analysis.outputs.sarif }} - - # # Upload SARIF file as an Artifact to download and view - # # - name: Upload SARIF as an Artifact - # # uses: actions/upload-artifact@v3 - # # with: - # # name: sarif-file - # # path: ${{ steps.run-analysis.outputs.sarif }} + microsoft-analyze: + permissions: + actions: read # only required for a private repository by github/codeql-action/upload-sarif to get the Action run status + contents: read # for actions/checkout to fetch code + security-events: write # for github/codeql-action/upload-sarif to upload SARIF results + name: Microsoft Analyze + runs-on: windows-latest + + env: + # Path to the CMake build directory. + build: '${{ github.workspace }}/build' + config: 'Debug' + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + - name: VCPKG Install (Windows) + uses: ./.github/workflows/windows-vcpkg + with: + key: ${{ runner.os }}-${{ env.config }} + + - name: Configure CMake + run: cmake -B ${{ env.build }} -DCMAKE_BUILD_TYPE=${{ env.config }} + + # Build is not required unless generated source files are used + # - name: Build CMake + # run: cmake --build ${{ env.build }} --config ${{ env.config }} + + - name: Run MSVC Code Analysis + uses: microsoft/msvc-code-analysis-action@v0.1.1 + # Provide a unique ID to access the sarif output path + id: run-analysis + with: + cmakeBuildDirectory: ${{ env.build }} + buildConfiguration: ${{ env.config }} + # Ruleset file that will determine what checks will be run + ruleset: NativeRecommendedRules.ruleset + # Paths to ignore analysis of CMake targets and includes + # ignoredPaths: ${{ github.workspace }}/dependencies;${{ github.workspace }}/test + + # Upload SARIF file to GitHub Code Scanning Alerts + - name: Upload SARIF to GitHub + uses: github/codeql-action/upload-sarif@v3 + with: + sarif_file: ${{ steps.run-analysis.outputs.sarif }} + + # # Upload SARIF file as an Artifact to download and view + # - name: Upload SARIF as an Artifact + # uses: actions/upload-artifact@v4 + # with: + # name: sarif-file + # path: ${{ steps.run-analysis.outputs.sarif }} diff --git a/.github/workflows/download-cache.yml b/.github/workflows/download-cache.yml new file mode 100644 index 0000000..ad436ac --- /dev/null +++ b/.github/workflows/download-cache.yml @@ -0,0 +1,22 @@ +on: + workflow_dispatch: + inputs: + cache-key: + description: 'The key of the cache to retrieve' + required: true + +jobs: + download_and_upload_cache: + runs-on: ubuntu-latest + steps: + - name: Restore cache + uses: actions/cache@v4 + with: + path: ./cache + key: ${{ inputs.cache-key }} + + - name: Upload cached data as artifact + uses: actions/upload-artifact@v3 + with: + name: cached-data-artifact + path: ./cache diff --git a/.github/workflows/windows-vcpkg/action.yml b/.github/workflows/windows-vcpkg/action.yml new file mode 100644 index 0000000..a613609 --- /dev/null +++ b/.github/workflows/windows-vcpkg/action.yml @@ -0,0 +1,37 @@ +name: Windows VCPKG + +inputs: + key: + required: true + type: string + +runs: + using: "composite" + steps: + - name: Set Env + shell: powershell + run: | + echo "VCPKG_ROOT=${env:VCPKG_INSTALLATION_ROOT}" | Out-File -FilePath $env:GITHUB_ENV -Append + echo "VCPKG_CACHE=${env:LOCALAPPDATA}\vcpkg\archives" | Out-File -FilePath $env:GITHUB_ENV -Append + + - name: Fetch VCPKG Cache (Windows) + id: fetch-vcpkg-cache + if: runner.os == 'Windows' + uses: actions/cache/restore@v4 + with: + key: ${{ inputs.key }}-vcpkg-${{ hashFiles('vcpkg.json') }} + path: ${{ env.VCPKG_CACHE }} + + - name: VCPKG Install (Windows) + if: runner.os == 'Windows' + shell: powershell + run: | + echo "CMAKE_TOOLCHAIN_FILE=${env:VCPKG_ROOT}\scripts\buildsystems\vcpkg.cmake" | Out-File -FilePath $env:GITHUB_ENV -Append + vcpkg install --debug + + - name: Always Save VCPKG Cache (Windows) + if: always() && runner.os == 'Windows' && steps.fetch-vcpkg-cache.outputs.cache-hit != 'true' + uses: actions/cache/save@v4 + with: + key: ${{ steps.fetch-vcpkg-cache.outputs.cache-primary-key }} + path: ${{ env.VCPKG_CACHE }} diff --git a/CMakeLists.txt b/CMakeLists.txt index 33895f2..5f11c91 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,13 +4,13 @@ ## Author Francois Michaut ## ## Started on Sun Aug 28 19:26:51 2022 Francois Michaut -## Last update Mon Aug 4 23:34:08 2025 Francois Michaut +## Last update Tue Aug 5 19:07:23 2025 Francois Michaut ## ## CMakeLists.txt : CMake to build the CppSockets library ## cmake_minimum_required (VERSION 3.15) -set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED True) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) diff --git a/include/CppSockets/Certificate.hpp b/include/CppSockets/Certificate.hpp index b39939f..1539ce7 100644 --- a/include/CppSockets/Certificate.hpp +++ b/include/CppSockets/Certificate.hpp @@ -4,7 +4,7 @@ ** Author Francois Michaut ** ** Started on Fri Aug 1 09:50:33 2025 Francois Michaut -** Last update Mon Aug 4 23:45:31 2025 Francois Michaut +** Last update Tue Aug 5 19:08:13 2025 Francois Michaut ** ** Certificate.hpp : Classes to create and manage Certificates */ @@ -18,12 +18,6 @@ #include #include -#if __cplusplus < 202002L -namespace std { - using u8string = basic_string; // NOLINT(cert-dcl58-cpp) -} -#endif - namespace CppSockets { class x509NameEntry; @@ -164,8 +158,8 @@ namespace CppSockets { // TODO: Get methods // TODO: Provide overloads for hardcoded time - void set_not_before(int offset_day, std::int64_t offset_sec, time_t *in_tm); - void set_not_after(int offset_day, std::int64_t offset_sec, time_t *in_tm); + void set_not_before(int offset_day, std::int64_t offset_sec, time_t *in_tm = nullptr); + void set_not_after(int offset_day, std::int64_t offset_sec, time_t *in_tm = nullptr); void set_version(std::int64_t version); [[nodiscard]] diff --git a/source/Certificate.cpp b/source/Certificate.cpp index b5de03e..107142b 100644 --- a/source/Certificate.cpp +++ b/source/Certificate.cpp @@ -4,7 +4,7 @@ ** Author Francois Michaut ** ** Started on Sat Aug 2 22:41:35 2025 Francois Michaut -** Last update Tue Aug 5 13:08:40 2025 Francois Michaut +** Last update Tue Aug 5 19:12:12 2025 Francois Michaut ** ** Certificate.cpp : Implementation of classes to create and manage Certificates */ @@ -72,19 +72,19 @@ namespace CppSockets { } void x509Name::add_entry(const std::string &field_name, int type, const std::u8string &data, int loc, int set) { - auto ret = X509_NAME_add_entry_by_txt(m_ptr.get(), field_name.c_str(), type, data.c_str(), numeric_cast(data.size()), loc, set); + auto ret = X509_NAME_add_entry_by_txt(m_ptr.get(), field_name.c_str(), type, reinterpret_cast(data.c_str()), numeric_cast(data.size()), loc, set); check_or_throw_openssl_error(ret); } void x509Name::add_entry(const ASN1_OBJECT *obj, int type, const std::u8string &data, int loc, int set) { - auto ret = X509_NAME_add_entry_by_OBJ(m_ptr.get(), obj, type, data.c_str(), numeric_cast(data.size()), loc, set); + auto ret = X509_NAME_add_entry_by_OBJ(m_ptr.get(), obj, type, reinterpret_cast(data.c_str()), numeric_cast(data.size()), loc, set); check_or_throw_openssl_error(ret); } void x509Name::add_entry(int nid, int type, const std::u8string &data, int loc, int set) { - auto ret = X509_NAME_add_entry_by_NID(m_ptr.get(), nid, type, data.c_str(), numeric_cast(data.size()), loc, set); + auto ret = X509_NAME_add_entry_by_NID(m_ptr.get(), nid, type, reinterpret_cast(data.c_str()), numeric_cast(data.size()), loc, set); check_or_throw_openssl_error(ret); } @@ -129,19 +129,19 @@ namespace CppSockets { } x509NameEntry::x509NameEntry(const std::string &name, int type, const std::u8string &data) : - m_ptr(X509_NAME_ENTRY_create_by_txt(nullptr, name.c_str(), type, data.c_str(), numeric_cast(data.size()))) + m_ptr(X509_NAME_ENTRY_create_by_txt(nullptr, name.c_str(), type, reinterpret_cast(data.c_str()), numeric_cast(data.size()))) { REQUIRED_PTR(m_ptr, "X509_NAME_ENTRY") } x509NameEntry::x509NameEntry(const ASN1_OBJECT *obj, int type, const std::u8string &data) : - m_ptr(X509_NAME_ENTRY_create_by_OBJ(nullptr, obj, type, data.c_str(), numeric_cast(data.size()))) + m_ptr(X509_NAME_ENTRY_create_by_OBJ(nullptr, obj, type, reinterpret_cast(data.c_str()), numeric_cast(data.size()))) { REQUIRED_PTR(m_ptr, "X509_NAME_ENTRY") } x509NameEntry::x509NameEntry(int nid, int type, const std::u8string &data) : - m_ptr(X509_NAME_ENTRY_create_by_NID(nullptr, nid, type, data.c_str(), numeric_cast(data.size()))) + m_ptr(X509_NAME_ENTRY_create_by_NID(nullptr, nid, type, reinterpret_cast(data.c_str()), numeric_cast(data.size()))) { REQUIRED_PTR(m_ptr, "X509_NAME_ENTRY") } @@ -157,7 +157,7 @@ namespace CppSockets { } void x509NameEntry::set_data(int type, const std::u8string &data) { - auto ret = X509_NAME_ENTRY_set_data(m_ptr.get(), type, data.c_str(), numeric_cast(data.size())); + auto ret = X509_NAME_ENTRY_set_data(m_ptr.get(), type, reinterpret_cast(data.c_str()), numeric_cast(data.size())); check_or_throw_openssl_error(ret); } diff --git a/source/Socket.cpp b/source/Socket.cpp index 41a6a90..49aee5e 100644 --- a/source/Socket.cpp +++ b/source/Socket.cpp @@ -4,7 +4,7 @@ ** Author Francois Michaut ** ** Started on Sat Jan 15 01:27:40 2022 Francois Michaut -** Last update Tue Aug 5 00:04:25 2025 Francois Michaut +** Last update Tue Aug 5 14:46:12 2025 Francois Michaut ** ** Socket.cpp : Protable C++ socket class implementation */ @@ -46,7 +46,7 @@ namespace CppSockets { { socklen_t len = sizeof(int); - Socket::getsockopt(sockfd, SOL_SOCKET, SO_TYPE, (SockOptType *)&m_type, &len); + Socket::getsockopt(sockfd, SOL_SOCKET, SO_TYPE, reinterpret_cast(&m_type), &len); #ifdef OS_LINUX Socket::getsockopt(sockfd, SOL_SOCKET, SO_DOMAIN, &m_domain, &len); Socket::getsockopt(sockfd, SOL_SOCKET, SO_PROTOCOL, &m_protocol, &len); @@ -128,7 +128,7 @@ namespace CppSockets { std::size_t nb = 1; while (nb != 0 && (len == -1 || total < len)) { - nb = this->read(buff.data(), BUFF_SIZE); + nb = this->read(buff.data(), buff.size()); if (nb > 0) { res << std::string(buff.data(), nb); } @@ -168,7 +168,7 @@ namespace CppSockets { auto Socket::set_reuseaddr(bool value) -> int { int val = static_cast(value); - return this->setsockopt(SOL_SOCKET, SO_REUSEADDR, (SockOptType *)&val, sizeof(val)); + return this->setsockopt(SOL_SOCKET, SO_REUSEADDR, reinterpret_cast(&val), sizeof(val)); } auto Socket::getsockopt(int level, int optname, SockOptType *optval, socklen_t *optlen) -> int { // NOLINT(readability-make-member-function-const) diff --git a/source/TlsSocket.cpp b/source/TlsSocket.cpp index 247af78..c49fb83 100644 --- a/source/TlsSocket.cpp +++ b/source/TlsSocket.cpp @@ -4,7 +4,7 @@ ** Author Francois Michaut ** ** Started on Wed Sep 14 21:04:42 2022 Francois Michaut -** Last update Sun Aug 3 22:18:06 2025 Francois Michaut +** Last update Tue Aug 5 13:49:19 2025 Francois Michaut ** ** SecureSocket.cpp : TLS socket wrapper implementation */ @@ -154,13 +154,13 @@ namespace CppSockets { std::size_t nb = 0; std::size_t total; - if (SSL_peek(m_ssl.get(), buff.data(), BUFF_SIZE) <= 0) { + if (SSL_peek(m_ssl.get(), buff.data(), buff.size()) <= 0) { set_connected(false); // TODO: we should replace this with check_for_error } check_for_error("Failed to read from socket", 1); // Do not raise an error if peek failed total = SSL_pending(m_ssl.get()); while (total != 0 && len != 0) { - nb = this->read(buff.data(), (BUFF_SIZE > len ? len : BUFF_SIZE)); + nb = this->read(buff.data(), (buff.size() > len ? len : buff.size())); res << std::string(buff.data(), nb); total -= nb; if (len != -1)