Compare commits

..

24 Commits

Author SHA1 Message Date
Jakub Jelen
854795c654 libssh 0.11.1
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Sahana Prasad <sahana@redhat.com>
2024-08-29 15:36:46 +02:00
Jakub Jelen
da064c9a18 ttyopts: Adjust the default TTY modes to be sane
The "sane" default is now based on the man stty "sane" alias with addition of
utf8.

Fixes: #270

Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 48d474f78c)
2024-08-29 15:07:00 +02:00
Carlo Bramini
c85dc05436 CYGWIN: fix build.
Signed-off-by: Carlo Bramini <carlo_bramini@users.sourceforge.net>
Reviewed-by: Jakub Jelen <jjelen@redhat.com>
(cherry picked from commit e298600303)
2024-08-19 15:17:03 +02:00
Jakub Jelen
8d0d3d4d7b Add explicit -Werror=unused-variable
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
Reviewed-by: Eshan Kelkar <eshankelkar@galorithm.com>
(cherry picked from commit 8295945011)
2024-08-19 15:17:01 +02:00
Jakub Jelen
0b2e13bc9b cmake: Do not build server examples and tests when built without server
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
Reviewed-by: Eshan Kelkar <eshankelkar@galorithm.com>
(cherry picked from commit 8363929104)
2024-08-19 15:17:00 +02:00
Jakub Jelen
51f4a5743d kex: Avoid unused variable when built without server
Fixes: #267

Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
Reviewed-by: Eshan Kelkar <eshankelkar@galorithm.com>
(cherry picked from commit 71e1baeb5f)
2024-08-19 15:16:58 +02:00
Jakub Jelen
e816256333 config: Do not parse unsupported ControlPath/ControlMaster
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 82b363f294)
2024-08-19 15:16:54 +02:00
Jakub Jelen
960a6d1cdd tests: Do not crash on cleanup when sshd does not come up
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 8fb2c5d2fd)
2024-08-19 15:16:51 +02:00
Jakub Jelen
1fa9ea7f43 tests: Do not override verbosity set by environment
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 9ce53b6972)
2024-08-19 15:16:48 +02:00
Jakub Jelen
afa77c11ca test: Workaround the new OpenSSH failure rate limiting
The new OpenSSH rate limits the failed authentication attempts per source
address and drops connection when the amount is reached, which is happening
in our testsuite.

By whitelisting the IP address of the client on the socket wrapper,
this allows the tests to pass.

https://man.openbsd.org/sshd_config.5#PerSourcePenaltyExemptList

Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 7b89ff760a)
2024-08-19 15:16:35 +02:00
Andreas Schneider
825de355d4 cpack: Make sure to not package .git file
Signed-off-by: Andreas Schneider <asn@samba.org>
Reviewed-by: Jakub Jelen <jjelen@redhat.com>
(cherry picked from commit 362ab3a684)
2024-08-19 15:16:33 +02:00
Jakub Jelen
a910526e10 tests: Avoid unused variables
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit ea97d41bbb)
2024-08-19 15:16:31 +02:00
Jakub Jelen
dfc3cb7112 wrapper: Use calloc instead of zerostructp
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit c85268c38b)
2024-08-19 15:16:30 +02:00
Jakub Jelen
3264d3e83c wrapper: Avoid asymmetric termination of gzip context
For some reason, both compress and decompress contexts were terminated
with both compress and decompress end functions (if the deflateEnd worked),
which was causing for some another unexplained reasons issues on i686
architecture when running the torture_packet unit test.

Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit c9cfeb9b83)
2024-08-19 15:16:28 +02:00
Jakub Jelen
6030d2fcd5 tests: Describe reason for using internal-sftp
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit deedc0e108)
2024-08-19 15:16:26 +02:00
Jakub Jelen
406a014d58 tests: Remove needless printf
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 57073d588a)
2024-08-19 15:16:24 +02:00
Jakub Jelen
af0153f30f tests: Rewrite fs_wrapper for readability
includes also additional syscalls for 32b archs.

Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit d416ef533f)
2024-08-19 15:16:21 +02:00
Jakub Jelen
84dde6d302 tests: Assemble the output into single buffer
... before checking the content.

This test was failing randomly when the read returned only partial buffer.

Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 2743b510ac)
2024-08-19 15:16:19 +02:00
Jakub Jelen
dd38f523e1 tests: Be explicit about types.
Casting int to bool might not always work as expected

Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 41d370864e)
2024-08-19 15:16:14 +02:00
JamesWrigley
5318ddaabc Use CMake's C_STANDARD property
This is more portable than specifying a compiler flag explicitly.

Signed-off-by: James Wrigley <james@puiterwijk.org>
Reviewed-by: Jakub Jelen <jjelen@redhat.com>
(cherry picked from commit 7e4ea0d111)
2024-08-19 15:16:11 +02:00
Francesco Rollo
2f50ef2fe6 tests: add support for IPv4/IPv6 loopback network ID fallback in torture_config_match_localnetwork.c
Signed-off-by: Francesco <eferollo@gmail.com>
Reviewed-by: Jakub Jelen <jjelen@redhat.com>
(cherry picked from commit b0b2e8fefd)
2024-08-02 11:21:02 +02:00
Jakub Jelen
eae3a60ef8 Fix proxy_disconnect on systems without pthread
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit b804aa9286)
2024-08-02 11:20:56 +02:00
Jakub Jelen
318f675ef8 match: Workaround matching on systems without IPv6
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit ab10f5c2f7)
2024-08-02 11:20:54 +02:00
Jakub Jelen
7beb580aab Conditional compilation of localnetwork matching
Some architectures (esp32) might not have this API.

Fixes: #263

Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
(cherry picked from commit 9634668258)
2024-08-02 11:20:52 +02:00
281 changed files with 10751 additions and 31250 deletions

View File

@@ -22,8 +22,8 @@ BinPackArguments: false
BinPackParameters: false
AllowAllArgumentsOnNextLine: false
AllowShortFunctionsOnASingleLine: Empty
BreakAfterReturnType: ExceptShortType
# TODO with Clang 19, replace the below with
# BreakAfterReturnType: ExceptShortType
AlwaysBreakAfterReturnType: AllDefinitions
AlignEscapedNewlines: Left
ForEachMacros: ['ssh_callbacks_iterate']
AlignConsecutiveMacros: 'Consecutive'

View File

@@ -1,6 +0,0 @@
---
line_width: 80
tab_size: 4
use_tabchars: false
separate_ctrl_name_with_space: true
separate_fn_name_with_space: false

View File

@@ -12,12 +12,7 @@ indent_style = space
indent_size = 4
tab_width = 4
[CMakeLists.txt]
[{CMakeLists.txt,*.cmake}]
indent_style = space
indent_size = 4
tab_width = 4
[*.cmake]
indent_style = space
indent_size = 4
tab_width = 4
tab_width = 4

1
.gitignore vendored
View File

@@ -10,4 +10,3 @@ tags
/build
/obj*
doc/tags.xml
.DS_Store

View File

