Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
132 changes: 81 additions & 51 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ env:
-DENABLE_CRYPTO=ON -DENABLE_NETSSL=ON -DENABLE_JWT=ON
-DENABLE_ENCODINGS=ON -DENABLE_PDF=ON
-DENABLE_ZIP=ON -DENABLE_SEVENZIP=ON
-DENABLE_REDIS=ON -DENABLE_MONGODB=ON
-DENABLE_REDIS=ON -DENABLE_MONGODB=ON -DENABLE_SSH=ON
-DENABLE_DATA=ON -DENABLE_DATA_SQLITE=ON
-DENABLE_PROMETHEUS=ON
-DENABLE_ACTIVERECORD=ON -DENABLE_ACTIVERECORD_COMPILER=ON
Expand All @@ -59,7 +59,7 @@ env:
-DENABLE_XML=ON -DENABLE_JSON=ON -DENABLE_NET=ON -DENABLE_UTIL=ON
-DENABLE_CRYPTO=ON -DENABLE_NETSSL=ON -DENABLE_NETSSL_WIN=ON -DENABLE_JWT=ON
-DENABLE_DATA=ON -DENABLE_DATA_SQLITE=ON -DENABLE_DATA_ODBC=ON
-DENABLE_ZIP=ON -DENABLE_ENCODINGS=ON
-DENABLE_ZIP=ON -DENABLE_ENCODINGS=ON -DENABLE_SSH=ON
-DENABLE_PDF=ON -DENABLE_PROMETHEUS=ON
-DENABLE_ACTIVERECORD=ON -DENABLE_ACTIVERECORD_COMPILER=ON
-DENABLE_CPPPARSER=ON
Expand Down Expand Up @@ -183,7 +183,7 @@ jobs:
- run: sudo sysctl vm.mmap_rnd_bits
- run: sudo sysctl -w vm.mmap_rnd_bits=28
- run: >-
sudo apt -y update && sudo apt -y install libssl-dev libltdl-dev apache2-dev libapr1-dev libaprutil1-dev libavahi-client-dev
sudo apt -y update && sudo apt -y install libssl-dev libssh-dev libltdl-dev apache2-dev libapr1-dev libaprutil1-dev libavahi-client-dev
libsqlite3-dev redis-server
- uses: supercharge/mongodb-github-action@1.12.1
- run: >-
Expand Down Expand Up @@ -450,9 +450,9 @@ jobs:
ASAN_OPTIONS: ${{ matrix.asan_options }}
steps:
- uses: actions/checkout@v5
- name: Install OpenSSL, Redis, MongoDB
- name: Install OpenSSL, libssh, Redis, MongoDB
run: |
brew install openssl@3 redis
brew install openssl@3 libssh redis
brew tap mongodb/brew
brew install mongodb-community
- name: Start Redis and MongoDB
Expand Down Expand Up @@ -567,9 +567,9 @@ jobs:
TSAN_OPTIONS: ${{ matrix.name == 'tsan' && format('suppressions={0}/tsan.suppress,second_deadlock_stack=1', github.workspace) || '' }}
steps:
- uses: actions/checkout@v5
- name: Install OpenSSL, Redis, MongoDB
- name: Install OpenSSL, libssh, Redis, MongoDB
run: |
brew install openssl@3 redis
brew install openssl@3 libssh redis
brew tap mongodb/brew
brew install mongodb-community
- name: Start Redis and MongoDB
Expand Down Expand Up @@ -611,64 +611,89 @@ jobs:
- uses: TheMrMilchmann/setup-msvc-dev@v4
with:
arch: x64
- name: Install OpenSSL (FireDaemon portable zip)
- name: Uninstall pre-existing OpenSSL / libssh
shell: pwsh
env:
# Major.minor track. 3.6 = latest, 3.5 = LTS. Latest patch is scraped
# from the KB page; falls back to OPENSSL_ZIP_FALLBACK if scrape fails.
OPENSSL_TRACK: "3.6"
OPENSSL_ZIP_FALLBACK: openssl-3.6.2.zip
# Runner images carry preinstalled OpenSSL/OpenSSH and cached vcpkg
# ports. Scrub all three so only our vcpkg install remains. vcpkg is
# the single source of OpenSSL (pulled in as a transitive dep of
# libssh), matching the rule: no second OpenSSL in CI.
run: |
$ProgressPreference = 'SilentlyContinue'
# FireDaemon ships a portable OpenSSL zip with the legacy provider
# included (ossl-modules/legacy.dll) -- needed for DES-ECB and PKCS12
# tests that exercise RC2/3DES PBE. No winget, no registry, no admin.
# Detect latest patch version from the KB page.
$kb = "https://kb.firedaemon.com/support/solutions/articles/4000121705-openssl-binary-distributions-for-microsoft-windows"
$zipName = $env:OPENSSL_ZIP_FALLBACK
try {
$html = Invoke-WebRequest -Uri $kb -UseBasicParsing -TimeoutSec 30
$pattern = "openssl-" + [regex]::Escape($env:OPENSSL_TRACK) + "\.(\d+)([a-z]?)\.zip"
$found = [regex]::Matches($html.Content, $pattern) |
ForEach-Object { $_.Value } | Select-Object -Unique
if ($found.Count -gt 0) {
$zipName = $found | Sort-Object {
if ($_ -match "openssl-[\d\.]+\.(\d+)([a-z]?)\.zip") {
$patch = [int]$Matches[1]
$suffix = if ($Matches[2]) { [int][char]$Matches[2] } else { 0 }
$patch * 100 + $suffix
} else { 0 }
} -Descending | Select-Object -First 1
}
} catch {
Write-Host "Version scrape failed ($_); using fallback $zipName"
vcpkg remove libssh:x64-windows openssl:x64-windows --recurse 2>&1 | Out-Host
$drop = @(
'C:\Program Files\OpenSSL\bin',
'C:\Program Files\OpenSSL-Win64\bin',
'C:\OpenSSL-Win64\bin',
'C:\Windows\System32\OpenSSH'
)
$clean = ($env:PATH -split ';' | Where-Object {
$p = $_.TrimEnd('\'); $drop -notcontains $p
}) -join ';'
"PATH=$clean" | Out-File -FilePath $env:GITHUB_ENV -Append
foreach ($d in 'C:\OpenSSL-Win64','C:\Program Files\OpenSSL','C:\Program Files\OpenSSL-Win64') {
if (Test-Path $d) { Remove-Item -Recurse -Force -ErrorAction SilentlyContinue $d }
}
Write-Host "Selected: $zipName"
# Install into the job sandbox so every job gets a clean copy.
$url = "https://download.firedaemon.com/FireDaemon-OpenSSL/$zipName"
$zip = Join-Path $env:RUNNER_TEMP $zipName
$installDir = Join-Path $env:RUNNER_TEMP "openssl"
Write-Host "Downloading $url"
Invoke-WebRequest -Uri $url -OutFile $zip -UseBasicParsing
Expand-Archive -Path $zip -DestinationPath $installDir -Force
$root = Join-Path $installDir "x64"
if (-not (Test-Path "$root\bin\libssl-3-x64.dll")) {
Write-Error "libssl-3-x64.dll missing under $root"
exit 1
- name: Install OpenSSL + libssh (vcpkg)
shell: pwsh
# libssh drags in openssl as a transitive dep -- we deliberately use
# that single copy for the whole build. Explicit Test-Path assertions
# fail fast on missing files.
run: |
$ProgressPreference = 'SilentlyContinue'
vcpkg install libssh:x64-windows
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
$root = "$env:VCPKG_INSTALLATION_ROOT\installed\x64-windows"
$required = @(
"$root\bin\libcrypto-3-x64.dll",
"$root\bin\libssl-3-x64.dll",
"$root\bin\ssh.dll",
"$root\lib\libcrypto.lib",
"$root\lib\libssl.lib",
"$root\lib\ssh.lib",
"$root\include\openssl\ssl.h",
"$root\include\libssh\libssh.h"
)
foreach ($p in $required) {
if (-not (Test-Path $p)) { Write-Error "Missing: $p"; exit 1 }
}
if (-not (Test-Path "$root\lib\ossl-modules\legacy.dll")) {
Write-Error "legacy.dll missing under $root\lib\ossl-modules"
# Legacy provider needed for PKCS12 (RC2/3DES PBE) and DES-ECB tests.
# vcpkg normally places legacy.dll under $root\bin; recursive search
# tolerates layout changes across vcpkg versions.
$legacy = Get-ChildItem -Path $root -Filter legacy.dll -Recurse -ErrorAction SilentlyContinue |
Select-Object -First 1
if ($null -eq $legacy) {
Write-Error "legacy.dll not found under $root -- OpenSSL legacy provider missing"
exit 1
}
"OPENSSL_ROOT_DIR=$root" | Out-File -FilePath $env:GITHUB_ENV -Append
"OPENSSL_ROOT_DIR=$root" | Out-File -FilePath $env:GITHUB_ENV -Append
"LIBSSH_ROOT_DIR=$root" | Out-File -FilePath $env:GITHUB_ENV -Append
"OPENSSL_MODULES=$($legacy.DirectoryName)" | Out-File -FilePath $env:GITHUB_ENV -Append
Add-Content $env:GITHUB_PATH "$root\bin"
"OPENSSL_MODULES=$root\lib\ossl-modules" | Out-File -FilePath $env:GITHUB_ENV -Append
Write-Host "OPENSSL_ROOT_DIR=$root"
Write-Host "LIBSSH_ROOT_DIR=$root"
Write-Host "OPENSSL_MODULES=$($legacy.DirectoryName)"
- name: Verify OpenSSL / libssh DLL resolution
shell: pwsh
# Prove the loader will pick DLLs from the vcpkg tree, not from
# residue elsewhere on the runner. Fails the job on any mismatch.
run: |
foreach ($dll in 'libcrypto-3-x64.dll','libssl-3-x64.dll','ssh.dll') {
$cmd = Get-Command $dll -ErrorAction SilentlyContinue
if ($null -eq $cmd) { Write-Error "$dll not resolvable on PATH"; exit 1 }
$resolved = [System.IO.Path]::GetFullPath($cmd.Source)
$expected = [System.IO.Path]::GetFullPath("$env:LIBSSH_ROOT_DIR\bin\$dll")
Write-Host "$dll -> $resolved"
if ($resolved -ne $expected) {
Write-Error "$dll resolves to $resolved, expected $expected"
exit 1
}
}
- run: >-
cmake -S. -Bcmake-build -G Ninja -DCMAKE_BUILD_TYPE=Release
-DCMAKE_INTERPROCEDURAL_OPTIMIZATION=ON
${{ env.POCO_CMAKE_WINDOWS_FULL }}
-DOPENSSL_ROOT_DIR="${{ env.OPENSSL_ROOT_DIR }}"
-DCMAKE_PREFIX_PATH="${{ env.LIBSSH_ROOT_DIR }}"
- run: cmake --build cmake-build --parallel $env:NUMBER_OF_PROCESSORS
- uses: ./.github/actions/retry-action
env:
Expand All @@ -681,6 +706,11 @@ jobs:
cd cmake-build;
ctest ${{ env.POCO_CTEST_COMMON }} --parallel $env:NUMBER_OF_PROCESSORS -E "(DataMySQL)|(DataODBC)|(Redis)|(MongoDB)"
- uses: ./.github/actions/upload-test-report
- name: Uninstall OpenSSL / libssh
if: always()
shell: pwsh
run: |
vcpkg remove libssh:x64-windows openssl:x64-windows --recurse 2>&1 | Out-Host

# clang-cl toolchain exception: reduced scope (Foundation + Util smoke).
windows-2025-clang-cmake:
Expand Down
14 changes: 14 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,7 @@ option(ENABLE_DATA "Enable Data" ${_enable_default})
option(ENABLE_DATA_SQLITE "Enable Data SQlite" ${_enable_default})
option(ENABLE_MONGODB "Enable MongoDB" ${_enable_default})
option(ENABLE_REDIS "Enable Redis" ${_enable_default})
option(ENABLE_SSH "Enable SSH" OFF)
option(ENABLE_PROMETHEUS "Enable Prometheus" ${_enable_default})
option(ENABLE_UTIL "Enable Util" ${_enable_default})
option(ENABLE_NET "Enable Net" ${_enable_default})
Expand Down Expand Up @@ -446,6 +447,14 @@ if(ENABLE_MONGODB OR ENABLE_REDIS OR ENABLE_PROMETHEUS)
set(ENABLE_NET ON CACHE BOOL "Enable Net" FORCE)
endif()

if(ENABLE_SSH)
find_package(libssh CONFIG)
if(NOT libssh_FOUND)
message(STATUS "libssh not found - disabling SSH")
set(ENABLE_SSH OFF CACHE BOOL "Enable SSH" FORCE)
endif()
endif()

if(ENABLE_NETSSL)
set(ENABLE_CRYPTO ON CACHE BOOL "Enable Crypto" FORCE)
set(ENABLE_NET ON CACHE BOOL "Enable Net" FORCE)
Expand Down Expand Up @@ -571,6 +580,11 @@ if(EXISTS ${PROJECT_SOURCE_DIR}/Redis AND ENABLE_REDIS)
list(APPEND Poco_COMPONENTS "Redis")
endif()

if(EXISTS ${PROJECT_SOURCE_DIR}/SSH AND ENABLE_SSH)
add_subdirectory(SSH)
list(APPEND Poco_COMPONENTS "SSH")
endif()

if(ENABLE_DNSSD)
add_subdirectory(DNSSD)
list(APPEND Poco_COMPONENTS "DNSSD")
Expand Down
46 changes: 46 additions & 0 deletions SSH/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# Sources
file(GLOB SRCS_G "src/*.cpp")
POCO_SOURCES_AUTO(SRCS ${SRCS_G})

# Headers
file(GLOB_RECURSE HDRS_G "include/*.h")
POCO_HEADERS_AUTO(SRCS ${HDRS_G})

# Version Resource
if(MSVC AND BUILD_SHARED_LIBS)
source_group("Resources" FILES ${PROJECT_SOURCE_DIR}/DLLVersion.rc)
list(APPEND SRCS ${PROJECT_SOURCE_DIR}/DLLVersion.rc)
endif()

add_library(SSH ${SRCS})
add_library(Poco::SSH ALIAS SSH)
set_target_properties(SSH
PROPERTIES
VERSION ${SHARED_LIBRARY_VERSION} SOVERSION ${SHARED_LIBRARY_VERSION}
OUTPUT_NAME PocoSSH
DEFINE_SYMBOL SSH_EXPORTS
)

target_link_libraries(SSH PUBLIC Poco::Foundation)
target_link_libraries(SSH PRIVATE ssh)
if(WIN32)
target_link_libraries(SSH PUBLIC ws2_32)
endif()
target_include_directories(SSH
PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/src
)

POCO_INSTALL(SSH)
POCO_GENERATE_PACKAGE(SSH)

if(ENABLE_TESTS)
add_subdirectory(testsuite)
endif()

if(ENABLE_SAMPLES)
add_subdirectory(samples)
endif()
22 changes: 22 additions & 0 deletions SSH/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#
# Makefile
#
# Makefile for Poco SSH Library
#

include $(POCO_BASE)/build/rules/global

ifeq ($(OSNAME),Darwin)
SYSFLAGS += $(shell pkg-config --cflags libssh 2>/dev/null)
SYSLIBS += $(shell pkg-config --libs libssh 2>/dev/null || echo -lssh)
else
SYSLIBS += -lssh
endif

objects = SSHChannelStream SSHClient SSHException SSHHostKeyManager SSHServer SSHSession

target = PocoSSH
target_version = 1
target_libs = PocoFoundation

include $(POCO_BASE)/build/rules/lib
3 changes: 3 additions & 0 deletions SSH/cmake/PocoSSHConfig.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
include(CMakeFindDependencyMacro)
find_dependency(PocoFoundation)
include("${CMAKE_CURRENT_LIST_DIR}/PocoSSHTargets.cmake")
1 change: 1 addition & 0 deletions SSH/dependencies
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Foundation
62 changes: 62 additions & 0 deletions SSH/include/Poco/SSH/SSH.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
//
// SSH.h
//
// Library: SSH
// Package: SSH
// Module: SSH
//
// Basic definitions for the Poco SSH library.
// This file must be the first file included by every other SSH
// header file.
//
// Copyright (c) 2026, Aleph ONE Software Engineering LLC
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//


#ifndef SSH_SSH_INCLUDED
#define SSH_SSH_INCLUDED


#include "Poco/Foundation.h"


//
// The following block is the standard way of creating macros which make exporting
// from a DLL simpler. All files within this DLL are compiled with the SSH_EXPORTS
// symbol defined on the command line. this symbol should not be defined on any project
// that uses this DLL. This way any other project whose source files include this file see
// SSH_API functions as being imported from a DLL, whereas this DLL sees symbols
// defined with this macro as being exported.
//
#if defined(_WIN32) && defined(POCO_DLL)
#if defined(SSH_EXPORTS)
#define SSH_API __declspec(dllexport)
#else
#define SSH_API __declspec(dllimport)
#endif
#endif


#if !defined(SSH_API)
#if !defined(POCO_NO_GCC_API_ATTRIBUTE) && defined (__GNUC__) && (__GNUC__ >= 4)
#define SSH_API __attribute__ ((visibility ("default")))
#else
#define SSH_API
#endif
#endif


//
// Automatically link SSH library.
//
#if defined(_MSC_VER)
#if !defined(POCO_NO_AUTOMATIC_LIBS) && !defined(SSH_EXPORTS)
#pragma comment(lib, "PocoSSH" POCO_LIB_SUFFIX)
#endif
#endif


#endif // SSH_SSH_INCLUDED
Loading
Loading