@@ -3,7 +3,6 @@ variables:
BUILD_IMAGES_PROJECT: libssh/build-images
CENTOS8_BUILD: buildenv-c8s
CENTOS9_BUILD: buildenv-c9s
CENTOS10_BUILD: buildenv-c10s
FEDORA_BUILD: buildenv-fedora
MINGW_BUILD: buildenv-mingw
TUMBLEWEED_BUILD: buildenv-tumbleweed
@@ -17,7 +16,7 @@ stages:
- analysis
# This is some black magic to select between branch pipelines and
# merge request pipelines to avoid running same pipelines twice
# merge request pipelines to avoid running same pipelines in twice
workflow:
rules:
- if: '$CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS && $CI_PIPELINE_SOURCE == "push"'
@@ -27,17 +26,13 @@ workflow:
when: never
- if: '$CI_COMMIT_BRANCH'
.build_options:
.build:
stage: build
variables:
CMAKE_DEFAULT_OPTIONS: "-DCMAKE_BUILD_TYPE=RelWithDebInfo -DPICKY_DEVELOPER=ON"
CMAKE_DEFAULT_DEBUG_OPTIONS: "-DCMAKE_C_FLAGS='-O0 -g -ggdb' -DPICKY_DEVELOPER=ON"
CMAKE_BUILD_OPTIONS: "-DWITH_BLOWFISH_CIPHER=ON -DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON -DWITH_FIDO2=ON -DWITH_DEBUG_CRYPTO=ON -DWITH_DEBUG_PACKET=ON -DWITH_DEBUG_CALLTRACE=ON"
CMAKE_BUILD_OPTIONS: "-DWITH_BLOWFISH_CIPHER=ON -DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON -DWITH_DEBUG_CRYPTO=ON -DWITH_DEBUG_PACKET=ON -DWITH_DEBUG_CALLTRACE=ON"
CMAKE_TEST_OPTIONS: "-DUNIT_TESTING=ON -DCLIENT_TESTING=ON -DSERVER_TESTING=ON -DGSSAPI_TESTING=ON -DWITH_BENCHMARKS=ON -DFUZZ_TESTING=ON"
CMAKE_OPTIONS: $CMAKE_DEFAULT_OPTIONS $CMAKE_BUILD_OPTIONS $CMAKE_TEST_OPTIONS
.build:
extends: .build_options
stage: build
before_script: &build
- uname -a
- cat /etc/os-release
@@ -79,41 +74,13 @@ workflow:
.fedora:
extends: .tests
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD
variables:
CMAKE_ADDITIONAL_OPTIONS: -DWITH_PKCS11_URI=ON
.tumbleweed:
extends: .tests
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$TUMBLEWEED_BUILD
.centos:
extends: .tests
variables:
OPENSSL_ENABLE_SHA1_SIGNATURES: 1
.centos10:
extends: .centos
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$CENTOS10_BUILD
.centos9:
extends: .centos
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$CENTOS9_BUILD
# Unit testing only, no client and pkd testing, because cwrap is not available
# for MinGW
.mingw:
extends: .tests
variables:
WINEDEBUG: -all
script:
- $WINEBIN $CMAKE_DEFAULT_OPTIONS
-DWITH_SFTP=ON
-DWITH_SERVER=ON
-DWITH_ZLIB=ON
-DWITH_PCAP=ON
-DWITH_FIDO2=ON
-DUNIT_TESTING=ON .. &&
make -j$(nproc) &&
ctest --output-on-failure -E torture_rand
.fips:
extends: .tests
variables:
@@ -140,7 +107,7 @@ review:
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD
script:
- ERROR=0
codespell --ignore-words-list=keypair,sorce,ned,nd,ue,pendin || ERROR=1;
codespell --ignore-words-list=keypair,sorce,ned,nd,ue || ERROR=1;
./.gitlab-ci/clang-format-check.sh || ERROR=1;
./.gitlab-ci/git-check-signoff-trailer.sh ${CI_MERGE_REQUEST_DIFF_BASE_SHA} || ERROR=1;
./.gitlab-ci/shellcheck.sh || ERROR=1;
@@ -155,31 +122,13 @@ review:
###############################################################################
# CentOS builds #
###############################################################################
centos10s/openssl_3.5.x/x86_64:
extends: .centos10
variables:
CMAKE_ADDITIONAL_OPTIONS: -DWITH_PKCS11_URI=ON -DWITH_PKCS11_PROVIDER=ON
script:
- cmake $CMAKE_OPTIONS $CMAKE_ADDITIONAL_OPTIONS .. &&
make -j$(nproc) &&
ctest --output-on-failure
centos10s/openssl_3.5.x/x86_64/fips:
extends: .fips
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$CENTOS10_BUILD
variables:
CMAKE_ADDITIONAL_OPTIONS: -DWITH_PKCS11_URI=ON -DWITH_PKCS11_PROVIDER=ON
OPENSSL_ENABLE_SHA1_SIGNATURES: 1
script:
- cmake $CMAKE_OPTIONS $CMAKE_ADDITIONAL_OPTIONS .. &&
make -j$(nproc) &&
OPENSSL_FORCE_FIPS_MODE=1 ctest --output-on-failure
centos9s/openssl_3.5.x/x86_64:
extends: .centos9
centos9s/openssl_3.0.x/x86_64:
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$CENTOS9_BUILD
extends: .tests
variables:
CMAKE_ADDITIONAL_OPTIONS: -DWITH_PKCS11_URI=ON
script:
- export OPENSSL_ENABLE_SHA1_SIGNATURES=1
- cmake $CMAKE_OPTIONS $CMAKE_ADDITIONAL_OPTIONS .. &&
make -j$(nproc) &&
ctest --output-on-failure
@@ -190,12 +139,11 @@ centos9s/mbedtls_2.x/x86_64:
variables:
CMAKE_ADDITIONAL_OPTIONS: "-DWITH_MBEDTLS=ON -DWITH_DEBUG_CRYPTO=ON -DWITH_BLOWFISH_CIPHER=OFF"
centos9s/openssl_3.5.x/x86_64/fips:
centos9s/openssl_3.0.x/x86_64/fips:
extends: .fips
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$CENTOS9_BUILD
variables:
OPENSSL_ENABLE_SHA1_SIGNATURES: 1
script:
- export OPENSSL_ENABLE_SHA1_SIGNATURES=1
- cmake $CMAKE_OPTIONS $CMAKE_ADDITIONAL_OPTIONS .. &&
make -j$(nproc) &&
OPENSSL_FORCE_FIPS_MODE=1 ctest --output-on-failure
@@ -235,10 +183,8 @@ fedora/docs:
fedora/ninja:
extends: .fedora
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD
variables:
CTEST_OUTPUT_ON_FAILURE: 1
script:
- cmake -G Ninja $CMAKE_OPTIONS ../ && ninja && ninja test
- cmake -G Ninja $CMAKE_OPTIONS ../ && ninja && CTEST_OUTPUT_ON_FAILURE=1 ninja test
fedora/coverage:
extends: .fedora
@@ -258,15 +204,15 @@ fedora/coverage:
coverage_format: cobertura
path: obj/coverage_xml.xml
fedora/openssl_3.x/x86_64:
fedora/openssl_3.0.x/x86_64:
extends: .fedora
fedora/openssl_3.x/x86_64/pkcs11-provider:
fedora/openssl_3.0.x/x86_64/pkcs11-provider:
variables:
CMAKE_ADDITIONAL_OPTIONS: -DWITH_PKCS11_URI=ON -DWITH_PKCS11_PROVIDER=ON
extends: .fedora
fedora/openssl_3.x/x86_64/minimal:
fedora/openssl_3.0.x/x86_64/minimal:
extends: .fedora
variables:
script:
@@ -276,10 +222,9 @@ fedora/openssl_3.x/x86_64/minimal:
-DWITH_SERVER=OFF
-DWITH_ZLIB=OFF
-DWITH_PCAP=OFF
-DWITH_GSSAPI=OFF
-DWITH_GEX=OFF
-DUNIT_TESTING=ON
-DCLIENT_TESTING=ON .. &&
-DCLIENT_TESTING=ON
-DWITH_GEX=OFF .. &&
make -j$(nproc)
.valgrind:
@@ -361,26 +306,47 @@ fedora/undefined-sanitizer:
fedora/libgcrypt/x86_64:
extends: .fedora
variables:
CMAKE_ADDITIONAL_OPTIONS: "-DWITH_GCRYPT=ON"
CMAKE_ADDITIONAL_OPTIONS: "-DWITH_GCRYPT=ON -DWITH_DEBUG_CRYPTO=ON"
fedora/mbedtls_3.x/x86_64:
fedora/mbedtls_2.x/x86_64:
extends: .fedora
variables:
CMAKE_ADDITIONAL_OPTIONS: "-DWITH_MBEDTLS=ON"
CMAKE_ADDITIONAL_OPTIONS: "-DWITH_MBEDTLS=ON -DWITH_DEBUG_CRYPTO=ON "
# Unit testing only, no client and pkd testing, because cwrap is not available
# for MinGW
fedora/mingw64:
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$MINGW_BUILD
extends: .mingw
variables:
WINEPATH: /usr/x86_64-w64-mingw32/sys-root/mingw/bin
WINEBIN: mingw64-cmake
extends: .tests
script:
- export WINEPATH=/usr/x86_64-w64-mingw32/sys-root/mingw/bin
- export WINEDEBUG=-all
- mingw64-cmake $CMAKE_DEFAULT_OPTIONS
-DWITH_SFTP=ON
-DWITH_SERVER=ON
-DWITH_ZLIB=ON
-DWITH_PCAP=ON
-DUNIT_TESTING=ON .. &&
make -j$(nproc) &&
ctest --output-on-failure
# Unit testing only, no client and pkd testing, because cwrap is not available
# for MinGW
fedora/mingw32:
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$MINGW_BUILD
extends: .mingw
variables:
WINEPATH: /usr/i686-w64-mingw32/sys-root/mingw/bin
WINEBIN: mingw32-cmake
extends: .tests
script:
- export WINEPATH=/usr/i686-w64-mingw32/sys-root/mingw/bin
- export WINEDEBUG=-all
- mingw32-cmake $CMAKE_DEFAULT_OPTIONS
-DWITH_SFTP=ON
-DWITH_SERVER=ON
-DWITH_ZLIB=ON
-DWITH_PCAP=ON
-DUNIT_TESTING=ON .. &&
make -j$(nproc) &&
ctest --output-on-failure
###############################################################################
# Fedora csbuild #
@@ -389,8 +355,6 @@ fedora/mingw32:
stage: analysis
variables:
GIT_DEPTH: "100"
CSCPPC_ADD_OPTS: "--library=./.gitlab-ci/cmocka.cfg"
CMAKE_OPTIONS: "-DCMAKE_BUILD_TYPE=Debug -DPICKY_DEVELOPER=ON -DUNIT_TESTING=ON -DCLIENT_TESTING=ON -DSERVER_TESTING=ON -DFUZZ_TESTING=ON"
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD
before_script:
- |
@@ -408,14 +372,6 @@ fedora/mingw32:
git branch --contains $CI_COMMIT_BEFORE_SHA 2>/dev/null || export CI_COMMIT_BEFORE_SHA=$(git rev-parse "${CI_COMMIT_SHA}~20")
export CI_COMMIT_RANGE="$CI_COMMIT_BEFORE_SHA..$CI_COMMIT_SHA"
script:
- csbuild
--build-dir=obj-csbuild
--build-cmd "rm -rf CMakeFiles CMakeCache.txt && cmake $CMAKE_OPTIONS $CMAKE_ADDITIONAL_OPTIONS @SRCDIR@ && make clean && make -j$(nproc)"
--git-commit-range $CI_COMMIT_RANGE
--color
--print-current --print-fixed
tags:
- saas-linux-small-amd64
except:
@@ -428,75 +384,36 @@ fedora/mingw32:
paths:
- obj-csbuild/
fedora/csbuild/openssl_3.x:
fedora/csbuild/openssl_3.0.x:
extends: .csbuild
script:
- csbuild
--build-dir=obj-csbuild
--build-cmd "rm -rf CMakeFiles CMakeCache.txt && cmake -DCMAKE_BUILD_TYPE=Debug -DPICKY_DEVELOPER=ON -DUNIT_TESTING=ON -DCLIENT_TESTING=ON -DSERVER_TESTING=ON -DFUZZ_TESTING=ON @SRCDIR@ && make clean && make -j$(nproc)"
--git-commit-range $CI_COMMIT_RANGE
--color
--print-current --print-fixed
fedora/csbuild/libgcrypt:
extends: .csbuild
variables:
CMAKE_ADDITIONAL_OPTIONS: -DWITH_GCRYPT=ON
script:
- csbuild
--build-dir=obj-csbuild
--build-cmd "rm -rf CMakeFiles CMakeCache.txt && cmake -DCMAKE_BUILD_TYPE=Debug -DPICKY_DEVELOPER=ON -DUNIT_TESTING=ON -DCLIENT_TESTING=ON -DSERVER_TESTING=ON -DFUZZ_TESTING=ON -DWITH_GCRYPT=ON @SRCDIR@ && make clean && make -j$(nproc)"
--git-commit-range $CI_COMMIT_RANGE
--color
--print-current --print-fixed
fedora/csbuild/mbedtls:
extends: .csbuild
variables:
CMAKE_ADDITIONAL_OPTIONS: -DWITH_MBEDTLS=ON
###############################################################################
# Fedora abidiff #
###############################################################################
fedora/abidiff:
stage: analysis
variables:
GIT_DEPTH: "100"
CMAKE_OPTIONS: $CMAKE_DEFAULT_DEBUG_OPTIONS $CMAKE_BUILD_OPTIONS
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD
before_script:
- uname -a
- cat /etc/os-release
- mount
- df -h
- cat /proc/swaps
- free -h
- |
# for merge requests
if [[ -n "$CI_MERGE_REQUEST_DIFF_BASE_SHA" ]]; then
export CI_COMMIT_BEFORE_SHA="$CI_MERGE_REQUEST_DIFF_BASE_SHA"
fi
# for branches run
if [[ -z "$CI_COMMIT_BEFORE_SHA" ]]; then
export CI_COMMIT_BEFORE_SHA=$(git rev-parse "${CI_COMMIT_SHA}~20")
fi
# Check if the commit exists in this branch
# This is not the case for a force push
git branch --contains $CI_COMMIT_BEFORE_SHA 2>/dev/null || export CI_COMMIT_BEFORE_SHA=$(git rev-parse "${CI_COMMIT_SHA}~20")
- mkdir -p obj-${CI_COMMIT_BEFORE_SHA}
- mkdir -p obj-${CI_COMMIT_SHA}
- export INSTALL_DIR1=$(pwd)/install/${CI_COMMIT_BEFORE_SHA}
- export INSTALL_DIR2=$(pwd)/install/${CI_COMMIT_SHA}
script:
- git checkout ${CI_COMMIT_BEFORE_SHA}
- pushd obj-${CI_COMMIT_BEFORE_SHA}
- cmake ${CMAKE_OPTIONS} -DCMAKE_INSTALL_PREFIX=${INSTALL_DIR1} .. &&
make -j$(nproc) && make -j$(nproc) install
- popd
- ls -l ${INSTALL_DIR1}/lib*/
- git checkout ${CI_COMMIT_SHA}
- pushd obj-${CI_COMMIT_SHA}
- cmake ${CMAKE_OPTIONS} -DCMAKE_INSTALL_PREFIX=${INSTALL_DIR2} .. &&
make -j$(nproc) && make -j$(nproc) install
- popd
- ls -l ${INSTALL_DIR2}/lib*/
- ./.gitlab-ci/checkabi.sh ${INSTALL_DIR1} ${INSTALL_DIR2}
tags:
- saas-linux-small-amd64
except:
- tags
only:
- merge_requests
- csbuild
--build-dir=obj-csbuild
--build-cmd "rm -rf CMakeFiles CMakeCache.txt && cmake -DCMAKE_BUILD_TYPE=Debug -DPICKY_DEVELOPER=ON -DUNIT_TESTING=ON -DCLIENT_TESTING=ON -DSERVER_TESTING=ON -DFUZZ_TESTING=ON -DWITH_MBEDTLS=ON @SRCDIR@ && make clean && make -j$(nproc)"
--git-commit-range $CI_COMMIT_RANGE
--color
--print-current --print-fixed
###############################################################################
# Ubuntu builds #
@@ -509,7 +426,7 @@ ubuntu/openssl_3.0.x/x86_64:
###############################################################################
# Alpine builds #
###############################################################################
alpine/openssl_3.x/musl:
alpine/openssl_3.0.x/musl:
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$ALPINE_BUILD
extends: .tests
script:
@@ -526,10 +443,10 @@ alpine/openssl_3.x/musl:
###############################################################################
# Tumbleweed builds #
###############################################################################
tumbleweed/openssl_3.x/x86_64/gcc:
tumbleweed/openssl_3.0.x/x86_64/gcc:
extends: .tumbleweed
tumbleweed/openssl_3.x/x86/gcc:
tumbleweed/openssl_3.0.x/x86/gcc:
extends: .tumbleweed
script:
- cmake
@@ -542,12 +459,12 @@ tumbleweed/openssl_3.x/x86/gcc:
-DUNIT_TESTING=ON .. &&
make -j$(nproc)
tumbleweed/openssl_3.x/x86_64/gcc7:
tumbleweed/openssl_3.0.x/x86_64/gcc7:
extends: .tumbleweed
variables:
CMAKE_ADDITIONAL_OPTIONS: "-DCMAKE_C_COMPILER=gcc-7 -DCMAKE_CXX_COMPILER=g++-7"
tumbleweed/openssl_3.x/x86/gcc7:
tumbleweed/openssl_3.0.x/x86/gcc7:
extends: .tumbleweed
script:
- cmake
@@ -559,7 +476,7 @@ tumbleweed/openssl_3.x/x86/gcc7:
make -j$(nproc) &&
ctest --output-on-failure
tumbleweed/openssl_3.x/x86_64/clang:
tumbleweed/openssl_3.0.x/x86_64/clang:
extends: .tumbleweed
variables:
CMAKE_ADDITIONAL_OPTIONS: "-DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++"
@@ -569,19 +486,13 @@ tumbleweed/mbedtls-3.6.x/x86_64/gcc:
variables:
CMAKE_ADDITIONAL_OPTIONS: "-DKRB5_CONFIG=/usr/lib/mit/bin/krb5-config -DWITH_MBEDTLS=ON -DWITH_DEBUG_CRYPTO=ON -DWITH_BLOWFISH_CIPHER=OFF "
tumbleweed/mbedtls-3.6.x/x86_64/clang:
extends: .tumbleweed
variables:
CMAKE_ADDITIONAL_OPTIONS: "-DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DKRB5_CONFIG=/usr/lib/mit/bin/krb5-config -DWITH_MBEDTLS=ON -DWITH_DEBUG_CRYPTO=ON -DWITH_BLOWFISH_CIPHER=OFF "
tumbleweed/static-analysis:
extends: .tests
stage: analysis
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$TUMBLEWEED_BUILD
variables:
CCC_CC: clang
CCC_CXX: clang++
script:
- export CCC_CC=clang
- export CCC_CXX=clang++
- scan-build cmake
-DCMAKE_BUILD_TYPE=Debug
-DCMAKE_C_COMPILER=clang
@@ -605,12 +516,19 @@ tumbleweed/static-analysis:
freebsd/openssl_1.1.1/x86_64:
image:
extends: .tests
variables:
CMAKE_OPTIONS: $CMAKE_DEFAULT_OPTIONS -DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON -DUNIT_TESTING=ON
before_script:
- mkdir -p obj && cd obj && cmake $CMAKE_OPTIONS ..
- mkdir -p obj && cd obj && cmake
-DCMAKE_BUILD_TYPE=RelWithDebInfo
-DPICKY_DEVELOPER=ON
-DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON
-DUNIT_TESTING=ON ..
script:
- cmake $CMAKE_OPTIONS .. &&
- cmake $CMAKE_DEFAULT_OPTIONS
-DWITH_SFTP=ON
-DWITH_SERVER=ON
-DWITH_ZLIB=ON
-DWITH_PCAP=ON
-DUNIT_TESTING=ON .. &&
make &&
ctest --output-on-failure
tags:
@@ -620,6 +538,7 @@ freebsd/openssl_1.1.1/x86_64:
- branches@libssh/libssh-mirror
- branches@cryptomilk/libssh-mirror
- branches@jjelen/libssh-mirror
- branches@marco.fortina/libssh-mirror
###############################################################################
@@ -628,7 +547,9 @@ freebsd/openssl_1.1.1/x86_64:
# 2024-05-13: These jobs run out of the stages as they take extremely long and
# usually timeout with the update to Gitlab 17.0
.vs:
stage: test
stage: analysis
needs: []
allow_failure: true
cache:
key: vcpkg.${CI_JOB_NAME}
paths:
@@ -658,14 +579,13 @@ freebsd/openssl_1.1.1/x86_64:
- vcpkg install cmocka
- vcpkg install openssl
- vcpkg install zlib
- vcpkg install libfido2
- vcpkg integrate install
- mkdir -p obj; if ($?) {cd obj}; if (! $?) {exit 1}
- cmake
-A $PLATFORM
-DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake
-DPICKY_DEVELOPER=ON
-DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON -DWITH_FIDO2=ON
-DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON
-DUNIT_TESTING=ON ..
visualstudio/x86_64:
@@ -721,38 +641,3 @@ coverity:
when: on_failure
paths:
- obj/cov-int/*.txt
###############################################################################
# MacOS #
###############################################################################
.macos:
extends: .build_options
tags:
- saas-macos-medium-m1
image: macos-14-xcode-15
before_script:
- echo "MacOS runner started"
- brew update
- brew install cmake openssl cmocka doxygen
- mkdir obj && cd obj
only:
- branches@libssh/libssh-mirror
- branches@cryptomilk/libssh-mirror
- branches@jjelen/libssh-mirror
# TODO add -DFUZZ_TESTING=ON clang cant find _LLVMFuzzerInitialize on arm64
macos-m1:
extends: .macos
variables:
HOMEBREW_NO_AUTO_UPDATE: 1
CMAKE_TEST_OPTIONS: "-DUNIT_TESTING=ON"
stage: test
script:
- cmake $CMAKE_OPTIONS .. &&
make -j$(sysctl -n hw.logicalcpu) &&
ctest --output-on-failure
artifacts:
expire_in: 1 week
when: on_failure
paths:
- obj/

View File

@@ -1,42 +0,0 @@
#!/bin/bash
INSTALL_DIR1=${1}
INSTALL_DIR2=${2}
abidiff \
--headers-dir1 "${INSTALL_DIR1}/include/libssh/" \
--headers-dir2 "${INSTALL_DIR2}/include/libssh/" \
"${INSTALL_DIR1}/lib64/libssh.so" \
"${INSTALL_DIR2}/lib64/libssh.so" \
--fail-no-debug-info
abiret=$?
ABIDIFF_ERROR=$(((abiret & 0x01) != 0))
ABIDIFF_USAGE_ERROR=$(((abiret & 0x02) != 0))
ABIDIFF_ABI_CHANGE=$(((abiret & 0x04) != 0))
ABIDIFF_ABI_INCOMPATIBLE_CHANGE=$(((abiret & 0x08) != 0))
ABIDIFF_UNKNOWN_BIT_SET=$(((abiret & 0xf0) != 0))
if [ $ABIDIFF_ERROR -ne 0 ]; then
echo "abidiff reported ABIDIFF_ERROR."
exit 1
fi
if [ $ABIDIFF_USAGE_ERROR -ne 0 ]; then
echo "abidiff reported ABIDIFF_USAGE_ERROR."
exit 1
fi
if [ $ABIDIFF_UNKNOWN_BIT_SET -ne 0 ]; then
echo "abidiff reported ABIDIFF_UNKNOWN_BIT_SET."
exit 1
fi
if [ $ABIDIFF_ABI_INCOMPATIBLE_CHANGE -ne 0 ]; then
echo "abidiff result ABIDIFF_ABI_INCOMPATIBLE_CHANGE, this breaks the API!"
exit 1
fi
if [ $ABIDIFF_ABI_CHANGE -ne 0 ]; then
echo "Ignoring abidiff result ABI_CHANGE"
fi
exit 0

View File

@@ -1,475 +0,0 @@
<?xml version="1.0"?>
<!--
cppcheck library configuration for cmocka
This file provides cppcheck with information about cmocka's assertion functions
and their behavior, particularly that assertion failures do not return.
This helps cppcheck understand that after assert_non_null(ptr), the pointer
is guaranteed to be non-NULL, eliminating false positives like:
- nullPointerArithmeticOutOfMemory
- nullPointer
- etc.
Usage:
cppcheck --library=cmocka.cfg [other options] <source files>
For more information on cppcheck library format, see:
https://cppcheck.sourceforge.io/manual.html#library-configuration
-->
<def format="2">
<!-- Core functions -->
<function name="_fail">
<noreturn>true</noreturn>
<arg nr="1" direction="in">
<not-null/>
</arg>
<arg nr="2" direction="in"/>
</function>
<!-- Boolean assertions -->
<function name="_assert_true">
<arg nr="1" direction="in">
<valid>arg1 != 0</valid>
</arg>
<arg nr="2" direction="in">
<not-null/>
</arg>
<arg nr="3" direction="in">
<not-null/>
</arg>
<arg nr="4" direction="in"/>
</function>
<function name="_assert_false">
<arg nr="1" direction="in">
<valid>arg1 == 0</valid>
</arg>
<arg nr="2" direction="in">
<not-null/>
</arg>
<arg nr="3" direction="in">
<not-null/>
</arg>
<arg nr="4" direction="in"/>
</function>
<!-- Pointer assertions -->
<function name="_assert_ptr_equal_msg">
<arg nr="1" direction="in">
<valid>arg1 == arg2</valid>
</arg>
<arg nr="2" direction="in"/>
<arg nr="3" direction="in">
<not-null/>
</arg>
<arg nr="4" direction="in"/>
<arg nr="5" direction="in"/>
</function>
<function name="_assert_ptr_not_equal_msg">
<arg nr="1" direction="in">
<valid>arg1 != arg2</valid>
</arg>
<arg nr="2" direction="in"/>
<arg nr="3" direction="in">
<not-null/>
</arg>
<arg nr="4" direction="in"/>
<arg nr="5" direction="in"/>
</function>
<!-- Integer assertions -->
<function name="_assert_int_equal">
<arg nr="1" direction="in">
<valid>arg1 == arg2</valid>
</arg>
<arg nr="2" direction="in"/>
<arg nr="3" direction="in">
<not-null/>
</arg>
<arg nr="4" direction="in"/>
</function>
<function name="_assert_int_not_equal">
<arg nr="1" direction="in">
<valid>arg1 != arg2</valid>
</arg>
<arg nr="2" direction="in"/>
<arg nr="3" direction="in">
<not-null/>
</arg>
<arg nr="4" direction="in"/>
</function>
<function name="_assert_uint_equal">
<arg nr="1" direction="in">
<valid>arg1 == arg2</valid>
</arg>
<arg nr="2" direction="in"/>
<arg nr="3" direction="in">
<not-null/>
</arg>
<arg nr="4" direction="in"/>
</function>
<function name="_assert_uint_not_equal">
<arg nr="1" direction="in">
<valid>arg1 != arg2</valid>
</arg>
<arg nr="2" direction="in"/>
<arg nr="3" direction="in">
<not-null/>
</arg>
<arg nr="4" direction="in"/>
</function>
<!-- Float/double assertions -->
<function name="_assert_float_equal">
<arg nr="1" direction="in"/>
<arg nr="2" direction="in"/>
<arg nr="3" direction="in"/>
<arg nr="4" direction="in">
<not-null/>
</arg>
<arg nr="5" direction="in"/>
</function>
<function name="_assert_float_not_equal">
<arg nr="1" direction="in"/>
<arg nr="2" direction="in"/>
<arg nr="3" direction="in"/>
<arg nr="4" direction="in">
<not-null/>
</arg>
<arg nr="5" direction="in"/>
</function>
<function name="_assert_double_equal">
<arg nr="1" direction="in"/>
<arg nr="2" direction="in"/>
<arg nr="3" direction="in"/>
<arg nr="4" direction="in">
<not-null/>
</arg>
<arg nr="5" direction="in"/>
</function>
<function name="_assert_double_not_equal">
<arg nr="1" direction="in"/>
<arg nr="2" direction="in"/>
<arg nr="3" direction="in"/>
<arg nr="4" direction="in">
<not-null/>
</arg>
<arg nr="5" direction="in"/>
</function>
<!-- String assertions -->
<function name="_assert_string_equal">
<arg nr="1" direction="in">
<not-null/>
</arg>
<arg nr="2" direction="in">
<not-null/>
</arg>
<arg nr="3" direction="in">
<not-null/>
</arg>
<arg nr="4" direction="in"/>
</function>
<function name="_assert_string_not_equal">
<arg nr="1" direction="in">
<not-null/>
</arg>
<arg nr="2" direction="in">
<not-null/>
</arg>
<arg nr="3" direction="in">
<not-null/>
</arg>
<arg nr="4" direction="in"/>
</function>
<!-- Memory assertions -->
<function name="_assert_memory_equal">
<arg nr="1" direction="in">
<not-null/>
</arg>
<arg nr="2" direction="in">
<not-null/>
</arg>
<arg nr="3" direction="in"/>
<arg nr="4" direction="in">
<not-null/>
</arg>
<arg nr="5" direction="in"/>
</function>
<function name="_assert_memory_not_equal">
<arg nr="1" direction="in">
<not-null/>
</arg>
<arg nr="2" direction="in">
<not-null/>
</arg>
<arg nr="3" direction="in"/>
<arg nr="4" direction="in">
<not-null/>
</arg>
<arg nr="5" direction="in"/>
</function>
<!-- Range assertions -->
<function name="_assert_int_in_range">
<arg nr="1" direction="in">
<valid>arg2 &lt;= arg1 &amp;&amp; arg1 &lt;= arg3</valid>
</arg>
<arg nr="2" direction="in"/>
<arg nr="3" direction="in"/>
<arg nr="4" direction="in">
<not-null/>
</arg>
<arg nr="5" direction="in"/>
</function>
<function name="_assert_int_not_in_range">
<arg nr="1" direction="in">
<valid>arg1 &lt; arg2 || arg3 &lt; arg1</valid>
</arg>
<arg nr="2" direction="in"/>
<arg nr="3" direction="in"/>
<arg nr="4" direction="in">
<not-null/>
</arg>
<arg nr="5" direction="in"/>
</function>
<function name="_assert_uint_in_range">
<arg nr="1" direction="in">
<valid>arg2 &lt;= arg1 &amp;&amp; arg1 &lt;= arg3</valid>
</arg>
<arg nr="2" direction="in"/>
<arg nr="3" direction="in"/>
<arg nr="4" direction="in">
<not-null/>
</arg>
<arg nr="5" direction="in"/>
</function>
<function name="_assert_uint_not_in_range">
<arg nr="1" direction="in">
<valid>arg1 &lt; arg2 || arg3 &lt; arg1</valid>
</arg>
<arg nr="2" direction="in"/>
<arg nr="3" direction="in"/>
<arg nr="4" direction="in">
<not-null/>
</arg>
<arg nr="5" direction="in"/>
</function>
<function name="_assert_float_in_range">
<arg nr="1" direction="in"/>
<arg nr="2" direction="in"/>
<arg nr="3" direction="in"/>
<arg nr="4" direction="in"/>
<arg nr="5" direction="in">
<not-null/>
</arg>
<arg nr="6" direction="in"/>
</function>
<function name="_assert_float_not_in_range">
<arg nr="1" direction="in"/>
<arg nr="2" direction="in"/>
<arg nr="3" direction="in"/>
<arg nr="4" direction="in"/>
<arg nr="5" direction="in">
<not-null/>
</arg>
<arg nr="6" direction="in"/>
</function>
<!-- Set assertions -->
<function name="_assert_int_in_set">
<arg nr="1" direction="in"/>
<arg nr="2" direction="in">
<not-null/>
</arg>
<arg nr="3" direction="in"/>
<arg nr="4" direction="in">
<not-null/>
</arg>
<arg nr="5" direction="in">
<not-null/>
</arg>
<arg nr="6" direction="in"/>
</function>
<function name="_assert_int_not_in_set">
<arg nr="1" direction="in"/>
<arg nr="2" direction="in">
<not-null/>
</arg>
<arg nr="3" direction="in"/>
<arg nr="4" direction="in">
<not-null/>
</arg>
<arg nr="5" direction="in">
<not-null/>
</arg>
<arg nr="6" direction="in"/>
</function>
<function name="_assert_uint_in_set">
<arg nr="1" direction="in"/>
<arg nr="2" direction="in">
<not-null/>
</arg>
<arg nr="3" direction="in"/>
<arg nr="4" direction="in">
<not-null/>
</arg>
<arg nr="5" direction="in">
<not-null/>
</arg>
<arg nr="6" direction="in"/>
</function>
<function name="_assert_uint_not_in_set">
<arg nr="1" direction="in"/>
<arg nr="2" direction="in">
<not-null/>
</arg>
<arg nr="3" direction="in"/>
<arg nr="4" direction="in">
<not-null/>
</arg>
<arg nr="5" direction="in">
<not-null/>
</arg>
<arg nr="6" direction="in"/>
</function>
<function name="_assert_not_in_set">
<arg nr="1" direction="in"/>
<arg nr="2" direction="in">
<not-null/>
</arg>
<arg nr="3" direction="in"/>
<arg nr="4" direction="in">
<not-null/>
</arg>
<arg nr="5" direction="in">
<not-null/>
</arg>
<arg nr="6" direction="in"/>
</function>
<function name="_assert_float_in_set">
<arg nr="1" direction="in"/>
<arg nr="2" direction="in">
<not-null/>
</arg>
<arg nr="3" direction="in"/>
<arg nr="4" direction="in"/>
<arg nr="5" direction="in">
<not-null/>
</arg>
<arg nr="6" direction="in">
<not-null/>
</arg>
<arg nr="7" direction="in"/>
</function>
<function name="_assert_float_not_in_set">
<arg nr="1" direction="in"/>
<arg nr="2" direction="in">
<not-null/>
</arg>
<arg nr="3" direction="in"/>
<arg nr="4" direction="in"/>
<arg nr="5" direction="in">
<not-null/>
</arg>
<arg nr="6" direction="in">
<not-null/>
</arg>
<arg nr="7" direction="in"/>
</function>
<!-- Return code assertion -->
<function name="_assert_return_code">
<arg nr="1" direction="in">
<valid>0 &lt;= arg1</valid>
</arg>
<arg nr="2" direction="in"/>
<arg nr="3" direction="in">
<not-null/>
</arg>
<arg nr="4" direction="in">
<not-null/>
</arg>
<arg nr="5" direction="in"/>
</function>
<!-- Macro definitions -->
<!-- Boolean macros -->
<define name="assert_true(c)" value="_assert_true(cast_to_uintmax_type(c), #c, __FILE__, __LINE__)"/>
<define name="assert_false(c)" value="_assert_false(cast_to_uintmax_type(c), #c, __FILE__, __LINE__)"/>
<!-- Pointer macros -->
<define name="assert_non_null(c)" value="assert_ptr_not_equal((c), NULL)"/>
<define name="assert_non_null_msg(c, msg)" value="assert_ptr_not_equal_msg((c), NULL, (msg))"/>
<define name="assert_null(c)" value="assert_ptr_equal((c), NULL)"/>
<define name="assert_null_msg(c, msg)" value="assert_ptr_equal_msg((c), NULL, (msg))"/>
<define name="assert_ptr_equal(a, b)" value="assert_ptr_equal_msg((a), (b), NULL)"/>
<define name="assert_ptr_equal_msg(a, b, msg)" value="_assert_ptr_equal_msg((const void*)(a), (const void*)(b), __FILE__, __LINE__, (msg))"/>
<define name="assert_ptr_not_equal(a, b)" value="_assert_ptr_not_equal_msg((const void*)(a), (const void*)(b), __FILE__, __LINE__, NULL)"/>
<define name="assert_ptr_not_equal_msg(a, b, msg)" value="_assert_ptr_not_equal_msg((const void*)(a), (const void*)(b), __FILE__, __LINE__, (msg))"/>
<!-- Integer macros -->
<define name="assert_int_equal(a, b)" value="_assert_int_equal(cast_to_intmax_type(a), cast_to_intmax_type(b), __FILE__, __LINE__)"/>
<define name="assert_int_not_equal(a, b)" value="_assert_int_not_equal(cast_to_intmax_type(a), cast_to_intmax_type(b), __FILE__, __LINE__)"/>
<define name="assert_uint_equal(a, b)" value="_assert_uint_equal(cast_to_uintmax_type(a), cast_to_uintmax_type(b), __FILE__, __LINE__)"/>
<define name="assert_uint_not_equal(a, b)" value="_assert_uint_not_equal(cast_to_uintmax_type(a), cast_to_uintmax_type(b), __FILE__, __LINE__)"/>
<!-- Float/double macros -->
<define name="assert_float_equal(a, b, epsilon)" value="_assert_float_equal((float)(a), (float)(b), (float)(epsilon), __FILE__, __LINE__)"/>
<define name="assert_float_not_equal(a, b, epsilon)" value="_assert_float_not_equal((float)(a), (float)(b), (float)(epsilon), __FILE__, __LINE__)"/>
<define name="assert_double_equal(a, b, epsilon)" value="_assert_double_equal((double)(a), (double)(b), (double)(epsilon), __FILE__, __LINE__)"/>
<define name="assert_double_not_equal(a, b, epsilon)" value="_assert_double_not_equal((double)(a), (double)(b), (double)(epsilon), __FILE__, __LINE__)"/>
<!-- String macros -->
<define name="assert_string_equal(a, b)" value="_assert_string_equal((const char*)(a), (const char*)(b), __FILE__, __LINE__)"/>
<define name="assert_string_not_equal(a, b)" value="_assert_string_not_equal((const char*)(a), (const char*)(b), __FILE__, __LINE__)"/>
<!-- Memory macros -->
<define name="assert_memory_equal(a, b, size)" value="_assert_memory_equal((const void*)(a), (const void*)(b), size, __FILE__, __LINE__)"/>
<define name="assert_memory_not_equal(a, b, size)" value="_assert_memory_not_equal((const void*)(a), (const void*)(b), size, __FILE__, __LINE__)"/>
<!-- Range macros -->
<define name="assert_int_in_range(value, minimum, maximum)" value="_assert_int_in_range(cast_to_intmax_type(value), cast_to_intmax_type(minimum), cast_to_intmax_type(maximum), __FILE__, __LINE__)"/>
<define name="assert_int_not_in_range(value, minimum, maximum)" value="_assert_int_not_in_range(cast_to_intmax_type(value), cast_to_intmax_type(minimum), cast_to_intmax_type(maximum), __FILE__, __LINE__)"/>
<define name="assert_uint_in_range(value, minimum, maximum)" value="_assert_uint_in_range(cast_to_uintmax_type(value), cast_to_uintmax_type(minimum), cast_to_uintmax_type(maximum), __FILE__, __LINE__)"/>
<define name="assert_uint_not_in_range(value, minimum, maximum)" value="_assert_uint_not_in_range(cast_to_uintmax_type(value), cast_to_uintmax_type(minimum), cast_to_uintmax_type(maximum), __FILE__, __LINE__)"/>
<define name="assert_in_range(value, minimum, maximum)" value="assert_uint_in_range(value, minimum, maximum)"/>
<define name="assert_not_in_range(value, minimum, maximum)" value="assert_uint_not_in_range(value, minimum, maximum)"/>
<define name="assert_float_in_range(value, minimum, maximum, epsilon)" value="_assert_float_in_range((double)(value), (double)(minimum), (double)(maximum), (double)(epsilon), __FILE__, __LINE__)"/>
<define name="assert_float_not_in_range(value, minimum, maximum, epsilon)" value="_assert_float_not_in_range((double)(value), (double)(minimum), (double)(maximum), (double)(epsilon), __FILE__, __LINE__)"/>
<!-- Set macros -->
<define name="assert_in_set(value, values, number_of_values)" value="_assert_not_in_set(cast_to_uintmax_type(value), (uintmax_t*)(values), number_of_values, __FILE__, __LINE__, 0)"/>
<define name="assert_not_in_set(value, values, number_of_values)" value="_assert_not_in_set(cast_to_uintmax_type(value), (uintmax_t*)(values), number_of_values, __FILE__, __LINE__, 1)"/>
<define name="assert_int_in_set(value, values, number_of_values)" value="_assert_int_in_set(cast_to_intmax_type(value), (intmax_t*)(values), number_of_values, __FILE__, __LINE__, 0)"/>
<define name="assert_int_not_in_set(value, values, number_of_values)" value="_assert_int_not_in_set(cast_to_intmax_type(value), (intmax_t*)(values), number_of_values, __FILE__, __LINE__, 1)"/>
<define name="assert_uint_in_set(value, values, number_of_values)" value="_assert_uint_in_set(cast_to_uintmax_type(value), (uintmax_t*)(values), number_of_values, __FILE__, __LINE__, 0)"/>
<define name="assert_uint_not_in_set(value, values, number_of_values)" value="_assert_uint_not_in_set(cast_to_uintmax_type(value), (uintmax_t*)(values), number_of_values, __FILE__, __LINE__, 1)"/>
<define name="assert_float_in_set(value, values, number_of_values, epsilon)" value="_assert_float_in_set((double)(value), (double*)(values), number_of_values, (double)(epsilon), __FILE__, __LINE__, 0)"/>
<define name="assert_float_not_in_set(value, values, number_of_values, epsilon)" value="_assert_float_not_in_set((double)(value), (double*)(values), number_of_values, (double)(epsilon), __FILE__, __LINE__, 1)"/>
<!-- Return code macro -->
<define name="assert_return_code(rc, error)" value="_assert_return_code(cast_to_intmax_type(rc), (int32_t)(error), #rc, __FILE__, __LINE__)"/>
</def>

View File

@@ -1,16 +0,0 @@
Add a description of the new feature/bug fix. Reference any relevant bugs.
## Checklist
* [ ] Commits have `Signed-off-by:` with name/author being identical to the commit author
* [ ] Code modified for feature
* [ ] Test suite updated with functionality tests
* [ ] Test suite updated with negative tests
* [ ] Documentation updated
* [ ] The project pipelines timeout is [extended](https://docs.gitlab.com/ee/ci/pipelines/settings.html#set-a-limit-for-how-long-jobs-can-run) at least to 2 hours.
## Reviewer's checklist:
* [ ] Any issues marked for closing are addressed
* [ ] There is a test suite reasonably covering new functionality or modifications
* [ ] Function naming, parameters, return values, types, etc., are consistent and according to [CONTRIBUTING.md](https://gitlab.com/libssh/libssh-mirror/-/blob/master/CONTRIBUTING.md)
* [ ] This feature/change has adequate documentation added
* [ ] No obvious mistakes in the code

View File

@@ -1,6 +1,12 @@
CHANGELOG
=========
version 0.11.1 (released 2024-08-30)
* Fixed default TTY modes that are set when stdin is not connected to tty (#270)
* Fixed zlib cleanup procedure, which could crash on i386
* Various test fixes improving their stability
* Fixed cygwin build
version 0.11.0 (released 2024-07-31)
* Deprecations and Removals:
* Dropped support for DSA

View File

@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.14.0)
cmake_minimum_required(VERSION 3.12.0)
# Specify search path for CMake modules to be loaded by include()
# and find_package()
@@ -9,7 +9,7 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules")
include(DefineCMakeDefaults)
include(DefineCompilerFlags)
project(libssh VERSION 0.11.00 LANGUAGES C)
project(libssh VERSION 0.11.1 LANGUAGES C CXX)
# global needed variable
set(APPLICATION_NAME ${PROJECT_NAME})
@@ -21,7 +21,7 @@ set(APPLICATION_NAME ${PROJECT_NAME})
# Increment AGE. Set REVISION to 0
# If the source code was changed, but there were no interface changes:
# Increment REVISION.
set(LIBRARY_VERSION "4.10.0")
set(LIBRARY_VERSION "4.10.1")
set(LIBRARY_SOVERSION "4")
# where to look first for cmake modules, before ${CMAKE_ROOT}/Modules/ is checked
@@ -41,8 +41,6 @@ macro_ensure_out_of_source_build("${PROJECT_NAME} requires an out of source buil
# Copy library files to a lib sub-directory
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib")
set(LIBSSSH_PC_REQUIRES_PRIVATE "")
# search for libraries
if (WITH_ZLIB)
find_package(ZLIB REQUIRED)
@@ -68,7 +66,6 @@ find_package(Threads)
if (WITH_GSSAPI)
find_package(GSSAPI)
list(APPEND LIBSSH_PC_REQUIRES_PRIVATE ${GSSAPI_PC_REQUIRES})
endif (WITH_GSSAPI)
if (WITH_NACL)
@@ -78,16 +75,6 @@ if (WITH_NACL)
endif (NOT NACL_FOUND)
endif (WITH_NACL)
if (WITH_FIDO2)
find_package(libfido2)
if (LIBFIDO2_FOUND)
set(HAVE_LIBFIDO2 ON)
else (LIBFIDO2_FOUND)
set(HAVE_LIBFIDO2 OFF)
message(WARNING "libfido2 was not found. Internal support for interacting with FIDO2/U2F devices using the USB HID protocol will not be available.")
endif (LIBFIDO2_FOUND)
endif (WITH_FIDO2)
# Disable symbol versioning in non UNIX platforms
if (UNIX)
find_package(ABIMap 0.3.1)
@@ -203,13 +190,12 @@ endif (WITH_SYMBOL_VERSIONING AND ABIMAP_FOUND)
# Coverage
if (WITH_COVERAGE)
ENABLE_LANGUAGE(CXX)
include(CodeCoverage)
setup_target_for_coverage_lcov(
NAME "coverage"
EXECUTABLE make test
DEPENDENCIES ssh tests)
set(GCOVR_ADDITIONAL_ARGS --xml-pretty --exclude-unreachable-branches --print-summary --gcov-ignore-parse-errors)
set(GCOVR_ADDITIONAL_ARGS --xml-pretty --exclude-unreachable-branches --print-summary)
setup_target_for_coverage_gcovr_xml(
NAME "coverage_xml"
EXECUTABLE make test
@@ -248,10 +234,6 @@ message(STATUS "Client code testing: ${CLIENT_TESTING}")
message(STATUS "Blowfish cipher support: ${HAVE_BLOWFISH}")
message(STATUS "PKCS #11 URI support: ${WITH_PKCS11_URI}")
message(STATUS "With PKCS #11 provider support: ${WITH_PKCS11_PROVIDER}")
message(STATUS "With FIDO2/U2F support: ${WITH_FIDO2}")
if (WITH_FIDO2)
message(STATUS "With libfido2 (internal usb-hid support): ${HAVE_LIBFIDO2}")
endif (WITH_FIDO2)
set(_SERVER_TESTING OFF)
if (WITH_SERVER)
set(_SERVER_TESTING ${SERVER_TESTING})
@@ -266,15 +248,9 @@ message(STATUS "Benchmarks: ${WITH_BENCHMARKS}")
message(STATUS "Symbol versioning: ${WITH_SYMBOL_VERSIONING}")
message(STATUS "Allow ABI break: ${WITH_ABI_BREAK}")
message(STATUS "Release is final: ${WITH_FINAL}")
if (WITH_HERMETIC_USR)
message(STATUS "User global client config: ${USR_GLOBAL_CLIENT_CONFIG}")
endif ()
message(STATUS "Global client config: ${GLOBAL_CLIENT_CONFIG}")
if (WITH_SERVER)
if (WITH_HERMETIC_USR)
message(STATUS "User global bind config: ${USR_GLOBAL_BIND_CONFIG}")
endif ()
message(STATUS "Global bind config: ${GLOBAL_BIND_CONFIG}")
message(STATUS "Global bind config: ${GLOBAL_BIND_CONFIG}")
endif()
message(STATUS "********************************************")

View File

@@ -117,25 +117,6 @@ libssh Developer's Certificate of Origin for each patch, or inside each
patch. Just the sign-off message is all that is required once we've
received the initial email.
## Continuous Integration
Contributing patches through Merge Request workflow on Gitlab allows us to run
various checks on various configuration as part of Gitlab CI. Unfortunately,
some pipelines are slower (as they involve building dependencies) so the default
timeout of 1 hour needs to be extended at least to 2 hours. This can be done in
project settings of your libssh fork:
https://docs.gitlab.com/ee/ci/pipelines/settings.html#set-a-limit-for-how-long-jobs-can-run
Otherwise you will encounter errors like these, usually on visualstudio builds:
```
ERROR: Job failed: execution took longer than 1h0m0s seconds
The script exceeded the maximum execution time set for the job
```
Note, that the built dependencies are cached so after successful build in your
namespace, the rebuilds should be much faster.
# Coding conventions in the libssh tree
@@ -536,37 +517,6 @@ Bad example:
break;
}
## ABI Versioning and Symbol Management
To maintain [ABI](https://en.wikipedia.org/wiki/Application_binary_interface) stability
and ensure backward compatibility, libssh uses **symbol versioning** to track and manage
exported functions and variables. This allows libssh to introduce new symbols or modify
existing functions in an ABI-compatible way.
When introducing a new symbol:
1. Use the `LIBSSH_API` macro to mark the symbol as part of the public API.
2. If you have [abimap](https://github.com/ansasaki/abimap) installed, the new symbols are
automatically generated in the `src/libssh_dev.map` file in the **build** directory and used automatically for building the updated library. But, depending on the version of `abimap` under use, you may face linker errors like: `unable to find version dependency LIBSSH_4_9_0`. In this case, you need to manually replace the existing `src/libssh.map` file with the generated `libssh_dev.map` file to update the symbol versioning.
3. If you do not have abimap installed, the modified/added symbols must manually be added to the
`src/libssh.map` file. The symbols must be added in the following format (assuming that 4_10_0 is the latest released version):
```
LIBSSH_AFTER_4_10_0
{
global:
new_function;
new_variable;
} LIBSSH_4_10_0;
```
4. After following either of the above steps, the library can be successfully built and
tested without any linker errors.
5. When submitting the patch, make sure that any new symbols have been added to `libssh.map` as described in step 3, so that the new additions may not be excluded from the next release due to human error.
Also, to maintain ABI compatibility, existing symbols must not be removed. Instead, they can
be marked as deprecated using the `LIBSSH_DEPRECATED` macro. This allows the symbol to be
removed in a future release without breaking the ABI.
Have fun and happy libssh hacking!

View File

@@ -92,12 +92,9 @@ if (UNIX)
endif (WITH_STACK_PROTECTOR_STRONG)
if (NOT WINDOWS AND NOT CYGWIN)
# apple m* chips do not support this option
if (NOT ${CMAKE_SYSTEM_PROCESSOR} STREQUAL arm64)
check_c_compiler_flag_ssp("-fstack-clash-protection" WITH_STACK_CLASH_PROTECTION)
if (WITH_STACK_CLASH_PROTECTION)
list(APPEND SUPPORTED_COMPILER_FLAGS "-fstack-clash-protection")
endif()
check_c_compiler_flag_ssp("-fstack-clash-protection" WITH_STACK_CLASH_PROTECTION)
if (WITH_STACK_CLASH_PROTECTION)
list(APPEND SUPPORTED_COMPILER_FLAGS "-fstack-clash-protection")
endif()
endif()

View File

@@ -104,11 +104,6 @@ if (OPENSSL_FOUND)
check_function_exists(RAND_priv_bytes HAVE_OPENSSL_RAND_PRIV_BYTES)
check_function_exists(EVP_chacha20 HAVE_OPENSSL_EVP_CHACHA20)
# Check for ML-KEM768 availability (OpenSSL 3.5+)
if (OPENSSL_VERSION VERSION_GREATER_EQUAL "3.5.0")
set(HAVE_MLKEM 1)
endif ()
unset(CMAKE_REQUIRED_INCLUDES)
unset(CMAKE_REQUIRED_LIBRARIES)
endif()
@@ -139,7 +134,6 @@ check_function_exists(strncpy HAVE_STRNCPY)
check_function_exists(strndup HAVE_STRNDUP)
check_function_exists(strtoull HAVE_STRTOULL)
check_function_exists(explicit_bzero HAVE_EXPLICIT_BZERO)
check_function_exists(memset_explicit HAVE_MEMSET_EXPLICIT)
check_function_exists(memset_s HAVE_MEMSET_S)
if (HAVE_GLOB_H)
@@ -232,7 +226,6 @@ if (GCRYPT_FOUND)
endif (GCRYPT_VERSION VERSION_GREATER "1.4.6")
if (NOT GCRYPT_VERSION VERSION_LESS "1.7.0")
set(HAVE_GCRYPT_CHACHA_POLY 1)
set(HAVE_GCRYPT_CURVE25519 1)
endif (NOT GCRYPT_VERSION VERSION_LESS "1.7.0")
endif (GCRYPT_FOUND)
@@ -243,13 +236,6 @@ if (MBEDTLS_FOUND)
set(CMAKE_REQUIRED_INCLUDES "${MBEDTLS_INCLUDE_DIR}/mbedtls")
check_include_file(chacha20.h HAVE_MBEDTLS_CHACHA20_H)
check_include_file(poly1305.h HAVE_MBEDTLS_POLY1305_H)
if (MBEDTLS_VERSION VERSION_LESS "3.0.0")
check_symbol_exists(MBEDTLS_ECP_DP_CURVE25519_ENABLED "config.h" HAVE_MBEDTLS_CURVE25519)
else()
check_symbol_exists(MBEDTLS_ECP_DP_CURVE25519_ENABLED "mbedtls_config.h" HAVE_MBEDTLS_CURVE25519)
endif()
if (WITH_BLOWFISH_CIPHER)
check_include_file(blowfish.h HAVE_BLOWFISH)
endif()

View File

@@ -13,7 +13,6 @@ option(WITH_INTERNAL_DOC "Compile doxygen internal documentation" OFF)
option(BUILD_SHARED_LIBS "Build shared libraries" ON)
option(WITH_PKCS11_URI "Build with PKCS#11 URI support" OFF)
option(WITH_PKCS11_PROVIDER "Use the PKCS#11 provider for accessing pkcs11 objects" OFF)
option(WITH_FIDO2 "Build with FIDO2/U2F support" OFF)
option(UNIT_TESTING "Build with unit tests" OFF)
option(CLIENT_TESTING "Build with client tests; requires openssh" OFF)
option(SERVER_TESTING "Build with server tests; requires openssh and dropbear" OFF)
@@ -28,7 +27,6 @@ option(WITH_INSECURE_NONE "Enable insecure none cipher and MAC algorithms (not s
option(WITH_EXEC "Enable libssh to execute arbitrary commands from configuration files or options (match exec, proxy commands and OpenSSH-based proxy-jumps)." ON)
option(FUZZ_TESTING "Build with fuzzer for the server and client (automatically enables none cipher!)" OFF)
option(PICKY_DEVELOPER "Build with picky developer flags" OFF)
option(WITH_HERMETIC_USR "Build with support for hermetic /usr/" OFF)
if (WITH_ZLIB)
set(WITH_LIBZ ON)
@@ -61,11 +59,6 @@ if (NOT GLOBAL_CLIENT_CONFIG)
set(GLOBAL_CLIENT_CONFIG "/etc/ssh/ssh_config")
endif (NOT GLOBAL_CLIENT_CONFIG)
if (WITH_HERMETIC_USR)
set(USR_GLOBAL_BIND_CONFIG "/usr${GLOBAL_BIND_CONFIG}")
set(USR_GLOBAL_CLIENT_CONFIG "/usr${GLOBAL_CLIENT_CONFIG}")
endif (WITH_HERMETIC_USR)
if (FUZZ_TESTING)
set(WITH_INSECURE_NONE ON)
endif (FUZZ_TESTING)

View File

@@ -38,16 +38,14 @@ First, you need to configure the compilation, using CMake. Go inside the
`build` dir. Create it if it doesn't exist.
GNU/Linux, MacOS X, MSYS/MinGW:
cmake -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Debug ..
cmake -DUNIT_TESTING=ON -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Debug ..
make
On Windows you should choose a makefile generator with -G or use
cmake-gui.exe ..
To enable building tests use -DUNIT_TESTING=ON. For this, the
[cmocka](https://cmocka.org) dependency is required.
To enable additional client tests against a local OpenSSH server, add the
compile option -DCLIENT_TESTING=ON. These tests require an OpenSSH
server package and some wrapper libraries (see optional requirements) to

View File

@@ -117,7 +117,6 @@ function(ADD_CMOCKA_TEST _TARGET_NAME)
${TARGET_SYSTEM_EMULATOR} ${_TARGET_NAME}
)
if (WITH_COVERAGE)
ENABLE_LANGUAGE(CXX)
include(CodeCoverage)
append_coverage_compiler_flags_to_target(${_TARGET_NAME})
endif (WITH_COVERAGE)

View File

@@ -39,15 +39,6 @@ find_path(GCRYPT_INCLUDE_DIR
include
)
find_path(GCRYPT_ERROR_INCLUDE_DIR
NAMES
gpg-error.h
HINTS
${_GCRYPT_ROOT_HINTS_AND_PATHS}
PATH_SUFFIXES
include
)
find_library(GCRYPT_LIBRARY
NAMES
gcrypt
@@ -65,10 +56,8 @@ find_library(GCRYPT_ERROR_LIBRARY
libgpg-error6-0
HINTS
${_GCRYPT_ROOT_HINTS_AND_PATHS}
PATH_SUFFIXES
lib
)
set(GCRYPT_LIBRARIES ${GCRYPT_ERROR_LIBRARY} ${GCRYPT_LIBRARY})
set(GCRYPT_LIBRARIES ${GCRYPT_LIBRARY} ${GCRYPT_ERROR_LIBRARY})
if (GCRYPT_INCLUDE_DIR)
file(STRINGS "${GCRYPT_INCLUDE_DIR}/gcrypt.h" _gcrypt_version_str REGEX "^#define GCRYPT_VERSION \"[0-9]+\\.[0-9]+\\.[0-9]")
@@ -94,25 +83,5 @@ else (GCRYPT_VERSION)
GCRYPT_LIBRARIES)
endif (GCRYPT_VERSION)
# show the GCRYPT_INCLUDE_DIRS, GCRYPT_LIBRARIES and GCRYPT_ERROR_INCLUDE_DIR variables only in the advanced view
mark_as_advanced(GCRYPT_INCLUDE_DIR GCRYPT_ERROR_INCLUDE_DIR GCRYPT_LIBRARIES)
if(GCRYPT_FOUND)
if(NOT TARGET libgcrypt::libgcrypt)
add_library(libgcrypt::libgcrypt UNKNOWN IMPORTED)
set_target_properties(libgcrypt::libgcrypt PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${GCRYPT_INCLUDE_DIR}"
INTERFACE_LINK_LIBRARIES libgcrypt::libgcrypt
IMPORTED_LINK_INTERFACE_LANGUAGES "C"
IMPORTED_LOCATION "${GCRYPT_LIBRARY}")
endif()
if(NOT TARGET libgpg-error::libgpg-error)
add_library(libgpg-error::libgpg-error UNKNOWN IMPORTED)
set_target_properties(libgpg-error::libgpg-error PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${GCRYPT_ERROR_INCLUDE_DIR}"
INTERFACE_LINK_LIBRARIES libgpg-error::libgpg-error
IMPORTED_LINK_INTERFACE_LANGUAGES "C"
IMPORTED_LOCATION "${GCRYPT_ERROR_LIBRARY}")
endif()
endif()
# show the GCRYPT_INCLUDE_DIRS and GCRYPT_LIBRARIES variables only in the advanced view
mark_as_advanced(GCRYPT_INCLUDE_DIR GCRYPT_LIBRARIES)

View File

@@ -11,8 +11,6 @@
# GSSAPI_INCLUDE_DIR - the GSSAPI include directory
# GSSAPI_LIBRARIES - Link these to use GSSAPI
# GSSAPI_DEFINITIONS - Compiler switches required for using GSSAPI
# GSSAPI_PC_REQUIRES - pkg-config module name if found, needed for
# Requires.private for static linking
#
#=============================================================================
# Copyright (c) 2013 Andreas Schneider <asn@cryptomilk.org>
@@ -26,23 +24,12 @@
#=============================================================================
#
set(_mit_modname "mit-krb5-gssapi")
set(_heimdal_modname "heimdal-gssapi")
if(NOT _GSSAPI_ROOT_HINTS AND NOT _GSSAPI_ROOT_PATHS)
find_package(PkgConfig QUIET)
if (PKG_CONFIG_FOUND)
pkg_search_module(_GSSAPI ${_mit_modname} ${_heimdal_modname})
endif()
endif()
find_path(GSSAPI_ROOT_DIR
NAMES
include/gssapi.h
include/gssapi/gssapi.h
HINTS
${_GSSAPI_ROOT_HINTS}
"${_GSSAPI_INCLUDEDIR}"
PATHS
${_GSSAPI_ROOT_PATHS}
)
@@ -330,15 +317,9 @@ endif (GSSAPI_FLAVOR_HEIMDAL)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(GSSAPI DEFAULT_MSG GSSAPI_LIBRARIES GSSAPI_INCLUDE_DIR)
if(GSSAPI_FOUND)
if(_GSSAPI_FOUND) # via pkg-config
if (GSSAPI_FLAVOR_MIT)
set(GSSAPI_PC_REQUIRES ${_mit_modname})
elseif (GSSAPI_FLAVOR_HEIMDAL)
set(GSSAPI_PC_REQUIRES ${_heimdal_modname})
endif()
endif()
endif()
if (GSSAPI_INCLUDE_DIRS AND GSSAPI_LIBRARIES)
set(GSSAPI_FOUND TRUE)
endif (GSSAPI_INCLUDE_DIRS AND GSSAPI_LIBRARIES)
# show the GSSAPI_INCLUDE_DIR and GSSAPI_LIBRARIES variables only in the advanced view
mark_as_advanced(GSSAPI_INCLUDE_DIR GSSAPI_LIBRARIES)
# show the GSSAPI_INCLUDE_DIRS and GSSAPI_LIBRARIES variables only in the advanced view
mark_as_advanced(GSSAPI_INCLUDE_DIRS GSSAPI_LIBRARIES)

View File

@@ -72,23 +72,21 @@ find_library(MBEDTLS_X509_LIBRARY
set(MBEDTLS_LIBRARIES ${MBEDTLS_SSL_LIBRARY} ${MBEDTLS_CRYPTO_LIBRARY}
${MBEDTLS_X509_LIBRARY})
# mbedtls 2.8
if (MBEDTLS_INCLUDE_DIR AND EXISTS "${MBEDTLS_INCLUDE_DIR}/mbedtls/version.h")
# mbedtls 2.8
file(STRINGS "${MBEDTLS_INCLUDE_DIR}/mbedtls/version.h" _mbedtls_version_str REGEX
"^#[\t ]*define[\t ]+MBEDTLS_VERSION_STRING[\t ]+\"[0-9]+.[0-9]+.[0-9]+\"")
string(REGEX REPLACE "^.*MBEDTLS_VERSION_STRING.*([0-9]+\\.[0-9]+\\.[0-9]+).*$"
string(REGEX REPLACE "^.*MBEDTLS_VERSION_STRING.*([0-9]+.[0-9]+.[0-9]+).*"
"\\1" MBEDTLS_VERSION "${_mbedtls_version_str}")
endif()
# mbedtls 3.6
if (NOT MBEDTLS_VERSION AND MBEDTLS_INCLUDE_DIR AND EXISTS "${MBEDTLS_INCLUDE_DIR}/mbedtls/build_info.h")
file(STRINGS "${MBEDTLS_INCLUDE_DIR}/mbedtls/build_info.h" _mbedtls_version_str REGEX
elseif (MBEDTLS_INCLUDE_DIR AND EXISTS "${MBEDTLS_INCLUDE_DIR}/mbedtls/build_info.h")
# mbedtls 3.6
file(STRINGS "${MBEDTLS_INCLUDE_DIR}/mbedtls/version.h" _mbedtls_version_str REGEX
"^#[\t ]*define[\t ]+MBEDTLS_VERSION_STRING[\t ]+\"[0-9]+.[0-9]+.[0-9]+\"")
string(REGEX REPLACE "^.*MBEDTLS_VERSION_STRING.*([0-9]+\\.[0-9]+\\.[0-9]+).*$"
string(REGEX REPLACE "^.*MBEDTLS_VERSION_STRING.*([0-9]+.[0-9]+.[0-9]+).*"
"\\1" MBEDTLS_VERSION "${_mbedtls_version_str}")
endif()
endif ()
include(FindPackageHandleStandardArgs)
if (MBEDTLS_VERSION)
@@ -112,32 +110,3 @@ endif (MBEDTLS_VERSION)
# show the MBEDTLS_INCLUDE_DIRS and MBEDTLS_LIBRARIES variables only in the advanced view
mark_as_advanced(MBEDTLS_INCLUDE_DIR MBEDTLS_LIBRARIES)
if(MBEDTLS_FOUND)
if(NOT TARGET MbedTLS::mbedcrypto)
add_library(MbedTLS::mbedcrypto UNKNOWN IMPORTED)
set_target_properties(MbedTLS::mbedcrypto PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${MBEDTLS_INCLUDE_DIR}"
INTERFACE_LINK_LIBRARIES MbedTLS::mbedcrypto
IMPORTED_LINK_INTERFACE_LANGUAGES "C"
IMPORTED_LOCATION "${MBEDTLS_CRYPTO_LIBRARY}")
endif()
if(NOT TARGET MbedTLS::mbedx509)
add_library(MbedTLS::mbedx509 UNKNOWN IMPORTED)
set_target_properties(MbedTLS::mbedx509 PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${MBEDTLS_INCLUDE_DIR}"
INTERFACE_LINK_LIBRARIES MbedTLS::mbedx509
IMPORTED_LINK_INTERFACE_LANGUAGES "C"
IMPORTED_LOCATION "${MBEDTLS_X509_LIBRARY}")
endif()
if(NOT TARGET MbedTLS::mbedtls)
add_library(MbedTLS::mbedtls UNKNOWN IMPORTED)
set_target_properties(MbedTLS::mbedtls PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${MBEDTLS_INCLUDE_DIR}"
INTERFACE_LINK_LIBRARIES MbedTLS::mbedtls
IMPORTED_LINK_INTERFACE_LANGUAGES "C"
IMPORTED_LOCATION "${MBEDTLS_LIBRARY}")
endif()
endif()

View File

@@ -1,63 +0,0 @@
# - Try to find libfido2
# Once done this will define
#
# LIBFIDO2_ROOT_DIR - Set this variable to the root installation of libfido2
#
# Read-Only variables:
# LIBFIDO2_FOUND - system has libfido2
# LIBFIDO2_INCLUDE_DIR - the libfido2 include directory
# LIBFIDO2_LIBRARIES - Link these to use libfido2
#
# The libfido2 library provides support for communicating
# with FIDO2/U2F devices over USB/NFC.
#
# Copyright (c) 2025 Praneeth Sarode <praneethsarode@gmail.com>
#
# Redistribution and use is allowed according to the terms of the New
# BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
#
set(_LIBFIDO2_ROOT_HINTS
$ENV{LIBFIDO2_ROOT_DIR}
${LIBFIDO2_ROOT_DIR}
)
set(_LIBFIDO2_ROOT_PATHS
"$ENV{PROGRAMFILES}/libfido2"
)
set(_LIBFIDO2_ROOT_HINTS_AND_PATHS
HINTS ${_LIBFIDO2_ROOT_HINTS}
PATHS ${_LIBFIDO2_ROOT_PATHS}
)
find_path(LIBFIDO2_INCLUDE_DIR
NAMES
fido.h
HINTS
${_LIBFIDO2_ROOT_HINTS_AND_PATHS}
PATH_SUFFIXES
include
)
find_library(LIBFIDO2_LIBRARY
NAMES
fido2
HINTS
${_LIBFIDO2_ROOT_HINTS_AND_PATHS}
PATH_SUFFIXES
lib
lib64
)
set(LIBFIDO2_LIBRARIES
${LIBFIDO2_LIBRARY}
)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(libfido2 DEFAULT_MSG LIBFIDO2_LIBRARIES LIBFIDO2_INCLUDE_DIR)
# show the LIBFIDO2_INCLUDE_DIR and LIBFIDO2_LIBRARIES variables only in the advanced view
mark_as_advanced(LIBFIDO2_INCLUDE_DIR LIBFIDO2_LIBRARIES)

View File

@@ -9,11 +9,9 @@
#cmakedefine SOURCEDIR "${SOURCEDIR}"
/* Global bind configuration file path */
#cmakedefine USR_GLOBAL_BIND_CONFIG "${USR_GLOBAL_BIND_CONFIG}"
#cmakedefine GLOBAL_BIND_CONFIG "${GLOBAL_BIND_CONFIG}"
/* Global client configuration file path */
#cmakedefine USR_GLOBAL_CLIENT_CONFIG "${USR_GLOBAL_CLIENT_CONFIG}"
#cmakedefine GLOBAL_CLIENT_CONFIG "${GLOBAL_CLIENT_CONFIG}"
/************************** HEADER FILES *************************/
@@ -87,9 +85,6 @@
/* Define to 1 if you have elliptic curve cryptography in openssl */
#cmakedefine HAVE_OPENSSL_ECC 1
/* Define to 1 if mbedTLS supports curve25519 */
#cmakedefine HAVE_MBEDTLS_CURVE25519 1
/* Define to 1 if you have elliptic curve cryptography in gcrypt */
#cmakedefine HAVE_GCRYPT_ECC 1
@@ -102,9 +97,6 @@
/* Define to 1 if you have gcrypt with ChaCha20/Poly1305 support */
#cmakedefine HAVE_GCRYPT_CHACHA_POLY 1
/* Define to 1 if you have gcrypt with curve25519 support */
#cmakedefine HAVE_GCRYPT_CURVE25519
/*************************** FUNCTIONS ***************************/
/* Define to 1 if you have the `EVP_chacha20' function. */
@@ -179,9 +171,6 @@
/* Define to 1 if you have the `explicit_bzero' function. */
#cmakedefine HAVE_EXPLICIT_BZERO 1
/* Define to 1 if you have the `memset_explicit' function. */
#cmakedefine HAVE_MEMSET_EXPLICIT 1
/* Define to 1 if you have the `memset_s' function. */
#cmakedefine HAVE_MEMSET_S 1
@@ -194,9 +183,6 @@
/* Define to 1 if we have support for blowfish */
#cmakedefine HAVE_BLOWFISH 1
/* Define to 1 if we have support for ML-KEM */
#cmakedefine HAVE_MLKEM 1
/*************************** LIBRARIES ***************************/
/* Define to 1 if you have the `crypto' library (-lcrypto). */
@@ -214,10 +200,6 @@
/* Define to 1 if you have the `cmocka' library (-lcmocka). */
#cmakedefine HAVE_CMOCKA 1
/* Define to 1 if you have the `libfido2' library (-lfido2).
* This is required for interacting with FIDO2/U2F devices over USB-HID. */
#cmakedefine HAVE_LIBFIDO2 1
/**************************** OPTIONS ****************************/
#cmakedefine HAVE_GCC_THREAD_LOCAL_STORAGE 1
@@ -284,9 +266,6 @@
/* Define to 1 if we want to build a support for PKCS #11 provider. */
#cmakedefine WITH_PKCS11_PROVIDER 1
/* Define to 1 if you want to enable FIDO2/U2F support */
#cmakedefine WITH_FIDO2 1
/*************************** ENDIAN *****************************/
/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most

View File

@@ -1,225 +1,91 @@
#
# Build the documentation
#
# To build the documentation with a local doxygen-awesome-css tarball:
#
# cmake -S . -B obj \
# -DDOXYGEN_AWESOME_CSS_TARBALL=/path/to/doxygen-awesome-css.tar.gz cmake
# --build obj --target docs
#
# The tarball can be downloaded from:
# https://github.com/jothepro/doxygen-awesome-css/archive/refs/tags/v2.4.1.tar.gz
#
if (${CMAKE_VERSION} VERSION_GREATER "3.8.99")
find_package(Doxygen)
if (DOXYGEN_FOUND)
# Allow specifying a local tarball for doxygen-awesome-css (useful for
# packaging)
if (NOT DEFINED DOXYGEN_AWESOME_CSS_TARBALL)
set(DOXYGEN_AWESOME_CSS_TARBALL
"https://github.com/jothepro/doxygen-awesome-css/archive/refs/tags/v2.4.1.tar.gz"
)
endif ()
include(FetchContent)
FetchContent_Declare(
doxygen-awesome-css URL ${DOXYGEN_AWESOME_CSS_TARBALL}
DOWNLOAD_EXTRACT_TIMESTAMP TRUE)
FetchContent_MakeAvailable(doxygen-awesome-css)
# Get the path to doxygen-awesome.css
FetchContent_GetProperties(doxygen-awesome-css SOURCE_DIR AWESOME_CSS_DIR)
# Project title shown in documentation
set(DOXYGEN_PROJECT_NAME ${PROJECT_NAME})
# Project version number shown in documentation
set(DOXYGEN_PROJECT_NUMBER ${PROJECT_VERSION})
# Brief description shown below project name
set(DOXYGEN_PROJECT_BRIEF "The SSH library")
# Project favicon (browser tab icon)
set(DOXYGEN_PROJECT_ICON ${CMAKE_CURRENT_SOURCE_DIR}/favicon.png)
# Number of spaces used for indentation in code blocks
set(DOXYGEN_TAB_SIZE 4)
# Generate output optimized for C (vs C++)
set(DOXYGEN_OPTIMIZE_OUTPUT_FOR_C YES)
# Enable parsing of markdown in comments
set(DOXYGEN_MARKDOWN_SUPPORT YES)
# Warn about undocumented members to improve documentation quality
set(DOXYGEN_WARN_IF_UNDOCUMENTED YES)
# Do not extract private class members
set(DOXYGEN_EXTRACT_PRIVATE NO)
# Do not include internal documentation
set(DOXYGEN_INTERNAL_DOCS NO)
# Disable built-in clipboard (using doxygen-awesome extension instead)
set(DOXYGEN_HTML_COPY_CLIPBOARD NO)
# Disable page outline panel (using interactive TOC extension instead)
set(DOXYGEN_PAGE_OUTLINE_PANEL NO)
set(DOXYGEN_FULL_PATH_NAMES NO)
set(DOXYGEN_GENERATE_TAGFILE "tags.xml")
# Required configuration for doxygen-awesome-css theme Generate treeview
# sidebar for navigation
set(DOXYGEN_GENERATE_TREEVIEW YES)
# Enable default index pages
set(DOXYGEN_DISABLE_INDEX NO)
# Use top navigation bar instead of full sidebar (required for theme
# compatibility)
set(DOXYGEN_FULL_SIDEBAR NO)
# Use light color style (required for Doxygen >= 1.9.5)
set(DOXYGEN_HTML_COLORSTYLE LIGHT)
# Disable diagram generation (not relevant for C projects)
set(DOXYGEN_HAVE_DOT NO)
set(DOXYGEN_CLASS_DIAGRAMS NO)
set(DOXYGEN_CALL_GRAPH NO)
set(DOXYGEN_CALLER_GRAPH NO)
# Preprocessor defines to use when parsing code
set(DOXYGEN_PREDEFINED DOXYGEN WITH_SERVER WITH_SFTP
set(DOXYGEN_PREDEFINED DOXYGEN
WITH_SERVER
WITH_SFTP
PRINTF_ATTRIBUTE\(x,y\))
set(DOXYGEN_DOT_GRAPH_MAX_NODES 100)
# Exclude patterns for files we don't want to document
set(DOXYGEN_EXCLUDE_PATTERNS */src/external/* fe25519.h ge25519.h sc25519.h
blf.h)
# Exclude internal structures from documentation
set(DOXYGEN_EXCLUDE_SYMBOLS_STRUCTS
chacha20_poly1305_keysched,
dh_ctx,
dh_ctx,
dh_keypair,
error_struct,
packet_struct,
pem_get_password_struct,
ssh_tokens_st,
sftp_attributes_struct,
sftp_client_message_struct,
sftp_dir_struct,
sftp_ext_struct,
sftp_file_struct,
sftp_message_struct,
sftp_packet_struct,
sftp_request_queue_struct,
sftp_session_struct,
sftp_status_message_struct,
ssh_agent_state_struct,
ssh_agent_struct,
ssh_auth_auto_state_struct,
ssh_auth_request,
ssh_bind_config_keyword_table_s,
ssh_bind_config_match_keyword_table_s,
ssh_bind_struct,
ssh_buffer_struct,
ssh_channel_callbacks_struct,
ssh_channel_read_termination_struct,
ssh_channel_request,
ssh_channel_request_open,
ssh_channel_struct,
ssh_cipher_struct,
ssh_common_struct,
ssh_config_keyword_table_s,
ssh_config_match_keyword_table_s,
ssh_connector_struct,
ssh_counter_struct,
ssh_crypto_struct,
ssh_event_fd_wrapper,
ssh_event_struct,
ssh_global_request,
ssh_gssapi_struct,
ssh_hmac_struct,
ssh_iterator,
ssh_kbdint_struct,
ssh_kex_struct,
ssh_key_struct,
ssh_knownhosts_entry,
ssh_list,
ssh_mac_ctx_struct,
ssh_message_struct,
ssh_packet_callbacks_struct,
ssh_packet_header,
ssh_poll_ctx_struct,
ssh_poll_handle_struct,
ssh_pollfd_struct,
ssh_private_key_struct,
ssh_public_key_struct,
ssh_scp_struct,
ssh_service_request,
ssh_session_struct,
ssh_signature_struct,
ssh_socket_struct,
ssh_string_struct,
ssh_threads_callbacks_struct,
ssh_timestamp)
set(DOXYGEN_EXCLUDE_SYMBOLS_MACRO
SSH_FXP*,
SSH_SOCKET*,
SERVERBANNER,
SOCKOPT_TYPE_ARG4,
SSH_FILEXFER*,
SSH_FXF*,
SSH_S_*,
SFTP_*,
NSS_BUFLEN_PASSWD,
CLOCK,
MAX_LINE_SIZE,
PKCS11_URI,
KNOWNHOSTS_MAXTYPES)
set(DOXYGEN_EXCLUDE_SYMBOLS_TYPEDEFS
sftp_attributes,
sftp_client_message,
sftp_dir,
sftp_ext,
sftp_file,
sftp_message,
sftp_packet,
sftp_request_queue,
sftp_session,
sftp_status_message,
sftp_statvfs_t,
poll_fn,
ssh_callback_int,
ssh_callback_data,
ssh_callback_int_int,
ssh_message_callback,
ssh_channel_callback_int,
ssh_channel_callback_data,
ssh_callbacks,
ssh_gssapi_select_oid_callback,
ssh_gssapi_accept_sec_ctx_callback,
ssh_gssapi_verify_mic_callback,
ssh_server_callbacks,
ssh_socket_callbacks,
ssh_packet_callbacks,
ssh_channel_callbacks,
ssh_bind,
ssh_bind_callbacks)
set(DOXYGEN_EXCLUDE_SYMBOLS
${DOXYGEN_EXCLUDE_SYMBOLS_STRUCTS} ${DOXYGEN_EXCLUDE_SYMBOLS_MACRO}
${DOXYGEN_EXCLUDE_SYMBOLS_TYPEDEFS})
# Custom layout file to rename "Topics" to "API Reference" and simplify
# navigation
set(DOXYGEN_LAYOUT_FILE ${CMAKE_CURRENT_SOURCE_DIR}/DoxygenLayout.xml)
# Custom HTML header with doxygen-awesome extension initialization
set(DOXYGEN_HTML_HEADER ${CMAKE_CURRENT_SOURCE_DIR}/header.html)
# Modern CSS theme for documentation with custom libssh.org color scheme
set(DOXYGEN_HTML_EXTRA_STYLESHEET
${AWESOME_CSS_DIR}/doxygen-awesome.css
${CMAKE_CURRENT_SOURCE_DIR}/doxygen-custom.css)
# JavaScript extensions: dark mode toggle, copy button, paragraph links,
# interactive TOC
set(DOXYGEN_HTML_EXTRA_FILES
${AWESOME_CSS_DIR}/doxygen-awesome-darkmode-toggle.js
${AWESOME_CSS_DIR}/doxygen-awesome-fragment-copy-button.js
${AWESOME_CSS_DIR}/doxygen-awesome-paragraph-link.js
${AWESOME_CSS_DIR}/doxygen-awesome-interactive-toc.js)
set(DOXYGEN_EXCLUDE ${CMAKE_CURRENT_SOURCE_DIR}/that_style)
set(DOXYGEN_HTML_HEADER ${CMAKE_CURRENT_SOURCE_DIR}/that_style/header.html)
set(DOXYGEN_HTML_EXTRA_STYLESHEET ${CMAKE_CURRENT_SOURCE_DIR}/that_style/that_style.css)
set(DOXYGEN_HTML_EXTRA_FILES ${CMAKE_CURRENT_SOURCE_DIR}/that_style/img/nav_edge_left.svg
${CMAKE_CURRENT_SOURCE_DIR}/that_style/img/nav_edge_right.svg
${CMAKE_CURRENT_SOURCE_DIR}/that_style/img/nav_edge_inter.svg
${CMAKE_CURRENT_SOURCE_DIR}/that_style/img/sync_off.png
${CMAKE_CURRENT_SOURCE_DIR}/that_style/img/sync_on.png
${CMAKE_CURRENT_SOURCE_DIR}/that_style/img/splitbar_handle.svg
${CMAKE_CURRENT_SOURCE_DIR}/that_style/img/doc.svg
${CMAKE_CURRENT_SOURCE_DIR}/that_style/img/mag_glass.svg
${CMAKE_CURRENT_SOURCE_DIR}/that_style/img/folderclosed.svg
${CMAKE_CURRENT_SOURCE_DIR}/that_style/img/folderopen.svg
${CMAKE_CURRENT_SOURCE_DIR}/that_style/js/striped_bg.js)
set(DOXYGEN_EXCLUDE_PATTERNS */src/external/* fe25519.h ge25519.h sc25519.h
blf.h)
set(DOXYGEN_EXCLUDE_SYMBOLS_STRUCTS chacha20_poly1305_keysched,dh_ctx,dh_ctx,dh_keypair,error_struct,
packet_struct,pem_get_password_struct,ssh_tokens_st,
sftp_attributes_struct,sftp_client_message_struct,
sftp_dir_struct,sftp_ext_struct,sftp_file_struct,sftp_message_struct,
sftp_packet_struct,sftp_request_queue_struct,sftp_session_struct,
sftp_status_message_struct,ssh_agent_state_struct,
ssh_agent_struct,ssh_auth_auto_state_struct,ssh_auth_request,
ssh_bind_config_keyword_table_s,ssh_bind_config_match_keyword_table_s,
ssh_bind_struct,ssh_buffer_struct,ssh_channel_callbacks_struct,
ssh_channel_read_termination_struct,ssh_channel_request,
ssh_channel_request_open,ssh_channel_struct,ssh_cipher_struct,
ssh_common_struct,ssh_config_keyword_table_s,
ssh_config_match_keyword_table_s,ssh_connector_struct,
ssh_counter_struct,ssh_crypto_struct,ssh_event_fd_wrapper,
ssh_event_struct,ssh_global_request,ssh_gssapi_struct,ssh_hmac_struct,
ssh_iterator,ssh_kbdint_struct,ssh_kex_struct,ssh_key_struct,
ssh_knownhosts_entry,ssh_list,ssh_mac_ctx_struct,ssh_message_struct,
ssh_packet_callbacks_struct,ssh_packet_header,ssh_poll_ctx_struct,
ssh_poll_handle_struct,ssh_pollfd_struct,ssh_private_key_struct,
ssh_public_key_struct,ssh_scp_struct,ssh_service_request,
ssh_session_struct,ssh_signature_struct,ssh_socket_struct,
ssh_string_struct,ssh_threads_callbacks_struct,ssh_timestamp,)
set(DOXYGEN_EXCLUDE_SYMBOLS_MACRO SSH_FXP*,SSH_SOCKET*,SERVERBANNER,SOCKOPT_TYPE_ARG4,SSH_FILEXFER*,
SSH_FXF*,SSH_S_*,SFTP_*,NSS_BUFLEN_PASSWD,CLOCK,MAX_LINE_SIZE,
PKCS11_URI,KNOWNHOSTS_MAXTYPES,)
set(DOXYGEN_EXCLUDE_SYMBOLS_TYPEDEFS sftp_attributes,sftp_client_message,sftp_dir,sftp_ext,sftp_file,
sftp_message,sftp_packet,sftp_request_queue,sftp_session,
sftp_status_message,sftp_statvfs_t,poll_fn,ssh_callback_int,
ssh_callback_data,ssh_callback_int_int,ssh_message_callback,
ssh_channel_callback_int,ssh_channel_callback_data,ssh_callbacks,
ssh_gssapi_select_oid_callback,ssh_gssapi_accept_sec_ctx_callback,
ssh_gssapi_verify_mic_callback,ssh_server_callbacks,ssh_socket_callbacks,
ssh_packet_callbacks,ssh_channel_callbacks,ssh_bind,ssh_bind_callbacks,)
set(DOXYGEN_EXCLUDE_SYMBOLS ${DOXYGEN_EXCLUDE_SYMBOLS_STRUCTS}
${DOXYGEN_EXCLUDE_SYMBOLS_MACRO}
${DOXYGEN_EXCLUDE_SYMBOLS_TYPEDEFS})
# This updates the Doxyfile if we do changes here
set(_doxyfile_template "${CMAKE_BINARY_DIR}/CMakeDoxyfile.in")
set(_target_doxyfile "${CMAKE_CURRENT_BINARY_DIR}/Doxyfile.docs")
configure_file("${_doxyfile_template}" "${_target_doxyfile}")
doxygen_add_docs(docs ${CMAKE_SOURCE_DIR}/include/libssh
${CMAKE_SOURCE_DIR}/src ${CMAKE_CURRENT_SOURCE_DIR})
doxygen_add_docs(docs
${CMAKE_SOURCE_DIR}/include/libssh
${CMAKE_SOURCE_DIR}/src
${CMAKE_CURRENT_SOURCE_DIR})
add_custom_target(
docs_coverage COMMAND ${CMAKE_SOURCE_DIR}/doc/doc_coverage.sh
${CMAKE_BINARY_DIR})
endif (DOXYGEN_FOUND)
add_custom_target(docs_coverage COMMAND ${CMAKE_SOURCE_DIR}/doc/doc_coverage.sh ${CMAKE_BINARY_DIR})
endif() # DOXYGEN_FOUND
endif() # CMAKE_VERSION

View File

@@ -1,242 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<doxygenlayout version="2.0">
<!-- Generated by doxygen 1.14.0 -->
<!-- Navigation index tabs for HTML output -->
<navindex>
<tab type="mainpage" visible="yes" title=""/>
<tab type="topics" visible="yes" title="API Reference" intro=""/>
<tab type="pages" visible="yes" title="" intro=""/>
<tab type="files" visible="yes" title="">
<tab type="filelist" visible="yes" title="" intro=""/>
<tab type="globals" visible="yes" title="" intro=""/>
</tab>
<tab type="structs" visible="yes" title="">
<tab type="structlist" visible="yes" title="" intro=""/>
<tab type="structindex" visible="$ALPHABETICAL_INDEX" title=""/>
</tab>
</navindex>
<!-- Layout definition for a class page -->
<class>
<briefdescription visible="yes"/>
<includes visible="$SHOW_HEADERFILE"/>
<inheritancegraph visible="yes"/>
<collaborationgraph visible="yes"/>
<memberdecl>
<nestedclasses visible="yes" title=""/>
<publictypes visible="yes" title=""/>
<services visible="yes" title=""/>
<interfaces visible="yes" title=""/>
<publicslots visible="yes" title=""/>
<signals visible="yes" title=""/>
<publicmethods visible="yes" title=""/>
<publicstaticmethods visible="yes" title=""/>
<publicattributes visible="yes" title=""/>
<publicstaticattributes visible="yes" title=""/>
<protectedtypes visible="yes" title=""/>
<protectedslots visible="yes" title=""/>
<protectedmethods visible="yes" title=""/>
<protectedstaticmethods visible="yes" title=""/>
<protectedattributes visible="yes" title=""/>
<protectedstaticattributes visible="yes" title=""/>
<packagetypes visible="yes" title=""/>
<packagemethods visible="yes" title=""/>
<packagestaticmethods visible="yes" title=""/>
<packageattributes visible="yes" title=""/>
<packagestaticattributes visible="yes" title=""/>
<properties visible="yes" title=""/>
<events visible="yes" title=""/>
<privatetypes visible="yes" title=""/>
<privateslots visible="yes" title=""/>
<privatemethods visible="yes" title=""/>
<privatestaticmethods visible="yes" title=""/>
<privateattributes visible="yes" title=""/>
<privatestaticattributes visible="yes" title=""/>
<friends visible="yes" title=""/>
<related visible="yes" title="" subtitle=""/>
<membergroups visible="yes"/>
</memberdecl>
<detaileddescription visible="yes" title=""/>
<memberdef>
<inlineclasses visible="yes" title=""/>
<typedefs visible="yes" title=""/>
<enums visible="yes" title=""/>
<services visible="yes" title=""/>
<interfaces visible="yes" title=""/>
<constructors visible="yes" title=""/>
<functions visible="yes" title=""/>
<related visible="yes" title=""/>
<variables visible="yes" title=""/>
<properties visible="yes" title=""/>
<events visible="yes" title=""/>
</memberdef>
<allmemberslink visible="yes"/>
<usedfiles visible="$SHOW_USED_FILES"/>
<authorsection visible="yes"/>
</class>
<!-- Layout definition for a namespace page -->
<namespace>
<briefdescription visible="yes"/>
<memberdecl>
<nestednamespaces visible="yes" title=""/>
<constantgroups visible="yes" title=""/>
<interfaces visible="yes" title=""/>
<classes visible="yes" title=""/>
<concepts visible="yes" title=""/>
<structs visible="yes" title=""/>
<exceptions visible="yes" title=""/>
<typedefs visible="yes" title=""/>
<sequences visible="yes" title=""/>
<dictionaries visible="yes" title=""/>
<enums visible="yes" title=""/>
<functions visible="yes" title=""/>
<variables visible="yes" title=""/>
<properties visible="yes" title=""/>
<membergroups visible="yes"/>
</memberdecl>
<detaileddescription visible="yes" title=""/>
<memberdef>
<inlineclasses visible="yes" title=""/>
<typedefs visible="yes" title=""/>
<sequences visible="yes" title=""/>
<dictionaries visible="yes" title=""/>
<enums visible="yes" title=""/>
<functions visible="yes" title=""/>
<variables visible="yes" title=""/>
<properties visible="yes" title=""/>
</memberdef>
<authorsection visible="yes"/>
</namespace>
<!-- Layout definition for a concept page -->
<concept>
<briefdescription visible="yes"/>
<includes visible="$SHOW_HEADERFILE"/>
<definition visible="yes" title=""/>
<detaileddescription visible="yes" title=""/>
<authorsection visible="yes"/>
</concept>
<!-- Layout definition for a file page -->
<file>
<briefdescription visible="yes"/>
<includes visible="$SHOW_INCLUDE_FILES"/>
<includegraph visible="yes"/>
<includedbygraph visible="yes"/>
<sourcelink visible="yes"/>
<memberdecl>
<interfaces visible="yes" title=""/>
<classes visible="yes" title=""/>
<structs visible="yes" title=""/>
<exceptions visible="yes" title=""/>
<namespaces visible="yes" title=""/>
<concepts visible="yes" title=""/>
<constantgroups visible="yes" title=""/>
<defines visible="yes" title=""/>
<typedefs visible="yes" title=""/>
<sequences visible="yes" title=""/>
<dictionaries visible="yes" title=""/>
<enums visible="yes" title=""/>
<functions visible="yes" title=""/>
<variables visible="yes" title=""/>
<properties visible="yes" title=""/>
<membergroups visible="yes"/>
</memberdecl>
<detaileddescription visible="yes" title=""/>
<memberdef>
<inlineclasses visible="yes" title=""/>
<defines visible="yes" title=""/>
<typedefs visible="yes" title=""/>
<sequences visible="yes" title=""/>
<dictionaries visible="yes" title=""/>
<enums visible="yes" title=""/>
<functions visible="yes" title=""/>
<variables visible="yes" title=""/>
<properties visible="yes" title=""/>
</memberdef>
<authorsection/>
</file>
<!-- Layout definition for a group page -->
<group>
<briefdescription visible="yes"/>
<groupgraph visible="yes"/>
<memberdecl>
<nestedgroups visible="yes" title=""/>
<modules visible="yes" title=""/>
<dirs visible="yes" title=""/>
<files visible="yes" title=""/>
<namespaces visible="yes" title=""/>
<concepts visible="yes" title=""/>
<classes visible="yes" title=""/>
<defines visible="yes" title=""/>
<typedefs visible="yes" title=""/>
<sequences visible="yes" title=""/>
<dictionaries visible="yes" title=""/>
<enums visible="yes" title=""/>
<enumvalues visible="yes" title=""/>
<functions visible="yes" title=""/>
<variables visible="yes" title=""/>
<signals visible="yes" title=""/>
<publicslots visible="yes" title=""/>
<protectedslots visible="yes" title=""/>
<privateslots visible="yes" title=""/>
<events visible="yes" title=""/>
<properties visible="yes" title=""/>
<friends visible="yes" title=""/>
<membergroups visible="yes"/>
</memberdecl>
<detaileddescription visible="yes" title=""/>
<memberdef>
<pagedocs/>
<inlineclasses visible="yes" title=""/>
<defines visible="yes" title=""/>
<typedefs visible="yes" title=""/>
<sequences visible="yes" title=""/>
<dictionaries visible="yes" title=""/>
<enums visible="yes" title=""/>
<enumvalues visible="yes" title=""/>
<functions visible="yes" title=""/>
<variables visible="yes" title=""/>
<signals visible="yes" title=""/>
<publicslots visible="yes" title=""/>
<protectedslots visible="yes" title=""/>
<privateslots visible="yes" title=""/>
<events visible="yes" title=""/>
<properties visible="yes" title=""/>
<friends visible="yes" title=""/>
</memberdef>
<authorsection visible="yes"/>
</group>
<!-- Layout definition for a C++20 module page -->
<module>
<briefdescription visible="yes"/>
<exportedmodules visible="yes"/>
<memberdecl>
<concepts visible="yes" title=""/>
<classes visible="yes" title=""/>
<enums visible="yes" title=""/>
<typedefs visible="yes" title=""/>
<functions visible="yes" title=""/>
<variables visible="yes" title=""/>
<membergroups visible="yes" title=""/>
</memberdecl>
<detaileddescription visible="yes" title=""/>
<memberdecl>
<files visible="yes"/>
</memberdecl>
</module>
<!-- Layout definition for a directory page -->
<directory>
<briefdescription visible="yes"/>
<directorygraph visible="yes"/>
<memberdecl>
<dirs visible="yes"/>
<files visible="yes"/>
</memberdecl>
<detaileddescription visible="yes" title=""/>
</directory>
</doxygenlayout>

View File

@@ -105,7 +105,7 @@ Here is a small example of password authentication:
@code
int authenticate_password(ssh_session session)
{
char *password = NULL;
char *password;
int rc;
password = getpass("Enter your password: ");
@@ -218,7 +218,7 @@ int authenticate_kbdint(ssh_session session)
rc = ssh_userauth_kbdint(session, NULL, NULL);
while (rc == SSH_AUTH_INFO)
{
const char *name = NULL, *instruction = NULL;
const char *name, *instruction;
int nprompts, iprompt;
name = ssh_userauth_kbdint_getname(session);
@@ -231,7 +231,7 @@ int authenticate_kbdint(ssh_session session)
printf("%s\n", instruction);
for (iprompt = 0; iprompt < nprompts; iprompt++)
{
const char *prompt = NULL;
const char *prompt;
char echo;
prompt = ssh_userauth_kbdint_getprompt(session, iprompt, &echo);
@@ -251,7 +251,7 @@ int authenticate_kbdint(ssh_session session)
}
else
{
char *ptr = NULL;
char *ptr;
ptr = getpass(prompt);
if (ssh_userauth_kbdint_setanswer(session, iprompt, ptr) < 0)
@@ -354,7 +354,7 @@ The following example shows how to retrieve and dispose the issue banner:
int display_banner(ssh_session session)
{
int rc;
char *banner = NULL;
char *banner;
/*
*** Does not work without calling ssh_userauth_none() first ***

View File

@@ -22,7 +22,7 @@ a SSH session that uses this channel:
@code
int show_remote_files(ssh_session session)
{
ssh_channel channel = NULL;
ssh_channel channel;
int rc;
channel = ssh_channel_new(session);
@@ -91,10 +91,4 @@ that it used:
}
@endcode
Warning: In a single channel, only ONE command can be executed!
If you want to executed multiple commands, allocate separate channels for
them or consider opening interactive shell.
Attempting to run multiple consecutive commands in one channel will fail.
*/

View File

@@ -1,127 +0,0 @@
/**
* Custom color scheme for libssh documentation
* Based on libssh.org color palette
*/
html {
/* Primary colors - using libssh.org orange accent */
--primary-color: #F78C40;
--primary-dark-color: #f57900;
--primary-light-color: #fab889;
/* Accent color - neutral gray */
--primary-lighter-color: #5A5A5A;
/* Page colors - clean white background */
--page-background-color: #ffffff;
--page-foreground-color: #333333;
--page-secondary-foreground-color: #666666;
/* Links - use the warm orange color */
--link-color: #F78C40;
--link-hover-color: #f0690a;
/* Code blocks and fragments - very light background */
--code-background: #f9f9f9;
--fragment-background: #f9f9f9;
/* Borders - subtle light grey */
--separator-color: #e0e0e0;
--border-light-color: #f0f0f0;
/* Side navigation - pure white */
--side-nav-background: #ffffff;
/* Menu colors - warm orange accent */
--menu-selected-background: #F78C40;
/* Tables and boxes - lighter */
--tablehead-background: #fbc7a2;
--tablehead-foreground: #333333;
}
/* Header styling with libssh brand colors */
#titlearea {
background-color: #5A5A5A;
background-image: linear-gradient(to right, #5A5A5A, #6a6a6a);
border-bottom: 3px solid #F78C40;
}
#projectname {
color: #ffffff !important;
}
#projectbrief {
color: #fab889 !important;
}
/* Top navigation tabs */
#top {
background: linear-gradient(to bottom, #5A5A5A 0%, #6a6a6a 100%);
}
.tabs, .tabs2, .tabs3 {
background-image: none;
background-color: transparent;
}
.tablist li {
background: rgba(255, 255, 255, 0.1);
border-right: 1px solid rgba(255, 255, 255, 0.2);
}
.tablist li:hover {
background: rgba(255, 255, 255, 0.2);
}
.tablist li.current {
background: #F78C40;
border-bottom: 3px solid #f57900;
}
/* Tab text colors - comprehensive selectors */
#nav-path ul li a,
.tabs a,
.tabs2 a,
.tabs3 a,
.tablist a,
.tablist a:link,
.tablist a:visited,
.tablist li a,
#main-nav a,
.sm > li > a,
.sm > li > a .sub-arrow {
color: #ffffff !important;
text-shadow: 0px 1px 2px rgba(0, 0, 0, 0.3);
}
/* Active/current tab text */
#nav-path ul li.current a,
.tabs .current a,
.tabs2 .current a,
.tabs3 .current a,
.tablist .current a,
.tablist .current a:link,
.tablist .current a:visited,
.tablist li.current a,
#main-nav .current a,
.sm .current a {
color: #333333 !important;
text-shadow: none;
}
/* Dropdown arrow - white color for top menu */
.sm-dox a span.sub-arrow {
border-right-color: #ffffff !important;
border-bottom-color: #ffffff !important;
}
/* Dropdown menu text - must be dark on white background */
/* Make this as specific as possible to override white color */
.sm-dox > li > ul > li > a,
.sm-dox li ul li a,
.sm-dox ul li a,
#main-menu ul li a {
color: #333333 !important;
text-shadow: none !important;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 858 B

View File

@@ -1,601 +0,0 @@
/**
@page libssh_tutor_fido2 Chapter 11: FIDO2/U2F Keys Support
@section fido2_intro Introduction
The traditional SSH public key model stores the private key on disk
and anyone who obtains that file (and possibly its passphrase) can impersonate
the user. FIDO2 authenticators, such as USB security keys, are hardware tokens
that generate or securely store private key material within a secure element
and may require explicit user interaction such as a touch, PIN, or biometric
verification for use. Hence, security keys are far safer from theft or
exfiltration than traditional file-based SSH keys. libssh provides support
for FIDO2/U2F security keys as hardware-backed SSH authentication credentials.
This chapter explains the concepts, build prerequisites, the API, and
usage patterns for enrolling (creating) and using security key-backed SSH
keys, including resident (discoverable) credentials.
@subsection fido2_resident_keys Resident Keys
Two credential storage modes exist for security keys:
- Non-resident (default): A credential ID (key handle) and metadata are
stored on the client-side in a key file. This key handle must be
presented to the FIDO2/U2F device while signing. This is somewhat
similar to traditional SSH keys, except that the key handle is not the
private key itself, but used in combination with the device's master key
to derive the actual private key.
- Resident (discoverable): The credential (and metadata like user id) is
stored on the device. No local file is needed; the device can enumerate or
locate the credential internally when queried.
Advantages of resident keys include portability (using the same device
across hosts) and resilience (no loss if the local machine is destroyed).
Although, they may be limited by the storage of the authenticator.
@subsection fido2_presence_verification User Presence vs. User Verification
FIDO2 distinguishes between:
- User Presence (UP): A simple physical interaction (touch) to confirm a
human is present.
- User Verification (UV): Verification of the users identity through
biometric authentication or a PIN.
Requiring UV provides additional protection if the device is stolen
and used without the PIN/biometric.
libssh exposes flags controlling these requirements (see below).
@subsection fido2_callbacks The Callback Abstraction
Different environments may need to access security keys through different
transport layers (e.g., USB-HID, NFC, Bluetooth, etc.). To accommodate
this variability, libssh does not hard-code a single implementation.
Instead, it defines a small callback interface (`ssh_sk_callbacks`) used for all
security key operations. Any implementation of this callback interface can be used
by higher-level PKI functions to perform enroll/sign/load_resident_keys
operations without needing to know the transport specifics. Hence, users can
define their own implementations for these callbacks to support different
transport protocols or custom hardware. Refer @ref fido2_custom_callbacks
for additional details.
The callback interface is defined in `libssh/callbacks.h` and the behaviour
and return values are specified by `libssh/sk_api.h`, which is the same
interface defined by OpenSSH for its security key support. This means that
any callback implementations (also called "middleware" in OpenSSH terminology)
developed for OpenSSH can be adapted to libssh with minimal changes.
The following operations are abstracted by the callback interface:
- api_version(): Report the version of the SK API that the callback implementation
is based on, so that libssh can check whether this implementation would be
compatible with the SK API version that it supports.
Refer @ref fido2_custom_callbacks_version for additional details.
- enroll(): Create (enroll) a new credential, returning public key, key
handle, attestation data.
- sign(): Produce a signature for supplied inputs using an existing key
handle.
- load_resident_keys(): Enumerate resident (discoverable) credentials stored
on the authenticator.
libssh provides a default implementation of the `ssh_sk_callbacks` using
the libfido2 library for the USB-HID transport protocol. Hence, by default,
libssh can interact with any FIDO2/U2F device that supports USB-HID and is
compatible with libfido2, without requiring any additional modifications.
@subsection fido2_build Building with FIDO2 Support
To enable FIDO2/U2F support, libssh must be built with the WITH_FIDO2
build option as follows:
@verbatim
cmake -DWITH_FIDO2=ON <other options> ..
@endverbatim
libssh will also build the default USB-HID `ssh_sk_callbacks`, if the
libfido2 library and headers are installed on your system.
@warning If built without libfido2, support for interacting with FIDO2/U2F
devices over USB-HID will not be available.
@subsection fido2_api_overview API Overview
Security key operations are configured through the `ssh_pki_ctx`
which allows to specify both general PKI options and FIDO2-specific
options such as the sk_callbacks, challenge data, application string, flags, etc.
The following sections describe the options that can be configured and how
the `ssh_pki_ctx` is used in conjunction with `ssh_key` to perform
enrollment, signing, and resident key loading operations.
@subsection fido2_key_objects Security Key Objects & Metadata
Security keys are surfaced as `ssh_key` objects of type
`SSH_KEYTYPE_SK_ECDSA` and `SSH_KEYTYPE_SK_ED25519` (corresponding to the
OpenSSH public key algorithm names `sk-ecdsa-sha2-nistp256@openssh.com` and
`sk-ssh-ed25519@openssh.com`). In addition to standard key handling, libssh
exposes the following helper functions to retrieve embedded SK metadata:
- ssh_key_get_sk_application(): Returns the relying party / application
(RP ID) string. The Relying Party ID (RP ID) is a string
that identifies the application or service requesting key enrollment. It
ensures that a credential is bound to a specific origin, preventing
phishing across sites. During registration, the authenticator associates
the credential with this RP ID so that it can later only be used for
authentication requests from the same relying party. For SSH keys, the
common format is "ssh:user@host".
- ssh_key_get_sk_user_id(): Returns a copy of the user ID associated with a key
which represents a unique identifier for the user within the relying
party (application) context. It is typically a string (such as an
email, or a random identifier) that helps distinguish credentials
belonging to different users for the same application.
Though the user ID can be binary data according to the FIDO2 spec, libssh only
supports NUL-terminated strings for enrolling new keys in order to remain compatible
with the OpenSSH's sk-api interface.
However, libssh does support loading existing resident keys with user IDs containing
arbitrary binary data. It does so by using an `ssh_string` to store the loaded key's
user_id, and an `ssh_string` can contain arbitrary binary data that can not be stored
in a traditional NUL-terminated string (like null bytes).
@note The user_id is NOT stored in the key file for non-resident keys. It is only
available for resident (discoverable) keys loaded from the authenticator via
ssh_sk_resident_keys_load(). For keys imported from files, this function returns
NULL.
- ssh_key_get_sk_flags(): Returns the flags associated with the key. The
following are the supported flags and they can be combined using
bitwise OR:
- SSH_SK_USER_PRESENCE_REQD : Require user presence (touch).
- SSH_SK_USER_VERIFICATION_REQD : Require user verification
(PIN/biometric).
- SSH_SK_RESIDENT_KEY : Request a resident discoverable credential.
- SSH_SK_FORCE_OPERATION : Force resident (discoverable) credential
creation even if one with same application and user_id already
exists.
These functions perform no additional communication with the
authenticator, this metadata is captured during enrollment/loading and
cached in the `ssh_key`.
@subsection fido2_options Setting Security Key Context Options
Options are set via ssh_pki_ctx_options_set().
Representative security key options:
- SSH_PKI_OPTION_SK_APPLICATION (const char *): Required relying party ID
If not set, a default value of "ssh:" is used.
- SSH_PKI_OPTION_SK_FLAGS (uint8_t *): Flags described above. If not set,
defaults to SSH_SK_USER_PRESENCE_REQD. This is because OpenSSH `sshd`
requires user presence for security key authentication by default.
- SSH_PKI_OPTION_SK_USER_ID (const char *): Represents a unique identifier
for the user within the relying party (application) context.
It is typically a string (such as an email, or a random identifier) that
helps distinguish credentials belonging to different users for the same
application. If not set, defaults to 64 zeros.
- SSH_PKI_OPTION_SK_CHALLENGE (ssh_buffer): Custom challenge; if omitted a
random 32-byte challenge is generated.
- SSH_PKI_OPTION_SK_CALLBACKS (ssh_sk_callbacks): Replace the default
callbacks with custom callbacks.
PIN callback: Use ssh_pki_ctx_set_sk_pin_callback() to register a function
matching `ssh_auth_callback` to prompt for and supply a PIN. The callback may
be called multiple times to ask for the pin depending on the authenticator policy.
Callback options: Callback implementations may accept additional configuration
name/value options such as the path to the fido device. These options can be provided via
`ssh_pki_ctx_sk_callbacks_option_set()`. Refer @ref fido2_custom_callbacks_options
for additional details.
The built-in callback implementation provided by libssh supports additional options,
with their names defined in `libssh.h` prefixed with `SSH_SK_OPTION_NAME_*`, such as:
SSH_SK_OPTION_NAME_DEVICE_PATH: Used for specifying a device path.
If the device path is not specified and multiple devices are connected, then
depending upon the operation and the flags set, the callback implementation may
automatically select a suitable device, or the user may be prompted to touch the
device they want to use.
SSH_SK_OPTION_NAME_USER_ID: Used for setting the user ID.
Note that the user ID can also be set using the ssh_pki_ctx_options_set() API.
@subsection fido2_enrollment Enrollment Example
An enrollment operation creates a new credential on the authenticator and
returns an ssh_key object representing it. The application and user_id
fields are required for creating the credential. The other options are
optional. A successful enrollment returns the public key, key handle, and
metadata which are stored in the ssh_key object, and may optionally return
attestation data which is used for verifying the authenticator model and
firmware version.
Below is a simple example enrolling an Ed25519 security key (non-resident)
requiring user presence only:
@code
#include <libssh/libssh.h>
#include <string.h>
static int pin_cb(const char *prompt,
char *buf,
size_t len,
int echo,
int verify,
void *userdata)
{
(void)prompt;
(void)echo;
(void)verify;
(void)userdata;
/* In a real application, the user would be prompted to enter the PIN */
const char *pin = "4242";
size_t l = strlen(pin);
if (l + 1 > len) {
return SSH_ERROR;
}
memcpy(buf, pin, l + 1);
return SSH_OK;
}
int enroll_sk_key()
{
const char *app = "ssh:user@host";
const char *user_id = "alice";
uint8_t flags = SSH_SK_USER_PRESENCE_REQD | SSH_SK_USER_VERIFICATION_REQD;
const char *device_path = "/dev/hidraw6"; /* Optional device path */
ssh_pki_ctx pki_ctx = ssh_pki_ctx_new();
ssh_pki_ctx_options_set(pki_ctx, SSH_PKI_OPTION_SK_APPLICATION, app);
ssh_pki_ctx_options_set(pki_ctx, SSH_PKI_OPTION_SK_USER_ID, user_id);
ssh_pki_ctx_options_set(pki_ctx, SSH_PKI_OPTION_SK_FLAGS, &flags);
ssh_pki_ctx_set_sk_pin_callback(pki_ctx, pin_cb, NULL);
ssh_pki_ctx_sk_callbacks_option_set(pki_ctx,
SSH_SK_OPTION_NAME_DEVICE_PATH,
device_path,
true);
ssh_key enrolled = NULL;
int rc = ssh_pki_generate_key(SSH_KEYTYPE_SK_ED25519,
pki_ctx,
&enrolled); /* produces sk-ed25519 key */
/* Save enrolled key using ssh_pki_export_privkey_file, retrieve attestation
* buffer etc. */
/* Free context and key when done */
}
@endcode
After a successful enrollment, you can retrieve the attestation buffer
(if provided by the authenticator) from the PKI context:
@code
ssh_buffer att_buf = NULL;
rc = ssh_pki_ctx_get_sk_attestation_buffer(pki_ctx, &att_buf);
if (rc == SSH_OK && att_buf != NULL) {
/* att_buf now contains the serialized attestation
* ("ssh-sk-attest-v01"). You can inspect, save, or
* parse the buffer as needed
*/
ssh_buffer_free(att_buf);
}
@endcode
Notes:
- The attestation buffer is only populated if the enrollment operation
succeeds and the authenticator provides attestation data.
- `ssh_pki_ctx_get_sk_attestation_buffer()` returns a copy of the attestation
buffer; the caller must free it with `ssh_buffer_free()`.
@subsection fido2_signing Authenticating with a Stored Security Key Public Key
To authenticate using a security key, the application typically loads the
previously enrolled sk-* private key, establishes an SSH connection, and
calls `ssh_userauth_publickey()`. libssh automatically recognizes security
key types and transparently handles the required hardware-backed
authentication steps such as prompting for a touch or PIN using the
configured security key callbacks.
Example:
@code
#include <libssh/libssh.h>
#include <stdio.h>
int auth_with_sk_file(const char *host,
const char *user,
const char *privkey_path)
{
ssh_session session = NULL;
ssh_key privkey = NULL;
int rc = SSH_ERROR;
session = ssh_new();
ssh_options_set(session, SSH_OPTIONS_HOST, host);
ssh_options_set(session, SSH_OPTIONS_USER, user);
ssh_connect(session);
ssh_pki_import_privkey_file(privkey_path, NULL, NULL, NULL, &privkey);
ssh_pki_ctx pki_ctx = ssh_pki_ctx_new();
/* Optionally set PIN callback, device path, etc. */
/* ssh_pki_ctx_set_sk_pin_callback(pki_ctx, pin_cb, NULL); */
ssh_options_set(session, SSH_OPTIONS_PKI_CONTEXT, pki_ctx);
rc = ssh_userauth_publickey(session, user, privkey);
if (rc == SSH_AUTH_SUCCESS) {
printf("Authenticated with security key.\n");
rc = SSH_OK;
} else {
fprintf(stderr,
"Authentication failed rc=%d err=%s\n",
rc,
ssh_get_error(session));
rc = SSH_ERROR;
}
/* Free resources */
}
@endcode
@subsection fido2_resident Resident Key Enumeration
Resident keys stored on the device can be discovered and loaded with
ssh_sk_resident_keys_load() which takes a PKI context (configured with
a PIN callback) and returns each key as an ssh_key and the number of keys loaded.
Example:
@code
#include <libssh/libssh.h>
#include <stdio.h>
#include <string.h>
static int pin_cb(const char *prompt,
char *buf,
size_t len,
int echo,
int verify,
void *userdata)
{
(void)prompt;
(void)echo;
(void)verify;
(void)userdata;
const char *pin = "4242";
size_t l = strlen(pin);
if (l + 1 > len) {
return SSH_ERROR;
}
memcpy(buf, pin, l + 1);
return SSH_OK;
}
int auth_with_resident(const char *host,
const char *user,
const char *application,
const char *user_id)
{
ssh_pki_ctx pki_ctx = NULL;
size_t num_found = 0;
ssh_key *keys = NULL;
ssh_key final_key = NULL;
int rc = SSH_ERROR;
ssh_string cur_application = NULL;
ssh_string cur_user_id = NULL;
ssh_string expected_application = NULL;
ssh_string expected_user_id = NULL;
pki_ctx = ssh_pki_ctx_new();
ssh_pki_ctx_set_sk_pin_callback(pki_ctx, pin_cb, NULL);
expected_application = ssh_string_from_char(application);
expected_user_id = ssh_string_from_char(user_id);
rc = ssh_sk_resident_keys_load(pki_ctx, &keys, &num_found);
for (size_t i = 0; i < num_found; i++) {
cur_application = ssh_key_get_sk_application(keys[i]);
cur_user_id = ssh_key_get_sk_user_id(keys[i]);
if (ssh_string_cmp(cur_application, expected_application) == 0 &&
ssh_string_cmp(cur_user_id, expected_user_id) == 0) {
SSH_STRING_FREE(cur_application);
SSH_STRING_FREE(cur_user_id);
final_key = keys[i];
break;
}
SSH_STRING_FREE(cur_application);
SSH_STRING_FREE(cur_user_id);
}
SSH_STRING_FREE(expected_application);
SSH_STRING_FREE(expected_user_id);
/* Continue with authentication using the ssh_key with
* ssh_userauth_publickey as usual, and free resources when done. */
}
@endcode
@subsection fido2_sshsig Signing using the sshsig API
Security keys can also be used for general-purpose signing of arbitrary data
(without SSH authentication) using the existing `sshsig_sign()` and `sshsig_verify()`
functions. These functions work seamlessly with security key types
(`SSH_KEYTYPE_SK_ECDSA` and `SSH_KEYTYPE_SK_ED25519`) and will automatically
invoke the configured security key callbacks to perform hardware-backed signing
operations.
@subsection fido2_custom_callbacks Implementing Custom Callback Implementations
Users may need to implement custom callback implementations to support
different transport protocols (e.g., NFC, Bluetooth) beyond the default USB-HID
support. This section describes how to implement and integrate custom callback
implementations.
To implement custom callbacks, you must include the following headers:
@code
#include <libssh/callbacks.h> /* For ssh_sk_callbacks_struct */
#include <libssh/sk_api.h> /* For SK API constants and data structures */
@endcode
The `libssh/sk_api.h` header provides the complete interface specification including
request/response structures, flags, and version macros.
@subsubsection fido2_custom_callbacks_version API Version Compatibility
libssh validates callback implementations by checking the API version returned by
the `api_version()` callback. To ensure compatibility, libssh compares the major
version (upper 16 bits) of the returned value with `LIBSSH_SK_API_VERSION_MAJOR`.
If they don't match, libssh will reject the callback implementation.
This ensures that the callbacks' SK API matches the major version expected by libssh,
while allowing minor version differences.
@subsubsection fido2_custom_callbacks_implementation Implementation Example
Here's a minimal example of defining and using custom callbacks:
@code
#include <libssh/libssh.h>
#include <libssh/callbacks.h>
#include <libssh/sk_api.h>
/* Your custom API version callback */
static uint32_t my_sk_api_version(void)
{
/* Match the major version, set your own minor version */
return SSH_SK_VERSION_MAJOR | 0x0001;
}
/* Your custom enroll callback */
static int my_sk_enroll(uint32_t alg,
const uint8_t *challenge,
size_t challenge_len,
const char *application,
uint8_t flags,
const char *pin,
struct sk_option **options,
struct sk_enroll_response **enroll_response)
{
/* Parse options array to extract custom parameters */
if (options != NULL) {
for (size_t i = 0; options[i] != NULL; i++) {
if (strcmp(options[i]->name, "my_custom_option") == 0) {
/* Use options[i]->value */
}
}
}
/* Implement your enroll logic here */
/* ... */
return SSH_SK_ERR_GENERAL; /* Return appropriate error code */
}
/* Implement other required callbacks: sign, load_resident_keys */
/* ... */
/* Define your callback structure */
static struct ssh_sk_callbacks_struct my_sk_callbacks = {
.size = sizeof(struct ssh_sk_callbacks_struct),
.api_version = my_sk_api_version,
.enroll = my_sk_enroll,
.sign = my_sk_sign, /* Your implementation */
.load_resident_keys = my_sk_load_resident_keys, /* Your implementation */
};
/* Usage example */
void use_custom_callbacks(void)
{
ssh_pki_ctx pki_ctx = ssh_pki_ctx_new();
/* Set your custom callbacks */
ssh_pki_ctx_options_set(pki_ctx,
SSH_PKI_OPTION_SK_CALLBACKS,
&my_sk_callbacks);
/* Pass custom options to your callbacks */
ssh_pki_ctx_sk_callbacks_option_set(pki_ctx,
"my_custom_option",
"my_custom_value",
false);
/* Use the context for enrollment, signing, etc. */
}
@endcode
@subsubsection fido2_custom_callbacks_options Passing Custom Options
The `ssh_pki_ctx_sk_callbacks_option_set()` function allows you to pass
implementation-specific options as name/value string pairs:
@code
ssh_pki_ctx_sk_callbacks_option_set(pki_ctx,
"option_name",
"option_value",
required);
@endcode
Parameters:
- `option_name`: The name of the option (e.g., "device_path", "my_custom_param")
- `option_value`: The string value for this option
- `required`: If true, this option must be processed by the callback implementation
and cannot be ignored. If false, the option is advisory and can be skipped if the
callback implementation does not support it.
These options are passed to your callbacks in the `struct sk_option **options`
parameter as a NULL-terminated array. Each `sk_option` has the following fields:
- `name`: The option name (char *)
- `value`: The option value (char *)
- `required`: Whether the option must be processed (uint8_t, non-zero = required)
@subsubsection fido2_custom_callbacks_openssh OpenSSH Middleware Compatibility
Since libssh uses the same SK API as OpenSSH, middleware implementations developed
for OpenSSH can be adapted with minimal changes.
To adapt an OpenSSH middleware for libssh, create a wrapper that populates
`ssh_sk_callbacks_struct` with pointers to the middleware's functions.
@subsection fido2_testing Testing and Environment Variables
Unit tests covering USB-HID enroll/sign/load_resident_keys operations can be found
in the `tests/unittests/torture_sk_usbhid.c` file. To run these tests you
must have libfido2 installed and the WITH_FIDO2=ON build option set.
Additionally, you must ensure the following:
- An actual FIDO2 device must be connected to the test machine.
- The TORTURE_SK_USBHID environment variable must be set.
- The environment variable TORTURE_SK_PIN=<device PIN> must be set.
If these are not set, the tests are skipped.
The higher level PKI integration tests can be found in
`tests/unittests/torture_pki_sk.c` and the tests related to the sshsig API
can be found in `tests/unittests/torture_pki_sshsig.c`.
These use the callback implementation provided by OpenSSH's sk-dummy.so,
which simulates an authenticator without requiring any hardware. Hence, these tests
can be run in the CI environment.
However, these tests can also be configured to use the default USB-HID callbacks
by setting the same environment variables as described above.
The following devices were tested during development:
- Yubico Security Key NFC - USB-A
*/

View File

@@ -100,7 +100,7 @@ used to retrieve google's home page from the remote SSH server.
@code
int direct_forwarding(ssh_session session)
{
ssh_channel forwarding_channel = NULL;
ssh_channel forwarding_channel;
int rc = SSH_ERROR;
char *http_get = "GET / HTTP/1.1\nHost: www.google.com\n\n";
int nbytes, nwritten;
@@ -161,7 +161,7 @@ local libssh application, which handles them:
int web_server(ssh_session session)
{
int rc;
ssh_channel channel = NULL;
ssh_channel channel;
char buffer[256];
int nbytes, nwritten;
int port = 0;

View File

@@ -79,7 +79,7 @@ Here is a small example of how to use it:
int main()
{
ssh_session my_ssh_session = NULL;
ssh_session my_ssh_session;
int verbosity = SSH_LOG_PROTOCOL;
int port = 22;
@@ -126,7 +126,7 @@ Here's an example:
int main()
{
ssh_session my_ssh_session = NULL;
ssh_session my_ssh_session;
int rc;
my_ssh_session = ssh_new();
@@ -190,8 +190,8 @@ int verify_knownhost(ssh_session session)
ssh_key srv_pubkey = NULL;
size_t hlen;
char buf[10];
char *hexa = NULL;
char *p = NULL;
char *hexa;
char *p;
int cmp;
int rc;
@@ -317,9 +317,9 @@ The example below shows an authentication with password:
int main()
{
ssh_session my_ssh_session = NULL;
ssh_session my_ssh_session;
int rc;
char *password = NULL;
char *password;
// Open session and set options
my_ssh_session = ssh_new();
@@ -380,7 +380,7 @@ The example below shows how to execute a remote command:
@code
int show_remote_processes(ssh_session session)
{
ssh_channel channel = NULL;
ssh_channel channel;
int rc;
char buffer[256];
int nbytes;

View File

@@ -1,92 +0,0 @@
<!-- HTML header for doxygen 1.14.0-->
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="$langISO">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=11"/>
<meta name="generator" content="Doxygen $doxygenversion"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<!--BEGIN PROJECT_NAME--><title>$projectname: $title</title><!--END PROJECT_NAME-->
<!--BEGIN !PROJECT_NAME--><title>$title</title><!--END !PROJECT_NAME-->
<!--BEGIN PROJECT_ICON-->
<link rel="icon" href="$relpath^$projecticon" type="image/x-icon" />
<!--END PROJECT_ICON-->
<link href="$relpath^tabs.css" rel="stylesheet" type="text/css"/>
<!--BEGIN FULL_SIDEBAR-->
<script type="text/javascript">var page_layout=1;</script>
<!--END FULL_SIDEBAR-->
<script type="text/javascript" src="$relpath^jquery.js"></script>
<script type="text/javascript" src="$relpath^dynsections.js"></script>
<!--BEGIN COPY_CLIPBOARD-->
<script type="text/javascript" src="$relpath^clipboard.js"></script>
<!--END COPY_CLIPBOARD-->
$treeview
$search
$mathjax
$darkmode
<link href="$relpath^$stylesheet" rel="stylesheet" type="text/css" />
$extrastylesheet
<script type="text/javascript" src="$relpath^doxygen-awesome-darkmode-toggle.js"></script>
<script type="text/javascript">
DoxygenAwesomeDarkModeToggle.init()
</script>
<script type="text/javascript" src="$relpath^doxygen-awesome-fragment-copy-button.js"></script>
<script type="text/javascript">
DoxygenAwesomeFragmentCopyButton.init()
</script>
<script type="text/javascript" src="$relpath^doxygen-awesome-paragraph-link.js"></script>
<script type="text/javascript">
DoxygenAwesomeParagraphLink.init()
</script>
<script type="text/javascript" src="$relpath^doxygen-awesome-interactive-toc.js"></script>
<script type="text/javascript">
DoxygenAwesomeInteractiveToc.init()
</script>
</head>
<body>
<!--BEGIN FULL_SIDEBAR-->
<div id="side-nav" class="ui-resizable side-nav-resizable"><!-- do not remove this div, it is closed by doxygen! -->
<!--END FULL_SIDEBAR-->
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<!--BEGIN TITLEAREA-->
<div id="titlearea">
<table cellspacing="0" cellpadding="0">
<tbody>
<tr id="projectrow">
<!--BEGIN PROJECT_LOGO-->
<td id="projectlogo"><img alt="Logo" src="$relpath^$projectlogo"$logosize/></td>
<!--END PROJECT_LOGO-->
<!--BEGIN PROJECT_NAME-->
<td id="projectalign">
<div id="projectname">$projectname<!--BEGIN PROJECT_NUMBER--><span id="projectnumber">&#160;$projectnumber</span><!--END PROJECT_NUMBER-->
</div>
<!--BEGIN PROJECT_BRIEF--><div id="projectbrief">$projectbrief</div><!--END PROJECT_BRIEF-->
</td>
<!--END PROJECT_NAME-->
<!--BEGIN !PROJECT_NAME-->
<!--BEGIN PROJECT_BRIEF-->
<td>
<div id="projectbrief">$projectbrief</div>
</td>
<!--END PROJECT_BRIEF-->
<!--END !PROJECT_NAME-->
<!--BEGIN DISABLE_INDEX-->
<!--BEGIN SEARCHENGINE-->
<!--BEGIN !FULL_SIDEBAR-->
<td>$searchbox</td>
<!--END !FULL_SIDEBAR-->
<!--END SEARCHENGINE-->
<!--END DISABLE_INDEX-->
</tr>
<!--BEGIN SEARCHENGINE-->
<!--BEGIN FULL_SIDEBAR-->
<tr><td colspan="2">$searchbox</td></tr>
<!--END FULL_SIDEBAR-->
<!--END SEARCHENGINE-->
</tbody>
</table>
</div>
<!--END TITLEAREA-->
<!-- end header part -->

View File

@@ -48,8 +48,6 @@ Table of contents:
@subpage libssh_tutor_sftp_aio
@subpage libssh_tutor_fido2
@subpage libssh_tutor_todo
*/

View File

@@ -19,7 +19,7 @@ the interesting functions as you go.
The libssh library provides:
- <strong>Key Exchange Methods</strong>: <i>sntrup761x25519-sha512, sntrup761x25519-sha512@openssh.com, mlkem768x25519-sha256, mlkem768nistp256-sha256, mlkem1024nistp384-sha384, curve25519-sha256, curve25519-sha256@libssh.org, ecdh-sha2-nistp256, ecdh-sha2-nistp384, ecdh-sha2-nistp521</i>, diffie-hellman-group1-sha1, diffie-hellman-group14-sha1
- <strong>Key Exchange Methods</strong>: <i>curve25519-sha256, curve25519-sha256@libssh.org, ecdh-sha2-nistp256, ecdh-sha2-nistp384, ecdh-sha2-nistp521</i>, diffie-hellman-group1-sha1, diffie-hellman-group14-sha1
- <strong>Public Key Algorithms</strong>: ssh-ed25519, ecdsa-sha2-nistp256, ecdsa-sha2-nistp384, ecdsa-sha2-nistp521, ssh-rsa, rsa-sha2-512, rsa-sha2-256
- <strong>Ciphers</strong>: <i>aes256-ctr, aes192-ctr, aes128-ctr</i>, aes256-cbc (rijndael-cbc@lysator.liu.se), aes192-cbc, aes128-cbc, 3des-cbc, blowfish-cbc
- <strong>Compression Schemes</strong>: zlib, <i>zlib@openssh.com</i>, none

View File

@@ -81,6 +81,10 @@ We recommend the users to provide a specific PKCS #11 URI so that it matches onl
If the engine discovers multiple slots that could potentially contain the private keys referenced
by the provided PKCS #11 URI, the engine will not try to authenticate.
For testing, the SoftHSM PKCS#11 library is used.
For testing, the SoftHSM PKCS#11 library is used. But it has some issues with
OpenSSL initialization/cleanup when used with OpenSSL 3.0 so we are using it
indirectly through a p11-kit remoting as described in the following article:
https://p11-glue.github.io/p11-glue/p11-kit/manual/remoting.html
*/

View File

@@ -26,7 +26,7 @@ The code sample below achieves these tasks:
@code
int shell_session(ssh_session session)
{
ssh_channel channel = NULL;
ssh_channel channel;
int rc;
channel = ssh_channel_new(session);

21
doc/that_style/LICENSE Normal file
View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2017 Jan-Lukas Wynen
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.

22
doc/that_style/README.md Normal file
View File

@@ -0,0 +1,22 @@
# that style
A plain, more modern HTML style for Doxygen
## Requirements
- Doxygen (tested with version 1.8.13)
- *optional*: a sass/scss compiler if you want to modify the style
## Simple usage
Tell Doxygen about the files for that style as shown in [doxyfile.conf](doxyfile.conf). You might need to adjust the
paths depending on where you installed that style.
When you run Doxygen, all files are copied into to generated HTML folder. So you don't need to keep the originals around
unless you want to re-generate the documentation.
## Advanced
that style uses a custom javascript to hack some nice stripes into some tables. It has to be loaded from HTML. Hence you need
to use the provided custom header. Since its default content may change when Doxygen is updated, there might be syntax error in
the generated HTML. If this is the case, you can remove the custom header (adjust your doxyfile.conf). This has no
disadvantages other than removing the stripes.
[that_style.css](that_style.css) was generated from the scss files in the folder [sass](sass). If you want to change the style,
use those files in order to have better control. For instance, you can easily change most colors by modifying the variables
in the beginning of [that_style.scss](sass/that_style.scss).

View File

@@ -0,0 +1,56 @@
<!-- HTML header for doxygen 1.8.13-->
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
<meta name="generator" content="Doxygen $doxygenversion"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<!--BEGIN PROJECT_NAME--><title>$projectname: $title</title><!--END PROJECT_NAME-->
<!--BEGIN !PROJECT_NAME--><title>$title</title><!--END !PROJECT_NAME-->
<link href="$relpath^tabs.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="$relpath^jquery.js"></script>
<script type="text/javascript" src="$relpath^dynsections.js"></script>
$treeview
$search
$mathjax
<link href="$relpath^$stylesheet" rel="stylesheet" type="text/css" />
<script src="$relpath^striped_bg.js"></script>
$extrastylesheet
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<!--BEGIN TITLEAREA-->
<div id="titlearea">
<table cellspacing="0" cellpadding="0">
<tbody>
<tr style="height: 56px;">
<!--BEGIN PROJECT_LOGO-->
<td id="projectlogo"><img alt="Logo" src="$relpath^$projectlogo"/></td>
<!--END PROJECT_LOGO-->
<!--BEGIN PROJECT_NAME-->
<td id="projectalign" style="padding-left: 0.5em;">
<div id="projectname">$projectname
<!--BEGIN PROJECT_NUMBER-->&#160;<span id="projectnumber">$projectnumber</span><!--END PROJECT_NUMBER-->
</div>
<!--BEGIN PROJECT_BRIEF--><div id="projectbrief">$projectbrief</div><!--END PROJECT_BRIEF-->
</td>
<!--END PROJECT_NAME-->
<!--BEGIN !PROJECT_NAME-->
<!--BEGIN PROJECT_BRIEF-->
<td style="padding-left: 0.5em;">
<div id="projectbrief">$projectbrief</div>
</td>
<!--END PROJECT_BRIEF-->
<!--END !PROJECT_NAME-->
<!--BEGIN DISABLE_INDEX-->
<!--BEGIN SEARCHENGINE-->
<td>$searchbox</td>
<!--END SEARCHENGINE-->
<!--END DISABLE_INDEX-->
</tr>
</tbody>
</table>
</div>
<!--END TITLEAREA-->
<!-- end header part -->

View File

@@ -0,0 +1,97 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="24"
height="22"
viewBox="0 0 6.3499999 5.8208335"
version="1.1"
id="svg8"
sodipodi:docname="doc.svg"
inkscape:version="0.92.1 r">
<defs
id="defs2" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="32"
inkscape:cx="11.139212"
inkscape:cy="14.811193"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:showpageshadow="false"
units="px"
inkscape:window-width="2560"
inkscape:window-height="1357"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1" />
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-291.17915)">
<path
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#4d4d4d;stroke-width:0.26458329;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="M 3.315043,291.8406 H 1.4552083 v 4.49792 h 3.1749999 v -3.10055 z"
id="path5095"
inkscape:connector-curvature="0" />
<path
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#4d4d4d;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m 3.1837239,291.84114 v 1.71186 h 1.4472656 v -0.31418 H 3.4473958 v -1.39768 z"
id="path5128"
inkscape:connector-curvature="0" />
<rect
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#4d4d4d;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.52916664;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
id="rect5132"
width="2.1166668"
height="0.26458332"
x="1.8520833"
y="293.82498" />
<rect
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#4d4d4d;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.52916664;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
id="rect5136"
width="1.0583334"
height="0.26458332"
x="1.8520832"
y="294.35416" />
<rect
y="294.88333"
x="1.8520832"
height="0.26458332"
width="1.8520833"
id="rect5138"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#4d4d4d;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.52916664;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
<rect
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#4d4d4d;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.52916664;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
id="rect4543"
width="1.5875"
height="0.26458332"
x="1.8520832"
y="295.41248" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 6.5 KiB

View File

@@ -0,0 +1,77 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="24"
height="22"
viewBox="0 0 6.3499998 5.8208335"
version="1.1"
id="svg8"
inkscape:version="0.92.1 r"
sodipodi:docname="folderclosed.svg"
inkscape:export-filename="/home/jl/Prog/doxygen_style/folderclosed.png"
inkscape:export-xdpi="96"
inkscape:export-ydpi="96">
<defs
id="defs2" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="51.113139"
inkscape:cx="7.7057751"
inkscape:cy="12.584171"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:snap-global="false"
units="px"
inkscape:showpageshadow="false"
inkscape:window-width="2560"
inkscape:window-height="1357"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:measure-start="0,0"
inkscape:measure-end="0,0" />
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-291.17915)">
<path
inkscape:connector-curvature="0"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#4d4d4d;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.26458332;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:stroke fill markers;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m 0.52916667,292.2374 -0.26458334,0.52925 v 3.43958 H 4.7625001 v -3.43958 H 2.38125 L 2.1166667,292.2374 Z"
id="rect4498"
sodipodi:nodetypes="cccccccc" />
<path
inkscape:connector-curvature="0"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#cccccc;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.66145831;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="M 2.9104167,292.76665 2.38125,293.56034 H 0.26458333 v 0.26464 H 2.38125 l 0.5291667,-0.79375 h 1.8520834 v -0.26458 z"
id="rect4500"
sodipodi:nodetypes="ccccccccc" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.4 KiB

View File

@@ -0,0 +1,83 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="24"
height="22"
viewBox="0 0 6.3499998 5.8208335"
version="1.1"
id="svg8"
inkscape:version="0.92.1 r"
sodipodi:docname="folderopen.svg"
inkscape:export-filename="/home/jl/Prog/doxygen_style/folderopen.png"
inkscape:export-xdpi="96"
inkscape:export-ydpi="96">
<defs
id="defs2" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="43.725861"
inkscape:cx="8.2043861"
inkscape:cy="13.464183"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:snap-global="false"
units="px"
inkscape:showpageshadow="false"
inkscape:window-width="2560"
inkscape:window-height="1357"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:measure-start="0,0"
inkscape:measure-end="0,0" />
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-291.17915)">
<path
inkscape:connector-curvature="0"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#4d4d4d;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.66145831;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m 0.52916667,292.23748 -0.26458334,0.52917 v 3.43958 H 4.762461 l 7.8e-5,-3.43958 H 2.38125 l -0.2645833,-0.52917 z"
id="path5228"
sodipodi:nodetypes="cccccccc" />
<path
inkscape:connector-curvature="0"
id="path5279"
d="M 1.0583333,293.5604 H 5.55625 L 4.7625,296.20603 H 0.26458333 Z"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ececec;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.66145831;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
sodipodi:nodetypes="ccccc" />
<path
sodipodi:nodetypes="ccccccc"
inkscape:connector-curvature="0"
id="path5234"
d="M 1.0583333,294.35415 H 3.175 l 0.5291667,-0.52917 H 5.55625 L 4.7625,296.20603 H 0.26458333 Z"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#4d4d4d;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.66145831;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.1 KiB

View File

@@ -0,0 +1,73 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="22"
height="22"
viewBox="0 0 5.8208332 5.8208335"
version="1.1"
id="svg8"
inkscape:version="0.92.1 r"
sodipodi:docname="mag_glass.svg">
<defs
id="defs2" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="32"
inkscape:cx="8.961936"
inkscape:cy="10.205344"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="false"
units="px"
inkscape:showpageshadow="false"
inkscape:snap-bbox="false"
inkscape:bbox-nodes="true"
inkscape:window-width="2560"
inkscape:window-height="1357"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:snap-global="false" />
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-291.17915)">
<path
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#333333;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.99999988;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="M 6.9101562 2.4082031 C 3.1105656 2.4082031 -5.9211895e-16 5.5081643 0 9.3027344 C 0 13.097342 3.1105656 16.197266 6.9101562 16.197266 C 8.2869348 16.197266 9.5698699 15.787508 10.650391 15.087891 L 15.162109 19.587891 L 16.636719 18.115234 L 12.214844 13.707031 C 13.214837 12.510659 13.818359 10.974238 13.818359 9.3027344 C 13.818359 5.5081643 10.709747 2.4082031 6.9101562 2.4082031 z M 6.9101562 4.9101562 C 9.3624717 4.9101562 11.324219 6.8631249 11.324219 9.3027344 C 11.324219 11.742382 9.3624717 13.695312 6.9101562 13.695312 C 4.4578408 13.695312 2.5019531 11.742382 2.5019531 9.3027344 C 2.5019531 6.8631249 4.4578408 4.9101562 6.9101562 4.9101562 z "
transform="matrix(0.26458333,0,0,0.26458333,0,291.17915)"
id="rect4524" />
<path
transform="matrix(0.99422295,0,0,0.68955299,-0.83134947,91.755588)"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#333333;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.63466448;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
inkscape:transform-center-y="0.25905895"
d="m 5.6074138,294.49889 -1.0836583,-1.87695 2.1673165,0 z"
id="path4491" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.8 KiB

View File

@@ -0,0 +1,73 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="10.53333"
height="32"
viewBox="0 0 9.8749964 30"
id="svg2"
version="1.1"
inkscape:version="0.92.1 r"
sodipodi:docname="nav_edge_inter.svg">
<defs
id="defs4" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="32"
inkscape:cx="8.6823304"
inkscape:cy="16.225639"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
units="px"
inkscape:snap-bbox="true"
inkscape:bbox-paths="false"
inkscape:bbox-nodes="true"
inkscape:snap-bbox-edge-midpoints="true"
inkscape:object-nodes="true"
inkscape:window-width="2560"
inkscape:window-height="1357"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1" />
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-1022.3622)">
<path
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m 0,1022.3622 v 15 15 l 8,-15 z"
id="path4143"
inkscape:connector-curvature="0" />
<path
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#333333;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.9375px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m 1.2910156,1022.3496 -0.82421872,0.4473 7.87890622,14.5527 -7.87890622,14.5527 0.82421872,0.4473 8.1210938,-15 z"
id="path5240"
inkscape:connector-curvature="0" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.8 KiB

View File

@@ -0,0 +1,73 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="8.5333338"
height="32"
viewBox="0 0 8.0000001 30"
id="svg2"
version="1.1"
inkscape:version="0.92.1 r"
sodipodi:docname="nav_edge_left.svg">
<defs
id="defs4" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="32"
inkscape:cx="5.3721385"
inkscape:cy="14.16429"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
units="px"
inkscape:snap-bbox="true"
inkscape:bbox-paths="false"
inkscape:bbox-nodes="false"
inkscape:snap-bbox-edge-midpoints="false"
inkscape:object-nodes="true"
inkscape:window-width="2560"
inkscape:window-height="1357"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1" />
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-1022.3622)">
<path
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:6;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="M 0 0 L 0 32 L 8.5332031 16 L 0 0 z "
transform="matrix(0.93749998,0,0,0.93749998,0,1022.3622)"
id="rect4586" />
<path
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m 0,1022.3622 v 15 15 l 8,-15 z"
id="path4143"
inkscape:connector-curvature="0" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

@@ -0,0 +1,73 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="8"
height="30"
viewBox="0 0 8.0000001 30"
id="svg2"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="nav_edge.svg">
<defs
id="defs4" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="32"
inkscape:cx="5.3721385"
inkscape:cy="14.16429"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
units="px"
inkscape:snap-bbox="true"
inkscape:bbox-paths="false"
inkscape:bbox-nodes="false"
inkscape:snap-bbox-edge-midpoints="false"
inkscape:object-nodes="true"
inkscape:window-width="2560"
inkscape:window-height="1357"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1" />
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-1022.3622)">
<path
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m 0,1022.3622 0,15 0,15 8,-15 -8,-15 z"
id="path4143"
inkscape:connector-curvature="0" />
<path
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m 1e-8,1022.3622 7.99999999,15 0,-15 -8,0 z m 7.99999999,15 -8,15 8,0 0,-15 z"
id="rect4136"
inkscape:connector-curvature="0" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

@@ -0,0 +1,120 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="6"
height="9"
viewBox="0 0 1.5875 2.3812501"
version="1.1"
id="svg8"
inkscape:version="0.92.1 r"
sodipodi:docname="splitbar_handle.svg">
<defs
id="defs2" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="32"
inkscape:cx="8.7681488"
inkscape:cy="-2.7929517"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="false"
units="px"
inkscape:showpageshadow="false"
showguides="false"
inkscape:window-width="2560"
inkscape:window-height="1357"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1">
<inkscape:grid
type="xygrid"
id="grid4487" />
</sodipodi:namedview>
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-294.61873)">
<rect
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.52916664;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
id="rect4485"
width="0.26458335"
height="0.26458332"
x="0.26458332"
y="294.8833" />
<rect
y="294.8833"
x="1.0583333"
height="0.26458332"
width="0.26458335"
id="rect4489"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.52916664;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
<rect
y="295.41248"
x="0.26458329"
height="0.26458332"
width="0.26458335"
id="rect4491"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.52916664;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
<rect
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.52916664;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
id="rect4493"
width="0.26458335"
height="0.26458332"
x="1.0583333"
y="295.41248" />
<rect
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.52916664;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
id="rect4495"
width="0.26458335"
height="0.26458332"
x="0.26458332"
y="295.94165" />
<rect
y="295.94165"
x="1.0583333"
height="0.26458332"
width="0.26458335"
id="rect4497"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.52916664;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
<rect
y="296.47079"
x="0.26458329"
height="0.26458332"
width="0.26458335"
id="rect4499"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.52916664;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
<rect
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.52916664;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
id="rect4501"
width="0.26458335"
height="0.26458332"
x="1.0583333"
y="296.47079" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 483 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 488 B

View File

@@ -0,0 +1,32 @@
// Adds extra CSS classes "even" and "odd" to .memberdecls to allow
// striped backgrounds.
function MemberDeclsStriper () {
var counter = 0;
this.stripe = function() {
$(".memberdecls tbody").children().each(function(i) {
// reset counter at every heading -> always start with even
if ($(this).is(".heading")) {
counter = 0;
}
// add extra classes
if (counter % 2 == 1) {
$(this).addClass("odd");
}
else {
$(this).addClass("even");
}
// advance counter at every separator
// this is the only way to reliably detect which table rows belong together
if ($(this).is('[class^="separator"]')) {
counter++;
}
});
}
}
// execute the function
$(document).ready(new MemberDeclsStriper().stripe);

File diff suppressed because it is too large Load Diff

View File

@@ -30,8 +30,8 @@ int authenticate_kbdint(ssh_session session, const char *password)
err = ssh_userauth_kbdint(session, NULL, NULL);
while (err == SSH_AUTH_INFO) {
const char *instruction = NULL;
const char *name = NULL;
const char *instruction;
const char *name;
char buffer[128];
int i, n;
@@ -48,8 +48,8 @@ int authenticate_kbdint(ssh_session session, const char *password)
}
for (i = 0; i < n; i++) {
const char *answer = NULL;
const char *prompt = NULL;
const char *answer;
const char *prompt;
char echo;
prompt = ssh_userauth_kbdint_getprompt(session, i, &echo);
@@ -58,7 +58,7 @@ int authenticate_kbdint(ssh_session session, const char *password)
}
if (echo) {
char *p = NULL;
char *p;
printf("%s", prompt);
@@ -66,6 +66,7 @@ int authenticate_kbdint(ssh_session session, const char *password)
return SSH_AUTH_ERROR;
}
buffer[sizeof(buffer) - 1] = '\0';
if ((p = strchr(buffer, '\n'))) {
*p = '\0';
}
@@ -74,7 +75,7 @@ int authenticate_kbdint(ssh_session session, const char *password)
return SSH_AUTH_ERROR;
}
memset(buffer, 0, sizeof(buffer));
memset(buffer, 0, strlen(buffer));
} else {
if (password && strstr(prompt, "Password:")) {
answer = password;
@@ -142,11 +143,11 @@ int authenticate_console(ssh_session session)
int rc;
int method;
char password[128] = {0};
char *banner = NULL;
char *banner;
// Try to authenticate
rc = ssh_userauth_none(session, NULL);
if (rc == SSH_AUTH_ERROR || !ssh_is_connected(session)) {
if (rc == SSH_AUTH_ERROR) {
error(session);
return rc;
}
@@ -155,7 +156,7 @@ int authenticate_console(ssh_session session)
while (rc != SSH_AUTH_SUCCESS) {
if (method & SSH_AUTH_METHOD_GSSAPI_MIC){
rc = ssh_userauth_gssapi(session);
if (rc == SSH_AUTH_ERROR || !ssh_is_connected(session)) {
if(rc == SSH_AUTH_ERROR) {
error(session);
return rc;
} else if (rc == SSH_AUTH_SUCCESS) {
@@ -165,7 +166,7 @@ int authenticate_console(ssh_session session)
// Try to authenticate with public key first
if (method & SSH_AUTH_METHOD_PUBLICKEY) {
rc = ssh_userauth_publickey_auto(session, NULL, NULL);
if (rc == SSH_AUTH_ERROR || !ssh_is_connected(session)) {
if (rc == SSH_AUTH_ERROR) {
error(session);
return rc;
} else if (rc == SSH_AUTH_SUCCESS) {
@@ -205,7 +206,7 @@ int authenticate_console(ssh_session session)
// Try to authenticate with keyboard interactive";
if (method & SSH_AUTH_METHOD_INTERACTIVE) {
rc = authenticate_kbdint(session, NULL);
if (rc == SSH_AUTH_ERROR || !ssh_is_connected(session)) {
if (rc == SSH_AUTH_ERROR) {
error(session);
return rc;
} else if (rc == SSH_AUTH_SUCCESS) {
@@ -220,7 +221,7 @@ int authenticate_console(ssh_session session)
// Try to authenticate with password
if (method & SSH_AUTH_METHOD_PASSWORD) {
rc = ssh_userauth_password(session, NULL, password);
if (rc == SSH_AUTH_ERROR || !ssh_is_connected(session)) {
if (rc == SSH_AUTH_ERROR) {
error(session);
return rc;
} else if (rc == SSH_AUTH_SUCCESS) {

View File

@@ -21,57 +21,47 @@ clients must be made or how a client should react.
#include "examples_common.h"
#include <stdio.h>
ssh_session connect_ssh(const char *host, const char *port, const char *user, int verbosity)
{
ssh_session session = NULL;
int auth = 0;
ssh_session connect_ssh(const char *host, const char *user,int verbosity){
ssh_session session;
int auth=0;
session = ssh_new();
if (session == NULL) {
return NULL;
}
session=ssh_new();
if (session == NULL) {
return NULL;
}
if (user != NULL) {
if (ssh_options_set(session, SSH_OPTIONS_USER, user) < 0) {
ssh_free(session);
return NULL;
}
if(user != NULL){
if (ssh_options_set(session, SSH_OPTIONS_USER, user) < 0) {
ssh_free(session);
return NULL;
}
}
if (port != NULL) {
if (ssh_options_set(session, SSH_OPTIONS_PORT_STR, port) < 0) {
ssh_free(session);
return NULL;
}
}
if (ssh_options_set(session, SSH_OPTIONS_HOST, host) < 0) {
ssh_free(session);
return NULL;
}
ssh_options_set(session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity);
if (ssh_connect(session)) {
fprintf(stderr, "Connection failed : %s\n", ssh_get_error(session));
ssh_disconnect(session);
ssh_free(session);
return NULL;
}
if (verify_knownhost(session) < 0) {
ssh_disconnect(session);
ssh_free(session);
return NULL;
}
auth = authenticate_console(session);
if (auth == SSH_AUTH_SUCCESS) {
return session;
} else if (auth == SSH_AUTH_DENIED) {
fprintf(stderr, "Authentication failed\n");
} else {
fprintf(stderr,
"Error while authenticating : %s\n",
ssh_get_error(session));
}
if (ssh_options_set(session, SSH_OPTIONS_HOST, host) < 0) {
ssh_free(session);
return NULL;
}
ssh_options_set(session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity);
if(ssh_connect(session)){
fprintf(stderr,"Connection failed : %s\n",ssh_get_error(session));
ssh_disconnect(session);
ssh_free(session);
return NULL;
}
if(verify_knownhost(session)<0){
ssh_disconnect(session);
ssh_free(session);
return NULL;
}
auth=authenticate_console(session);
if(auth==SSH_AUTH_SUCCESS){
return session;
} else if(auth==SSH_AUTH_DENIED){
fprintf(stderr,"Authentication failed\n");
} else {
fprintf(stderr,"Error while authenticating : %s\n",ssh_get_error(session));
}
ssh_disconnect(session);
ssh_free(session);
return NULL;
}

View File

@@ -16,11 +16,11 @@ clients must be made or how a client should react.
#include <libssh/libssh.h>
/** Zero a structure */
#define ZERO_STRUCT(x) memset(&(x), 0, sizeof(x))
#define ZERO_STRUCT(x) memset((char *)&(x), 0, sizeof(x))
int authenticate_console(ssh_session session);
int authenticate_kbdint(ssh_session session, const char *password);
int verify_knownhost(ssh_session session);
ssh_session connect_ssh(const char *hostname, const char *port, const char *user, int verbosity);
ssh_session connect_ssh(const char *hostname, const char *user, int verbosity);
#endif /* EXAMPLES_COMMON_H_ */

View File

@@ -5,13 +5,13 @@
#include "examples_common.h"
int main(void) {
ssh_session session = NULL;
ssh_channel channel = NULL;
ssh_session session;
ssh_channel channel;
char buffer[256];
int rbytes, wbytes, total = 0;
int rc;
session = connect_ssh("localhost", NULL, NULL, 0);
session = connect_ssh("localhost", NULL, 0);
if (session == NULL) {
ssh_finalize();
return 1;

View File

@@ -350,12 +350,7 @@ int main(int argc, char *argv[])
goto end;
}
if (arguments.file == NULL) {
fprintf(stderr, "Error: Missing argument file\n");
goto end;
}
if (arguments.action_list) {
if (arguments.action_list && arguments.file) {
list_fingerprint(arguments.file);
goto end;
}

View File

@@ -38,7 +38,7 @@ int verify_knownhost(ssh_session session)
char buf[10];
unsigned char *hash = NULL;
size_t hlen;
ssh_key srv_pubkey = NULL;
ssh_key srv_pubkey;
int rc;
rc = ssh_get_server_publickey(session, &srv_pubkey);

View File

@@ -26,11 +26,10 @@ program.
#define BUF_SIZE 16384
#endif
static char **sources = NULL;
static char **sources;
static int nsources;
static char *destination = NULL;
static char *destination;
static int verbosity = 0;
static char *port = NULL;
struct location {
int is_ssh;
@@ -50,10 +49,9 @@ enum {
static void usage(const char *argv0) {
fprintf(stderr, "Usage : %s [options] [[user@]host1:]file1 ... \n"
" [[user@]host2:]destination\n"
"sample scp client - libssh-%s\n"
"Options :\n"
" -P : use port to connect to remote host\n"
" -v : increase verbosity of libssh. Can be used multiple times\n",
"sample scp client - libssh-%s\n",
// "Options :\n",
// " -r : use RSA to verify host public key\n",
argv0,
ssh_version(0));
exit(0);
@@ -62,14 +60,11 @@ static void usage(const char *argv0) {
static int opts(int argc, char **argv) {
int i;
while((i = getopt(argc, argv, "P:v")) != -1) {
while((i = getopt(argc, argv, "v")) != -1) {
switch(i) {
case 'v':
verbosity++;
break;
case 'P':
port = optarg;
break;
default:
fprintf(stderr, "unknown option %c\n", optopt);
usage(argv[0]);
@@ -119,14 +114,9 @@ static void location_free(struct location *loc)
}
}
static struct location *parse_location(char *loc)
{
struct location *location = NULL;
char *ptr = NULL;
if (loc == NULL) {
return NULL;
}
static struct location *parse_location(char *loc) {
struct location *location;
char *ptr;
location = malloc(sizeof(struct location));
if (location == NULL) {
@@ -188,7 +178,7 @@ static void close_location(struct location *loc) {
static int open_location(struct location *loc, int flag) {
if (loc->is_ssh && flag == WRITE) {
loc->session = connect_ssh(loc->host, port, loc->user, verbosity);
loc->session = connect_ssh(loc->host, loc->user, verbosity);
if (!loc->session) {
fprintf(stderr, "Couldn't connect to %s\n", loc->host);
return -1;
@@ -214,7 +204,7 @@ static int open_location(struct location *loc, int flag) {
}
return 0;
} else if (loc->is_ssh && flag == READ) {
loc->session = connect_ssh(loc->host, port, loc->user, verbosity);
loc->session = connect_ssh(loc->host, loc->user, verbosity);
if (!loc->session) {
fprintf(stderr, "Couldn't connect to %s\n", loc->host);
return -1;

View File

@@ -35,8 +35,8 @@ clients must be made or how a client should react.
static int authenticated=0;
static int tries = 0;
static int error = 0;
static ssh_channel chan = NULL;
static char *username = NULL;
static ssh_channel chan=NULL;
static char *username;
static ssh_gssapi_creds client_creds = NULL;
static int auth_password(ssh_session session, const char *user,
@@ -204,12 +204,11 @@ static error_t parse_opt (int key, char *arg, struct argp_state *state) {
static struct argp argp = {options, parse_opt, args_doc, doc, NULL, NULL, NULL};
#endif /* HAVE_ARGP_H */
int main(int argc, char **argv)
{
ssh_session session = NULL;
ssh_bind sshbind = NULL;
ssh_event mainloop = NULL;
ssh_session client_session = NULL;
int main(int argc, char **argv){
ssh_session session;
ssh_bind sshbind;
ssh_event mainloop;
ssh_session client_session;
struct ssh_server_callbacks_struct cb = {
.userdata = NULL,
@@ -220,7 +219,7 @@ int main(int argc, char **argv)
char buf[BUF_SIZE];
char host[128]="";
char *ptr = NULL;
char *ptr;
int i,r, rc;
sshbind=ssh_bind_new();
@@ -337,3 +336,4 @@ int main(int argc, char **argv)
ssh_finalize();
return 0;
}

View File

@@ -148,7 +148,6 @@ static error_t parse_opt(int key, char *arg, struct argp_state *state)
ssh_bind sshbind = state->input;
static int no_default_keys = 0;
static int rsa_already_set = 0, ecdsa_already_set = 0;
static int verbosity = 0;
switch (key)
{
@@ -177,10 +176,8 @@ static error_t parse_opt(int key, char *arg, struct argp_state *state)
strncpy(authorizedkeys, arg, DEF_STR_SIZE - 1);
break;
case 'v':
verbosity++;
ssh_bind_options_set(sshbind,
SSH_BIND_OPTIONS_LOG_VERBOSITY,
&verbosity);
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_LOG_VERBOSITY_STR,
"3");
break;
case ARGP_KEY_ARG:
if (state->arg_num >= 1)
@@ -216,7 +213,10 @@ static struct argp argp = {options, parse_opt, args_doc, doc, NULL, NULL, NULL};
#endif /* HAVE_ARGP_H */
/* A userdata struct for channel. */
struct channel_data_struct {
struct channel_data_struct
{
/* Event which is used to poll the above descriptors. */
ssh_event event;
sftp_session sftp;
};
@@ -378,11 +378,18 @@ static void handle_session(ssh_event event, ssh_session session)
do {
/* Poll the main event which takes care of the session, the channel and
* even our child process's stdout/stderr (once it's started). */
if (ssh_event_dopoll(event, 100) == SSH_ERROR) {
if (ssh_event_dopoll(event, -1) == SSH_ERROR) {
ssh_channel_close(sdata.channel);
}
} while (ssh_channel_is_open(sdata.channel) &&
!ssh_channel_is_eof(sdata.channel));
/* If child process's stdout/stderr has been registered with the event,
* or the child process hasn't started yet, continue. */
if (cdata.event != NULL) {
continue;
}
/* FIXME The server keeps hanging in the poll above when the client
* closes the channel */
} while (ssh_channel_is_open(sdata.channel));
ssh_channel_send_eof(sdata.channel);
ssh_channel_close(sdata.channel);

View File

@@ -244,11 +244,10 @@ static error_t parse_opt (int key, char *arg, struct argp_state *state) {
static struct argp argp = {options, parse_opt, args_doc, doc, NULL, NULL, NULL};
#endif /* HAVE_ARGP_H */
int main(int argc, char **argv)
{
ssh_session session = NULL;
ssh_bind sshbind = NULL;
ssh_event mainloop = NULL;
int main(int argc, char **argv){
ssh_session session;
ssh_bind sshbind;
ssh_event mainloop;
struct ssh_server_callbacks_struct cb = {
.userdata = NULL,
.auth_none_function = auth_none,
@@ -340,3 +339,4 @@ int main(int argc, char **argv)
ssh_finalize();
return 0;
}

View File

@@ -174,8 +174,8 @@ static error_t parse_opt (int key, char *arg, struct argp_state *state) {
static struct argp argp = {options, parse_opt, args_doc, doc, NULL, NULL, NULL};
#endif /* HAVE_ARGP_H */
static const char *name = NULL;
static const char *instruction = NULL;
static const char *name;
static const char *instruction;
static const char *prompts[2];
static char echo[] = { 1, 0 };
@@ -279,12 +279,11 @@ static int authenticate(ssh_session session) {
return 0;
}
int main(int argc, char **argv)
{
ssh_session session = NULL;
ssh_bind sshbind = NULL;
ssh_message message = NULL;
ssh_channel chan = NULL;
int main(int argc, char **argv){
ssh_session session;
ssh_bind sshbind;
ssh_message message;
ssh_channel chan=0;
char buf[BUF_SIZE];
int auth=0;
int shell=0;
@@ -412,3 +411,4 @@ int main(int argc, char **argv)
ssh_finalize();
return 0;
}

View File

@@ -32,163 +32,151 @@ static const char *createcommand =
"cd /tmp/libssh_tests && date > a && date > b && mkdir c && date > d";
static char *host = NULL;
static void usage(const char *argv0)
{
fprintf(stderr,
"Usage : %s [options] host\n"
"sample tiny scp downloader client - libssh-%s\n"
"This program will create files in /tmp and try to fetch them\n",
argv0,
ssh_version(0));
exit(0);
static void usage(const char *argv0){
fprintf(stderr,"Usage : %s [options] host\n"
"sample tiny scp downloader client - libssh-%s\n"
"This program will create files in /tmp and try to fetch them\n",
// "Options :\n",
// " -r : use RSA to verify host public key\n",
argv0,
ssh_version(0));
exit(0);
}
static int opts(int argc, char **argv)
{
int i;
while ((i = getopt(argc, argv, "v")) != -1) {
switch (i) {
case 'v':
verbosity++;
break;
default:
fprintf(stderr, "unknown option %c\n", optopt);
usage(argv[0]);
return -1;
}
}
host = argv[optind];
if (host == NULL)
static int opts(int argc, char **argv){
int i;
while((i=getopt(argc,argv,"v"))!=-1){
switch(i){
case 'v':
verbosity++;
break;
default:
fprintf(stderr,"unknown option %c\n",optopt);
usage(argv[0]);
return 0;
}
static void create_files(ssh_session session)
{
ssh_channel channel = ssh_channel_new(session);
char buffer[1];
int rc;
if (channel == NULL) {
fprintf(stderr, "Error creating channel: %s\n", ssh_get_error(session));
exit(EXIT_FAILURE);
}
if (ssh_channel_open_session(channel) != SSH_OK) {
fprintf(stderr, "Error creating channel: %s\n", ssh_get_error(session));
ssh_channel_free(channel);
exit(EXIT_FAILURE);
}
if (ssh_channel_request_exec(channel, createcommand) != SSH_OK) {
fprintf(stderr,
"Error executing command: %s\n",
ssh_get_error(session));
ssh_channel_close(channel);
ssh_channel_free(channel);
exit(EXIT_FAILURE);
}
while (!ssh_channel_is_eof(channel)) {
rc = ssh_channel_read(channel, buffer, 1, 1);
if (rc != 1) {
fprintf(stderr, "Error reading from channel\n");
ssh_channel_close(channel);
ssh_channel_free(channel);
return;
}
rc = write(1, buffer, 1);
if (rc < 0) {
fprintf(stderr, "Error writing to buffer\n");
ssh_channel_close(channel);
ssh_channel_free(channel);
return;
}
}
ssh_channel_close(channel);
ssh_channel_free(channel);
}
static int fetch_files(ssh_session session)
{
int size;
char buffer[BUF_SIZE];
int mode;
char *filename = NULL;
int r;
ssh_scp scp = ssh_scp_new(session,
SSH_SCP_READ | SSH_SCP_RECURSIVE,
"/tmp/libssh_tests/*");
if (ssh_scp_init(scp) != SSH_OK) {
fprintf(stderr, "error initializing scp: %s\n", ssh_get_error(session));
ssh_scp_free(scp);
return -1;
}
printf("Trying to download 3 files (a,b,d) and 1 directory (c)\n");
do {
r = ssh_scp_pull_request(scp);
switch (r) {
case SSH_SCP_REQUEST_NEWFILE:
size = ssh_scp_request_get_size(scp);
filename = strdup(ssh_scp_request_get_filename(scp));
mode = ssh_scp_request_get_permissions(scp);
printf("downloading file %s, size %d, perms 0%o\n",
filename,
size,
mode);
free(filename);
ssh_scp_accept_request(scp);
r = ssh_scp_read(scp, buffer, sizeof(buffer));
if (r == SSH_ERROR) {
fprintf(stderr,
"Error reading scp: %s\n",
ssh_get_error(session));
ssh_scp_close(scp);
ssh_scp_free(scp);
return -1;
}
printf("done\n");
break;
case SSH_ERROR:
fprintf(stderr, "Error: %s\n", ssh_get_error(session));
ssh_scp_close(scp);
ssh_scp_free(scp);
return -1;
case SSH_SCP_REQUEST_WARNING:
fprintf(stderr, "Warning: %s\n", ssh_scp_request_get_warning(scp));
break;
case SSH_SCP_REQUEST_NEWDIR:
filename = strdup(ssh_scp_request_get_filename(scp));
mode = ssh_scp_request_get_permissions(scp);
printf("downloading directory %s, perms 0%o\n", filename, mode);
free(filename);
ssh_scp_accept_request(scp);
break;
case SSH_SCP_REQUEST_ENDDIR:
printf("End of directory\n");
break;
case SSH_SCP_REQUEST_EOF:
printf("End of requests\n");
goto end;
}
} while (1);
end:
ssh_scp_close(scp);
ssh_scp_free(scp);
return 0;
}
host = argv[optind];
if(host == NULL)
usage(argv[0]);
return 0;
}
int main(int argc, char **argv)
{
ssh_session session = NULL;
if (opts(argc, argv) < 0)
return EXIT_FAILURE;
session = connect_ssh(host, NULL, NULL, verbosity);
if (session == NULL)
return EXIT_FAILURE;
create_files(session);
fetch_files(session);
ssh_disconnect(session);
ssh_free(session);
ssh_finalize();
return 0;
static void create_files(ssh_session session){
ssh_channel channel=ssh_channel_new(session);
char buffer[1];
int rc;
if(channel == NULL){
fprintf(stderr,"Error creating channel: %s\n",ssh_get_error(session));
exit(EXIT_FAILURE);
}
if(ssh_channel_open_session(channel) != SSH_OK){
fprintf(stderr,"Error creating channel: %s\n",ssh_get_error(session));
ssh_channel_free(channel);
exit(EXIT_FAILURE);
}
if(ssh_channel_request_exec(channel,createcommand) != SSH_OK){
fprintf(stderr,"Error executing command: %s\n",ssh_get_error(session));
ssh_channel_close(channel);
ssh_channel_free(channel);
exit(EXIT_FAILURE);
}
while(!ssh_channel_is_eof(channel)){
rc = ssh_channel_read(channel,buffer,1,1);
if (rc != 1) {
fprintf(stderr, "Error reading from channel\n");
ssh_channel_close(channel);
ssh_channel_free(channel);
return;
}
rc = write(1, buffer, 1);
if (rc < 0) {
fprintf(stderr, "Error writing to buffer\n");
ssh_channel_close(channel);
ssh_channel_free(channel);
return;
}
}
ssh_channel_close(channel);
ssh_channel_free(channel);
}
static int fetch_files(ssh_session session){
int size;
char buffer[BUF_SIZE];
int mode;
char *filename;
int r;
ssh_scp scp=ssh_scp_new(session, SSH_SCP_READ | SSH_SCP_RECURSIVE, "/tmp/libssh_tests/*");
if(ssh_scp_init(scp) != SSH_OK){
fprintf(stderr,"error initializing scp: %s\n",ssh_get_error(session));
ssh_scp_free(scp);
return -1;
}
printf("Trying to download 3 files (a,b,d) and 1 directory (c)\n");
do {
r=ssh_scp_pull_request(scp);
switch(r){
case SSH_SCP_REQUEST_NEWFILE:
size=ssh_scp_request_get_size(scp);
filename=strdup(ssh_scp_request_get_filename(scp));
mode=ssh_scp_request_get_permissions(scp);
printf("downloading file %s, size %d, perms 0%o\n",filename,size,mode);
free(filename);
ssh_scp_accept_request(scp);
r=ssh_scp_read(scp,buffer,sizeof(buffer));
if(r==SSH_ERROR){
fprintf(stderr,"Error reading scp: %s\n",ssh_get_error(session));
ssh_scp_close(scp);
ssh_scp_free(scp);
return -1;
}
printf("done\n");
break;
case SSH_ERROR:
fprintf(stderr,"Error: %s\n",ssh_get_error(session));
ssh_scp_close(scp);
ssh_scp_free(scp);
return -1;
case SSH_SCP_REQUEST_WARNING:
fprintf(stderr,"Warning: %s\n",ssh_scp_request_get_warning(scp));
break;
case SSH_SCP_REQUEST_NEWDIR:
filename=strdup(ssh_scp_request_get_filename(scp));
mode=ssh_scp_request_get_permissions(scp);
printf("downloading directory %s, perms 0%o\n",filename,mode);
free(filename);
ssh_scp_accept_request(scp);
break;
case SSH_SCP_REQUEST_ENDDIR:
printf("End of directory\n");
break;
case SSH_SCP_REQUEST_EOF:
printf("End of requests\n");
goto end;
}
} while (1);
end:
ssh_scp_close(scp);
ssh_scp_free(scp);
return 0;
}
int main(int argc, char **argv){
ssh_session session;
if(opts(argc,argv)<0)
return EXIT_FAILURE;
session=connect_ssh(host,NULL,verbosity);
if(session == NULL)
return EXIT_FAILURE;
create_files(session);
fetch_files(session);
ssh_disconnect(session);
ssh_free(session);
ssh_finalize();
return 0;
}

View File

@@ -5,60 +5,60 @@
#define LIMIT 0x100000000UL
int main(void)
{
ssh_session session = NULL;
ssh_channel channel = NULL;
char buffer[1024 * 1024] = {0};
int rc;
uint64_t total = 0;
uint64_t lastshown = 4096;
session = connect_ssh("localhost", NULL, NULL, 0);
if (session == NULL) {
return 1;
}
channel = ssh_channel_new(session);
if (channel == NULL) {
ssh_disconnect(session);
return 1;
}
rc = ssh_channel_open_session(channel);
if (rc < 0) {
ssh_channel_close(channel);
ssh_disconnect(session);
return 1;
}
rc = ssh_channel_request_exec(channel, "cat > /dev/null");
if (rc < 0) {
ssh_channel_close(channel);
ssh_disconnect(session);
return 1;
}
while ((rc = ssh_channel_write(channel, buffer, sizeof(buffer))) > 0) {
total += rc;
if (total / 2 >= lastshown) {
printf("written %llx\n", (long long unsigned int)total);
lastshown = total;
}
if (total > LIMIT)
break;
}
if (rc < 0) {
printf("error : %s\n", ssh_get_error(session));
ssh_channel_close(channel);
ssh_disconnect(session);
return 1;
}
ssh_channel_send_eof(channel);
ssh_channel_close(channel);
int main(void) {
ssh_session session;
ssh_channel channel;
char buffer[1024*1024];
int rc;
uint64_t total=0;
uint64_t lastshown=4096;
session = connect_ssh("localhost", NULL, 0);
if (session == NULL) {
return 1;
}
channel = ssh_channel_new(session);
if (channel == NULL) {
ssh_disconnect(session);
return 1;
}
return 0;
rc = ssh_channel_open_session(channel);
if (rc < 0) {
ssh_channel_close(channel);
ssh_disconnect(session);
return 1;
}
rc = ssh_channel_request_exec(channel, "cat > /dev/null");
if (rc < 0) {
ssh_channel_close(channel);
ssh_disconnect(session);
return 1;
}
while ((rc = ssh_channel_write(channel, buffer, sizeof(buffer))) > 0) {
total += rc;
if(total/2 >= lastshown){
printf("written %llx\n", (long long unsigned int) total);
lastshown=total;
}
if(total > LIMIT)
break;
}
if (rc < 0) {
printf("error : %s\n",ssh_get_error(session));
ssh_channel_close(channel);
ssh_disconnect(session);
return 1;
}
ssh_channel_send_eof(channel);
ssh_channel_close(channel);
ssh_disconnect(session);
return 0;
}

View File

@@ -70,7 +70,6 @@
#include <errno.h>
#include <fcntl.h>
#include <inttypes.h>
#include <poll.h>
#include <pthread.h>
#include <stddef.h>
@@ -232,7 +231,7 @@ static void _logging_callback(int priority, const char *function,
milliseconds = _current_timestamp();
fprintf(fp, "[%s.%" PRId64 ", %d] %s: %s\n", buf, milliseconds, priority,
fprintf(fp, "[%s.%jd, %d] %s: %s\n", buf, milliseconds, priority,
function, buffer);
fclose(fp);
}

View File

@@ -39,6 +39,8 @@
#include <libssh/callbacks.h>
#include <libssh/libssh.h>
#include <libssh/sftp.h>
#include "examples_common.h"
#define MAXCMD 10
@@ -51,7 +53,7 @@ static struct termios terminal;
static char *pcap_file = NULL;
static char *proxycommand = NULL;
static char *proxycommand;
static int auth_callback(const char *prompt,
char *buf,
@@ -86,24 +88,22 @@ static void add_cmd(char *cmd)
static void usage(void)
{
fprintf(
stderr,
"Usage : ssh [options] [login@]hostname\n"
"sample client - libssh-%s\n"
"Options :\n"
" -l user : log in as user\n"
" -p port : connect to port\n"
" -o option : set configuration option (e.g., -o Compression=yes)\n"
" -r : use RSA to verify host public key\n"
" -F file : parse configuration file instead of default one\n"
fprintf(stderr,
"Usage : ssh [options] [login@]hostname\n"
"sample client - libssh-%s\n"
"Options :\n"
" -l user : log in as user\n"
" -p port : connect to port\n"
" -r : use RSA to verify host public key\n"
" -F file : parse configuration file instead of default one\n"
#ifdef WITH_PCAP
" -P file : create a pcap debugging file\n"
" -P file : create a pcap debugging file\n"
#endif
#ifndef _WIN32
" -T proxycommand : command to execute as a socket proxy\n"
" -T proxycommand : command to execute as a socket proxy\n"
#endif
"\n",
ssh_version(0));
"\n",
ssh_version(0));
exit(0);
}
@@ -112,8 +112,8 @@ static int opts(int argc, char **argv)
{
int i;
while ((i = getopt(argc, argv, "T:P:F:")) != -1) {
switch (i) {
while((i = getopt(argc,argv,"T:P:F:")) != -1) {
switch(i){
case 'P':
pcap_file = optarg;
break;
@@ -159,14 +159,16 @@ static void cfmakeraw(struct termios *termios_p)
static void do_cleanup(int i)
{
(void)i;
/* unused variable */
(void) i;
tcsetattr(0, TCSANOW, &terminal);
tcsetattr(0, TCSANOW, &terminal);
}
static void do_exit(int i)
{
(void)i;
/* unused variable */
(void) i;
do_cleanup(0);
exit(0);
@@ -177,7 +179,7 @@ static int signal_delayed = 0;
#ifdef SIGWINCH
static void sigwindowchanged(int i)
{
(void)i;
(void) i;
signal_delayed = 1;
}
#endif
@@ -211,18 +213,18 @@ static void select_loop(ssh_session session,ssh_channel channel)
/* stdin */
connector_in = ssh_connector_new(session);
ssh_connector_set_out_channel(connector_in, channel, SSH_CONNECTOR_STDINOUT);
ssh_connector_set_in_fd(connector_in, STDIN_FILENO);
ssh_connector_set_in_fd(connector_in, 0);
ssh_event_add_connector(event, connector_in);
/* stdout */
connector_out = ssh_connector_new(session);
ssh_connector_set_out_fd(connector_out, STDOUT_FILENO);
ssh_connector_set_out_fd(connector_out, 1);
ssh_connector_set_in_channel(connector_out, channel, SSH_CONNECTOR_STDINOUT);
ssh_event_add_connector(event, connector_out);
/* stderr */
connector_err = ssh_connector_new(session);
ssh_connector_set_out_fd(connector_err, STDERR_FILENO);
ssh_connector_set_out_fd(connector_err, 2);
ssh_connector_set_in_channel(connector_err, channel, SSH_CONNECTOR_STDERR);
ssh_event_add_connector(event, connector_err);
@@ -249,9 +251,9 @@ static void select_loop(ssh_session session,ssh_channel channel)
static void shell(ssh_session session)
{
ssh_channel channel = NULL;
ssh_channel channel;
struct termios terminal_local;
int interactive = isatty(0);
int interactive=isatty(0);
channel = ssh_channel_new(session);
if (channel == NULL) {
@@ -337,7 +339,7 @@ static void batch_shell(ssh_session session)
static int client(ssh_session session)
{
int auth = 0;
char *banner = NULL;
char *banner;
int state;
if (user) {
@@ -421,7 +423,7 @@ static void cleanup_pcap(void)
int main(int argc, char **argv)
{
ssh_session session = NULL;
ssh_session session;
ssh_init();
session = ssh_new();

View File

@@ -192,6 +192,9 @@ static struct argp argp = {options, parse_opt, args_doc, doc, NULL, NULL, NULL};
static int
parse_opt(int argc, char **argv, ssh_bind sshbind)
{
int no_default_keys = 0;
int rsa_already_set = 0;
int ecdsa_already_set = 0;
int key;
while((key = getopt(argc, argv, "a:e:k:p:P:r:u:v")) != -1) {
@@ -199,10 +202,16 @@ parse_opt(int argc, char **argv, ssh_bind sshbind)
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_BINDPORT_STR, optarg);
} else if (key == 'k') {
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_HOSTKEY, optarg);
/* We can't track the types of keys being added with this
option, so let's ensure we keep the keys we're adding
by just not setting the default keys */
no_default_keys = 1;
} else if (key == 'r') {
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_HOSTKEY, optarg);
rsa_already_set = 1;
} else if (key == 'e') {
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_HOSTKEY, optarg);
ecdsa_already_set = 1;
} else if (key == 'a') {
strncpy(authorizedkeys, optarg, DEF_STR_SIZE-1);
} else if (key == 'u') {
@@ -247,6 +256,12 @@ parse_opt(int argc, char **argv, ssh_bind sshbind)
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_BINDADDR, argv[optind]);
if (!no_default_keys) {
set_default_keys(sshbind,
rsa_already_set,
ecdsa_already_set);
}
return 0;
}
#endif /* HAVE_ARGP_H */

View File

@@ -361,7 +361,7 @@ my_fd_data_function(UNUSED_PARAM(socket_t fd),
{
struct event_fd_data_struct *event_fd_data = (struct event_fd_data_struct *)userdata;
ssh_channel channel = event_fd_data->channel;
ssh_session session = NULL;
ssh_session session;
int len, i, wr;
char buf[BUF_SIZE];
int blocking;
@@ -455,8 +455,8 @@ open_tcp_socket(ssh_message msg)
{
struct sockaddr_in sin;
int forwardsock = -1;
struct hostent *host = NULL;
const char *dest_hostname = NULL;
struct hostent *host;
const char *dest_hostname;
int dest_port;
forwardsock = socket(AF_INET, SOCK_STREAM, 0);
@@ -499,8 +499,8 @@ message_callback(UNUSED_PARAM(ssh_session session),
UNUSED_PARAM(void *userdata))
{
ssh_channel channel;
int socket_fd, *pFd = NULL;
struct ssh_channel_callbacks_struct *cb_chan = NULL;
int socket_fd, *pFd;
struct ssh_channel_callbacks_struct *cb_chan;
struct event_fd_data_struct *event_fd_data;
_ssh_log(SSH_LOG_PACKET, "=== message_callback", "Message type: %d",
@@ -655,8 +655,8 @@ static struct argp argp = {options, parse_opt, args_doc, doc, NULL, NULL, NULL};
int
main(int argc, char **argv)
{
ssh_session session = NULL;
ssh_bind sshbind = NULL;
ssh_session session;
ssh_bind sshbind;
struct ssh_server_callbacks_struct cb = {
.userdata = NULL,
.auth_password_function = auth_password,

View File

@@ -39,237 +39,223 @@ clients must be made or how a client should react.
#define BUF_SIZE 4096
#endif
char *host = NULL;
const char *desthost = "localhost";
const char *port = "22";
char *host;
const char *desthost="localhost";
const char *port="22";
#ifdef WITH_PCAP
#include <libssh/pcap.h>
char *pcap_file = NULL;
char *pcap_file=NULL;
#endif
static void usage(void)
{
fprintf(stderr,
"Usage : sshnetcat [user@]host forwarded_host forwarded_port\n");
exit(1);
fprintf(stderr,"Usage : sshnetcat [user@]host forwarded_host forwarded_port\n");
exit(1);
}
static int opts(int argc, char **argv)
{
static int opts(int argc, char **argv){
int i;
while ((i = getopt(argc, argv, "P:")) != -1) {
switch (i) {
while((i=getopt(argc,argv,"P:"))!=-1){
switch(i){
#ifdef WITH_PCAP
case 'P':
pcap_file = optarg;
break;
case 'P':
pcap_file=optarg;
break;
#endif
default:
fprintf(stderr, "unknown option %c\n", optopt);
usage();
default:
fprintf(stderr,"unknown option %c\n",optopt);
usage();
}
}
if (optind < argc)
host = argv[optind++];
if (optind < argc)
desthost = argv[optind++];
if (optind < argc)
port = argv[optind++];
if (host == NULL)
if(optind < argc)
host=argv[optind++];
if(optind < argc)
desthost=argv[optind++];
if(optind < argc)
port=argv[optind++];
if(host==NULL)
usage();
return 0;
}
static void select_loop(ssh_session session, ssh_channel channel)
{
fd_set fds;
struct timeval timeout;
char buffer[BUF_SIZE];
/* channels will be set to the channels to poll.
* outchannels will contain the result of the poll
*/
ssh_channel channels[2], outchannels[2];
int lus;
int eof = 0;
int maxfd;
int ret;
while (channel) {
do {
static void select_loop(ssh_session session,ssh_channel channel){
fd_set fds;
struct timeval timeout;
char buffer[BUF_SIZE];
/* channels will be set to the channels to poll.
* outchannels will contain the result of the poll
*/
ssh_channel channels[2], outchannels[2];
int lus;
int eof=0;
int maxfd;
int ret;
while(channel){
do{
int fd;
ZERO_STRUCT(fds);
FD_ZERO(&fds);
if (!eof)
FD_SET(0, &fds);
timeout.tv_sec = 30;
timeout.tv_usec = 0;
FD_ZERO(&fds);
if(!eof)
FD_SET(0,&fds);
timeout.tv_sec=30;
timeout.tv_usec=0;
fd = ssh_get_fd(session);
if (fd == -1) {
fprintf(stderr,
"Error getting the session file descriptor: %s\n",
ssh_get_error(session));
fprintf(stderr, "Error getting the session file descriptor: %s\n",
ssh_get_error(session));
return;
}
FD_SET(fd, &fds);
maxfd = fd + 1;
channels[0] = channel; // set the first channel we want to read from
channels[1] = NULL;
ret = ssh_select(channels, outchannels, maxfd, &fds, &timeout);
if (ret == EINTR)
continue;
if (FD_ISSET(0, &fds)) {
lus = read(0, buffer, sizeof(buffer));
if (lus)
ssh_channel_write(channel, buffer, lus);
else {
eof = 1;
ssh_channel_send_eof(channel);
}
}
if (channel && ssh_channel_is_closed(channel)) {
ssh_channel_free(channel);
channel = NULL;
channels[0] = NULL;
}
if (outchannels[0]) {
while (channel && ssh_channel_is_open(channel) &&
ssh_channel_poll(channel, 0)) {
lus = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
if (lus == -1) {
fprintf(stderr,
"Error reading channel: %s\n",
ssh_get_error(session));
return;
channels[0]=channel; // set the first channel we want to read from
channels[1]=NULL;
ret=ssh_select(channels,outchannels,maxfd,&fds,&timeout);
if(ret==EINTR)
continue;
if(FD_ISSET(0,&fds)){
lus=read(0,buffer,sizeof(buffer));
if(lus)
ssh_channel_write(channel,buffer,lus);
else {
eof=1;
ssh_channel_send_eof(channel);
}
}
if(channel && ssh_channel_is_closed(channel)){
ssh_channel_free(channel);
channel=NULL;
channels[0]=NULL;
}
if(outchannels[0]){
while(channel && ssh_channel_is_open(channel) && ssh_channel_poll(channel,0)){
lus = ssh_channel_read(channel,buffer,sizeof(buffer),0);
if(lus==-1){
fprintf(stderr, "Error reading channel: %s\n",
ssh_get_error(session));
return;
}
if(lus==0){
ssh_channel_free(channel);
channel=channels[0]=NULL;
} else {
ret = write(1, buffer, lus);
if (ret < 0) {
fprintf(stderr, "Error writing to stdin: %s",
strerror(errno));
return;
}
}
}
while(channel && ssh_channel_is_open(channel) && ssh_channel_poll(channel,1)){ /* stderr */
lus = ssh_channel_read(channel, buffer, sizeof(buffer), 1);
if(lus==-1){
fprintf(stderr, "Error reading channel: %s\n",
ssh_get_error(session));
return;
}
if(lus==0){
ssh_channel_free(channel);
channel=channels[0]=NULL;
} else {
ret = write(2, buffer, lus);
if (ret < 0) {
fprintf(stderr, "Error writing to stderr: %s",
strerror(errno));
return;
}
}
if (lus == 0) {
ssh_channel_free(channel);
channel = channels[0] = NULL;
} else {
ret = write(1, buffer, lus);
if (ret < 0) {
fprintf(stderr,
"Error writing to stdin: %s",
strerror(errno));
return;
}
}
}
while (channel && ssh_channel_is_open(channel) &&
ssh_channel_poll(channel, 1)) { /* stderr */
lus = ssh_channel_read(channel, buffer, sizeof(buffer), 1);
if (lus == -1) {
fprintf(stderr,
"Error reading channel: %s\n",
ssh_get_error(session));
return;
}
if (lus == 0) {
ssh_channel_free(channel);
channel = channels[0] = NULL;
} else {
ret = write(2, buffer, lus);
if (ret < 0) {
fprintf(stderr,
"Error writing to stderr: %s",
strerror(errno));
return;
}
}
}
}
if (channel && ssh_channel_is_closed(channel)) {
ssh_channel_free(channel);
channel = NULL;
}
} while (ret == EINTR || ret == SSH_EINTR);
}
}
}
if(channel && ssh_channel_is_closed(channel)){
ssh_channel_free(channel);
channel=NULL;
}
} while (ret==EINTR || ret==SSH_EINTR);
}
}
static void forwarding(ssh_session session)
{
static void forwarding(ssh_session session){
ssh_channel channel;
int r;
channel = ssh_channel_new(session);
r = ssh_channel_open_forward(channel, desthost, atoi(port), "localhost", 22);
if (r < 0) {
printf("error forwarding port : %s\n", ssh_get_error(session));
if(r<0) {
printf("error forwarding port : %s\n",ssh_get_error(session));
return;
}
select_loop(session, channel);
select_loop(session,channel);
}
static int client(ssh_session session)
{
int auth = 0;
char *banner = NULL;
int state;
static int client(ssh_session session){
int auth=0;
char *banner;
int state;
if (ssh_options_set(session, SSH_OPTIONS_HOST, host) < 0)
return -1;
ssh_options_parse_config(session, NULL);
if (ssh_options_set(session, SSH_OPTIONS_HOST ,host) < 0)
return -1;
ssh_options_parse_config(session, NULL);
if (ssh_connect(session)) {
fprintf(stderr, "Connection failed : %s\n", ssh_get_error(session));
return -1;
}
state = verify_knownhost(session);
if (state != 0)
return -1;
ssh_userauth_none(session, NULL);
banner = ssh_get_issue_banner(session);
if (banner) {
printf("%s\n", banner);
free(banner);
}
auth = authenticate_console(session);
if (auth != SSH_AUTH_SUCCESS) {
return -1;
}
forwarding(session);
return 0;
if(ssh_connect(session)){
fprintf(stderr,"Connection failed : %s\n",ssh_get_error(session));
return -1;
}
state=verify_knownhost(session);
if (state != 0)
return -1;
ssh_userauth_none(session, NULL);
banner=ssh_get_issue_banner(session);
if(banner){
printf("%s\n",banner);
free(banner);
}
auth=authenticate_console(session);
if(auth != SSH_AUTH_SUCCESS){
return -1;
}
forwarding(session);
return 0;
}
#ifdef WITH_PCAP
ssh_pcap_file pcap;
void set_pcap(ssh_session session);
void set_pcap(ssh_session session)
{
if (!pcap_file)
return;
pcap = ssh_pcap_file_new();
if (ssh_pcap_file_open(pcap, pcap_file) == SSH_ERROR) {
printf("Error opening pcap file\n");
ssh_pcap_file_free(pcap);
pcap = NULL;
return;
}
ssh_set_pcap_file(session, pcap);
void set_pcap(ssh_session session){
if(!pcap_file)
return;
pcap=ssh_pcap_file_new();
if(ssh_pcap_file_open(pcap,pcap_file) == SSH_ERROR){
printf("Error opening pcap file\n");
ssh_pcap_file_free(pcap);
pcap=NULL;
return;
}
ssh_set_pcap_file(session,pcap);
}
void cleanup_pcap(void);
void cleanup_pcap(void)
{
ssh_pcap_file_free(pcap);
pcap = NULL;
ssh_pcap_file_free(pcap);
pcap = NULL;
}
#endif
int main(int argc, char **argv)
{
ssh_session session = NULL;
int main(int argc, char **argv){
ssh_session session;
session = ssh_new();
if (ssh_options_getopt(session, &argc, argv)) {
fprintf(stderr,
"error parsing command line :%s\n",
ssh_get_error(session));
usage();
if(ssh_options_getopt(session, &argc, argv)) {
fprintf(stderr, "error parsing command line :%s\n",
ssh_get_error(session));
usage();
}
opts(argc, argv);
opts(argc,argv);
#ifdef WITH_PCAP
set_pcap(session);
#endif

View File

@@ -29,13 +29,6 @@ if (WITH_SERVER)
endif (WITH_SFTP)
endif (WITH_SERVER)
if (WITH_FIDO2)
set(libssh_HDRS
${libssh_HDRS}
sk_api.h
)
endif (WITH_FIDO2)
install(
FILES
${libssh_HDRS}

View File

@@ -31,7 +31,6 @@ extern "C" {
bignum ssh_make_string_bn(ssh_string string);
ssh_string ssh_make_bignum_string(bignum num);
ssh_string ssh_make_padded_bignum_string(bignum num, size_t pad_len);
void ssh_print_bignum(const char *which, const_bignum num);
#ifdef __cplusplus

View File

@@ -52,7 +52,6 @@ enum ssh_bind_config_opcode_e {
BIND_CFG_MATCH,
BIND_CFG_PUBKEY_ACCEPTED_KEY_TYPES,
BIND_CFG_HOSTKEY_ALGORITHMS,
BIND_CFG_REQUIRED_RSA_SIZE,
BIND_CFG_MAX /* Keep this one last in the list */
};

View File

@@ -74,8 +74,6 @@ ssh_string ssh_buffer_get_ssh_string(ssh_buffer buffer);
uint32_t ssh_buffer_pass_bytes_end(ssh_buffer buffer, uint32_t len);
uint32_t ssh_buffer_pass_bytes(ssh_buffer buffer, uint32_t len);
ssh_buffer ssh_buffer_dup(const ssh_buffer buffer);
#ifdef __cplusplus
}
#endif

View File

@@ -113,17 +113,6 @@ typedef void (*ssh_status_callback) (ssh_session session, float status,
typedef void (*ssh_global_request_callback) (ssh_session session,
ssh_message message, void *userdata);
/**
* @brief SSH connect status callback. These are functions that report the
* status of the connection i,e. a function indicating the completed percentage
* of the connection
* steps.
* @param userdata Userdata to be passed to the callback function.
* @param status Percentage of connection status, going from 0.0 to 1.0
* once connection is done.
*/
typedef void (*ssh_connect_status_callback)(void *userdata, float status);
/**
* @brief Handles an SSH new channel open X11 request. This happens when the server
* sends back an X11 connection attempt. This is a client-side API
@@ -192,7 +181,7 @@ struct ssh_callbacks_struct {
* This function gets called during connection time to indicate the
* percentage of connection steps completed.
*/
ssh_connect_status_callback connect_status_function;
void (*connect_status_function)(void *userdata, float status);
/**
* This function will be called each time a global request is received.
*/
@@ -336,28 +325,6 @@ typedef int (*ssh_gssapi_accept_sec_ctx_callback) (ssh_session session,
typedef int (*ssh_gssapi_verify_mic_callback) (ssh_session session,
ssh_string mic, void *mic_buffer, size_t mic_buffer_size, void *userdata);
/**
* @brief Handles an SSH new channel open "direct-tcpip" request. This
* happens when the client forwards an incoming TCP connection on a port it
* wants to forward to the destination. This is a server-side API
* @param session current session handler
* @param destination_address the address that the TCP connection connected to
* @param destination_port the port that the TCP connection connected to
* @param originator_address the originator IP address
* @param originator_port the originator port
* @param userdata Userdata to be passed to the callback function.
* @returns a valid ssh_channel handle if the request is to be allowed
* @returns NULL if the request should not be allowed
* @warning The channel pointer returned by this callback must be closed by the
* application.
*/
typedef ssh_channel (*ssh_channel_open_request_direct_tcpip_callback)(
ssh_session session,
const char *destination_address,
int destination_port,
const char *originator_address,
int originator_port,
void *userdata);
/**
* This structure can be used to implement a libssh server, with appropriate callbacks.
@@ -408,12 +375,6 @@ struct ssh_server_callbacks_struct {
/* This function will be called when a MIC needs to be verified.
*/
ssh_gssapi_verify_mic_callback gssapi_verify_mic_function;
/**
* This function will be called when an incoming "direct-tcpip"
* request is received.
*/
ssh_channel_open_request_direct_tcpip_callback
channel_open_request_direct_tcpip_function;
};
typedef struct ssh_server_callbacks_struct *ssh_server_callbacks;
@@ -1154,177 +1115,6 @@ struct ssh_jump_callbacks_struct {
ssh_jump_authenticate_callback authenticate;
};
/* Security key callbacks */
/*
* Forward declarations for structs that have been defined in sk_api.h.
* If you need to work with the fields inside them, please include
* libssh/sk_api.h
*/
struct sk_enroll_response;
struct sk_sign_response;
struct sk_resident_key;
struct sk_option;
#define LIBSSH_SK_API_VERSION_MAJOR 0x000a0000
/**
* @brief FIDO2/U2F SK API version callback.
*
* Returns the version of the FIDO2/U2F API that the callbacks implement.
* This callback allows custom callback implementations to specify their
* SK API version for compatibility checking with libssh's security key
* interface.
*
* @details Version compatibility is determined by comparing the major version
* portion (upper 16 bits) of the returned value with SSH_SK_VERSION_MAJOR.
*
* For compatibility, implementations should return a version where:
* (returned_version & SSH_SK_VERSION_MAJOR_MASK) == SSH_SK_VERSION_MAJOR
*
* This ensures that the callbacks' SK API matches the major version expected
* by libssh, while allowing minor version differences for backward
* compatibility.
*
* @see LIBSSH_SK_API_VERSION_MAJOR Current expected major API version
* @see SSH_SK_VERSION_MAJOR_MASK Mask for extracting major version (0xffff0000)
*/
typedef uint32_t (*sk_api_version_callback)(void);
/**
* @brief FIDO2/U2F key enrollment callback.
*
* Enrolls a new FIDO2/U2F security key credential (private key generation).
* This callback handles the creation of new FIDO2/U2F credentials, including
* both resident and non-resident keys.
*
* @param[in] alg The cryptographic algorithm to use
* @param[in] challenge Random challenge data for enrollment
* @param[in] challenge_len Length of the challenge data
* @param[in] application Application identifier (relying party ID)
* @param[in] flags Enrollment flags
* @param[in] pin PIN for user verification (may be NULL)
* @param[in] options Array of enrollment options (device path, user ID, etc.)
* @param[out] enroll_response Enrollment response containing public key,
* key handle, signature, and attestation data
*
* @returns SSH_OK on success, SSH_SK_ERR_* codes on failure.
*/
typedef int (*sk_enroll_callback)(uint32_t alg,
const uint8_t *challenge,
size_t challenge_len,
const char *application,
uint8_t flags,
const char *pin,
struct sk_option **options,
struct sk_enroll_response **enroll_response);
/**
* @brief FIDO2/U2F security key signing callback.
*
* Signs data using a FIDO2 security key credential. This callback performs
* cryptographic signing operations using previously enrolled FIDO2/U2F
* credentials.
*
* @param[in] alg The cryptographic algorithm used by the key
* @param[in] data Data to be signed
* @param[in] data_len Length of the data to sign
* @param[in] application Application identifier (relying party ID)
* @param[in] key_handle Key handle identifying the credential
* @param[in] key_handle_len Length of the key handle
* @param[in] flags Signing flags
* @param[in] pin PIN for user verification (may be NULL)
* @param[in] options Array of signing options (device path, etc.)
* @param[out] sign_response Signature response containing signature data,
* flags, and counter information
*
* @returns SSH_OK on success, SSH_SK_ERR_* codes on failure.
*/
typedef int (*sk_sign_callback)(uint32_t alg,
const uint8_t *data,
size_t data_len,
const char *application,
const uint8_t *key_handle,
size_t key_handle_len,
uint8_t flags,
const char *pin,
struct sk_option **options,
struct sk_sign_response **sign_response);
/**
* @brief FIDO2 security key resident keys loading callback.
*
* Enumerates and loads all resident keys (discoverable credentials) stored
* on FIDO2 devices. Resident keys are credentials stored directly on
* the device itself and can be discovered without prior knowledge
* of key handles.
*
* @param[in] pin PIN for accessing resident keys (required for most operations)
* @param[in] options Array of options (device path, etc.)
* @param[out] resident_keys Array of resident key structures containing key
* data, application IDs, user information, and metadata
* @param[out] num_keys_found Number of resident keys found and loaded
*
* @returns SSH_OK on success, SSH_SK_ERR_* codes on failure.
*/
typedef int (*sk_load_resident_keys_callback)(
const char *pin,
struct sk_option **options,
struct sk_resident_key ***resident_keys,
size_t *num_keys_found);
/**
* @brief FIDO2/U2F security key callbacks structure.
*
* This structure contains callbacks for FIDO2/U2F operations.
* It allows applications to provide custom implementations of FIDO2/U2F
* operations to override the default libfido2-based implementation.
*
* @warning These callbacks will only be called if libssh was built with
* FIDO2/U2F support enabled. (WITH_FIDO2 = ON).
*/
struct ssh_sk_callbacks_struct {
/** DON'T SET THIS use ssh_callbacks_init() instead. */
size_t size;
/**
* This callback returns the SK API version used by the callback
* implementation.
*
* @see sk_api_version_callback for detailed documentation
*/
sk_api_version_callback api_version;
/**
* This callback enrolls a new FIDO2/U2F credential, generating
* a new key pair and optionally storing it on the device itself
* (resident keys).
*
* @see sk_enroll_callback for detailed documentation
*/
sk_enroll_callback enroll;
/**
* This callback performs cryptographic signing operations using a
* previously enrolled FIDO2/U2F credential.
*
* @see sk_sign_callback for detailed documentation
*/
sk_sign_callback sign;
/**
* This callback enumerates and loads all resident keys (discoverable
* credentials) stored on the FIDO2 device.
*
* @see sk_load_resident_keys_callback for detailed documentation
*/
sk_load_resident_keys_callback load_resident_keys;
};
typedef struct ssh_sk_callbacks_struct *ssh_sk_callbacks;
const struct ssh_sk_callbacks_struct *ssh_sk_get_default_callbacks(void);
#ifdef __cplusplus
}
#endif

View File

@@ -24,7 +24,6 @@
#ifndef LIBSSH_CONFIG_H_
#define LIBSSH_CONFIG_H_
#include "libssh/libssh.h"
enum ssh_config_opcode_e {
/* Unknown opcode */
@@ -67,11 +66,7 @@ enum ssh_config_opcode_e {
SOC_CONTROLMASTER,
SOC_CONTROLPATH,
SOC_CERTIFICATE,
SOC_REQUIRED_RSA_SIZE,
SOC_MAX /* Keep this one last in the list */
};
enum ssh_config_opcode_e ssh_config_get_opcode(char *keyword);
int ssh_config_parse_line_cli(ssh_session session, const char *line);
#endif /* LIBSSH_CONFIG_H_ */

View File

@@ -45,11 +45,10 @@
#ifdef HAVE_OPENSSL_ECDH_H
#include <openssl/ecdh.h>
#endif
#include "libssh/curve25519.h"
#include "libssh/dh.h"
#include "libssh/ecdh.h"
#include "libssh/kex.h"
#include "libssh/sntrup761.h"
#include "libssh/curve25519.h"
#define DIGEST_MAX_LEN 64
@@ -57,44 +56,32 @@
#define AES_GCM_IVLEN 12
enum ssh_key_exchange_e {
/* diffie-hellman-group1-sha1 */
SSH_KEX_DH_GROUP1_SHA1 = 1,
/* diffie-hellman-group14-sha1 */
SSH_KEX_DH_GROUP14_SHA1,
/* diffie-hellman-group1-sha1 */
SSH_KEX_DH_GROUP1_SHA1=1,
/* diffie-hellman-group14-sha1 */
SSH_KEX_DH_GROUP14_SHA1,
#ifdef WITH_GEX
/* diffie-hellman-group-exchange-sha1 */
SSH_KEX_DH_GEX_SHA1,
/* diffie-hellman-group-exchange-sha256 */
SSH_KEX_DH_GEX_SHA256,
/* diffie-hellman-group-exchange-sha1 */
SSH_KEX_DH_GEX_SHA1,
/* diffie-hellman-group-exchange-sha256 */
SSH_KEX_DH_GEX_SHA256,
#endif /* WITH_GEX */
/* ecdh-sha2-nistp256 */
SSH_KEX_ECDH_SHA2_NISTP256,
/* ecdh-sha2-nistp384 */
SSH_KEX_ECDH_SHA2_NISTP384,
/* ecdh-sha2-nistp521 */
SSH_KEX_ECDH_SHA2_NISTP521,
/* curve25519-sha256@libssh.org */
SSH_KEX_CURVE25519_SHA256_LIBSSH_ORG,
/* curve25519-sha256 */
SSH_KEX_CURVE25519_SHA256,
/* diffie-hellman-group16-sha512 */
SSH_KEX_DH_GROUP16_SHA512,
/* diffie-hellman-group18-sha512 */
SSH_KEX_DH_GROUP18_SHA512,
/* diffie-hellman-group14-sha256 */
SSH_KEX_DH_GROUP14_SHA256,
/* sntrup761x25519-sha512@openssh.com */
SSH_KEX_SNTRUP761X25519_SHA512_OPENSSH_COM,
/* sntrup761x25519-sha512 */
SSH_KEX_SNTRUP761X25519_SHA512,
#ifdef HAVE_MLKEM
/* mlkem768x25519-sha256 */
SSH_KEX_MLKEM768X25519_SHA256,
/* mlkem768nistp256-sha256 */
SSH_KEX_MLKEM768NISTP256_SHA256,
/* mlkem1024nistp384-sha384 */
SSH_KEX_MLKEM1024NISTP384_SHA384,
#endif /* HAVE_MLKEM */
/* ecdh-sha2-nistp256 */
SSH_KEX_ECDH_SHA2_NISTP256,
/* ecdh-sha2-nistp384 */
SSH_KEX_ECDH_SHA2_NISTP384,
/* ecdh-sha2-nistp521 */
SSH_KEX_ECDH_SHA2_NISTP521,
/* curve25519-sha256@libssh.org */
SSH_KEX_CURVE25519_SHA256_LIBSSH_ORG,
/* curve25519-sha256 */
SSH_KEX_CURVE25519_SHA256,
/* diffie-hellman-group16-sha512 */
SSH_KEX_DH_GROUP16_SHA512,
/* diffie-hellman-group18-sha512 */
SSH_KEX_DH_GROUP18_SHA512,
/* diffie-hellman-group14-sha256 */
SSH_KEX_DH_GROUP14_SHA256,
};
enum ssh_cipher_e {
@@ -118,9 +105,6 @@ struct dh_ctx;
struct ssh_crypto_struct {
bignum shared_secret;
ssh_string hybrid_client_init;
ssh_string hybrid_server_reply;
ssh_string hybrid_shared_secret;
struct dh_ctx *dh_ctx;
#ifdef WITH_GEX
size_t dh_pmin; size_t dh_pn; size_t dh_pmax; /* preferred group parameters */
@@ -141,25 +125,9 @@ struct ssh_crypto_struct {
ssh_string ecdh_server_pubkey;
#endif
#ifdef HAVE_CURVE25519
#ifdef HAVE_LIBCRYPTO
EVP_PKEY *curve25519_privkey;
#elif defined(HAVE_GCRYPT_CURVE25519)
gcry_sexp_t curve25519_privkey;
#else
ssh_curve25519_privkey curve25519_privkey;
#endif
ssh_curve25519_pubkey curve25519_client_pubkey;
ssh_curve25519_pubkey curve25519_server_pubkey;
#endif
#ifdef HAVE_MLKEM
EVP_PKEY *mlkem_privkey;
ssh_string mlkem_client_pubkey;
ssh_string mlkem_ciphertext;
#endif
#ifdef HAVE_SNTRUP761
ssh_sntrup761_privkey sntrup761_privkey;
ssh_sntrup761_pubkey sntrup761_client_pubkey;
ssh_sntrup761_ciphertext sntrup761_ciphertext;
#endif
ssh_string dh_server_signature; /* information used by dh_handshake. */
size_t session_id_len;
@@ -255,8 +223,9 @@ int sshkdf_derive_key(struct ssh_crypto_struct *crypto,
size_t requested_len);
int secure_memcmp(const void *s1, const void *s2, size_t n);
void compress_cleanup(struct ssh_crypto_struct *crypto);
#if defined(HAVE_LIBCRYPTO) && !defined(WITH_PKCS11_PROVIDER)
ENGINE *pki_get_engine(void);
#endif /* HAVE_LIBCRYPTO */
#ifdef __cplusplus
}

View File

@@ -50,9 +50,6 @@ int crypto_scalarmult(unsigned char *q, const unsigned char *n, const unsigned c
typedef unsigned char ssh_curve25519_pubkey[CURVE25519_PUBKEY_SIZE];
typedef unsigned char ssh_curve25519_privkey[CURVE25519_PRIVKEY_SIZE];
int ssh_curve25519_init(ssh_session session);
int curve25519_do_create_k(ssh_session session, ssh_curve25519_pubkey k);
int ssh_curve25519_create_k(ssh_session session, ssh_curve25519_pubkey k);
int ssh_client_curve25519_init(ssh_session session);
void ssh_client_curve25519_remove_callbacks(ssh_session session);

View File

@@ -48,7 +48,6 @@ extern "C" {
extern struct ssh_packet_callbacks_struct ssh_ecdh_client_callbacks;
/* Backend-specific functions. */
int ssh_ecdh_init(ssh_session session);
int ssh_client_ecdh_init(ssh_session session);
void ssh_client_ecdh_remove_callbacks(ssh_session session);
int ecdh_build_k(ssh_session session);

View File

@@ -1,48 +0,0 @@
/*
* This file is part of the SSH Library
*
* Copyright (c) 2025 by Red Hat, Inc.
*
* Author: Sahana Prasad <sahana@redhat.com>
* Author: Pavol Žáčik <pzacik@redhat.com>
* Author: Claude (Anthropic)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef HYBRID_MLKEM_H_
#define HYBRID_MLKEM_H_
#include "libssh/mlkem.h"
#include "libssh/wrapper.h"
#include "config.h"
#ifdef __cplusplus
extern "C" {
#endif
int ssh_client_hybrid_mlkem_init(ssh_session session);
void ssh_client_hybrid_mlkem_remove_callbacks(ssh_session session);
#ifdef WITH_SERVER
void ssh_server_hybrid_mlkem_init(ssh_session session);
#endif /* WITH_SERVER */
#ifdef __cplusplus
}
#endif
#endif /* HYBRID_MLKEM_H_ */

View File

@@ -52,10 +52,10 @@ char *ssh_prefix_default_algos(enum ssh_kex_types_e algo, const char *list);
char **ssh_space_tokenize(const char *chain);
int ssh_get_kex1(ssh_session session);
char *ssh_find_matching(const char *in_d, const char *what_d);
const char *ssh_kex_get_supported_method(enum ssh_kex_types_e type);
const char *ssh_kex_get_default_methods(enum ssh_kex_types_e type);
const char *ssh_kex_get_fips_methods(enum ssh_kex_types_e type);
const char *ssh_kex_get_description(enum ssh_kex_types_e type);
const char *ssh_kex_get_supported_method(uint32_t algo);
const char *ssh_kex_get_default_methods(uint32_t algo);
const char *ssh_kex_get_fips_methods(uint32_t algo);
const char *ssh_kex_get_description(uint32_t algo);
char *ssh_client_select_hostkeys(ssh_session session);
int ssh_send_rekex(ssh_session session);
int server_set_kex(ssh_session session);

View File

@@ -121,15 +121,6 @@ typedef BN_CTX* bignum_CTX;
ssh_string pki_key_make_ecpoint_string(const EC_GROUP *g, const EC_POINT *p);
int pki_key_ecgroup_name_to_nid(const char *group);
#if defined(WITH_PKCS11_URI)
#if defined(WITH_PKCS11_PROVIDER)
int pki_load_pkcs11_provider(void);
#else
ENGINE *pki_get_engine(void);
#endif
#endif /* WITH_PKCS11_PROVIDER */
#endif /* HAVE_LIBCRYPTO */
#endif /* LIBCRYPTO_H_ */

View File

@@ -1,7 +1,7 @@
/*
* This file is part of the SSH Library
*
* Copyright (c) 2003-2025 by Aris Adamantiadis and the libssh team
* Copyright (c) 2003-2024 by Aris Adamantiadis and the libssh team
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -49,10 +49,9 @@
#endif
#endif
#include <inttypes.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <inttypes.h>
#ifdef _MSC_VER
typedef int mode_t;
@@ -107,7 +106,6 @@ typedef struct ssh_session_struct* ssh_session;
typedef struct ssh_string_struct* ssh_string;
typedef struct ssh_event_struct* ssh_event;
typedef struct ssh_connector_struct * ssh_connector;
typedef struct ssh_pki_ctx_struct *ssh_pki_ctx;
typedef void* ssh_gssapi_creds;
/* Socket type */
@@ -421,7 +419,6 @@ enum ssh_options_e {
SSH_OPTIONS_CERTIFICATE,
SSH_OPTIONS_PROXYJUMP,
SSH_OPTIONS_PROXYJUMP_CB_LIST_APPEND,
SSH_OPTIONS_PKI_CONTEXT,
};
enum {
@@ -723,17 +720,9 @@ LIBSSH_API int ssh_key_cmp(const ssh_key k1,
const ssh_key k2,
enum ssh_keycmp_e what);
LIBSSH_API ssh_key ssh_key_dup(const ssh_key key);
LIBSSH_API uint32_t ssh_key_get_sk_flags(const ssh_key key);
LIBSSH_API ssh_string ssh_key_get_sk_application(const ssh_key key);
LIBSSH_API ssh_string ssh_key_get_sk_user_id(const ssh_key key);
SSH_DEPRECATED LIBSSH_API int
ssh_pki_generate(enum ssh_keytypes_e type, int parameter, ssh_key *pkey);
LIBSSH_API int ssh_pki_generate_key(enum ssh_keytypes_e type,
ssh_pki_ctx pki_context,
ssh_key *pkey);
LIBSSH_API int ssh_pki_generate(enum ssh_keytypes_e type, int parameter,
ssh_key *pkey);
LIBSSH_API int ssh_pki_import_privkey_base64(const char *b64_key,
const char *passphrase,
ssh_auth_callback auth_fn,
@@ -854,7 +843,6 @@ LIBSSH_API int ssh_string_fill(ssh_string str, const void *data, size_t len);
do { if ((x) != NULL) { ssh_string_free(x); x = NULL; } } while(0)
LIBSSH_API void ssh_string_free(ssh_string str);
LIBSSH_API ssh_string ssh_string_from_char(const char *what);
LIBSSH_API ssh_string ssh_string_from_data(const void *data, size_t len);
LIBSSH_API size_t ssh_string_len(ssh_string str);
LIBSSH_API ssh_string ssh_string_new(size_t size);
LIBSSH_API const char *ssh_string_get_char(ssh_string str);
@@ -862,7 +850,6 @@ LIBSSH_API char *ssh_string_to_char(ssh_string str);
#define SSH_STRING_FREE_CHAR(x) \
do { if ((x) != NULL) { ssh_string_free_char(x); x = NULL; } } while(0)
LIBSSH_API void ssh_string_free_char(char *s);
LIBSSH_API int ssh_string_cmp(ssh_string s1, ssh_string s2);
LIBSSH_API int ssh_getpass(const char *prompt, char *buf, size_t len, int echo,
int verify);
@@ -887,7 +874,6 @@ LIBSSH_API const char* ssh_get_cipher_in(ssh_session session);
LIBSSH_API const char* ssh_get_cipher_out(ssh_session session);
LIBSSH_API const char* ssh_get_hmac_in(ssh_session session);
LIBSSH_API const char* ssh_get_hmac_out(ssh_session session);
LIBSSH_API const char *ssh_get_supported_methods(enum ssh_kex_types_e type);
LIBSSH_API ssh_buffer ssh_buffer_new(void);
LIBSSH_API void ssh_buffer_free(ssh_buffer buffer);
@@ -900,105 +886,6 @@ LIBSSH_API void *ssh_buffer_get(ssh_buffer buffer);
LIBSSH_API uint32_t ssh_buffer_get_len(ssh_buffer buffer);
LIBSSH_API int ssh_session_set_disconnect_message(ssh_session session, const char *message);
/* SSHSIG hashes data independently from the key used, so we use a new enum
to avoid confusion. See
https://gitlab.com/jas/ietf-sshsig-format/-/blob/cc70a225cbd695d5a6f20aaebdb4b92b0818e43a/ietf-sshsig-format.md#L137
*/
enum sshsig_digest_e {
SSHSIG_DIGEST_SHA2_256 = 0,
SSHSIG_DIGEST_SHA2_512 = 1,
};
LIBSSH_API int sshsig_sign(const void *data,
size_t data_length,
ssh_key privkey,
ssh_pki_ctx pki_context,
const char *sig_namespace,
enum sshsig_digest_e hash_alg,
char **signature);
LIBSSH_API int sshsig_verify(const void *data,
size_t data_length,
const char *signature,
const char *sig_namespace,
ssh_key *sign_key);
/* PKI context API */
enum ssh_pki_options_e {
SSH_PKI_OPTION_RSA_KEY_SIZE,
/* Security Key options */
SSH_PKI_OPTION_SK_APPLICATION,
SSH_PKI_OPTION_SK_FLAGS,
SSH_PKI_OPTION_SK_USER_ID,
SSH_PKI_OPTION_SK_CHALLENGE,
SSH_PKI_OPTION_SK_CALLBACKS,
};
/* FIDO2/U2F Operation Flags */
/** Requires user presence confirmation (tap/touch) */
#ifndef SSH_SK_USER_PRESENCE_REQD
#define SSH_SK_USER_PRESENCE_REQD 0x01
#endif
/** Requires user verification (PIN/biometric) - FIDO2 only */
#ifndef SSH_SK_USER_VERIFICATION_REQD
#define SSH_SK_USER_VERIFICATION_REQD 0x04
#endif
/** Force resident key enrollment even if a resident key with given user ID
* already exists - FIDO2 only */
#ifndef SSH_SK_FORCE_OPERATION
#define SSH_SK_FORCE_OPERATION 0x10
#endif
/** Create/use resident key stored on authenticator - FIDO2 only */
#ifndef SSH_SK_RESIDENT_KEY
#define SSH_SK_RESIDENT_KEY 0x20
#endif
LIBSSH_API ssh_pki_ctx ssh_pki_ctx_new(void);
LIBSSH_API int ssh_pki_ctx_options_set(ssh_pki_ctx context,
enum ssh_pki_options_e option,
const void *value);
LIBSSH_API int ssh_pki_ctx_set_sk_pin_callback(ssh_pki_ctx context,
ssh_auth_callback pin_callback,
void *userdata);
#define SSH_SK_OPTION_NAME_DEVICE_PATH "device"
#define SSH_SK_OPTION_NAME_USER_ID "user"
LIBSSH_API int ssh_pki_ctx_sk_callbacks_option_set(ssh_pki_ctx context,
const char *name,
const char *value,
bool required);
LIBSSH_API int ssh_pki_ctx_sk_callbacks_options_clear(ssh_pki_ctx context);
LIBSSH_API int
ssh_pki_ctx_get_sk_attestation_buffer(const struct ssh_pki_ctx_struct *context,
ssh_buffer *attestation_buffer);
LIBSSH_API void ssh_pki_ctx_free(ssh_pki_ctx context);
#define SSH_PKI_CTX_FREE(x) \
do { \
if ((x) != NULL) { \
ssh_pki_ctx_free(x); \
x = NULL; \
} \
} while (0)
/* Security key resident keys API */
LIBSSH_API int
ssh_sk_resident_keys_load(const struct ssh_pki_ctx_struct *pki_context,
ssh_key **resident_keys_result,
size_t *num_keys_found_result);
#ifndef LIBSSH_LEGACY_0_4
#include "libssh/legacy.h"
#endif

View File

@@ -28,7 +28,6 @@ struct ssh_auth_request {
int method;
char *password;
struct ssh_key_struct *pubkey;
struct ssh_key_struct *server_pubkey;
char *sigtype;
enum ssh_publickey_state_e signature_state;
char kbdint_response;

View File

@@ -1,64 +0,0 @@
/*
* This file is part of the SSH Library
*
* Copyright (c) 2025 by Red Hat, Inc.
*
* Author: Pavol Žáčik <pzacik@redhat.com>
*
* The SSH Library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, version 2.1 of the License.
*
* The SSH Library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with the SSH Library; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
* MA 02111-1307, USA.
*/
#ifndef MLKEM_H_
#define MLKEM_H_
#include "libssh/crypto.h"
#include "libssh/libssh.h"
#include "libssh/session.h"
#include "config.h"
#ifdef __cplusplus
extern "C" {
#endif
struct mlkem_type_info {
size_t pubkey_size;
size_t ciphertext_size;
const char *name;
};
extern const struct mlkem_type_info MLKEM768_INFO;
extern const struct mlkem_type_info MLKEM1024_INFO;
#define MLKEM_SHARED_SECRET_SIZE 32
typedef unsigned char ssh_mlkem_shared_secret[MLKEM_SHARED_SECRET_SIZE];
const struct mlkem_type_info *
kex_type_to_mlkem_info(enum ssh_key_exchange_e kex_type);
int ssh_mlkem_init(ssh_session session);
int ssh_mlkem_encapsulate(ssh_session session,
ssh_mlkem_shared_secret shared_secret);
int ssh_mlkem_decapsulate(const ssh_session session,
ssh_mlkem_shared_secret shared_secret);
#ifdef __cplusplus
}
#endif
#endif /* MLKEM_H_ */

View File

@@ -25,7 +25,6 @@
extern "C" {
#endif
int ssh_config_parse(ssh_session session, FILE *fp, bool global);
int ssh_config_parse_file(ssh_session session, const char *filename);
int ssh_config_parse_string(ssh_session session, const char *input);
int ssh_options_set_algo(ssh_session session,

View File

@@ -58,7 +58,6 @@ extern "C" {
SSH_PACKET_CALLBACK(ssh_packet_unimplemented);
SSH_PACKET_CALLBACK(ssh_packet_disconnect_callback);
SSH_PACKET_CALLBACK(ssh_packet_ignore_callback);
SSH_PACKET_CALLBACK(ssh_packet_debug_callback);
SSH_PACKET_CALLBACK(ssh_packet_dh_reply);
SSH_PACKET_CALLBACK(ssh_packet_newkeys);
SSH_PACKET_CALLBACK(ssh_packet_service_accept);

View File

@@ -46,24 +46,11 @@
#define MAX_PUBKEY_SIZE 0x100000 /* 1M */
#define MAX_PRIVKEY_SIZE 0x400000 /* 4M */
#define RSA_MIN_KEY_SIZE 1024
#define RSA_MIN_FIPS_KEY_SIZE 2048
#define RSA_DEFAULT_KEY_SIZE 3072
#define SSH_KEY_FLAG_EMPTY 0x0
#define SSH_KEY_FLAG_PUBLIC 0x0001
#define SSH_KEY_FLAG_PRIVATE 0x0002
#define SSH_KEY_FLAG_PKCS11_URI 0x0004
/* Constants matching the Lightweight Secure Shell Signature Format */
/* https://datatracker.ietf.org/doc/draft-josefsson-sshsig-format */
#define SSHSIG_VERSION 0x01
#define SSHSIG_MAGIC_PREAMBLE "SSHSIG"
#define SSHSIG_MAGIC_PREAMBLE_LEN (sizeof(SSHSIG_MAGIC_PREAMBLE) - 1)
#define SSHSIG_BEGIN_SIGNATURE "-----BEGIN SSH SIGNATURE-----"
#define SSHSIG_END_SIGNATURE "-----END SSH SIGNATURE-----"
#define SSHSIG_LINE_LENGTH 76
struct ssh_key_struct {
enum ssh_keytypes_e type;
int flags;
@@ -76,12 +63,11 @@ struct ssh_key_struct {
mbedtls_pk_context *pk;
mbedtls_ecdsa_context *ecdsa;
#elif defined(HAVE_LIBCRYPTO)
/* This holds either ENGINE/PROVIDER key for PKCS#11 support
* or just key in high-level format */
/* This holds either ENGINE key for PKCS#11 support or just key in
* high-level format */
EVP_PKEY *key;
/* keep this around for FIPS mode so we can parse the public keys. We won't
* be able to use them nor use the private keys though */
uint8_t *ed25519_pubkey;
uint8_t *ed25519_privkey;
#endif /* HAVE_LIBGCRYPT */
#ifndef HAVE_LIBCRYPTO
ed25519_pubkey *ed25519_pubkey;
@@ -90,14 +76,6 @@ struct ssh_key_struct {
ssh_string sk_application;
ssh_buffer cert;
enum ssh_keytypes_e cert_type;
/* Security Key specific private data */
uint8_t sk_flags;
ssh_string sk_key_handle;
ssh_string sk_reserved;
/* Resident key specific metadata */
ssh_string sk_user_id;
};
struct ssh_signature_struct {
@@ -149,11 +127,6 @@ enum ssh_digest_e ssh_key_hash_from_name(const char *name);
((kt) >= SSH_KEYTYPE_ECDSA_P256_CERT01 &&\
(kt) <= SSH_KEYTYPE_ED25519_CERT01))
#define is_sk_key_type(kt) \
((kt) == SSH_KEYTYPE_SK_ECDSA || (kt) == SSH_KEYTYPE_SK_ED25519 || \
(kt) == SSH_KEYTYPE_SK_ECDSA_CERT01 || \
(kt) == SSH_KEYTYPE_SK_ED25519_CERT01)
/* SSH Signature Functions */
ssh_signature ssh_signature_new(void);
void ssh_signature_free(ssh_signature sign);

View File

@@ -1,103 +0,0 @@
/*
* This file is part of the SSH Library
*
* Copyright (c) 2025 Praneeth Sarode <praneethsarode@gmail.com>
*
* The SSH Library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, version 2.1 of the License.
*
* The SSH Library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with the SSH Library; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
* MA 02111-1307, USA.
*/
#ifndef PKI_CONTEXT_H
#define PKI_CONTEXT_H
#include "libssh/callbacks.h"
#include "libssh/libssh.h"
/**
* @brief Security key context structure
*
* Context structure containing all parameters and callbacks
* needed for FIDO2/U2F security key operations.
*/
struct ssh_pki_ctx_struct {
/** @brief Desired RSA modulus size in bits
*
* Specified size of RSA keys to generate. If set to 0, defaults to 3072
* bits. Must be greater than or equal to 1024, as anything below is
* considered insecure.
*/
int rsa_key_size;
/** @brief Security key callbacks
*
* Provides enroll/sign/load_resident_keys operations.
*/
const struct ssh_sk_callbacks_struct *sk_callbacks;
/** @brief Application identifier string for the security key credential
*
* FIDO2 relying party identifier, typically "ssh:user@hostname" format.
* This is required for all security key operations.
*/
char *sk_application;
/** @brief FIDO2 operation flags
*
* Bitfield controlling authenticator behavior. Combine with bitwise OR:
* - SSH_SK_USER_PRESENCE_REQD (0x01): Require user touch
* - SSH_SK_USER_VERIFICATION_REQD (0x04): Require PIN/biometric
* - SSH_SK_FORCE_OPERATION (0x10): Override duplicate detection
* - SSH_SK_RESIDENT_KEY (0x20): Create discoverable credential
*/
uint8_t sk_flags;
/** @brief PIN callback for authenticator user verification (optional)
*
* Callback invoked to obtain a PIN or perform user verification when
* SSH_SK_USER_VERIFICATION_REQD is set or the authenticator requires it.
* If NULL, no interactive PIN retrieval is performed.
*/
ssh_auth_callback sk_pin_callback;
/** @brief User supplied pointer passed to callbacks (optional)
*
* Generic pointer set by the application and forwarded to
* interactive callbacks (e.g. PIN callback) to allow applications to
* carry state context.
*/
void *sk_userdata;
/** @brief Custom challenge data for enrollment (optional)
*
* Buffer containing challenge data signed by the authenticator.
* If NULL, a random 32-byte challenge is automatically generated.
*/
ssh_buffer sk_challenge_buffer;
/** @brief Options to be passed to the sk_callbacks (optional)
*
* NULL-terminated array of sk_option pointers owned by this context.
*/
struct sk_option **sk_callbacks_options;
/** @brief The buffer used to store attestation information returned in a
* key enrollment operation
*/
ssh_buffer sk_attestation_buffer;
};
/* Internal PKI context functions */
ssh_pki_ctx ssh_pki_ctx_dup(const ssh_pki_ctx context);
#endif /* PKI_CONTEXT_H */

View File

@@ -61,7 +61,6 @@ enum ssh_digest_e ssh_key_type_to_hash(ssh_session session,
enum ssh_keytypes_e type);
/* SSH Key Functions */
ssh_key pki_key_dup_common_init(const ssh_key key, int demote);
ssh_key pki_key_dup(const ssh_key key, int demote);
int pki_key_generate_rsa(ssh_key key, int parameter);
int pki_key_generate_ecdsa(ssh_key key, int parameter);
@@ -149,7 +148,6 @@ int pki_signature_from_ed25519_blob(ssh_signature sig, ssh_string sig_blob);
int pki_privkey_build_ed25519(ssh_key key,
ssh_string pubkey,
ssh_string privkey);
int pki_pubkey_build_ed25519(ssh_key key, ssh_string pubkey);
/* PKI Container OpenSSH */
ssh_key ssh_pki_openssh_pubkey_import(const char *text_key);
@@ -164,16 +162,6 @@ int pki_uri_import(const char *uri_name, ssh_key *key, enum ssh_key_e key_type);
#endif /* WITH_PKCS11_URI */
bool ssh_key_size_allowed_rsa(int min_size, ssh_key key);
/* Security Key Helper Functions */
int pki_buffer_pack_sk_priv_data(ssh_buffer buffer, const ssh_key key);
int pki_buffer_unpack_sk_priv_data(ssh_buffer buffer, ssh_key key);
int pki_sk_signature_buffer_prepare(const ssh_key key,
const ssh_signature sig,
const unsigned char *input,
size_t input_len,
ssh_buffer *sk_buffer_out);
#ifdef __cplusplus
}
#endif

View File

@@ -1,90 +0,0 @@
/*
* This file is part of the SSH Library
*
* Copyright (c) 2025 Praneeth Sarode <praneethsarode@gmail.com>
*
* The SSH Library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, version 2.1 of the License.
*
* The SSH Library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with the SSH Library; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
* MA 02111-1307, USA.
*/
#ifndef PKI_SK_H
#define PKI_SK_H
#include "libssh/libssh.h"
#include "libssh/pki.h"
#include <stdint.h>
#define SSH_SK_MAX_USER_ID_LEN 64
/**
* @brief Enroll a new security key using a U2F/FIDO2 authenticator
*
* Creates a new security key credential configured according to the parameters
* in the PKI context. This function handles key enrollment for both ECDSA and
* Ed25519 algorithms, generates appropriate challenges, and returns the
* enrolled key with optional attestation data.
*
* The PKI context must be configured with appropriate security key parameters
* using ssh_pki_ctx_options_set() before calling this function. Required
* options include SSH_PKI_OPTION_SK_APPLICATION, SSH_PKI_OPTION_SK_USER_ID, and
* SSH_PKI_OPTION_SK_CALLBACKS.
*
* @param[in] context The PKI context containing security key configuration and
* parameters
* @param[in] key_type The type of key to enroll (SSH_KEYTYPE_SK_ECDSA or
* SSH_KEYTYPE_SK_ED25519)
* @param[out] enrolled_key_result Pointer to store the enrolled ssh_key
*
* @return SSH_OK on success, SSH_ERROR on failure
*
* @see ssh_pki_ctx_new()
* @see ssh_pki_ctx_options_set()
* @see ssh_pki_ctx_get_sk_attestation_buffer()
*/
int pki_sk_enroll_key(ssh_pki_ctx context,
enum ssh_keytypes_e key_type,
ssh_key *enrolled_key_result);
/**
* @brief Sign arbitrary data using a security key and a PKI context
*
* This function performs signing operations configured according to the
* parameters in the PKI context and returns a properly formatted
* ssh_signature. The caller must free the signature when it is no longer
* needed.
*
* The PKI context should be configured with appropriate security key parameters
* using ssh_pki_ctx_options_set() before calling this function. The security
* key must have been previously enrolled or loaded.
*
* @param[in] context The PKI context containing security key configuration and
* parameters
* @param[in] key The security key to use for signing
* @param[in] data The data to sign
* @param[in] data_len Length of data to sign
*
* @return A valid ssh_signature on success, NULL on failure
*
* @see ssh_pki_ctx_new()
* @see ssh_pki_ctx_options_set()
* @see pki_sk_enroll_key()
* @see ssh_signature_free()
*/
ssh_signature pki_sk_do_sign(ssh_pki_ctx context,
const ssh_key key,
const uint8_t *data,
size_t data_len);
#endif /* PKI_SK_H */

View File

@@ -157,7 +157,6 @@ void ssh_poll_ctx_free(ssh_poll_ctx ctx);
int ssh_poll_ctx_add(ssh_poll_ctx ctx, ssh_poll_handle p);
int ssh_poll_ctx_add_socket (ssh_poll_ctx ctx, struct ssh_socket_struct *s);
void ssh_poll_ctx_remove(ssh_poll_ctx ctx, ssh_poll_handle p);
bool ssh_poll_is_locked(ssh_poll_handle p);
int ssh_poll_ctx_dopoll(ssh_poll_ctx ctx, int timeout);
ssh_poll_ctx ssh_poll_get_default_ctx(ssh_session session);
int ssh_event_add_poll(ssh_event event, ssh_poll_handle p);

View File

@@ -30,11 +30,10 @@
#define _LIBSSH_PRIV_H
#include <limits.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <stdbool.h>
#if !defined(HAVE_STRTOULL)
# if defined(HAVE___STRTOULL)
@@ -165,9 +164,6 @@ int ssh_gettimeofday(struct timeval *__p, void *__t);
#define gettimeofday ssh_gettimeofday
struct tm *ssh_localtime(const time_t *timer, struct tm *result);
# define localtime_r ssh_localtime
#define _XCLOSESOCKET closesocket
# ifdef HAVE_IO_H
@@ -333,7 +329,7 @@ int decompress_buffer(ssh_session session,ssh_buffer buf, size_t maxlen);
/* match.c */
int match_pattern_list(const char *string, const char *pattern,
size_t len, int dolower);
int match_hostname(const char *host, const char *pattern, size_t len);
int match_hostname(const char *host, const char *pattern, unsigned int len);
#ifndef _WIN32
int match_cidr_address_list(const char *address,
const char *addrlist,
@@ -357,48 +353,17 @@ int ssh_connector_remove_event(ssh_connector connector);
#define SAFE_FREE(x) do { if ((x) != NULL) {free(x); x=NULL;} } while(0)
/** Zero a structure */
#define ZERO_STRUCT(x) memset(&(x), 0, sizeof(x))
#define ZERO_STRUCT(x) memset((char *)&(x), 0, sizeof(x))
/** Zero a structure given a pointer to the structure */
#define ZERO_STRUCTP(x) do { if ((x) != NULL) memset((x), 0, sizeof(*(x))); } while(0)
#define ZERO_STRUCTP(x) do { if ((x) != NULL) memset((char *)(x), 0, sizeof(*(x))); } while(0)
/** Get the size of an array */
#define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0]))
/** Securely zero memory in a way that won't be optimized away */
#if defined(HAVE_MEMSET_EXPLICIT)
#define ssh_burn(ptr, len) memset_explicit((ptr), '\0', (len))
#elif defined(HAVE_EXPLICIT_BZERO)
#define ssh_burn(ptr, len) explicit_bzero((ptr), (len))
#elif defined(HAVE_MEMSET_S)
#define ssh_burn(ptr, len) memset_s((ptr), (len), '\0', (len))
#elif defined(HAVE_SECURE_ZERO_MEMORY)
#define ssh_burn(ptr, len) SecureZeroMemory((ptr), (len))
#else
#if defined(HAVE_GCC_VOLATILE_MEMORY_PROTECTION)
#define ssh_burn(ptr, len) \
do { \
memset((ptr), '\0', (len)); \
__asm__ volatile("" : : "g"(ptr) : "memory"); \
} while (0)
#else
#define ssh_burn(ptr, len) \
do { \
memset((ptr), '\0', (len)); \
} while (0)
#endif
#endif
void burn_free(void *ptr, size_t len);
/** Free memory space after zeroing it */
#define BURN_FREE(x, len) \
do { \
if ((x) != NULL) { \
burn_free((x), (len)); \
(x) = NULL; \
} \
} while (0)
#ifndef HAVE_EXPLICIT_BZERO
void explicit_bzero(void *s, size_t n);
#endif /* !HAVE_EXPLICIT_BZERO */
/**
* This is a hack to fix warnings. The idea is to use this everywhere that we
@@ -419,7 +384,6 @@ void burn_free(void *ptr, size_t len);
*/
#define discard_const_p(type, ptr) ((type *)discard_const(ptr))
#ifndef __VA_NARG__
/**
* Get the argument count of variadic arguments
*/
@@ -451,7 +415,6 @@ void burn_free(void *ptr, size_t len);
29, 28, 27, 26, 25, 24, 23, 22, 21, 20, \
19, 18, 17, 16, 15, 14, 13, 12, 11, 10, \
9, 8, 7, 6, 5, 4, 3, 2, 1, 0
#endif
#define CLOSE_SOCKET(s) do { if ((s) != SSH_INVALID_SOCKET) { _XCLOSESOCKET(s); (s) = SSH_INVALID_SOCKET;} } while(0)

View File

@@ -89,9 +89,6 @@ enum ssh_pending_call_e {
#define SSH_SESSION_FLAG_KEX_STRICT 0x0010
/* Unexpected packets have been sent while the session was still unencrypted */
#define SSH_SESSION_FLAG_KEX_TAINTED 0x0020
/* The scp on server can not handle quoted paths. Skip the mitigation for
* CVE-2019-14889 when using scp */
#define SSH_SESSION_FLAG_SCP_QUOTING_BROKEN 0x0040
/* codes to use with ssh_handle_packets*() */
/* Infinite timeout */
@@ -123,8 +120,6 @@ enum ssh_pending_call_e {
/* server-sig-algs extension */
#define SSH_EXT_SIG_RSA_SHA256 0x02
#define SSH_EXT_SIG_RSA_SHA512 0x04
/* Host-bound public key authentication extension */
#define SSH_EXT_PUBLICKEY_HOSTBOUND 0x08
/* members that are common to ssh_session and ssh_bind */
struct ssh_common_struct {
@@ -288,10 +283,6 @@ struct ssh_session_struct {
/* counters */
ssh_counter socket_counter;
ssh_counter raw_counter;
/* PKI context structure containing various parameters to configure PKI
* operations */
struct ssh_pki_ctx_struct *pki_context;
};
/** @internal

View File

@@ -79,7 +79,6 @@ typedef struct sftp_status_message_struct* sftp_status_message;
typedef struct sftp_statvfs_struct* sftp_statvfs_t;
typedef struct sftp_limits_struct* sftp_limits_t;
typedef struct sftp_aio_struct* sftp_aio;
typedef struct sftp_name_id_map_struct *sftp_name_id_map;
struct sftp_session_struct {
ssh_session session;
@@ -214,22 +213,6 @@ struct sftp_limits_struct {
uint64_t max_open_handles; /** maximum number of active handles allowed by server */
};
/**
* @brief SFTP names map structure to store the mapping between ids and names.
*
* This is mainly for the use of sftp_get_users_groups_by_id() function.
*/
struct sftp_name_id_map_struct {
/** @brief Count of name-id pairs in the map */
uint32_t count;
/** @brief Array of ids, ids[i] mapped to names[i] */
uint32_t *ids;
/** @brief Array of names, names[i] mapped to ids[i] */
char **names;
};
/**
* @brief Creates a new sftp session.
*
@@ -237,30 +220,24 @@ struct sftp_name_id_map_struct {
* with the server inside of the provided ssh session. This function call is
* usually followed by the sftp_init(), which initializes SFTP protocol itself.
*
* @param session The ssh session to use. The session *must* be in
* blocking mode since most `sftp_*` functions do not
* support the non-blocking API.
* @param session The ssh session to use.
*
* @return A new sftp session or NULL on error.
*
* @see sftp_free()
* @see sftp_init()
* @see ssh_set_blocking()
*/
LIBSSH_API sftp_session sftp_new(ssh_session session);
/**
* @brief Start a new sftp session with an existing channel.
*
* @param session The ssh session to use. The session *must* be in
* blocking mode since most `sftp_*` functions do not
* support the non-blocking API.
* @param session The ssh session to use.
* @param channel An open session channel with subsystem already allocated
*
* @return A new sftp session or NULL on error.
*
* @see sftp_free()
* @see ssh_set_blocking()
*/
LIBSSH_API sftp_session sftp_new_channel(ssh_session session, ssh_channel channel);
@@ -1211,58 +1188,6 @@ LIBSSH_API char *sftp_expand_path(sftp_session sftp, const char *path);
*/
LIBSSH_API char *sftp_home_directory(sftp_session sftp, const char *username);
/**
* @brief Create a new sftp_name_id_map struct.
*
* @param count The number of ids/names to store in the map.
*
* @return A pointer to the newly allocated sftp_name_id_map
* struct.
*/
LIBSSH_API sftp_name_id_map sftp_name_id_map_new(uint32_t count);
/**
* @brief Free the memory of an allocated `sftp_name_id_map` struct.
*
* @param map A pointer to the `sftp_name_id_map` struct to free.
*/
LIBSSH_API void sftp_name_id_map_free(sftp_name_id_map map);
/**
* @brief Retrieves usernames and group names based on provided user and group
* IDs.
*
* The retrieved names are stored in the `names` field of the
* `sftp_name_id_map` structure. In case a uid or gid is not found, an empty
* string is stored.
*
* This calls the "users-groups-by-id@openssh.com" extension.
* You should check if the extension is supported using:
*
* @code
* int supported = sftp_extension_supported(sftp,
* "users-groups-by-id@openssh.com", "1");
* @endcode
*
* @param sftp The SFTP session handle.
*
* @param users_map A pointer to a `sftp_name_id_map` struct with the user
* IDs. Can be NULL if only group names are needed.
*
* @param groups_map A pointer to a `sftp_name_id_map` struct with the group
* IDs. Can be NULL if only user names are needed.
*
* @return 0 on success, < 0 on error with ssh and sftp error set.
*
* @note The caller needs to free the memory used for
* the maps later using `sftp_name_id_map_free()`.
*
* @see sftp_get_error()
*/
LIBSSH_API int sftp_get_users_groups_by_id(sftp_session sftp,
sftp_name_id_map users_map,
sftp_name_id_map groups_map);
#ifdef WITH_SERVER
/**
* @brief Create a new sftp server session.

View File

@@ -21,8 +21,6 @@
#ifndef SFTP_PRIV_H
#define SFTP_PRIV_H
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
@@ -64,39 +62,6 @@ int sftp_read_and_dispatch(sftp_session sftp);
sftp_message sftp_dequeue(sftp_session sftp, uint32_t id);
/**
* @brief Receive the response of an sftp request
*
* In blocking mode, if the response hasn't arrived at the time of call, this
* function waits for the response to arrive.
*
* @param sftp The sftp session via which the request was sent.
*
* @param id The request identifier of the request whose
* corresponding response is required.
*
* @param blocking Flag to indicate the operating mode. true indicates
* blocking mode and false indicates non-blocking mode
*
* @param msg_ptr Pointer to the location to store the response message.
* In case of success, the message is allocated
* dynamically and must be freed (using
* sftp_message_free()) by the caller after usage. In case
* of failure, this is left untouched.
*
* @returns SSH_OK on success
* @returns SSH_ERROR on failure with the sftp and ssh errors set
* @returns SSH_AGAIN in case of non-blocking mode if the response hasn't
* arrived yet.
*
* @warning In blocking mode, this may block indefinitely for an invalid request
* identifier.
*/
int sftp_recv_response_msg(sftp_session sftp,
uint32_t id,
bool blocking,
sftp_message *msg_ptr);
/*
* Assigns a new SFTP ID for new requests and assures there is no collision
* between them.

View File

@@ -29,10 +29,6 @@ extern "C" {
#endif
#include <stdint.h>
#include "libssh/libssh.h"
#include "libssh/sftp.h"
/**
* @defgroup libssh_sftp_server The libssh SFTP server API
*

View File

@@ -1,283 +0,0 @@
/*
* Copyright (c) 2019 Google LLC
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*
* This file is a copy of the OpenSSH project's sk-api.h file pulled from
* https://github.com/openssh/openssh-portable/commit/a9cbe10da2be5be76755af0cea029db0f9c1f263
* with only the flags, algorithms, error codes, and struct definitions. The
* function declarations and other OpenSSH-specific code have been removed.
*/
#ifndef SK_API_H
#define SK_API_H 1
#include <stddef.h>
#include <stdint.h>
/* FIDO2/U2F Operation Flags */
/** Requires user presence confirmation (tap/touch) */
#ifndef SSH_SK_USER_PRESENCE_REQD
#define SSH_SK_USER_PRESENCE_REQD 0x01
#endif
/** Requires user verification (PIN/biometric) - FIDO2 only */
#ifndef SSH_SK_USER_VERIFICATION_REQD
#define SSH_SK_USER_VERIFICATION_REQD 0x04
#endif
/** Force resident key enrollment even if a resident key with given user ID
* already exists - FIDO2 only */
#ifndef SSH_SK_FORCE_OPERATION
#define SSH_SK_FORCE_OPERATION 0x10
#endif
/** Create/use resident key stored on authenticator - FIDO2 only */
#ifndef SSH_SK_RESIDENT_KEY
#define SSH_SK_RESIDENT_KEY 0x20
#endif
/* Algorithms */
/** ECDSA with P-256 curve */
#define SSH_SK_ECDSA 0x00
/** Ed25519 - FIDO2 only */
#define SSH_SK_ED25519 0x01
/* Error codes */
/** General unspecified failure */
#define SSH_SK_ERR_GENERAL -1
/** Requested algorithm/feature/option not supported */
#define SSH_SK_ERR_UNSUPPORTED -2
/** PIN (or other user verification) required but either missing or invalid */
#define SSH_SK_ERR_PIN_REQUIRED -3
/** No suitable security key / authenticator device was found */
#define SSH_SK_ERR_DEVICE_NOT_FOUND -4
/** Attempt to create a resident key that already exists (duplicate) */
#define SSH_SK_ERR_CREDENTIAL_EXISTS -5
/**
* @brief Response structure for FIDO2/U2F key enrollment operations
*
* Contains all data returned by a FIDO2/U2F authenticator after successful
* enrollment of a new credential.
*/
struct sk_enroll_response {
/** @brief FIDO2/U2F authenticator flags from the enrollment operation
*
* Contains flags indicating authenticator capabilities and state during
* enrollment, such as user presence (UP), user verification
* (UV), and resident key.
*/
uint8_t flags;
/** @brief Public key data in standard format
*
* For ECDSA (P-256): 65 bytes in SEC1 uncompressed point format
* (0x04 prefix + 32-byte X coordinate + 32-byte Y coordinate)
* For Ed25519: 32 bytes containing the raw public key (FIDO2 only)
*/
uint8_t *public_key;
/** @brief Length of public_key buffer in bytes
*
* Expected values: 65 for ECDSA P-256, 32 for Ed25519
*/
size_t public_key_len;
/** @brief Opaque credential handle/ID used to identify this key
*
* Authenticator-generated binary data that uniquely identifies this
* credential. Used in subsequent sign operations to specify which
* key to use. Format and contents are authenticator-specific.
*/
uint8_t *key_handle;
/** @brief Length of key_handle buffer in bytes
*
* Length varies by authenticator.
*/
size_t key_handle_len;
/** @brief Enrollment signature over the enrollment data
*
* FIDO2/U2F authenticator signature proving the credential was created
* by this specific authenticator. Used for enrollment verification.
* Format depends on algorithm.
*/
uint8_t *signature;
/** @brief Length of signature buffer in bytes
*
* Length varies by algorithm.
*/
size_t signature_len;
/** @brief X.509 attestation certificate
*
* Certificate that attests to the authenticity of the authenticator
* and the enrollment operation. Used to verify the authenticator's
* identity and manufacturer.
*/
uint8_t *attestation_cert;
/** @brief Length of attestation_cert buffer in bytes */
size_t attestation_cert_len;
/** @brief FIDO2/U2F authenticator data from enrollment
*
* CBOR-encoded authenticator data containing RP ID hash, flags,
* counter, and attested credential data. Used for attestation
* verification according to the FIDO2 specification.
*/
uint8_t *authdata;
/** @brief Length of authdata buffer in bytes
*
* Length varies depending on credential data and extensions.
*/
size_t authdata_len;
};
/**
* @brief Response structure for FIDO2/U2F key signing operations
*
* Contains signature components and metadata returned by a FIDO2/U2F
* authenticator after a successful signing operation.
*/
struct sk_sign_response {
/** @brief FIDO2/U2F authenticator flags from the signing operation
*
* Contains flags indicating authenticator state during signing,
* including user presence (UP) and user verification (UV) flags.
* Used to verify that proper user interaction occurred while signing.
*/
uint8_t flags;
/** @brief Authenticator signature counter value
*
* Monotonically increasing counter maintained by the authenticator.
* Incremented on each successful signing operation. Used to detect
* cloned or duplicated authenticators.
*/
uint32_t counter;
/** @brief R component of ECDSA signature or Ed25519 signature */
uint8_t *sig_r;
/** @brief Length of sig_r buffer in bytes */
size_t sig_r_len;
/** @brief S component of ECDSA signature */
uint8_t *sig_s;
/** @brief Length of sig_s buffer in bytes */
size_t sig_s_len;
};
/**
* @brief Structure representing a resident/discoverable credential
*
* Represents a FIDO2 resident key (discoverable credential) that is
* stored on the authenticator and can be discovered without providing
* a credential ID.
*/
struct sk_resident_key {
/** @brief Cryptographic algorithm identifier for this key
*
* SSH_SK_ECDSA (0x00): ECDSA with P-256 curve
* SSH_SK_ED25519 (0x01): Ed25519 signature algorithm
*/
uint32_t alg;
/** @brief Slot/index number of this key on the authenticator
*
* Zero-based index indicating the position of this resident key
* in the authenticator's internal storage. Used for key management
* and identification when multiple resident keys exist.
*/
size_t slot;
/** @brief Relying Party (application) identifier string
*
* The RP ID (typically a domain name) that this resident key
* is associated with. Determines which application/service
* this key can be used for.
*/
char *application;
/** @brief Embedded enrollment response containing key material
*
* Contains the same data as returned during initial enrollment,
* including public key, key handle, and associated metadata.
*/
struct sk_enroll_response key;
/** @brief Flags associated with this resident key
*
* SSH_SK_USER_PRESENCE_REQD: Requires user presence for operations
* SSH_SK_USER_VERIFICATION_REQD: Requires user verification
* (PIN/biometric)
*/
uint8_t flags;
/** @brief User identifier associated with this resident key
*
* Binary user ID that was provided during key enrollment.
* Used to identify which user account this key belongs to.
*/
uint8_t *user_id;
/** @brief Length of user_id buffer in bytes
*
* Length of the user identifier.
*/
size_t user_id_len;
};
/**
* @brief Configuration option structure for FIDO2/U2F operations
*
* Represents a single configuration parameter that can be passed
* to FIDO2/U2F middleware.
*/
struct sk_option {
/** @brief Option name/key identifier */
char *name;
/** @brief Option value as bytes */
char *value;
/** @brief Indicates if this option is required for the operation
*
* Non-zero if this option must be processed and cannot be ignored.
* Zero if this option is advisory and can be skipped if the
* middleware does not support it.
*/
uint8_t required;
};
/** Current SK API version */
#define SSH_SK_VERSION_MAJOR 0x000a0000
#define SSH_SK_VERSION_MAJOR_MASK 0xffff0000
#endif /* SK_API_H */

View File

@@ -1,213 +0,0 @@
/*
* This file is part of the SSH Library
*
* Copyright (c) 2025 Praneeth Sarode <praneethsarode@gmail.com>
*
* The SSH Library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, version 2.1 of the License.
*
* The SSH Library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with the SSH Library; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
* MA 02111-1307, USA.
*/
#ifndef SK_COMMON_H
#define SK_COMMON_H
#include "libssh/callbacks.h"
#include "libssh/sk_api.h"
#include <stdbool.h>
#define SK_MAX_USER_ID_LEN 64
#define SK_NOT_SUPPORTED_MSG \
"Security Key functionality is not supported in this build of libssh. " \
"Please enable support by building using the WITH_FIDO2 build option."
/**
* @brief Convert security key error code to human-readable string
*
* Converts a security key error code to a descriptive string representation
* that can be used for logging user-facing error messages.
*
* @param[in] sk_err The security key error code to convert.
*
* @return Constant string describing the error. Never returns NULL.
* Returns "Unknown error" for unrecognized error codes.
*
* @note The returned string is statically allocated and should not be freed.
*/
const char *ssh_sk_err_to_string(int sk_err);
/**
* @brief Securely clear the contents of an sk_enroll_response structure
*
* Overwrites sensitive data within the enrollment response structure with
* zeros to prevent information leakage. This function only clears and frees the
* contents and does not free the structure itself.
*
* @param[in] enroll_response The enrollment response structure to clear.
* Can be NULL (no operation performed).
*
* @note This function only frees the memory for the contents and does not free
* memory for the structure itself. Use sk_enroll_response_free() for complete
* cleanup, which also performs secure clearing internally.
*/
void sk_enroll_response_burn(struct sk_enroll_response *enroll_response);
/**
* @brief Securely free an sk_enroll_response structure
*
* Performs secure clearing of sensitive data within the enrollment response
* structure before freeing the allocated memory. This function internally
* calls sk_enroll_response_burn() before deallocation.
*
* @param[in] enroll_response The enrollment response structure to free.
* Can be NULL (no operation performed).
*
* @note Developers do not need to call sk_enroll_response_burn() before
* calling this function, as secure clearing is performed automatically.
*/
void sk_enroll_response_free(struct sk_enroll_response *enroll_response);
/**
* @brief Free an sk_sign_response structure
*
* Frees the memory allocated for a sign response structure and all its
* associated data. This function performs secure clearing of sensitive
* data before deallocation.
*
* @param[in] sign_response The sign response structure to free.
* Can be NULL (no operation performed).
*
* @note This is a secure free operation that clears sensitive data before
* memory deallocation to prevent information leakage.
*/
void sk_sign_response_free(struct sk_sign_response *sign_response);
/**
* @brief Free an sk_resident_key structure
*
* Frees the memory allocated for a resident key structure and all its
* associated data. This function performs secure clearing of sensitive
* data before deallocation.
*
* @param[in] resident_key The resident key structure to free.
* Can be NULL (no operation performed).
*
* @note This is a secure free operation that clears sensitive data before
* memory deallocation to prevent information leakage.
*/
void sk_resident_key_free(struct sk_resident_key *resident_key);
/**
* @brief Free an sk_option array and all its contents
*
* Frees a NULL-terminated array of sk_option structures, including all
* allocated memory for option names and values within each structure.
*
* @param[in] options NULL-terminated array of sk_option pointers to free.
* Can be NULL (no operation performed).
*
* @note The options array must be NULL-terminated for proper freeing.
* Each sk_option structure and its name/value strings will be freed.
*/
void sk_options_free(struct sk_option **options);
/**
* @brief Validate options and extract values for specific keys
*
* Validates that all required options are supported and extracts values
* for the specified keys. This function is primarily intended for use
* by the SK callback implementations.
*
* @param[in] options NULL-terminated array of sk_option pointers to validate.
* @param[in] keys NULL-terminated array of supported option keys.
* @param[out] values Pointer to array that will be allocated and filled with
* copied values (same order as keys). The caller must free
* this array and all contained strings when done.
*
* @return SSH_OK on success, SSH_ERROR if unsupported required options found
* or memory allocation fails.
*
* @note The values array is allocated by this function and contains copies
* of the option values. The caller must free both the array and all
* non-NULL string values within it. Values for keys not found in
* options will be set to NULL.
*/
int sk_options_validate_get(const struct sk_option **options,
const char **keys,
char ***values);
/**
* @brief Duplicate an array of sk_option structures
*
* Creates a deep copy of an array of security key options. Each option
* structure and its string fields are duplicated.
*
* @param[in] options The array of options to duplicate. Must be
* NULL-terminated array of struct sk_option pointers.
* Can be NULL.
*
* @return A newly allocated array of duplicated options on success,
* NULL on failure or if options is NULL.
* The returned array should be freed with SK_OPTIONS_FREE().
*/
struct sk_option **sk_options_dup(const struct sk_option **options);
/**
* @brief Check version compatibility of security key callbacks
*
* Validates that the provided security key callbacks use an SK API
* version whose major portion is the same as the major version that libssh
* supports.
*
* @param[in] callbacks Pointer to the sk_callbacks structure to check.
*
* @return true if the callbacks are compatible, false otherwise.
*/
bool sk_callbacks_check_compatibility(
const struct ssh_sk_callbacks_struct *callbacks);
/* Convenience macros for secure freeing with NULL checks and pointer reset */
#define SK_ENROLL_RESPONSE_FREE(x) \
do { \
if ((x) != NULL) { \
sk_enroll_response_free(x); \
x = NULL; \
} \
} while (0)
#define SK_SIGN_RESPONSE_FREE(x) \
do { \
if ((x) != NULL) { \
sk_sign_response_free(x); \
x = NULL; \
} \
} while (0)
#define SK_RESIDENT_KEY_FREE(x) \
do { \
if ((x) != NULL) { \
sk_resident_key_free(x); \
x = NULL; \
} \
} while (0)
#define SK_OPTIONS_FREE(x) \
do { \
if ((x) != NULL) { \
sk_options_free(x); \
x = NULL; \
} \
} while (0)
#endif /* SK_COMMON_H */

View File

@@ -1,37 +0,0 @@
/*
* This file is part of the SSH Library
*
* Copyright (c) 2025 Praneeth Sarode <praneethsarode@gmail.com>
*
* The SSH Library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, version 2.1 of the License.
*
* The SSH Library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with the SSH Library; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
* MA 02111-1307, USA.
*/
#ifndef SK_USBHID_H
#define SK_USBHID_H
/**
* @brief Get the USB-HID security key callbacks.
*
* This function returns a pointer to the implementation of
* security key callbacks for FIDO2/U2F devices using the USB-HID
* protocol.
*
* @return Pointer to the ssh_sk_callbacks_struct
*
* @see ssh_sk_callbacks_struct
*/
const struct ssh_sk_callbacks_struct *ssh_sk_get_usbhid_callbacks(void);
#endif /* SK_USBHID_H */

View File

@@ -1,86 +0,0 @@
/*
* This file is part of the SSH Library
*
* Copyright (c) 2013 by Aris Adamantiadis <aris@badcode.be>
* Copyright (c) 2023 Simon Josefsson <simon@josefsson.org>
* Copyright (c) 2025 Jakub Jelen <jjelen@redhat.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation,
* version 2.1 of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef SNTRUP761_H_
#define SNTRUP761_H_
#include "config.h"
#include "curve25519.h"
#include "libssh.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifdef HAVE_CURVE25519
#define HAVE_SNTRUP761 1
#endif
extern void crypto_hash_sha512(unsigned char *out,
const unsigned char *in,
unsigned long long inlen);
/*
* Derived from public domain source, written by (in alphabetical order):
* - Daniel J. Bernstein
* - Chitchanok Chuengsatiansup
* - Tanja Lange
* - Christine van Vredendaal
*/
#include <stdint.h>
#include <string.h>
#define SNTRUP761_SECRETKEY_SIZE 1763
#define SNTRUP761_PUBLICKEY_SIZE 1158
#define SNTRUP761_CIPHERTEXT_SIZE 1039
#define SNTRUP761_SIZE 32
typedef void sntrup761_random_func(void *ctx, size_t length, uint8_t *dst);
void sntrup761_keypair(uint8_t *pk,
uint8_t *sk,
void *random_ctx,
sntrup761_random_func *random);
void sntrup761_enc(uint8_t *c,
uint8_t *k,
const uint8_t *pk,
void *random_ctx,
sntrup761_random_func *random);
void sntrup761_dec(uint8_t *k, const uint8_t *c, const uint8_t *sk);
typedef unsigned char ssh_sntrup761_pubkey[SNTRUP761_PUBLICKEY_SIZE];
typedef unsigned char ssh_sntrup761_privkey[SNTRUP761_SECRETKEY_SIZE];
typedef unsigned char ssh_sntrup761_ciphertext[SNTRUP761_CIPHERTEXT_SIZE];
int ssh_client_sntrup761x25519_init(ssh_session session);
void ssh_client_sntrup761x25519_remove_callbacks(ssh_session session);
#ifdef WITH_SERVER
void ssh_server_sntrup761x25519_init(ssh_session session);
#endif /* WITH_SERVER */
#ifdef __cplusplus
}
#endif
#endif /* SNTRUP761_H_ */

View File

@@ -33,7 +33,7 @@ void ssh_socket_cleanup(void);
ssh_socket ssh_socket_new(ssh_session session);
void ssh_socket_reset(ssh_socket s);
void ssh_socket_free(ssh_socket s);
int ssh_socket_set_fd(ssh_socket s, socket_t fd);
void ssh_socket_set_fd(ssh_socket s, socket_t fd);
socket_t ssh_socket_get_fd(ssh_socket s);
void ssh_socket_set_connected(ssh_socket s, struct ssh_poll_handle_struct *p);
int ssh_socket_unix(ssh_socket s, const char *path);

Some files were not shown because too many files have changed in this diff Show More