mirror of
https://git.libssh.org/projects/libssh.git
synced 2026-02-06 18:29:50 +09:00
Compare commits
139 Commits
ef50a3c0f0
...
stable-0.1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
39a62cef44 | ||
|
|
7969b6de3c | ||
|
|
b207e39d28 | ||
|
|
6230b24ff5 | ||
|
|
e668b03dd7 | ||
|
|
77ce02d809 | ||
|
|
d61b0dc7cc | ||
|
|
d12eb770ac | ||
|
|
03b29a6874 | ||
|
|
99957fb561 | ||
|
|
3e9175e66a | ||
|
|
bf295abb5b | ||
|
|
7f14df3eac | ||
|
|
c206e5d84e | ||
|
|
274b8f19b3 | ||
|
|
39a88d62c9 | ||
|
|
94f12090b5 | ||
|
|
301d0e16df | ||
|
|
c182a21e11 | ||
|
|
3a28fbe5c6 | ||
|
|
65f363c9e3 | ||
|
|
1c763e29d1 | ||
|
|
7d85085d2a | ||
|
|
8e4d67aa9e | ||
|
|
266174a6d3 | ||
|
|
87db2659ec | ||
|
|
0fad4e6307 | ||
|
|
02cbd41b92 | ||
|
|
750693d10b | ||
|
|
56953f8aab | ||
|
|
0f1723b5c7 | ||
|
|
f1998d6064 | ||
|
|
d0ef7afdfa | ||
|
|
6e459f5756 | ||
|
|
51746e51f0 | ||
|
|
e7ef3f2962 | ||
|
|
b8d92bbcc7 | ||
|
|
f2aaee53df | ||
|
|
b026b24b55 | ||
|
|
028859ce99 | ||
|
|
d64f06f98a | ||
|
|
b298a04f96 | ||
|
|
962012bbf6 | ||
|
|
abfc42fad3 | ||
|
|
1ad67bd66e | ||
|
|
f553a6740a | ||
|
|
bac5d3f10a | ||
|
|
c8c3d418ee | ||
|
|
33be8038fe | ||
|
|
dff6c0821e | ||
|
|
82175044dc | ||
|
|
8559f59404 | ||
|
|
160fc7df10 | ||
|
|
a9d8a3d448 | ||
|
|
f13b91c2d8 | ||
|
|
90b4845e0c | ||
|
|
6ddb730a27 | ||
|
|
b35ee876ad | ||
|
|
697650caa9 | ||
|
|
5504ff4051 | ||
|
|
f79ec51b7f | ||
|
|
78485f446a | ||
|
|
3443aec901 | ||
|
|
261612179f | ||
|
|
5f4ffda887 | ||
|
|
6fd9cc8ce3 | ||
|
|
b595cc7ada | ||
|
|
d044b79de0 | ||
|
|
827c24055f | ||
|
|
1eff5d68f4 | ||
|
|
e4ede51d87 | ||
|
|
991b4422bd | ||
|
|
1a2c46781c | ||
|
|
65699380cf | ||
|
|
52e648c7f1 | ||
|
|
66314eeb71 | ||
|
|
573e0e48dc | ||
|
|
a2bb9b5d0c | ||
|
|
0de97c48d0 | ||
|
|
eeb498c0e3 | ||
|
|
715855d888 | ||
|
|
38004ecf94 | ||
|
|
edb1b8ba2c | ||
|
|
1e9e37580f | ||
|
|
8b5b785e0c | ||
|
|
d245706678 | ||
|
|
5911d058f1 | ||
|
|
3daa06dba7 | ||
|
|
45888d65ba | ||
|
|
33a73594e6 | ||
|
|
9cdcd16e82 | ||
|
|
12077f7294 | ||
|
|
f067d9e0d3 | ||
|
|
ec753057a5 | ||
|
|
39aefd479f | ||
|
|
2e5b6beec7 | ||
|
|
11c16531f0 | ||
|
|
69ee0062d7 | ||
|
|
13c69821dd | ||
|
|
543c730691 | ||
|
|
97bda86d41 | ||
|
|
77c9498dbe | ||
|
|
404452728d | ||
|
|
e111a63acb | ||
|
|
054682e72d | ||
|
|
5bff8b5dc6 | ||
|
|
758fbdd31b | ||
|
|
5c0add44e7 | ||
|
|
9f4e7eb06b | ||
|
|
1d157c57a3 | ||
|
|
7d35d25297 | ||
|
|
4119ad0fd8 | ||
|
|
771dc30f79 | ||
|
|
747dd17e64 | ||
|
|
093431f929 | ||
|
|
854795c654 | ||
|
|
da064c9a18 | ||
|
|
c85dc05436 | ||
|
|
8d0d3d4d7b | ||
|
|
0b2e13bc9b | ||
|
|
51f4a5743d | ||
|
|
e816256333 | ||
|
|
960a6d1cdd | ||
|
|
1fa9ea7f43 | ||
|
|
afa77c11ca | ||
|
|
825de355d4 | ||
|
|
a910526e10 | ||
|
|
dfc3cb7112 | ||
|
|
3264d3e83c | ||
|
|
6030d2fcd5 | ||
|
|
406a014d58 | ||
|
|
af0153f30f | ||
|
|
84dde6d302 | ||
|
|
dd38f523e1 | ||
|
|
5318ddaabc | ||
|
|
2f50ef2fe6 | ||
|
|
eae3a60ef8 | ||
|
|
318f675ef8 | ||
|
|
7beb580aab |
@@ -26,4 +26,3 @@ BreakAfterReturnType: ExceptShortType
|
||||
AlwaysBreakAfterReturnType: AllDefinitions
|
||||
AlignEscapedNewlines: Left
|
||||
ForEachMacros: ['ssh_callbacks_iterate']
|
||||
AlignConsecutiveMacros: 'Consecutive'
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -10,4 +10,3 @@ tags
|
||||
/build
|
||||
/obj*
|
||||
doc/tags.xml
|
||||
.DS_Store
|
||||
|
||||
131
.gitlab-ci.yml
131
.gitlab-ci.yml
@@ -27,17 +27,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_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
|
||||
@@ -229,15 +225,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:
|
||||
@@ -409,7 +405,7 @@ fedora/mingw32:
|
||||
paths:
|
||||
- obj-csbuild/
|
||||
|
||||
fedora/csbuild/openssl_3.x:
|
||||
fedora/csbuild/openssl_3.0.x:
|
||||
extends: .csbuild
|
||||
script:
|
||||
- csbuild
|
||||
@@ -439,62 +435,6 @@ fedora/csbuild/mbedtls:
|
||||
--color
|
||||
--print-current --print-fixed
|
||||
|
||||
###############################################################################
|
||||
# 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
|
||||
|
||||
###############################################################################
|
||||
# Ubuntu builds #
|
||||
@@ -507,7 +447,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:
|
||||
@@ -524,10 +464,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
|
||||
@@ -540,12 +480,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
|
||||
@@ -557,7 +497,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++"
|
||||
@@ -567,11 +507,6 @@ 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
|
||||
@@ -633,7 +568,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:
|
||||
@@ -725,41 +662,3 @@ coverity:
|
||||
when: on_failure
|
||||
paths:
|
||||
- obj/cov-int/*.txt
|
||||
|
||||
###############################################################################
|
||||
# MacOS #
|
||||
###############################################################################
|
||||
.macos:
|
||||
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
|
||||
- branches@marco.fortina/libssh-mirror
|
||||
|
||||
# TODO add -DFUZZ_TESTING=ON clang cant find _LLVMFuzzerInitialize on arm64
|
||||
macos-m1:
|
||||
extends: .macos
|
||||
variables:
|
||||
HOMEBREW_NO_AUTO_UPDATE: 1
|
||||
CMAKE_DEFAULT_OPTIONS: "-DCMAKE_BUILD_TYPE=RelWithDebInfo -DPICKY_DEVELOPER=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"
|
||||
CMAKE_OPTIONS: $CMAKE_DEFAULT_OPTIONS $CMAKE_BUILD_OPTIONS $CMAKE_TEST_OPTIONS
|
||||
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/
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
38
CHANGELOG
38
CHANGELOG
@@ -1,6 +1,44 @@
|
||||
CHANGELOG
|
||||
=========
|
||||
|
||||
version 0.11.3 (released 2025-09-09)
|
||||
* Security:
|
||||
* CVE-2025-8114: Fix NULL pointer dereference after allocation failure
|
||||
* CVE-2025-8277: Fix memory leak of ephemeral key pair during repeated wrong KEX
|
||||
* Potential UAF when send() fails during key exchange
|
||||
* Fix possible timeout during KEX if client sends authentication too early (#311)
|
||||
* Cleanup OpenSSL PKCS#11 provider when loaded
|
||||
* Zeroize buffers containing private key blobs during export
|
||||
|
||||
version 0.11.2 (released 2025-06-24)
|
||||
* Security:
|
||||
* CVE-2025-4877 - Write beyond bounds in binary to base64 conversion
|
||||
* CVE-2025-4878 - Use of uninitialized variable in privatekey_from_file()
|
||||
* CVE-2025-5318 - Likely read beyond bounds in sftp server handle management
|
||||
* CVE-2025-5351 - Double free in functions exporting keys
|
||||
* CVE-2025-5372 - ssh_kdf() returns a success code on certain failures
|
||||
* CVE-2025-5449 - Likely read beyond bounds in sftp server message decoding
|
||||
* CVE-2025-5987 - Invalid return code for chacha20 poly1305 with OpenSSL
|
||||
* Compatibility
|
||||
* Fixed compatibility with CPM.cmake
|
||||
* Compatibility with OpenSSH 10.0
|
||||
* Tests compatibility with new Dropbear releases
|
||||
* Removed p11-kit remoting from the pkcs11 testsuite
|
||||
* Bugfixes
|
||||
* Implement missing packet filter for DH GEX
|
||||
* Properly process the SSH2_MSG_DEBUG message
|
||||
* Allow escaping quotes in quoted arguments to ssh configuration
|
||||
* Do not fail with unknown match keywords in ssh configuration
|
||||
* Process packets before selecting signature algorithm during authentication
|
||||
* Do not fail hard when the SFTP status message is not sent by noncompliant
|
||||
servers
|
||||
|
||||
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
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
cmake_minimum_required(VERSION 3.12.0)
|
||||
cmake_minimum_required(VERSION 3.14.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.3 LANGUAGES C)
|
||||
|
||||
# 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.3")
|
||||
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)
|
||||
@@ -252,15 +249,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 "********************************************")
|
||||
|
||||
|
||||
@@ -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!
|
||||
|
||||
|
||||
@@ -226,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)
|
||||
|
||||
@@ -237,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()
|
||||
|
||||
@@ -27,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)
|
||||
@@ -60,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)
|
||||
|
||||
6
INSTALL
6
INSTALL
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
*/
|
||||
|
||||
@@ -19,7 +19,7 @@ the interesting functions as you go.
|
||||
|
||||
The libssh library provides:
|
||||
|
||||
- <strong>Key Exchange Methods</strong>: <i>sntrup761x25519-sha512@openssh.com, 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
|
||||
|
||||
@@ -303,6 +303,7 @@ span.lineno {
|
||||
padding-right: 4px;
|
||||
text-align: right;
|
||||
color: black;
|
||||
height: 100px;
|
||||
white-space: pre;
|
||||
border-right: 3px solid #1d7567;
|
||||
background-color: #323232; }
|
||||
|
||||
@@ -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;
|
||||
@@ -146,7 +147,7 @@ int authenticate_console(ssh_session session)
|
||||
|
||||
// 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) {
|
||||
|
||||
@@ -21,50 +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 *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 = NULL;
|
||||
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 (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;
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ 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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -119,10 +119,6 @@ static struct location *parse_location(char *loc)
|
||||
struct location *location = NULL;
|
||||
char *ptr = NULL;
|
||||
|
||||
if (loc == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
location = malloc(sizeof(struct location));
|
||||
if (location == NULL) {
|
||||
return NULL;
|
||||
|
||||
@@ -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, 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 = 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;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv){
|
||||
ssh_session session = NULL;
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -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, 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 = NULL;
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -40,236 +40,222 @@ clients must be made or how a client should react.
|
||||
#endif
|
||||
|
||||
char *host = NULL;
|
||||
const char *desthost = "localhost";
|
||||
const char *port = "22";
|
||||
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 = NULL;
|
||||
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)
|
||||
{
|
||||
int main(int argc, char **argv){
|
||||
ssh_session session = NULL;
|
||||
|
||||
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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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,34 +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,
|
||||
/* 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 {
|
||||
@@ -128,20 +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_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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
@@ -851,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);
|
||||
@@ -876,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);
|
||||
@@ -889,27 +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,
|
||||
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);
|
||||
|
||||
#ifndef LIBSSH_LEGACY_0_4
|
||||
#include "libssh/legacy.h"
|
||||
#endif
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -51,15 +51,6 @@
|
||||
#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;
|
||||
@@ -72,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;
|
||||
@@ -86,11 +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;
|
||||
};
|
||||
|
||||
struct ssh_signature_struct {
|
||||
@@ -142,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);
|
||||
|
||||
@@ -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,11 +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);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -157,6 +157,7 @@ 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);
|
||||
|
||||
@@ -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,10 +353,10 @@ 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]))
|
||||
@@ -369,17 +365,6 @@ int ssh_connector_remove_event(ssh_connector connector);
|
||||
void explicit_bzero(void *s, size_t n);
|
||||
#endif /* !HAVE_EXPLICIT_BZERO */
|
||||
|
||||
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)
|
||||
|
||||
/**
|
||||
* This is a hack to fix warnings. The idea is to use this everywhere that we
|
||||
* get the "discarding const" warning by the compiler. That doesn't actually
|
||||
|
||||
@@ -120,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 {
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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_ */
|
||||
@@ -129,7 +129,6 @@ int evp_build_pkey(const char* name, OSSL_PARAM_BLD *param_bld, EVP_PKEY **pkey,
|
||||
int evp_dup_dsa_pkey(const ssh_key key, ssh_key new_key, int demote);
|
||||
int evp_dup_rsa_pkey(const ssh_key key, ssh_key new_key, int demote);
|
||||
int evp_dup_ecdsa_pkey(const ssh_key key, ssh_key new_key, int demote);
|
||||
int evp_dup_ed25519_pkey(const ssh_key key, ssh_key new_key, int demote);
|
||||
#endif /* HAVE_LIBCRYPTO && OPENSSL_VERSION_NUMBER */
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -8,4 +8,3 @@ Description: The SSH Library
|
||||
Version: @PROJECT_VERSION@
|
||||
Libs: -L${libdir} -lssh
|
||||
Cflags: -I${includedir}
|
||||
Requires.private: @LIBSSH_PC_REQUIRES_PRIVATE@
|
||||
|
||||
@@ -1 +1 @@
|
||||
4.10.0
|
||||
4.10.3
|
||||
445
src/ABI/libssh-4.10.1.symbols
Normal file
445
src/ABI/libssh-4.10.1.symbols
Normal file
@@ -0,0 +1,445 @@
|
||||
_ssh_log
|
||||
buffer_free
|
||||
buffer_get
|
||||
buffer_get_len
|
||||
buffer_new
|
||||
channel_accept_x11
|
||||
channel_change_pty_size
|
||||
channel_close
|
||||
channel_forward_accept
|
||||
channel_forward_cancel
|
||||
channel_forward_listen
|
||||
channel_free
|
||||
channel_get_exit_status
|
||||
channel_get_session
|
||||
channel_is_closed
|
||||
channel_is_eof
|
||||
channel_is_open
|
||||
channel_new
|
||||
channel_open_forward
|
||||
channel_open_session
|
||||
channel_poll
|
||||
channel_read
|
||||
channel_read_buffer
|
||||
channel_read_nonblocking
|
||||
channel_request_env
|
||||
channel_request_exec
|
||||
channel_request_pty
|
||||
channel_request_pty_size
|
||||
channel_request_send_signal
|
||||
channel_request_sftp
|
||||
channel_request_shell
|
||||
channel_request_subsystem
|
||||
channel_request_x11
|
||||
channel_select
|
||||
channel_send_eof
|
||||
channel_set_blocking
|
||||
channel_write
|
||||
channel_write_stderr
|
||||
privatekey_free
|
||||
privatekey_from_file
|
||||
publickey_free
|
||||
publickey_from_file
|
||||
publickey_from_privatekey
|
||||
publickey_to_string
|
||||
sftp_aio_begin_read
|
||||
sftp_aio_begin_write
|
||||
sftp_aio_free
|
||||
sftp_aio_wait_read
|
||||
sftp_aio_wait_write
|
||||
sftp_async_read
|
||||
sftp_async_read_begin
|
||||
sftp_attributes_free
|
||||
sftp_canonicalize_path
|
||||
sftp_channel_default_data_callback
|
||||
sftp_channel_default_subsystem_request
|
||||
sftp_chmod
|
||||
sftp_chown
|
||||
sftp_client_message_free
|
||||
sftp_client_message_get_data
|
||||
sftp_client_message_get_filename
|
||||
sftp_client_message_get_flags
|
||||
sftp_client_message_get_submessage
|
||||
sftp_client_message_get_type
|
||||
sftp_client_message_set_filename
|
||||
sftp_close
|
||||
sftp_closedir
|
||||
sftp_dir_eof
|
||||
sftp_expand_path
|
||||
sftp_extension_supported
|
||||
sftp_extensions_get_count
|
||||
sftp_extensions_get_data
|
||||
sftp_extensions_get_name
|
||||
sftp_file_set_blocking
|
||||
sftp_file_set_nonblocking
|
||||
sftp_free
|
||||
sftp_fstat
|
||||
sftp_fstatvfs
|
||||
sftp_fsync
|
||||
sftp_get_client_message
|
||||
sftp_get_error
|
||||
sftp_handle
|
||||
sftp_handle_alloc
|
||||
sftp_handle_remove
|
||||
sftp_hardlink
|
||||
sftp_home_directory
|
||||
sftp_init
|
||||
sftp_limits
|
||||
sftp_limits_free
|
||||
sftp_lsetstat
|
||||
sftp_lstat
|
||||
sftp_mkdir
|
||||
sftp_new
|
||||
sftp_new_channel
|
||||
sftp_open
|
||||
sftp_opendir
|
||||
sftp_read
|
||||
sftp_readdir
|
||||
sftp_readlink
|
||||
sftp_rename
|
||||
sftp_reply_attr
|
||||
sftp_reply_data
|
||||
sftp_reply_handle
|
||||
sftp_reply_name
|
||||
sftp_reply_names
|
||||
sftp_reply_names_add
|
||||
sftp_reply_status
|
||||
sftp_rewind
|
||||
sftp_rmdir
|
||||
sftp_seek
|
||||
sftp_seek64
|
||||
sftp_send_client_message
|
||||
sftp_server_free
|
||||
sftp_server_init
|
||||
sftp_server_new
|
||||
sftp_server_version
|
||||
sftp_setstat
|
||||
sftp_stat
|
||||
sftp_statvfs
|
||||
sftp_statvfs_free
|
||||
sftp_symlink
|
||||
sftp_tell
|
||||
sftp_tell64
|
||||
sftp_unlink
|
||||
sftp_utimes
|
||||
sftp_write
|
||||
ssh_accept
|
||||
ssh_add_channel_callbacks
|
||||
ssh_auth_list
|
||||
ssh_basename
|
||||
ssh_bind_accept
|
||||
ssh_bind_accept_fd
|
||||
ssh_bind_fd_toaccept
|
||||
ssh_bind_free
|
||||
ssh_bind_get_fd
|
||||
ssh_bind_listen
|
||||
ssh_bind_new
|
||||
ssh_bind_options_parse_config
|
||||
ssh_bind_options_set
|
||||
ssh_bind_set_blocking
|
||||
ssh_bind_set_callbacks
|
||||
ssh_bind_set_fd
|
||||
ssh_blocking_flush
|
||||
ssh_buffer_add_data
|
||||
ssh_buffer_free
|
||||
ssh_buffer_get
|
||||
ssh_buffer_get_data
|
||||
ssh_buffer_get_len
|
||||
ssh_buffer_new
|
||||
ssh_buffer_reinit
|
||||
ssh_channel_accept_forward
|
||||
ssh_channel_accept_x11
|
||||
ssh_channel_cancel_forward
|
||||
ssh_channel_change_pty_size
|
||||
ssh_channel_close
|
||||
ssh_channel_free
|
||||
ssh_channel_get_exit_state
|
||||
ssh_channel_get_exit_status
|
||||
ssh_channel_get_session
|
||||
ssh_channel_is_closed
|
||||
ssh_channel_is_eof
|
||||
ssh_channel_is_open
|
||||
ssh_channel_listen_forward
|
||||
ssh_channel_new
|
||||
ssh_channel_open_auth_agent
|
||||
ssh_channel_open_forward
|
||||
ssh_channel_open_forward_port
|
||||
ssh_channel_open_forward_unix
|
||||
ssh_channel_open_reverse_forward
|
||||
ssh_channel_open_session
|
||||
ssh_channel_open_x11
|
||||
ssh_channel_poll
|
||||
ssh_channel_poll_timeout
|
||||
ssh_channel_read
|
||||
ssh_channel_read_nonblocking
|
||||
ssh_channel_read_timeout
|
||||
ssh_channel_request_auth_agent
|
||||
ssh_channel_request_env
|
||||
ssh_channel_request_exec
|
||||
ssh_channel_request_pty
|
||||
ssh_channel_request_pty_size
|
||||
ssh_channel_request_pty_size_modes
|
||||
ssh_channel_request_send_break
|
||||
ssh_channel_request_send_exit_signal
|
||||
ssh_channel_request_send_exit_status
|
||||
ssh_channel_request_send_signal
|
||||
ssh_channel_request_sftp
|
||||
ssh_channel_request_shell
|
||||
ssh_channel_request_subsystem
|
||||
ssh_channel_request_x11
|
||||
ssh_channel_select
|
||||
ssh_channel_send_eof
|
||||
ssh_channel_set_blocking
|
||||
ssh_channel_set_counter
|
||||
ssh_channel_window_size
|
||||
ssh_channel_write
|
||||
ssh_channel_write_stderr
|
||||
ssh_clean_pubkey_hash
|
||||
ssh_connect
|
||||
ssh_connector_free
|
||||
ssh_connector_new
|
||||
ssh_connector_set_in_channel
|
||||
ssh_connector_set_in_fd
|
||||
ssh_connector_set_out_channel
|
||||
ssh_connector_set_out_fd
|
||||
ssh_copyright
|
||||
ssh_dirname
|
||||
ssh_disconnect
|
||||
ssh_dump_knownhost
|
||||
ssh_event_add_connector
|
||||
ssh_event_add_fd
|
||||
ssh_event_add_session
|
||||
ssh_event_dopoll
|
||||
ssh_event_free
|
||||
ssh_event_new
|
||||
ssh_event_remove_connector
|
||||
ssh_event_remove_fd
|
||||
ssh_event_remove_session
|
||||
ssh_execute_message_callbacks
|
||||
ssh_finalize
|
||||
ssh_forward_accept
|
||||
ssh_forward_cancel
|
||||
ssh_forward_listen
|
||||
ssh_free
|
||||
ssh_get_cipher_in
|
||||
ssh_get_cipher_out
|
||||
ssh_get_clientbanner
|
||||
ssh_get_disconnect_message
|
||||
ssh_get_error
|
||||
ssh_get_error_code
|
||||
ssh_get_fd
|
||||
ssh_get_fingerprint_hash
|
||||
ssh_get_hexa
|
||||
ssh_get_hmac_in
|
||||
ssh_get_hmac_out
|
||||
ssh_get_issue_banner
|
||||
ssh_get_kex_algo
|
||||
ssh_get_log_callback
|
||||
ssh_get_log_level
|
||||
ssh_get_log_userdata
|
||||
ssh_get_openssh_version
|
||||
ssh_get_poll_flags
|
||||
ssh_get_pubkey
|
||||
ssh_get_pubkey_hash
|
||||
ssh_get_publickey
|
||||
ssh_get_publickey_hash
|
||||
ssh_get_random
|
||||
ssh_get_server_publickey
|
||||
ssh_get_serverbanner
|
||||
ssh_get_status
|
||||
ssh_get_version
|
||||
ssh_getpass
|
||||
ssh_gssapi_get_creds
|
||||
ssh_gssapi_set_creds
|
||||
ssh_handle_key_exchange
|
||||
ssh_init
|
||||
ssh_is_blocking
|
||||
ssh_is_connected
|
||||
ssh_is_server_known
|
||||
ssh_key_cmp
|
||||
ssh_key_dup
|
||||
ssh_key_free
|
||||
ssh_key_is_private
|
||||
ssh_key_is_public
|
||||
ssh_key_new
|
||||
ssh_key_type
|
||||
ssh_key_type_from_name
|
||||
ssh_key_type_to_char
|
||||
ssh_known_hosts_parse_line
|
||||
ssh_knownhosts_entry_free
|
||||
ssh_log
|
||||
ssh_message_auth_interactive_request
|
||||
ssh_message_auth_kbdint_is_response
|
||||
ssh_message_auth_password
|
||||
ssh_message_auth_pubkey
|
||||
ssh_message_auth_publickey
|
||||
ssh_message_auth_publickey_state
|
||||
ssh_message_auth_reply_pk_ok
|
||||
ssh_message_auth_reply_pk_ok_simple
|
||||
ssh_message_auth_reply_success
|
||||
ssh_message_auth_set_methods
|
||||
ssh_message_auth_user
|
||||
ssh_message_channel_request_channel
|
||||
ssh_message_channel_request_command
|
||||
ssh_message_channel_request_env_name
|
||||
ssh_message_channel_request_env_value
|
||||
ssh_message_channel_request_open_destination
|
||||
ssh_message_channel_request_open_destination_port
|
||||
ssh_message_channel_request_open_originator
|
||||
ssh_message_channel_request_open_originator_port
|
||||
ssh_message_channel_request_open_reply_accept
|
||||
ssh_message_channel_request_open_reply_accept_channel
|
||||
ssh_message_channel_request_pty_height
|
||||
ssh_message_channel_request_pty_pxheight
|
||||
ssh_message_channel_request_pty_pxwidth
|
||||
ssh_message_channel_request_pty_term
|
||||
ssh_message_channel_request_pty_width
|
||||
ssh_message_channel_request_reply_success
|
||||
ssh_message_channel_request_subsystem
|
||||
ssh_message_channel_request_x11_auth_cookie
|
||||
ssh_message_channel_request_x11_auth_protocol
|
||||
ssh_message_channel_request_x11_screen_number
|
||||
ssh_message_channel_request_x11_single_connection
|
||||
ssh_message_free
|
||||
ssh_message_get
|
||||
ssh_message_global_request_address
|
||||
ssh_message_global_request_port
|
||||
ssh_message_global_request_reply_success
|
||||
ssh_message_reply_default
|
||||
ssh_message_retrieve
|
||||
ssh_message_service_reply_success
|
||||
ssh_message_service_service
|
||||
ssh_message_subtype
|
||||
ssh_message_type
|
||||
ssh_mkdir
|
||||
ssh_new
|
||||
ssh_options_copy
|
||||
ssh_options_get
|
||||
ssh_options_get_port
|
||||
ssh_options_getopt
|
||||
ssh_options_parse_config
|
||||
ssh_options_set
|
||||
ssh_pcap_file_close
|
||||
ssh_pcap_file_free
|
||||
ssh_pcap_file_new
|
||||
ssh_pcap_file_open
|
||||
ssh_pki_copy_cert_to_privkey
|
||||
ssh_pki_export_privkey_base64
|
||||
ssh_pki_export_privkey_base64_format
|
||||
ssh_pki_export_privkey_file
|
||||
ssh_pki_export_privkey_file_format
|
||||
ssh_pki_export_privkey_to_pubkey
|
||||
ssh_pki_export_pubkey_base64
|
||||
ssh_pki_export_pubkey_file
|
||||
ssh_pki_generate
|
||||
ssh_pki_import_cert_base64
|
||||
ssh_pki_import_cert_file
|
||||
ssh_pki_import_privkey_base64
|
||||
ssh_pki_import_privkey_file
|
||||
ssh_pki_import_pubkey_base64
|
||||
ssh_pki_import_pubkey_file
|
||||
ssh_pki_key_ecdsa_name
|
||||
ssh_print_hash
|
||||
ssh_print_hexa
|
||||
ssh_privatekey_type
|
||||
ssh_publickey_to_file
|
||||
ssh_remove_channel_callbacks
|
||||
ssh_request_no_more_sessions
|
||||
ssh_scp_accept_request
|
||||
ssh_scp_close
|
||||
ssh_scp_deny_request
|
||||
ssh_scp_free
|
||||
ssh_scp_init
|
||||
ssh_scp_leave_directory
|
||||
ssh_scp_new
|
||||
ssh_scp_pull_request
|
||||
ssh_scp_push_directory
|
||||
ssh_scp_push_file
|
||||
ssh_scp_push_file64
|
||||
ssh_scp_read
|
||||
ssh_scp_request_get_filename
|
||||
ssh_scp_request_get_permissions
|
||||
ssh_scp_request_get_size
|
||||
ssh_scp_request_get_size64
|
||||
ssh_scp_request_get_warning
|
||||
ssh_scp_write
|
||||
ssh_select
|
||||
ssh_send_debug
|
||||
ssh_send_ignore
|
||||
ssh_send_issue_banner
|
||||
ssh_send_keepalive
|
||||
ssh_server_init_kex
|
||||
ssh_service_request
|
||||
ssh_session_export_known_hosts_entry
|
||||
ssh_session_get_known_hosts_entry
|
||||
ssh_session_has_known_hosts_entry
|
||||
ssh_session_is_known_server
|
||||
ssh_session_set_disconnect_message
|
||||
ssh_session_update_known_hosts
|
||||
ssh_set_agent_channel
|
||||
ssh_set_agent_socket
|
||||
ssh_set_auth_methods
|
||||
ssh_set_blocking
|
||||
ssh_set_callbacks
|
||||
ssh_set_channel_callbacks
|
||||
ssh_set_counters
|
||||
ssh_set_fd_except
|
||||
ssh_set_fd_toread
|
||||
ssh_set_fd_towrite
|
||||
ssh_set_log_callback
|
||||
ssh_set_log_level
|
||||
ssh_set_log_userdata
|
||||
ssh_set_message_callback
|
||||
ssh_set_pcap_file
|
||||
ssh_set_server_callbacks
|
||||
ssh_silent_disconnect
|
||||
ssh_string_burn
|
||||
ssh_string_copy
|
||||
ssh_string_data
|
||||
ssh_string_fill
|
||||
ssh_string_free
|
||||
ssh_string_free_char
|
||||
ssh_string_from_char
|
||||
ssh_string_get_char
|
||||
ssh_string_len
|
||||
ssh_string_new
|
||||
ssh_string_to_char
|
||||
ssh_threads_get_default
|
||||
ssh_threads_get_noop
|
||||
ssh_threads_get_pthread
|
||||
ssh_threads_set_callbacks
|
||||
ssh_try_publickey_from_file
|
||||
ssh_userauth_agent
|
||||
ssh_userauth_agent_pubkey
|
||||
ssh_userauth_autopubkey
|
||||
ssh_userauth_gssapi
|
||||
ssh_userauth_kbdint
|
||||
ssh_userauth_kbdint_getanswer
|
||||
ssh_userauth_kbdint_getinstruction
|
||||
ssh_userauth_kbdint_getname
|
||||
ssh_userauth_kbdint_getnanswers
|
||||
ssh_userauth_kbdint_getnprompts
|
||||
ssh_userauth_kbdint_getprompt
|
||||
ssh_userauth_kbdint_setanswer
|
||||
ssh_userauth_list
|
||||
ssh_userauth_none
|
||||
ssh_userauth_offer_pubkey
|
||||
ssh_userauth_password
|
||||
ssh_userauth_privatekey_file
|
||||
ssh_userauth_pubkey
|
||||
ssh_userauth_publickey
|
||||
ssh_userauth_publickey_auto
|
||||
ssh_userauth_publickey_auto_get_current_identity
|
||||
ssh_userauth_try_publickey
|
||||
ssh_version
|
||||
ssh_vlog
|
||||
ssh_write_knownhost
|
||||
string_burn
|
||||
string_copy
|
||||
string_data
|
||||
string_fill
|
||||
string_free
|
||||
string_from_char
|
||||
string_len
|
||||
string_new
|
||||
string_to_char
|
||||
445
src/ABI/libssh-4.10.2.symbols
Normal file
445
src/ABI/libssh-4.10.2.symbols
Normal file
@@ -0,0 +1,445 @@
|
||||
_ssh_log
|
||||
buffer_free
|
||||
buffer_get
|
||||
buffer_get_len
|
||||
buffer_new
|
||||
channel_accept_x11
|
||||
channel_change_pty_size
|
||||
channel_close
|
||||
channel_forward_accept
|
||||
channel_forward_cancel
|
||||
channel_forward_listen
|
||||
channel_free
|
||||
channel_get_exit_status
|
||||
channel_get_session
|
||||
channel_is_closed
|
||||
channel_is_eof
|
||||
channel_is_open
|
||||
channel_new
|
||||
channel_open_forward
|
||||
channel_open_session
|
||||
channel_poll
|
||||
channel_read
|
||||
channel_read_buffer
|
||||
channel_read_nonblocking
|
||||
channel_request_env
|
||||
channel_request_exec
|
||||
channel_request_pty
|
||||
channel_request_pty_size
|
||||
channel_request_send_signal
|
||||
channel_request_sftp
|
||||
channel_request_shell
|
||||
channel_request_subsystem
|
||||
channel_request_x11
|
||||
channel_select
|
||||
channel_send_eof
|
||||
channel_set_blocking
|
||||
channel_write
|
||||
channel_write_stderr
|
||||
privatekey_free
|
||||
privatekey_from_file
|
||||
publickey_free
|
||||
publickey_from_file
|
||||
publickey_from_privatekey
|
||||
publickey_to_string
|
||||
sftp_aio_begin_read
|
||||
sftp_aio_begin_write
|
||||
sftp_aio_free
|
||||
sftp_aio_wait_read
|
||||
sftp_aio_wait_write
|
||||
sftp_async_read
|
||||
sftp_async_read_begin
|
||||
sftp_attributes_free
|
||||
sftp_canonicalize_path
|
||||
sftp_channel_default_data_callback
|
||||
sftp_channel_default_subsystem_request
|
||||
sftp_chmod
|
||||
sftp_chown
|
||||
sftp_client_message_free
|
||||
sftp_client_message_get_data
|
||||
sftp_client_message_get_filename
|
||||
sftp_client_message_get_flags
|
||||
sftp_client_message_get_submessage
|
||||
sftp_client_message_get_type
|
||||
sftp_client_message_set_filename
|
||||
sftp_close
|
||||
sftp_closedir
|
||||
sftp_dir_eof
|
||||
sftp_expand_path
|
||||
sftp_extension_supported
|
||||
sftp_extensions_get_count
|
||||
sftp_extensions_get_data
|
||||
sftp_extensions_get_name
|
||||
sftp_file_set_blocking
|
||||
sftp_file_set_nonblocking
|
||||
sftp_free
|
||||
sftp_fstat
|
||||
sftp_fstatvfs
|
||||
sftp_fsync
|
||||
sftp_get_client_message
|
||||
sftp_get_error
|
||||
sftp_handle
|
||||
sftp_handle_alloc
|
||||
sftp_handle_remove
|
||||
sftp_hardlink
|
||||
sftp_home_directory
|
||||
sftp_init
|
||||
sftp_limits
|
||||
sftp_limits_free
|
||||
sftp_lsetstat
|
||||
sftp_lstat
|
||||
sftp_mkdir
|
||||
sftp_new
|
||||
sftp_new_channel
|
||||
sftp_open
|
||||
sftp_opendir
|
||||
sftp_read
|
||||
sftp_readdir
|
||||
sftp_readlink
|
||||
sftp_rename
|
||||
sftp_reply_attr
|
||||
sftp_reply_data
|
||||
sftp_reply_handle
|
||||
sftp_reply_name
|
||||
sftp_reply_names
|
||||
sftp_reply_names_add
|
||||
sftp_reply_status
|
||||
sftp_rewind
|
||||
sftp_rmdir
|
||||
sftp_seek
|
||||
sftp_seek64
|
||||
sftp_send_client_message
|
||||
sftp_server_free
|
||||
sftp_server_init
|
||||
sftp_server_new
|
||||
sftp_server_version
|
||||
sftp_setstat
|
||||
sftp_stat
|
||||
sftp_statvfs
|
||||
sftp_statvfs_free
|
||||
sftp_symlink
|
||||
sftp_tell
|
||||
sftp_tell64
|
||||
sftp_unlink
|
||||
sftp_utimes
|
||||
sftp_write
|
||||
ssh_accept
|
||||
ssh_add_channel_callbacks
|
||||
ssh_auth_list
|
||||
ssh_basename
|
||||
ssh_bind_accept
|
||||
ssh_bind_accept_fd
|
||||
ssh_bind_fd_toaccept
|
||||
ssh_bind_free
|
||||
ssh_bind_get_fd
|
||||
ssh_bind_listen
|
||||
ssh_bind_new
|
||||
ssh_bind_options_parse_config
|
||||
ssh_bind_options_set
|
||||
ssh_bind_set_blocking
|
||||
ssh_bind_set_callbacks
|
||||
ssh_bind_set_fd
|
||||
ssh_blocking_flush
|
||||
ssh_buffer_add_data
|
||||
ssh_buffer_free
|
||||
ssh_buffer_get
|
||||
ssh_buffer_get_data
|
||||
ssh_buffer_get_len
|
||||
ssh_buffer_new
|
||||
ssh_buffer_reinit
|
||||
ssh_channel_accept_forward
|
||||
ssh_channel_accept_x11
|
||||
ssh_channel_cancel_forward
|
||||
ssh_channel_change_pty_size
|
||||
ssh_channel_close
|
||||
ssh_channel_free
|
||||
ssh_channel_get_exit_state
|
||||
ssh_channel_get_exit_status
|
||||
ssh_channel_get_session
|
||||
ssh_channel_is_closed
|
||||
ssh_channel_is_eof
|
||||
ssh_channel_is_open
|
||||
ssh_channel_listen_forward
|
||||
ssh_channel_new
|
||||
ssh_channel_open_auth_agent
|
||||
ssh_channel_open_forward
|
||||
ssh_channel_open_forward_port
|
||||
ssh_channel_open_forward_unix
|
||||
ssh_channel_open_reverse_forward
|
||||
ssh_channel_open_session
|
||||
ssh_channel_open_x11
|
||||
ssh_channel_poll
|
||||
ssh_channel_poll_timeout
|
||||
ssh_channel_read
|
||||
ssh_channel_read_nonblocking
|
||||
ssh_channel_read_timeout
|
||||
ssh_channel_request_auth_agent
|
||||
ssh_channel_request_env
|
||||
ssh_channel_request_exec
|
||||
ssh_channel_request_pty
|
||||
ssh_channel_request_pty_size
|
||||
ssh_channel_request_pty_size_modes
|
||||
ssh_channel_request_send_break
|
||||
ssh_channel_request_send_exit_signal
|
||||
ssh_channel_request_send_exit_status
|
||||
ssh_channel_request_send_signal
|
||||
ssh_channel_request_sftp
|
||||
ssh_channel_request_shell
|
||||
ssh_channel_request_subsystem
|
||||
ssh_channel_request_x11
|
||||
ssh_channel_select
|
||||
ssh_channel_send_eof
|
||||
ssh_channel_set_blocking
|
||||
ssh_channel_set_counter
|
||||
ssh_channel_window_size
|
||||
ssh_channel_write
|
||||
ssh_channel_write_stderr
|
||||
ssh_clean_pubkey_hash
|
||||
ssh_connect
|
||||
ssh_connector_free
|
||||
ssh_connector_new
|
||||
ssh_connector_set_in_channel
|
||||
ssh_connector_set_in_fd
|
||||
ssh_connector_set_out_channel
|
||||
ssh_connector_set_out_fd
|
||||
ssh_copyright
|
||||
ssh_dirname
|
||||
ssh_disconnect
|
||||
ssh_dump_knownhost
|
||||
ssh_event_add_connector
|
||||
ssh_event_add_fd
|
||||
ssh_event_add_session
|
||||
ssh_event_dopoll
|
||||
ssh_event_free
|
||||
ssh_event_new
|
||||
ssh_event_remove_connector
|
||||
ssh_event_remove_fd
|
||||
ssh_event_remove_session
|
||||
ssh_execute_message_callbacks
|
||||
ssh_finalize
|
||||
ssh_forward_accept
|
||||
ssh_forward_cancel
|
||||
ssh_forward_listen
|
||||
ssh_free
|
||||
ssh_get_cipher_in
|
||||
ssh_get_cipher_out
|
||||
ssh_get_clientbanner
|
||||
ssh_get_disconnect_message
|
||||
ssh_get_error
|
||||
ssh_get_error_code
|
||||
ssh_get_fd
|
||||
ssh_get_fingerprint_hash
|
||||
ssh_get_hexa
|
||||
ssh_get_hmac_in
|
||||
ssh_get_hmac_out
|
||||
ssh_get_issue_banner
|
||||
ssh_get_kex_algo
|
||||
ssh_get_log_callback
|
||||
ssh_get_log_level
|
||||
ssh_get_log_userdata
|
||||
ssh_get_openssh_version
|
||||
ssh_get_poll_flags
|
||||
ssh_get_pubkey
|
||||
ssh_get_pubkey_hash
|
||||
ssh_get_publickey
|
||||
ssh_get_publickey_hash
|
||||
ssh_get_random
|
||||
ssh_get_server_publickey
|
||||
ssh_get_serverbanner
|
||||
ssh_get_status
|
||||
ssh_get_version
|
||||
ssh_getpass
|
||||
ssh_gssapi_get_creds
|
||||
ssh_gssapi_set_creds
|
||||
ssh_handle_key_exchange
|
||||
ssh_init
|
||||
ssh_is_blocking
|
||||
ssh_is_connected
|
||||
ssh_is_server_known
|
||||
ssh_key_cmp
|
||||
ssh_key_dup
|
||||
ssh_key_free
|
||||
ssh_key_is_private
|
||||
ssh_key_is_public
|
||||
ssh_key_new
|
||||
ssh_key_type
|
||||
ssh_key_type_from_name
|
||||
ssh_key_type_to_char
|
||||
ssh_known_hosts_parse_line
|
||||
ssh_knownhosts_entry_free
|
||||
ssh_log
|
||||
ssh_message_auth_interactive_request
|
||||
ssh_message_auth_kbdint_is_response
|
||||
ssh_message_auth_password
|
||||
ssh_message_auth_pubkey
|
||||
ssh_message_auth_publickey
|
||||
ssh_message_auth_publickey_state
|
||||
ssh_message_auth_reply_pk_ok
|
||||
ssh_message_auth_reply_pk_ok_simple
|
||||
ssh_message_auth_reply_success
|
||||
ssh_message_auth_set_methods
|
||||
ssh_message_auth_user
|
||||
ssh_message_channel_request_channel
|
||||
ssh_message_channel_request_command
|
||||
ssh_message_channel_request_env_name
|
||||
ssh_message_channel_request_env_value
|
||||
ssh_message_channel_request_open_destination
|
||||
ssh_message_channel_request_open_destination_port
|
||||
ssh_message_channel_request_open_originator
|
||||
ssh_message_channel_request_open_originator_port
|
||||
ssh_message_channel_request_open_reply_accept
|
||||
ssh_message_channel_request_open_reply_accept_channel
|
||||
ssh_message_channel_request_pty_height
|
||||
ssh_message_channel_request_pty_pxheight
|
||||
ssh_message_channel_request_pty_pxwidth
|
||||
ssh_message_channel_request_pty_term
|
||||
ssh_message_channel_request_pty_width
|
||||
ssh_message_channel_request_reply_success
|
||||
ssh_message_channel_request_subsystem
|
||||
ssh_message_channel_request_x11_auth_cookie
|
||||
ssh_message_channel_request_x11_auth_protocol
|
||||
ssh_message_channel_request_x11_screen_number
|
||||
ssh_message_channel_request_x11_single_connection
|
||||
ssh_message_free
|
||||
ssh_message_get
|
||||
ssh_message_global_request_address
|
||||
ssh_message_global_request_port
|
||||
ssh_message_global_request_reply_success
|
||||
ssh_message_reply_default
|
||||
ssh_message_retrieve
|
||||
ssh_message_service_reply_success
|
||||
ssh_message_service_service
|
||||
ssh_message_subtype
|
||||
ssh_message_type
|
||||
ssh_mkdir
|
||||
ssh_new
|
||||
ssh_options_copy
|
||||
ssh_options_get
|
||||
ssh_options_get_port
|
||||
ssh_options_getopt
|
||||
ssh_options_parse_config
|
||||
ssh_options_set
|
||||
ssh_pcap_file_close
|
||||
ssh_pcap_file_free
|
||||
ssh_pcap_file_new
|
||||
ssh_pcap_file_open
|
||||
ssh_pki_copy_cert_to_privkey
|
||||
ssh_pki_export_privkey_base64
|
||||
ssh_pki_export_privkey_base64_format
|
||||
ssh_pki_export_privkey_file
|
||||
ssh_pki_export_privkey_file_format
|
||||
ssh_pki_export_privkey_to_pubkey
|
||||
ssh_pki_export_pubkey_base64
|
||||
ssh_pki_export_pubkey_file
|
||||
ssh_pki_generate
|
||||
ssh_pki_import_cert_base64
|
||||
ssh_pki_import_cert_file
|
||||
ssh_pki_import_privkey_base64
|
||||
ssh_pki_import_privkey_file
|
||||
ssh_pki_import_pubkey_base64
|
||||
ssh_pki_import_pubkey_file
|
||||
ssh_pki_key_ecdsa_name
|
||||
ssh_print_hash
|
||||
ssh_print_hexa
|
||||
ssh_privatekey_type
|
||||
ssh_publickey_to_file
|
||||
ssh_remove_channel_callbacks
|
||||
ssh_request_no_more_sessions
|
||||
ssh_scp_accept_request
|
||||
ssh_scp_close
|
||||
ssh_scp_deny_request
|
||||
ssh_scp_free
|
||||
ssh_scp_init
|
||||
ssh_scp_leave_directory
|
||||
ssh_scp_new
|
||||
ssh_scp_pull_request
|
||||
ssh_scp_push_directory
|
||||
ssh_scp_push_file
|
||||
ssh_scp_push_file64
|
||||
ssh_scp_read
|
||||
ssh_scp_request_get_filename
|
||||
ssh_scp_request_get_permissions
|
||||
ssh_scp_request_get_size
|
||||
ssh_scp_request_get_size64
|
||||
ssh_scp_request_get_warning
|
||||
ssh_scp_write
|
||||
ssh_select
|
||||
ssh_send_debug
|
||||
ssh_send_ignore
|
||||
ssh_send_issue_banner
|
||||
ssh_send_keepalive
|
||||
ssh_server_init_kex
|
||||
ssh_service_request
|
||||
ssh_session_export_known_hosts_entry
|
||||
ssh_session_get_known_hosts_entry
|
||||
ssh_session_has_known_hosts_entry
|
||||
ssh_session_is_known_server
|
||||
ssh_session_set_disconnect_message
|
||||
ssh_session_update_known_hosts
|
||||
ssh_set_agent_channel
|
||||
ssh_set_agent_socket
|
||||
ssh_set_auth_methods
|
||||
ssh_set_blocking
|
||||
ssh_set_callbacks
|
||||
ssh_set_channel_callbacks
|
||||
ssh_set_counters
|
||||
ssh_set_fd_except
|
||||
ssh_set_fd_toread
|
||||
ssh_set_fd_towrite
|
||||
ssh_set_log_callback
|
||||
ssh_set_log_level
|
||||
ssh_set_log_userdata
|
||||
ssh_set_message_callback
|
||||
ssh_set_pcap_file
|
||||
ssh_set_server_callbacks
|
||||
ssh_silent_disconnect
|
||||
ssh_string_burn
|
||||
ssh_string_copy
|
||||
ssh_string_data
|
||||
ssh_string_fill
|
||||
ssh_string_free
|
||||
ssh_string_free_char
|
||||
ssh_string_from_char
|
||||
ssh_string_get_char
|
||||
ssh_string_len
|
||||
ssh_string_new
|
||||
ssh_string_to_char
|
||||
ssh_threads_get_default
|
||||
ssh_threads_get_noop
|
||||
ssh_threads_get_pthread
|
||||
ssh_threads_set_callbacks
|
||||
ssh_try_publickey_from_file
|
||||
ssh_userauth_agent
|
||||
ssh_userauth_agent_pubkey
|
||||
ssh_userauth_autopubkey
|
||||
ssh_userauth_gssapi
|
||||
ssh_userauth_kbdint
|
||||
ssh_userauth_kbdint_getanswer
|
||||
ssh_userauth_kbdint_getinstruction
|
||||
ssh_userauth_kbdint_getname
|
||||
ssh_userauth_kbdint_getnanswers
|
||||
ssh_userauth_kbdint_getnprompts
|
||||
ssh_userauth_kbdint_getprompt
|
||||
ssh_userauth_kbdint_setanswer
|
||||
ssh_userauth_list
|
||||
ssh_userauth_none
|
||||
ssh_userauth_offer_pubkey
|
||||
ssh_userauth_password
|
||||
ssh_userauth_privatekey_file
|
||||
ssh_userauth_pubkey
|
||||
ssh_userauth_publickey
|
||||
ssh_userauth_publickey_auto
|
||||
ssh_userauth_publickey_auto_get_current_identity
|
||||
ssh_userauth_try_publickey
|
||||
ssh_version
|
||||
ssh_vlog
|
||||
ssh_write_knownhost
|
||||
string_burn
|
||||
string_copy
|
||||
string_data
|
||||
string_fill
|
||||
string_free
|
||||
string_from_char
|
||||
string_len
|
||||
string_new
|
||||
string_to_char
|
||||
445
src/ABI/libssh-4.10.3.symbols
Normal file
445
src/ABI/libssh-4.10.3.symbols
Normal file
@@ -0,0 +1,445 @@
|
||||
_ssh_log
|
||||
buffer_free
|
||||
buffer_get
|
||||
buffer_get_len
|
||||
buffer_new
|
||||
channel_accept_x11
|
||||
channel_change_pty_size
|
||||
channel_close
|
||||
channel_forward_accept
|
||||
channel_forward_cancel
|
||||
channel_forward_listen
|
||||
channel_free
|
||||
channel_get_exit_status
|
||||
channel_get_session
|
||||
channel_is_closed
|
||||
channel_is_eof
|
||||
channel_is_open
|
||||
channel_new
|
||||
channel_open_forward
|
||||
channel_open_session
|
||||
channel_poll
|
||||
channel_read
|
||||
channel_read_buffer
|
||||
channel_read_nonblocking
|
||||
channel_request_env
|
||||
channel_request_exec
|
||||
channel_request_pty
|
||||
channel_request_pty_size
|
||||
channel_request_send_signal
|
||||
channel_request_sftp
|
||||
channel_request_shell
|
||||
channel_request_subsystem
|
||||
channel_request_x11
|
||||
channel_select
|
||||
channel_send_eof
|
||||
channel_set_blocking
|
||||
channel_write
|
||||
channel_write_stderr
|
||||
privatekey_free
|
||||
privatekey_from_file
|
||||
publickey_free
|
||||
publickey_from_file
|
||||
publickey_from_privatekey
|
||||
publickey_to_string
|
||||
sftp_aio_begin_read
|
||||
sftp_aio_begin_write
|
||||
sftp_aio_free
|
||||
sftp_aio_wait_read
|
||||
sftp_aio_wait_write
|
||||
sftp_async_read
|
||||
sftp_async_read_begin
|
||||
sftp_attributes_free
|
||||
sftp_canonicalize_path
|
||||
sftp_channel_default_data_callback
|
||||
sftp_channel_default_subsystem_request
|
||||
sftp_chmod
|
||||
sftp_chown
|
||||
sftp_client_message_free
|
||||
sftp_client_message_get_data
|
||||
sftp_client_message_get_filename
|
||||
sftp_client_message_get_flags
|
||||
sftp_client_message_get_submessage
|
||||
sftp_client_message_get_type
|
||||
sftp_client_message_set_filename
|
||||
sftp_close
|
||||
sftp_closedir
|
||||
sftp_dir_eof
|
||||
sftp_expand_path
|
||||
sftp_extension_supported
|
||||
sftp_extensions_get_count
|
||||
sftp_extensions_get_data
|
||||
sftp_extensions_get_name
|
||||
sftp_file_set_blocking
|
||||
sftp_file_set_nonblocking
|
||||
sftp_free
|
||||
sftp_fstat
|
||||
sftp_fstatvfs
|
||||
sftp_fsync
|
||||
sftp_get_client_message
|
||||
sftp_get_error
|
||||
sftp_handle
|
||||
sftp_handle_alloc
|
||||
sftp_handle_remove
|
||||
sftp_hardlink
|
||||
sftp_home_directory
|
||||
sftp_init
|
||||
sftp_limits
|
||||
sftp_limits_free
|
||||
sftp_lsetstat
|
||||
sftp_lstat
|
||||
sftp_mkdir
|
||||
sftp_new
|
||||
sftp_new_channel
|
||||
sftp_open
|
||||
sftp_opendir
|
||||
sftp_read
|
||||
sftp_readdir
|
||||
sftp_readlink
|
||||
sftp_rename
|
||||
sftp_reply_attr
|
||||
sftp_reply_data
|
||||
sftp_reply_handle
|
||||
sftp_reply_name
|
||||
sftp_reply_names
|
||||
sftp_reply_names_add
|
||||
sftp_reply_status
|
||||
sftp_rewind
|
||||
sftp_rmdir
|
||||
sftp_seek
|
||||
sftp_seek64
|
||||
sftp_send_client_message
|
||||
sftp_server_free
|
||||
sftp_server_init
|
||||
sftp_server_new
|
||||
sftp_server_version
|
||||
sftp_setstat
|
||||
sftp_stat
|
||||
sftp_statvfs
|
||||
sftp_statvfs_free
|
||||
sftp_symlink
|
||||
sftp_tell
|
||||
sftp_tell64
|
||||
sftp_unlink
|
||||
sftp_utimes
|
||||
sftp_write
|
||||
ssh_accept
|
||||
ssh_add_channel_callbacks
|
||||
ssh_auth_list
|
||||
ssh_basename
|
||||
ssh_bind_accept
|
||||
ssh_bind_accept_fd
|
||||
ssh_bind_fd_toaccept
|
||||
ssh_bind_free
|
||||
ssh_bind_get_fd
|
||||
ssh_bind_listen
|
||||
ssh_bind_new
|
||||
ssh_bind_options_parse_config
|
||||
ssh_bind_options_set
|
||||
ssh_bind_set_blocking
|
||||
ssh_bind_set_callbacks
|
||||
ssh_bind_set_fd
|
||||
ssh_blocking_flush
|
||||
ssh_buffer_add_data
|
||||
ssh_buffer_free
|
||||
ssh_buffer_get
|
||||
ssh_buffer_get_data
|
||||
ssh_buffer_get_len
|
||||
ssh_buffer_new
|
||||
ssh_buffer_reinit
|
||||
ssh_channel_accept_forward
|
||||
ssh_channel_accept_x11
|
||||
ssh_channel_cancel_forward
|
||||
ssh_channel_change_pty_size
|
||||
ssh_channel_close
|
||||
ssh_channel_free
|
||||
ssh_channel_get_exit_state
|
||||
ssh_channel_get_exit_status
|
||||
ssh_channel_get_session
|
||||
ssh_channel_is_closed
|
||||
ssh_channel_is_eof
|
||||
ssh_channel_is_open
|
||||
ssh_channel_listen_forward
|
||||
ssh_channel_new
|
||||
ssh_channel_open_auth_agent
|
||||
ssh_channel_open_forward
|
||||
ssh_channel_open_forward_port
|
||||
ssh_channel_open_forward_unix
|
||||
ssh_channel_open_reverse_forward
|
||||
ssh_channel_open_session
|
||||
ssh_channel_open_x11
|
||||
ssh_channel_poll
|
||||
ssh_channel_poll_timeout
|
||||
ssh_channel_read
|
||||
ssh_channel_read_nonblocking
|
||||
ssh_channel_read_timeout
|
||||
ssh_channel_request_auth_agent
|
||||
ssh_channel_request_env
|
||||
ssh_channel_request_exec
|
||||
ssh_channel_request_pty
|
||||
ssh_channel_request_pty_size
|
||||
ssh_channel_request_pty_size_modes
|
||||
ssh_channel_request_send_break
|
||||
ssh_channel_request_send_exit_signal
|
||||
ssh_channel_request_send_exit_status
|
||||
ssh_channel_request_send_signal
|
||||
ssh_channel_request_sftp
|
||||
ssh_channel_request_shell
|
||||
ssh_channel_request_subsystem
|
||||
ssh_channel_request_x11
|
||||
ssh_channel_select
|
||||
ssh_channel_send_eof
|
||||
ssh_channel_set_blocking
|
||||
ssh_channel_set_counter
|
||||
ssh_channel_window_size
|
||||
ssh_channel_write
|
||||
ssh_channel_write_stderr
|
||||
ssh_clean_pubkey_hash
|
||||
ssh_connect
|
||||
ssh_connector_free
|
||||
ssh_connector_new
|
||||
ssh_connector_set_in_channel
|
||||
ssh_connector_set_in_fd
|
||||
ssh_connector_set_out_channel
|
||||
ssh_connector_set_out_fd
|
||||
ssh_copyright
|
||||
ssh_dirname
|
||||
ssh_disconnect
|
||||
ssh_dump_knownhost
|
||||
ssh_event_add_connector
|
||||
ssh_event_add_fd
|
||||
ssh_event_add_session
|
||||
ssh_event_dopoll
|
||||
ssh_event_free
|
||||
ssh_event_new
|
||||
ssh_event_remove_connector
|
||||
ssh_event_remove_fd
|
||||
ssh_event_remove_session
|
||||
ssh_execute_message_callbacks
|
||||
ssh_finalize
|
||||
ssh_forward_accept
|
||||
ssh_forward_cancel
|
||||
ssh_forward_listen
|
||||
ssh_free
|
||||
ssh_get_cipher_in
|
||||
ssh_get_cipher_out
|
||||
ssh_get_clientbanner
|
||||
ssh_get_disconnect_message
|
||||
ssh_get_error
|
||||
ssh_get_error_code
|
||||
ssh_get_fd
|
||||
ssh_get_fingerprint_hash
|
||||
ssh_get_hexa
|
||||
ssh_get_hmac_in
|
||||
ssh_get_hmac_out
|
||||
ssh_get_issue_banner
|
||||
ssh_get_kex_algo
|
||||
ssh_get_log_callback
|
||||
ssh_get_log_level
|
||||
ssh_get_log_userdata
|
||||
ssh_get_openssh_version
|
||||
ssh_get_poll_flags
|
||||
ssh_get_pubkey
|
||||
ssh_get_pubkey_hash
|
||||
ssh_get_publickey
|
||||
ssh_get_publickey_hash
|
||||
ssh_get_random
|
||||
ssh_get_server_publickey
|
||||
ssh_get_serverbanner
|
||||
ssh_get_status
|
||||
ssh_get_version
|
||||
ssh_getpass
|
||||
ssh_gssapi_get_creds
|
||||
ssh_gssapi_set_creds
|
||||
ssh_handle_key_exchange
|
||||
ssh_init
|
||||
ssh_is_blocking
|
||||
ssh_is_connected
|
||||
ssh_is_server_known
|
||||
ssh_key_cmp
|
||||
ssh_key_dup
|
||||
ssh_key_free
|
||||
ssh_key_is_private
|
||||
ssh_key_is_public
|
||||
ssh_key_new
|
||||
ssh_key_type
|
||||
ssh_key_type_from_name
|
||||
ssh_key_type_to_char
|
||||
ssh_known_hosts_parse_line
|
||||
ssh_knownhosts_entry_free
|
||||
ssh_log
|
||||
ssh_message_auth_interactive_request
|
||||
ssh_message_auth_kbdint_is_response
|
||||
ssh_message_auth_password
|
||||
ssh_message_auth_pubkey
|
||||
ssh_message_auth_publickey
|
||||
ssh_message_auth_publickey_state
|
||||
ssh_message_auth_reply_pk_ok
|
||||
ssh_message_auth_reply_pk_ok_simple
|
||||
ssh_message_auth_reply_success
|
||||
ssh_message_auth_set_methods
|
||||
ssh_message_auth_user
|
||||
ssh_message_channel_request_channel
|
||||
ssh_message_channel_request_command
|
||||
ssh_message_channel_request_env_name
|
||||
ssh_message_channel_request_env_value
|
||||
ssh_message_channel_request_open_destination
|
||||
ssh_message_channel_request_open_destination_port
|
||||
ssh_message_channel_request_open_originator
|
||||
ssh_message_channel_request_open_originator_port
|
||||
ssh_message_channel_request_open_reply_accept
|
||||
ssh_message_channel_request_open_reply_accept_channel
|
||||
ssh_message_channel_request_pty_height
|
||||
ssh_message_channel_request_pty_pxheight
|
||||
ssh_message_channel_request_pty_pxwidth
|
||||
ssh_message_channel_request_pty_term
|
||||
ssh_message_channel_request_pty_width
|
||||
ssh_message_channel_request_reply_success
|
||||
ssh_message_channel_request_subsystem
|
||||
ssh_message_channel_request_x11_auth_cookie
|
||||
ssh_message_channel_request_x11_auth_protocol
|
||||
ssh_message_channel_request_x11_screen_number
|
||||
ssh_message_channel_request_x11_single_connection
|
||||
ssh_message_free
|
||||
ssh_message_get
|
||||
ssh_message_global_request_address
|
||||
ssh_message_global_request_port
|
||||
ssh_message_global_request_reply_success
|
||||
ssh_message_reply_default
|
||||
ssh_message_retrieve
|
||||
ssh_message_service_reply_success
|
||||
ssh_message_service_service
|
||||
ssh_message_subtype
|
||||
ssh_message_type
|
||||
ssh_mkdir
|
||||
ssh_new
|
||||
ssh_options_copy
|
||||
ssh_options_get
|
||||
ssh_options_get_port
|
||||
ssh_options_getopt
|
||||
ssh_options_parse_config
|
||||
ssh_options_set
|
||||
ssh_pcap_file_close
|
||||
ssh_pcap_file_free
|
||||
ssh_pcap_file_new
|
||||
ssh_pcap_file_open
|
||||
ssh_pki_copy_cert_to_privkey
|
||||
ssh_pki_export_privkey_base64
|
||||
ssh_pki_export_privkey_base64_format
|
||||
ssh_pki_export_privkey_file
|
||||
ssh_pki_export_privkey_file_format
|
||||
ssh_pki_export_privkey_to_pubkey
|
||||
ssh_pki_export_pubkey_base64
|
||||
ssh_pki_export_pubkey_file
|
||||
ssh_pki_generate
|
||||
ssh_pki_import_cert_base64
|
||||
ssh_pki_import_cert_file
|
||||
ssh_pki_import_privkey_base64
|
||||
ssh_pki_import_privkey_file
|
||||
ssh_pki_import_pubkey_base64
|
||||
ssh_pki_import_pubkey_file
|
||||
ssh_pki_key_ecdsa_name
|
||||
ssh_print_hash
|
||||
ssh_print_hexa
|
||||
ssh_privatekey_type
|
||||
ssh_publickey_to_file
|
||||
ssh_remove_channel_callbacks
|
||||
ssh_request_no_more_sessions
|
||||
ssh_scp_accept_request
|
||||
ssh_scp_close
|
||||
ssh_scp_deny_request
|
||||
ssh_scp_free
|
||||
ssh_scp_init
|
||||
ssh_scp_leave_directory
|
||||
ssh_scp_new
|
||||
ssh_scp_pull_request
|
||||
ssh_scp_push_directory
|
||||
ssh_scp_push_file
|
||||
ssh_scp_push_file64
|
||||
ssh_scp_read
|
||||
ssh_scp_request_get_filename
|
||||
ssh_scp_request_get_permissions
|
||||
ssh_scp_request_get_size
|
||||
ssh_scp_request_get_size64
|
||||
ssh_scp_request_get_warning
|
||||
ssh_scp_write
|
||||
ssh_select
|
||||
ssh_send_debug
|
||||
ssh_send_ignore
|
||||
ssh_send_issue_banner
|
||||
ssh_send_keepalive
|
||||
ssh_server_init_kex
|
||||
ssh_service_request
|
||||
ssh_session_export_known_hosts_entry
|
||||
ssh_session_get_known_hosts_entry
|
||||
ssh_session_has_known_hosts_entry
|
||||
ssh_session_is_known_server
|
||||
ssh_session_set_disconnect_message
|
||||
ssh_session_update_known_hosts
|
||||
ssh_set_agent_channel
|
||||
ssh_set_agent_socket
|
||||
ssh_set_auth_methods
|
||||
ssh_set_blocking
|
||||
ssh_set_callbacks
|
||||
ssh_set_channel_callbacks
|
||||
ssh_set_counters
|
||||
ssh_set_fd_except
|
||||
ssh_set_fd_toread
|
||||
ssh_set_fd_towrite
|
||||
ssh_set_log_callback
|
||||
ssh_set_log_level
|
||||
ssh_set_log_userdata
|
||||
ssh_set_message_callback
|
||||
ssh_set_pcap_file
|
||||
ssh_set_server_callbacks
|
||||
ssh_silent_disconnect
|
||||
ssh_string_burn
|
||||
ssh_string_copy
|
||||
ssh_string_data
|
||||
ssh_string_fill
|
||||
ssh_string_free
|
||||
ssh_string_free_char
|
||||
ssh_string_from_char
|
||||
ssh_string_get_char
|
||||
ssh_string_len
|
||||
ssh_string_new
|
||||
ssh_string_to_char
|
||||
ssh_threads_get_default
|
||||
ssh_threads_get_noop
|
||||
ssh_threads_get_pthread
|
||||
ssh_threads_set_callbacks
|
||||
ssh_try_publickey_from_file
|
||||
ssh_userauth_agent
|
||||
ssh_userauth_agent_pubkey
|
||||
ssh_userauth_autopubkey
|
||||
ssh_userauth_gssapi
|
||||
ssh_userauth_kbdint
|
||||
ssh_userauth_kbdint_getanswer
|
||||
ssh_userauth_kbdint_getinstruction
|
||||
ssh_userauth_kbdint_getname
|
||||
ssh_userauth_kbdint_getnanswers
|
||||
ssh_userauth_kbdint_getnprompts
|
||||
ssh_userauth_kbdint_getprompt
|
||||
ssh_userauth_kbdint_setanswer
|
||||
ssh_userauth_list
|
||||
ssh_userauth_none
|
||||
ssh_userauth_offer_pubkey
|
||||
ssh_userauth_password
|
||||
ssh_userauth_privatekey_file
|
||||
ssh_userauth_pubkey
|
||||
ssh_userauth_publickey
|
||||
ssh_userauth_publickey_auto
|
||||
ssh_userauth_publickey_auto_get_current_identity
|
||||
ssh_userauth_try_publickey
|
||||
ssh_version
|
||||
ssh_vlog
|
||||
ssh_write_knownhost
|
||||
string_burn
|
||||
string_copy
|
||||
string_data
|
||||
string_fill
|
||||
string_free
|
||||
string_from_char
|
||||
string_len
|
||||
string_new
|
||||
string_to_char
|
||||
@@ -87,7 +87,6 @@ set(libssh_SRCS
|
||||
connector.c
|
||||
crypto_common.c
|
||||
curve25519.c
|
||||
sntrup761.c
|
||||
dh.c
|
||||
ecdh.c
|
||||
error.c
|
||||
@@ -175,13 +174,6 @@ if (WITH_GCRYPT)
|
||||
chachapoly.c
|
||||
)
|
||||
endif (NOT HAVE_GCRYPT_CHACHA_POLY)
|
||||
|
||||
if (HAVE_GCRYPT_CURVE25519)
|
||||
set(libssh_SRCS
|
||||
${libssh_SRCS}
|
||||
curve25519_gcrypt.c
|
||||
)
|
||||
endif(HAVE_GCRYPT_CURVE25519)
|
||||
elseif (WITH_MBEDTLS)
|
||||
set(libssh_SRCS
|
||||
${libssh_SRCS}
|
||||
@@ -198,7 +190,6 @@ elseif (WITH_MBEDTLS)
|
||||
external/fe25519.c
|
||||
external/ge25519.c
|
||||
external/sc25519.c
|
||||
external/sntrup761.c
|
||||
)
|
||||
if (NOT (HAVE_MBEDTLS_CHACHA20_H AND HAVE_MBEDTLS_POLY1305_H))
|
||||
set(libssh_SRCS
|
||||
@@ -208,24 +199,17 @@ elseif (WITH_MBEDTLS)
|
||||
chachapoly.c
|
||||
)
|
||||
endif()
|
||||
if (HAVE_MBEDTLS_CURVE25519)
|
||||
set(libssh_SRCS
|
||||
${libssh_SRCS}
|
||||
curve25519_mbedcrypto.c
|
||||
)
|
||||
endif(HAVE_MBEDTLS_CURVE25519)
|
||||
|
||||
else (WITH_GCRYPT)
|
||||
set(libssh_SRCS
|
||||
${libssh_SRCS}
|
||||
threads/libcrypto.c
|
||||
pki_crypto.c
|
||||
ecdh_crypto.c
|
||||
curve25519_crypto.c
|
||||
getrandom_crypto.c
|
||||
md_crypto.c
|
||||
libcrypto.c
|
||||
dh_crypto.c
|
||||
external/sntrup761.c
|
||||
)
|
||||
if (NOT HAVE_OPENSSL_EVP_CHACHA20)
|
||||
set(libssh_SRCS
|
||||
@@ -277,10 +261,9 @@ if (WITH_GSSAPI AND GSSAPI_FOUND)
|
||||
endif (WITH_GSSAPI AND GSSAPI_FOUND)
|
||||
|
||||
if (NOT WITH_NACL)
|
||||
if (NOT (HAVE_LIBCRYPTO OR HAVE_MBEDTLS_CURVE25519 OR HAVE_GCRYPT_CURVE25519))
|
||||
if (NOT HAVE_LIBCRYPTO)
|
||||
set(libssh_SRCS
|
||||
${libssh_SRCS}
|
||||
curve25519_fallback.c
|
||||
external/curve25519_ref.c
|
||||
)
|
||||
endif()
|
||||
|
||||
399
src/agent.c
399
src/agent.c
@@ -67,94 +67,87 @@
|
||||
(((x) == SSH_AGENT_FAILURE) || ((x) == SSH_COM_AGENT2_FAILURE) || \
|
||||
((x) == SSH2_AGENT_FAILURE))
|
||||
|
||||
static uint32_t
|
||||
atomicio(struct ssh_agent_struct *agent, void *buf, uint32_t n, int do_read)
|
||||
{
|
||||
char *b = buf;
|
||||
uint32_t pos = 0;
|
||||
ssize_t res;
|
||||
ssh_pollfd_t pfd;
|
||||
ssh_channel channel = agent->channel;
|
||||
socket_t fd;
|
||||
static uint32_t atomicio(struct ssh_agent_struct *agent, void *buf, uint32_t n, int do_read) {
|
||||
char *b = buf;
|
||||
uint32_t pos = 0;
|
||||
ssize_t res;
|
||||
ssh_pollfd_t pfd;
|
||||
ssh_channel channel = agent->channel;
|
||||
socket_t fd;
|
||||
|
||||
/* Using a socket ? */
|
||||
if (channel == NULL) {
|
||||
fd = ssh_socket_get_fd(agent->sock);
|
||||
pfd.fd = fd;
|
||||
pfd.events = do_read ? POLLIN : POLLOUT;
|
||||
/* Using a socket ? */
|
||||
if (channel == NULL) {
|
||||
fd = ssh_socket_get_fd(agent->sock);
|
||||
pfd.fd = fd;
|
||||
pfd.events = do_read ? POLLIN : POLLOUT;
|
||||
|
||||
while (n > pos) {
|
||||
if (do_read) {
|
||||
res = recv(fd, b + pos, n - pos, 0);
|
||||
} else {
|
||||
res = send(fd, b + pos, n - pos, 0);
|
||||
}
|
||||
switch (res) {
|
||||
case -1:
|
||||
if (errno == EINTR) {
|
||||
continue;
|
||||
}
|
||||
while (n > pos) {
|
||||
if (do_read) {
|
||||
res = recv(fd, b + pos, n - pos, 0);
|
||||
} else {
|
||||
res = send(fd, b + pos, n - pos, 0);
|
||||
}
|
||||
switch (res) {
|
||||
case -1:
|
||||
if (errno == EINTR) {
|
||||
continue;
|
||||
}
|
||||
#ifdef EWOULDBLOCK
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK) {
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK) {
|
||||
#else
|
||||
if (errno == EAGAIN) {
|
||||
if (errno == EAGAIN) {
|
||||
#endif
|
||||
(void)ssh_poll(&pfd, 1, -1);
|
||||
continue;
|
||||
}
|
||||
return 0;
|
||||
case 0:
|
||||
/* read returns 0 on end-of-file */
|
||||
errno = do_read ? 0 : EPIPE;
|
||||
return pos;
|
||||
default:
|
||||
pos += (uint32_t)res;
|
||||
}
|
||||
}
|
||||
(void) ssh_poll(&pfd, 1, -1);
|
||||
continue;
|
||||
}
|
||||
return 0;
|
||||
case 0:
|
||||
/* read returns 0 on end-of-file */
|
||||
errno = do_read ? 0 : EPIPE;
|
||||
return pos;
|
||||
default:
|
||||
pos += (uint32_t) res;
|
||||
}
|
||||
}
|
||||
return pos;
|
||||
} else {
|
||||
/* using an SSH channel */
|
||||
while (n > pos) {
|
||||
if (do_read) {
|
||||
res = ssh_channel_read(channel, b + pos, n - pos, 0);
|
||||
} else {
|
||||
res = ssh_channel_write(channel, b + pos, n - pos);
|
||||
}
|
||||
if (res == SSH_AGAIN) {
|
||||
continue;
|
||||
}
|
||||
if (res == SSH_ERROR) {
|
||||
return 0;
|
||||
}
|
||||
pos += (uint32_t)res;
|
||||
}
|
||||
return pos;
|
||||
/* using an SSH channel */
|
||||
while (n > pos){
|
||||
if (do_read)
|
||||
res = ssh_channel_read(channel,b + pos, n-pos, 0);
|
||||
else
|
||||
res = ssh_channel_write(channel, b+pos, n-pos);
|
||||
if (res == SSH_AGAIN)
|
||||
continue;
|
||||
if (res == SSH_ERROR)
|
||||
return 0;
|
||||
pos += (uint32_t)res;
|
||||
}
|
||||
return pos;
|
||||
}
|
||||
}
|
||||
|
||||
ssh_agent ssh_agent_new(struct ssh_session_struct *session)
|
||||
{
|
||||
ssh_agent agent = NULL;
|
||||
ssh_agent ssh_agent_new(struct ssh_session_struct *session) {
|
||||
ssh_agent agent = NULL;
|
||||
|
||||
agent = calloc(1, sizeof(struct ssh_agent_struct));
|
||||
if (agent == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
agent = malloc(sizeof(struct ssh_agent_struct));
|
||||
if (agent == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
ZERO_STRUCTP(agent);
|
||||
|
||||
agent->count = 0;
|
||||
agent->sock = ssh_socket_new(session);
|
||||
if (agent->sock == NULL) {
|
||||
SAFE_FREE(agent);
|
||||
return NULL;
|
||||
}
|
||||
agent->channel = NULL;
|
||||
return agent;
|
||||
agent->count = 0;
|
||||
agent->sock = ssh_socket_new(session);
|
||||
if (agent->sock == NULL) {
|
||||
SAFE_FREE(agent);
|
||||
return NULL;
|
||||
}
|
||||
agent->channel = NULL;
|
||||
return agent;
|
||||
}
|
||||
|
||||
static void agent_set_channel(struct ssh_agent_struct *agent,
|
||||
ssh_channel channel)
|
||||
{
|
||||
agent->channel = channel;
|
||||
static void agent_set_channel(struct ssh_agent_struct *agent, ssh_channel channel){
|
||||
agent->channel = channel;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -175,19 +168,15 @@ static void agent_set_channel(struct ssh_agent_struct *agent,
|
||||
* @returns SSH_OK in case of success
|
||||
* SSH_ERROR in case of an error
|
||||
*/
|
||||
int ssh_set_agent_channel(ssh_session session, ssh_channel channel)
|
||||
{
|
||||
if (!session) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
if (!session->agent) {
|
||||
ssh_set_error(session,
|
||||
SSH_REQUEST_DENIED,
|
||||
"Session has no active agent");
|
||||
return SSH_ERROR;
|
||||
}
|
||||
agent_set_channel(session->agent, channel);
|
||||
return SSH_OK;
|
||||
int ssh_set_agent_channel(ssh_session session, ssh_channel channel){
|
||||
if (!session)
|
||||
return SSH_ERROR;
|
||||
if (!session->agent){
|
||||
ssh_set_error(session, SSH_REQUEST_DENIED, "Session has no active agent");
|
||||
return SSH_ERROR;
|
||||
}
|
||||
agent_set_channel(session->agent, channel);
|
||||
return SSH_OK;
|
||||
}
|
||||
|
||||
/** @brief sets the SSH agent socket.
|
||||
@@ -198,72 +187,64 @@ int ssh_set_agent_channel(ssh_session session, ssh_channel channel)
|
||||
* @returns SSH_OK in case of success
|
||||
* SSH_ERROR in case of an error
|
||||
*/
|
||||
int ssh_set_agent_socket(ssh_session session, socket_t fd)
|
||||
{
|
||||
if (!session) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
if (!session->agent) {
|
||||
ssh_set_error(session,
|
||||
SSH_REQUEST_DENIED,
|
||||
"Session has no active agent");
|
||||
return SSH_ERROR;
|
||||
}
|
||||
int ssh_set_agent_socket(ssh_session session, socket_t fd){
|
||||
if (!session)
|
||||
return SSH_ERROR;
|
||||
if (!session->agent){
|
||||
ssh_set_error(session, SSH_REQUEST_DENIED, "Session has no active agent");
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
ssh_socket_set_fd(session->agent->sock, fd);
|
||||
return SSH_OK;
|
||||
ssh_socket_set_fd(session->agent->sock, fd);
|
||||
return SSH_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
void ssh_agent_close(struct ssh_agent_struct *agent)
|
||||
{
|
||||
if (agent == NULL) {
|
||||
return;
|
||||
}
|
||||
void ssh_agent_close(struct ssh_agent_struct *agent) {
|
||||
if (agent == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
ssh_socket_close(agent->sock);
|
||||
ssh_socket_close(agent->sock);
|
||||
}
|
||||
|
||||
void ssh_agent_free(ssh_agent agent)
|
||||
{
|
||||
if (agent) {
|
||||
if (agent->ident) {
|
||||
SSH_BUFFER_FREE(agent->ident);
|
||||
}
|
||||
if (agent->sock) {
|
||||
ssh_agent_close(agent);
|
||||
ssh_socket_free(agent->sock);
|
||||
}
|
||||
SAFE_FREE(agent);
|
||||
void ssh_agent_free(ssh_agent agent) {
|
||||
if (agent) {
|
||||
if (agent->ident) {
|
||||
SSH_BUFFER_FREE(agent->ident);
|
||||
}
|
||||
if (agent->sock) {
|
||||
ssh_agent_close(agent);
|
||||
ssh_socket_free(agent->sock);
|
||||
}
|
||||
SAFE_FREE(agent);
|
||||
}
|
||||
}
|
||||
|
||||
static int agent_connect(ssh_session session)
|
||||
{
|
||||
const char *auth_sock = NULL;
|
||||
|
||||
if (session == NULL || session->agent == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (session->agent->channel != NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
auth_sock = session->opts.agent_socket ? session->opts.agent_socket
|
||||
: getenv("SSH_AUTH_SOCK");
|
||||
|
||||
if (auth_sock && *auth_sock) {
|
||||
if (ssh_socket_unix(session->agent->sock, auth_sock) < 0) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
static int agent_connect(ssh_session session) {
|
||||
const char *auth_sock = NULL;
|
||||
|
||||
if (session == NULL || session->agent == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (session->agent->channel != NULL)
|
||||
return 0;
|
||||
|
||||
auth_sock = session->opts.agent_socket ?
|
||||
session->opts.agent_socket : getenv("SSH_AUTH_SOCK");
|
||||
|
||||
if (auth_sock && *auth_sock) {
|
||||
if (ssh_socket_unix(session->agent->sock, auth_sock) < 0) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if 0
|
||||
@@ -287,66 +268,61 @@ static int agent_decode_reply(struct ssh_session_struct *session, int type) {
|
||||
#endif
|
||||
|
||||
static int agent_talk(struct ssh_session_struct *session,
|
||||
struct ssh_buffer_struct *request,
|
||||
struct ssh_buffer_struct *reply)
|
||||
{
|
||||
uint32_t len = 0;
|
||||
uint8_t tmpbuf[4];
|
||||
uint8_t *payload = tmpbuf;
|
||||
char err_msg[SSH_ERRNO_MSG_MAX] = {0};
|
||||
struct ssh_buffer_struct *request, struct ssh_buffer_struct *reply) {
|
||||
uint32_t len = 0;
|
||||
uint8_t tmpbuf[4];
|
||||
uint8_t *payload = tmpbuf;
|
||||
char err_msg[SSH_ERRNO_MSG_MAX] = {0};
|
||||
|
||||
len = ssh_buffer_get_len(request);
|
||||
SSH_LOG(SSH_LOG_TRACE, "Request length: %" PRIu32, len);
|
||||
PUSH_BE_U32(payload, 0, len);
|
||||
len = ssh_buffer_get_len(request);
|
||||
SSH_LOG(SSH_LOG_TRACE, "Request length: %" PRIu32, len);
|
||||
PUSH_BE_U32(payload, 0, len);
|
||||
|
||||
/* send length and then the request packet */
|
||||
if (atomicio(session->agent, payload, 4, 0) == 4) {
|
||||
if (atomicio(session->agent, ssh_buffer_get(request), len, 0) != len) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"atomicio sending request failed: %s",
|
||||
ssh_strerror(errno, err_msg, SSH_ERRNO_MSG_MAX));
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"atomicio sending request length failed: %s",
|
||||
ssh_strerror(errno, err_msg, SSH_ERRNO_MSG_MAX));
|
||||
return -1;
|
||||
/* send length and then the request packet */
|
||||
if (atomicio(session->agent, payload, 4, 0) == 4) {
|
||||
if (atomicio(session->agent, ssh_buffer_get(request), len, 0)
|
||||
!= len) {
|
||||
SSH_LOG(SSH_LOG_TRACE, "atomicio sending request failed: %s",
|
||||
strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"atomicio sending request length failed: %s",
|
||||
ssh_strerror(errno, err_msg, SSH_ERRNO_MSG_MAX));
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* wait for response, read the length of the response packet */
|
||||
if (atomicio(session->agent, payload, 4, 1) != 4) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"atomicio read response length failed: %s",
|
||||
ssh_strerror(errno, err_msg, SSH_ERRNO_MSG_MAX));
|
||||
return -1;
|
||||
}
|
||||
/* wait for response, read the length of the response packet */
|
||||
if (atomicio(session->agent, payload, 4, 1) != 4) {
|
||||
SSH_LOG(SSH_LOG_TRACE, "atomicio read response length failed: %s",
|
||||
strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
len = PULL_BE_U32(payload, 0);
|
||||
if (len > 256 * 1024) {
|
||||
ssh_set_error(session,
|
||||
SSH_FATAL,
|
||||
"Authentication response too long: %" PRIu32,
|
||||
len);
|
||||
return -1;
|
||||
}
|
||||
SSH_LOG(SSH_LOG_TRACE, "Response length: %" PRIu32, len);
|
||||
len = PULL_BE_U32(payload, 0);
|
||||
if (len > 256 * 1024) {
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
"Authentication response too long: %" PRIu32, len);
|
||||
return -1;
|
||||
}
|
||||
SSH_LOG(SSH_LOG_TRACE, "Response length: %" PRIu32, len);
|
||||
|
||||
payload = ssh_buffer_allocate(reply, len);
|
||||
if (payload == NULL) {
|
||||
SSH_LOG(SSH_LOG_DEBUG, "Not enough space");
|
||||
return -1;
|
||||
}
|
||||
payload = ssh_buffer_allocate(reply, len);
|
||||
if (payload == NULL) {
|
||||
SSH_LOG(SSH_LOG_DEBUG, "Not enough space");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (atomicio(session->agent, payload, len, 1) != len) {
|
||||
SSH_LOG(SSH_LOG_DEBUG,
|
||||
"Error reading response from authentication socket.");
|
||||
/* Rollback the unused space */
|
||||
ssh_buffer_pass_bytes_end(reply, len);
|
||||
return -1;
|
||||
}
|
||||
if (atomicio(session->agent, payload, len, 1) != len) {
|
||||
SSH_LOG(SSH_LOG_DEBUG,
|
||||
"Error reading response from authentication socket.");
|
||||
/* Rollback the unused space */
|
||||
ssh_buffer_pass_bytes_end(reply, len);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t ssh_agent_get_ident_count(struct ssh_session_struct *session)
|
||||
@@ -495,23 +471,22 @@ ssh_key ssh_agent_get_next_ident(struct ssh_session_struct *session,
|
||||
return key;
|
||||
}
|
||||
|
||||
int ssh_agent_is_running(ssh_session session)
|
||||
{
|
||||
if (session == NULL || session->agent == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ssh_socket_is_open(session->agent->sock)) {
|
||||
return 1;
|
||||
} else {
|
||||
if (agent_connect(session) < 0) {
|
||||
return 0;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
int ssh_agent_is_running(ssh_session session) {
|
||||
if (session == NULL || session->agent == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ssh_socket_is_open(session->agent->sock)) {
|
||||
return 1;
|
||||
} else {
|
||||
if (agent_connect(session) < 0) {
|
||||
return 0;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
ssh_string ssh_agent_sign_data(ssh_session session,
|
||||
@@ -525,7 +500,6 @@ ssh_string ssh_agent_sign_data(ssh_session session,
|
||||
unsigned int type = 0;
|
||||
unsigned int flags = 0;
|
||||
uint32_t dlen;
|
||||
size_t request_len;
|
||||
int rc;
|
||||
|
||||
request = ssh_buffer_new();
|
||||
@@ -551,14 +525,11 @@ ssh_string ssh_agent_sign_data(ssh_session session,
|
||||
* - 2 x uint32_t
|
||||
* - 1 x ssh_string (uint8_t + data)
|
||||
*/
|
||||
request_len = sizeof(uint8_t) * 2 +
|
||||
sizeof(uint32_t) * 2 +
|
||||
ssh_string_len(key_blob);
|
||||
/* this can't overflow the uint32_t as the
|
||||
* STRING_SIZE_MAX is (UINT32_MAX >> 8) + 1 */
|
||||
rc = ssh_buffer_allocate_size(request, (uint32_t)request_len);
|
||||
rc = ssh_buffer_allocate_size(request,
|
||||
sizeof(uint8_t) * 2 +
|
||||
sizeof(uint32_t) * 2 +
|
||||
ssh_string_len(key_blob));
|
||||
if (rc < 0) {
|
||||
SSH_STRING_FREE(key_blob);
|
||||
SSH_BUFFER_FREE(request);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
228
src/auth.c
228
src/auth.c
@@ -463,108 +463,6 @@ fail:
|
||||
return SSH_AUTH_ERROR;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
* @brief Adds the server's public key to the authentication request.
|
||||
*
|
||||
* This function is used internally when the hostbound public key authentication
|
||||
* extension is enabled. It export the server's public key and adds it to the
|
||||
* authentication buffer.
|
||||
*
|
||||
* @param[in] session The SSH session.
|
||||
*
|
||||
* @returns SSH_OK on success, SSH_ERROR if an error occurred.
|
||||
*/
|
||||
static int add_hostbound_pubkey(ssh_session session)
|
||||
{
|
||||
int rc;
|
||||
ssh_string server_pubkey_s = NULL;
|
||||
|
||||
if (session == NULL) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
if (session->current_crypto == NULL ||
|
||||
session->current_crypto->server_pubkey == NULL) {
|
||||
ssh_set_error(session,
|
||||
SSH_FATAL,
|
||||
"Invalid session or server public key");
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
rc = ssh_pki_export_pubkey_blob(session->current_crypto->server_pubkey,
|
||||
&server_pubkey_s);
|
||||
if (rc < 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
rc = ssh_buffer_add_ssh_string(session->out_buffer, server_pubkey_s);
|
||||
if (rc < 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
error:
|
||||
SSH_STRING_FREE(server_pubkey_s);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
* @brief Build a public key authentication request.
|
||||
*
|
||||
* This helper function creates a SSH2_MSG_USERAUTH_REQUEST message for public
|
||||
* key authentication and adds the server's public key if the hostbound
|
||||
* extension is enabled.
|
||||
*
|
||||
* @param[in] session The SSH session.
|
||||
* @param[in] username The username, may be NULL.
|
||||
* @param[in] auth_type Authentication type (0 for key offer, 1 for actual
|
||||
* auth).
|
||||
* @param[in] sig_type_c The signature algorithm name.
|
||||
* @param[in] pubkey_s The public key string.
|
||||
*
|
||||
* @return SSH_OK on success, SSH_ERROR if an error occurred.
|
||||
*/
|
||||
static int build_pubkey_auth_request(ssh_session session,
|
||||
const char *username,
|
||||
int has_signature,
|
||||
const char *sig_type_c,
|
||||
ssh_string pubkey_s)
|
||||
{
|
||||
int rc;
|
||||
const char *auth_method = "publickey";
|
||||
|
||||
if (session->extensions & SSH_EXT_PUBLICKEY_HOSTBOUND) {
|
||||
auth_method = "publickey-hostbound-v00@openssh.com";
|
||||
}
|
||||
|
||||
/* request */
|
||||
rc = ssh_buffer_pack(session->out_buffer,
|
||||
"bsssbsS",
|
||||
SSH2_MSG_USERAUTH_REQUEST,
|
||||
username ? username : session->opts.username,
|
||||
"ssh-connection",
|
||||
auth_method,
|
||||
has_signature, /* private key? */
|
||||
sig_type_c, /* algo */
|
||||
pubkey_s /* public key */
|
||||
);
|
||||
if (rc < 0) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
if (session->extensions & SSH_EXT_PUBLICKEY_HOSTBOUND) {
|
||||
rc = add_hostbound_pubkey(session);
|
||||
if (rc < 0) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
return SSH_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Try to authenticate with the given public key.
|
||||
*
|
||||
@@ -611,17 +509,17 @@ int ssh_userauth_try_publickey(ssh_session session,
|
||||
return SSH_AUTH_ERROR;
|
||||
}
|
||||
|
||||
switch (session->pending_call_state) {
|
||||
case SSH_PENDING_CALL_NONE:
|
||||
break;
|
||||
case SSH_PENDING_CALL_AUTH_OFFER_PUBKEY:
|
||||
goto pending;
|
||||
default:
|
||||
ssh_set_error(session,
|
||||
SSH_FATAL,
|
||||
"Wrong state (%d) during pending SSH call",
|
||||
session->pending_call_state);
|
||||
return SSH_AUTH_ERROR;
|
||||
switch(session->pending_call_state) {
|
||||
case SSH_PENDING_CALL_NONE:
|
||||
break;
|
||||
case SSH_PENDING_CALL_AUTH_OFFER_PUBKEY:
|
||||
goto pending;
|
||||
default:
|
||||
ssh_set_error(session,
|
||||
SSH_FATAL,
|
||||
"Wrong state (%d) during pending SSH call",
|
||||
session->pending_call_state);
|
||||
return SSH_AUTH_ERROR;
|
||||
}
|
||||
|
||||
/* Note, that this is intentionally before checking the signature type
|
||||
@@ -638,15 +536,13 @@ int ssh_userauth_try_publickey(ssh_session session,
|
||||
/* Check if the given public key algorithm is allowed */
|
||||
sig_type_c = ssh_key_get_signature_algorithm(session, pubkey->type);
|
||||
if (sig_type_c == NULL) {
|
||||
ssh_set_error(session,
|
||||
SSH_REQUEST_DENIED,
|
||||
ssh_set_error(session, SSH_REQUEST_DENIED,
|
||||
"Invalid key type (unknown)");
|
||||
return SSH_AUTH_DENIED;
|
||||
}
|
||||
rc = ssh_key_algorithm_allowed(session, sig_type_c);
|
||||
if (!rc) {
|
||||
ssh_set_error(session,
|
||||
SSH_REQUEST_DENIED,
|
||||
ssh_set_error(session, SSH_REQUEST_DENIED,
|
||||
"The key algorithm '%s' is not allowed to be used by"
|
||||
" PUBLICKEY_ACCEPTED_TYPES configuration option",
|
||||
sig_type_c);
|
||||
@@ -654,12 +550,9 @@ int ssh_userauth_try_publickey(ssh_session session,
|
||||
}
|
||||
allowed = ssh_key_size_allowed(session, pubkey);
|
||||
if (!allowed) {
|
||||
ssh_set_error(session,
|
||||
SSH_REQUEST_DENIED,
|
||||
ssh_set_error(session, SSH_REQUEST_DENIED,
|
||||
"The '%s' key type of size %d is not allowed by "
|
||||
"RSA_MIN_SIZE",
|
||||
sig_type_c,
|
||||
ssh_key_size(pubkey));
|
||||
"RSA_MIN_SIZE", sig_type_c, ssh_key_size(pubkey));
|
||||
return SSH_AUTH_DENIED;
|
||||
}
|
||||
|
||||
@@ -670,10 +563,20 @@ int ssh_userauth_try_publickey(ssh_session session,
|
||||
}
|
||||
|
||||
SSH_LOG(SSH_LOG_TRACE, "Trying signature type %s", sig_type_c);
|
||||
rc = build_pubkey_auth_request(session, username, 0, sig_type_c, pubkey_s);
|
||||
/* request */
|
||||
rc = ssh_buffer_pack(session->out_buffer, "bsssbsS",
|
||||
SSH2_MSG_USERAUTH_REQUEST,
|
||||
username ? username : session->opts.username,
|
||||
"ssh-connection",
|
||||
"publickey",
|
||||
0, /* private key ? */
|
||||
sig_type_c, /* algo */
|
||||
pubkey_s /* public key */
|
||||
);
|
||||
if (rc < 0) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
SSH_STRING_FREE(pubkey_s);
|
||||
|
||||
session->auth.current_method = SSH_AUTH_METHOD_PUBLICKEY;
|
||||
@@ -742,17 +645,16 @@ int ssh_userauth_publickey(ssh_session session,
|
||||
return SSH_AUTH_ERROR;
|
||||
}
|
||||
|
||||
switch (session->pending_call_state) {
|
||||
case SSH_PENDING_CALL_NONE:
|
||||
break;
|
||||
case SSH_PENDING_CALL_AUTH_PUBKEY:
|
||||
goto pending;
|
||||
default:
|
||||
ssh_set_error(
|
||||
session,
|
||||
SSH_FATAL,
|
||||
"Bad call during pending SSH call in ssh_userauth_try_publickey");
|
||||
return SSH_AUTH_ERROR;
|
||||
switch(session->pending_call_state) {
|
||||
case SSH_PENDING_CALL_NONE:
|
||||
break;
|
||||
case SSH_PENDING_CALL_AUTH_PUBKEY:
|
||||
goto pending;
|
||||
default:
|
||||
ssh_set_error(session,
|
||||
SSH_FATAL,
|
||||
"Bad call during pending SSH call in ssh_userauth_try_publickey");
|
||||
return SSH_AUTH_ERROR;
|
||||
}
|
||||
|
||||
/* Note, that this is intentionally before checking the signature type
|
||||
@@ -772,15 +674,13 @@ int ssh_userauth_publickey(ssh_session session,
|
||||
/* Check if the given public key algorithm is allowed */
|
||||
sig_type_c = ssh_key_get_signature_algorithm(session, key_type);
|
||||
if (sig_type_c == NULL) {
|
||||
ssh_set_error(session,
|
||||
SSH_REQUEST_DENIED,
|
||||
ssh_set_error(session, SSH_REQUEST_DENIED,
|
||||
"Invalid key type (unknown)");
|
||||
return SSH_AUTH_DENIED;
|
||||
}
|
||||
rc = ssh_key_algorithm_allowed(session, sig_type_c);
|
||||
if (!rc) {
|
||||
ssh_set_error(session,
|
||||
SSH_REQUEST_DENIED,
|
||||
ssh_set_error(session, SSH_REQUEST_DENIED,
|
||||
"The key algorithm '%s' is not allowed to be used by"
|
||||
" PUBLICKEY_ACCEPTED_TYPES configuration option",
|
||||
sig_type_c);
|
||||
@@ -788,12 +688,9 @@ int ssh_userauth_publickey(ssh_session session,
|
||||
}
|
||||
allowed = ssh_key_size_allowed(session, privkey);
|
||||
if (!allowed) {
|
||||
ssh_set_error(session,
|
||||
SSH_REQUEST_DENIED,
|
||||
ssh_set_error(session, SSH_REQUEST_DENIED,
|
||||
"The '%s' key type of size %d is not allowed by "
|
||||
"RSA_MIN_SIZE",
|
||||
sig_type_c,
|
||||
ssh_key_size(privkey));
|
||||
"RSA_MIN_SIZE", sig_type_c, ssh_key_size(privkey));
|
||||
return SSH_AUTH_DENIED;
|
||||
}
|
||||
|
||||
@@ -804,7 +701,16 @@ int ssh_userauth_publickey(ssh_session session,
|
||||
}
|
||||
|
||||
SSH_LOG(SSH_LOG_TRACE, "Sending signature type %s", sig_type_c);
|
||||
rc = build_pubkey_auth_request(session, username, 1, sig_type_c, str);
|
||||
/* request */
|
||||
rc = ssh_buffer_pack(session->out_buffer, "bsssbsS",
|
||||
SSH2_MSG_USERAUTH_REQUEST,
|
||||
username ? username : session->opts.username,
|
||||
"ssh-connection",
|
||||
"publickey",
|
||||
1, /* private key */
|
||||
sig_type_c, /* algo */
|
||||
str /* public key or cert */
|
||||
);
|
||||
if (rc < 0) {
|
||||
goto fail;
|
||||
}
|
||||
@@ -892,16 +798,14 @@ static int ssh_userauth_agent_publickey(ssh_session session,
|
||||
/* Check if the given public key algorithm is allowed */
|
||||
sig_type_c = ssh_key_get_signature_algorithm(session, pubkey->type);
|
||||
if (sig_type_c == NULL) {
|
||||
ssh_set_error(session,
|
||||
SSH_REQUEST_DENIED,
|
||||
ssh_set_error(session, SSH_REQUEST_DENIED,
|
||||
"Invalid key type (unknown)");
|
||||
SSH_STRING_FREE(pubkey_s);
|
||||
return SSH_AUTH_DENIED;
|
||||
}
|
||||
rc = ssh_key_algorithm_allowed(session, sig_type_c);
|
||||
if (!rc) {
|
||||
ssh_set_error(session,
|
||||
SSH_REQUEST_DENIED,
|
||||
ssh_set_error(session, SSH_REQUEST_DENIED,
|
||||
"The key algorithm '%s' is not allowed to be used by"
|
||||
" PUBLICKEY_ACCEPTED_TYPES configuration option",
|
||||
sig_type_c);
|
||||
@@ -910,21 +814,27 @@ static int ssh_userauth_agent_publickey(ssh_session session,
|
||||
}
|
||||
allowed = ssh_key_size_allowed(session, pubkey);
|
||||
if (!allowed) {
|
||||
ssh_set_error(session,
|
||||
SSH_REQUEST_DENIED,
|
||||
ssh_set_error(session, SSH_REQUEST_DENIED,
|
||||
"The '%s' key type of size %d is not allowed by "
|
||||
"RSA_MIN_SIZE",
|
||||
sig_type_c,
|
||||
ssh_key_size(pubkey));
|
||||
"RSA_MIN_SIZE", sig_type_c, ssh_key_size(pubkey));
|
||||
SSH_STRING_FREE(pubkey_s);
|
||||
return SSH_AUTH_DENIED;
|
||||
}
|
||||
|
||||
rc = build_pubkey_auth_request(session, username, 1, sig_type_c, pubkey_s);
|
||||
/* request */
|
||||
rc = ssh_buffer_pack(session->out_buffer, "bsssbsS",
|
||||
SSH2_MSG_USERAUTH_REQUEST,
|
||||
username ? username : session->opts.username,
|
||||
"ssh-connection",
|
||||
"publickey",
|
||||
1, /* private key */
|
||||
sig_type_c, /* algo */
|
||||
pubkey_s /* public key */
|
||||
);
|
||||
SSH_STRING_FREE(pubkey_s);
|
||||
if (rc < 0) {
|
||||
goto fail;
|
||||
}
|
||||
SSH_STRING_FREE(pubkey_s);
|
||||
|
||||
/* sign the buffer with the private key */
|
||||
sig_blob = ssh_pki_do_sign_agent(session, session->out_buffer, pubkey);
|
||||
@@ -982,7 +892,7 @@ void ssh_agent_state_free(void *data)
|
||||
if (state) {
|
||||
SSH_STRING_FREE_CHAR(state->comment);
|
||||
ssh_key_free(state->pubkey);
|
||||
free(state);
|
||||
free (state);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1008,7 +918,8 @@ void ssh_agent_state_free(void *data)
|
||||
* authentication. The username should only be set with ssh_options_set() only
|
||||
* before you connect to the server.
|
||||
*/
|
||||
int ssh_userauth_agent(ssh_session session, const char *username)
|
||||
int ssh_userauth_agent(ssh_session session,
|
||||
const char *username)
|
||||
{
|
||||
int rc = SSH_AUTH_ERROR;
|
||||
struct ssh_agent_state_struct *state = NULL;
|
||||
@@ -1027,11 +938,12 @@ int ssh_userauth_agent(ssh_session session, const char *username)
|
||||
}
|
||||
|
||||
if (!session->agent_state) {
|
||||
session->agent_state = calloc(1, sizeof(struct ssh_agent_state_struct));
|
||||
session->agent_state = malloc(sizeof(struct ssh_agent_state_struct));
|
||||
if (!session->agent_state) {
|
||||
ssh_set_error_oom(session);
|
||||
return SSH_AUTH_ERROR;
|
||||
}
|
||||
ZERO_STRUCTP(session->agent_state);
|
||||
session->agent_state->state = SSH_AGENT_STATE_NONE;
|
||||
}
|
||||
|
||||
|
||||
@@ -186,7 +186,7 @@ error:
|
||||
static int to_block4(unsigned long *block, const char *source, int num)
|
||||
{
|
||||
const char *ptr = NULL;
|
||||
size_t i;
|
||||
unsigned int i;
|
||||
|
||||
*block = 0;
|
||||
if (num < 1) {
|
||||
|
||||
73
src/bignum.c
73
src/bignum.c
@@ -27,52 +27,40 @@
|
||||
#include "libssh/bignum.h"
|
||||
#include "libssh/string.h"
|
||||
|
||||
static ssh_string make_bignum_string(bignum num, size_t pad_to_len)
|
||||
{
|
||||
ssh_string ptr = NULL;
|
||||
size_t pad = 0;
|
||||
size_t len = bignum_num_bytes(num);
|
||||
size_t bits = bignum_num_bits(num);
|
||||
ssh_string ssh_make_bignum_string(bignum num) {
|
||||
ssh_string ptr = NULL;
|
||||
size_t pad = 0;
|
||||
size_t len = bignum_num_bytes(num);
|
||||
size_t bits = bignum_num_bits(num);
|
||||
|
||||
if (pad_to_len == 0) {
|
||||
/* If the first bit is set we have a negative number */
|
||||
if (!(bits % 8) && bignum_is_bit_set(num, bits - 1)) {
|
||||
pad++;
|
||||
}
|
||||
} else {
|
||||
if (len > pad_to_len) {
|
||||
return NULL;
|
||||
}
|
||||
pad = pad_to_len - len;
|
||||
}
|
||||
if (len == 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* If the first bit is set we have a negative number */
|
||||
if (!(bits % 8) && bignum_is_bit_set(num, bits - 1)) {
|
||||
pad++;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_CRYPTO
|
||||
SSH_LOG(SSH_LOG_TRACE, "%zu bits, %zu bytes, %zu padding", bits, len, pad);
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"%zu bits, %zu bytes, %zu padding",
|
||||
bits, len, pad);
|
||||
#endif /* DEBUG_CRYPTO */
|
||||
|
||||
ptr = ssh_string_new(len + pad);
|
||||
if (ptr == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
ptr = ssh_string_new(len + pad);
|
||||
if (ptr == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* We have a negative number so we need a leading zero */
|
||||
if (pad) {
|
||||
memset(ptr->data, 0, pad);
|
||||
}
|
||||
/* We have a negative number so we need a leading zero */
|
||||
if (pad) {
|
||||
ptr->data[0] = 0;
|
||||
}
|
||||
|
||||
bignum_bn2bin(num, len, ptr->data + pad);
|
||||
bignum_bn2bin(num, len, ptr->data + pad);
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
ssh_string ssh_make_bignum_string(bignum num)
|
||||
{
|
||||
return make_bignum_string(num, 0);
|
||||
}
|
||||
|
||||
ssh_string ssh_make_padded_bignum_string(bignum num, size_t pad_len)
|
||||
{
|
||||
return make_bignum_string(num, pad_len);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
bignum ssh_make_string_bn(ssh_string string)
|
||||
@@ -83,11 +71,10 @@ bignum ssh_make_string_bn(ssh_string string)
|
||||
#ifdef DEBUG_CRYPTO
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Importing a %zu bits, %zu bytes object ...",
|
||||
len * 8,
|
||||
len);
|
||||
len * 8, len);
|
||||
#endif /* DEBUG_CRYPTO */
|
||||
|
||||
bignum_bin2bn(string->data, (int)len, &bn);
|
||||
bignum_bin2bn(string->data, len, &bn);
|
||||
|
||||
return bn;
|
||||
}
|
||||
@@ -99,9 +86,7 @@ void ssh_print_bignum(const char *name, const_bignum num)
|
||||
if (num != NULL) {
|
||||
bignum_bn2hex(num, &hex);
|
||||
}
|
||||
SSH_LOG(SSH_LOG_DEBUG,
|
||||
"%s value: %s",
|
||||
name,
|
||||
SSH_LOG(SSH_LOG_DEBUG, "%s value: %s", name,
|
||||
(hex == NULL) ? "(null)" : (char *)hex);
|
||||
ssh_crypto_free(hex);
|
||||
}
|
||||
|
||||
28
src/bind.c
28
src/bind.c
@@ -218,28 +218,12 @@ static int ssh_bind_import_keys(ssh_bind sshbind) {
|
||||
return SSH_OK;
|
||||
}
|
||||
|
||||
int ssh_bind_listen(ssh_bind sshbind) {
|
||||
int ssh_bind_listen(ssh_bind sshbind)
|
||||
{
|
||||
const char *host = NULL;
|
||||
socket_t fd;
|
||||
int rc;
|
||||
|
||||
/* Apply global bind configurations, if it hasn't been applied before */
|
||||
rc = ssh_bind_options_parse_config(sshbind, NULL);
|
||||
if (rc != 0) {
|
||||
ssh_set_error(sshbind, SSH_FATAL,"Could not parse global config");
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
/* Set default hostkey paths if no hostkey was found before */
|
||||
if (sshbind->ecdsakey == NULL &&
|
||||
sshbind->rsakey == NULL &&
|
||||
sshbind->ed25519key == NULL) {
|
||||
|
||||
sshbind->ecdsakey = strdup("/etc/ssh/ssh_host_ecdsa_key");
|
||||
sshbind->rsakey = strdup("/etc/ssh/ssh_host_rsa_key");
|
||||
sshbind->ed25519key = strdup("/etc/ssh/ssh_host_ed25519_key");
|
||||
}
|
||||
|
||||
/* Apply global bind configurations, if it hasn't been applied before */
|
||||
rc = ssh_bind_options_parse_config(sshbind, NULL);
|
||||
if (rc != 0) {
|
||||
@@ -289,10 +273,10 @@ int ssh_bind_listen(ssh_bind sshbind) {
|
||||
}
|
||||
|
||||
sshbind->bindfd = fd;
|
||||
} else {
|
||||
SSH_LOG(SSH_LOG_DEBUG, "Using app-provided bind socket");
|
||||
}
|
||||
return 0;
|
||||
} else {
|
||||
SSH_LOG(SSH_LOG_DEBUG, "Using app-provided bind socket");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ssh_bind_set_callbacks(ssh_bind sshbind, ssh_bind_callbacks callbacks, void *userdata)
|
||||
|
||||
@@ -669,8 +669,7 @@ int ssh_bind_config_parse_string(ssh_bind bind, const char *input)
|
||||
{
|
||||
char line[MAX_LINE_SIZE] = {0};
|
||||
const char *c = input, *line_start = input;
|
||||
unsigned int line_num = 0;
|
||||
size_t line_len;
|
||||
unsigned int line_num = 0, line_len;
|
||||
uint32_t parser_flags;
|
||||
int rv;
|
||||
|
||||
@@ -699,10 +698,8 @@ int ssh_bind_config_parse_string(ssh_bind bind, const char *input)
|
||||
}
|
||||
line_len = c - line_start;
|
||||
if (line_len > MAX_LINE_SIZE - 1) {
|
||||
SSH_LOG(SSH_LOG_WARN,
|
||||
"Line %u too long: %zu characters",
|
||||
line_num,
|
||||
line_len);
|
||||
SSH_LOG(SSH_LOG_WARN, "Line %u too long: %u characters",
|
||||
line_num, line_len);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
memcpy(line, line_start, line_len);
|
||||
|
||||
94
src/buffer.c
94
src/buffer.c
@@ -407,26 +407,20 @@ void *ssh_buffer_allocate(struct ssh_buffer_struct *buffer, uint32_t len)
|
||||
*
|
||||
* @return 0 on success, < 0 on error.
|
||||
*/
|
||||
int
|
||||
ssh_buffer_add_ssh_string(struct ssh_buffer_struct *buffer,
|
||||
struct ssh_string_struct *string)
|
||||
{
|
||||
size_t len;
|
||||
int rc;
|
||||
int ssh_buffer_add_ssh_string(struct ssh_buffer_struct *buffer,
|
||||
struct ssh_string_struct *string) {
|
||||
uint32_t len = 0;
|
||||
|
||||
if (string == NULL) {
|
||||
return -1;
|
||||
}
|
||||
if (string == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
len = ssh_string_len(string) + sizeof(uint32_t);
|
||||
/* this can't overflow the uint32_t as the
|
||||
* STRING_SIZE_MAX is (UINT32_MAX >> 8) + 1 */
|
||||
rc = ssh_buffer_add_data(buffer, string, (uint32_t)len);
|
||||
if (rc < 0) {
|
||||
return -1;
|
||||
}
|
||||
len = ssh_string_len(string);
|
||||
if (ssh_buffer_add_data(buffer, string, len + sizeof(uint32_t)) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -829,7 +823,6 @@ static int ssh_buffer_pack_allocate_va(struct ssh_buffer_struct *buffer,
|
||||
const char *p = NULL;
|
||||
ssh_string string = NULL;
|
||||
char *cstring = NULL;
|
||||
bignum b = NULL;
|
||||
size_t needed_size = 0;
|
||||
size_t len;
|
||||
size_t count;
|
||||
@@ -874,18 +867,13 @@ static int ssh_buffer_pack_allocate_va(struct ssh_buffer_struct *buffer,
|
||||
va_arg(ap, void *);
|
||||
count++; /* increase argument count */
|
||||
break;
|
||||
case 'F':
|
||||
case 'B':
|
||||
b = va_arg(ap, bignum);
|
||||
if (*p == 'F') {
|
||||
/* For padded bignum, we know the exact length */
|
||||
len = va_arg(ap, size_t);
|
||||
count++; /* increase argument count */
|
||||
needed_size += sizeof(uint32_t) + len;
|
||||
} else {
|
||||
/* The bignum bytes + 1 for possible padding */
|
||||
needed_size += sizeof(uint32_t) + bignum_num_bytes(b) + 1;
|
||||
}
|
||||
va_arg(ap, bignum);
|
||||
/*
|
||||
* Use a fixed size for a bignum
|
||||
* (they should normally be around 32)
|
||||
*/
|
||||
needed_size += 64;
|
||||
break;
|
||||
case 't':
|
||||
cstring = va_arg(ap, char *);
|
||||
@@ -991,40 +979,24 @@ ssh_buffer_pack_va(struct ssh_buffer_struct *buffer,
|
||||
case 's':
|
||||
cstring = va_arg(ap, char *);
|
||||
len = strlen(cstring);
|
||||
if (len > UINT32_MAX) {
|
||||
rc = SSH_ERROR;
|
||||
break;
|
||||
}
|
||||
o.dword = (uint32_t)len;
|
||||
rc = ssh_buffer_add_u32(buffer, htonl(o.dword));
|
||||
rc = ssh_buffer_add_u32(buffer, htonl(len));
|
||||
if (rc == SSH_OK){
|
||||
rc = ssh_buffer_add_data(buffer, cstring, o.dword);
|
||||
rc = ssh_buffer_add_data(buffer, cstring, len);
|
||||
}
|
||||
cstring = NULL;
|
||||
break;
|
||||
case 'P':
|
||||
len = va_arg(ap, size_t);
|
||||
if (len > UINT32_MAX) {
|
||||
rc = SSH_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
o.data = va_arg(ap, void *);
|
||||
count++; /* increase argument count */
|
||||
|
||||
rc = ssh_buffer_add_data(buffer, o.data, (uint32_t)len);
|
||||
rc = ssh_buffer_add_data(buffer, o.data, len);
|
||||
o.data = NULL;
|
||||
break;
|
||||
case 'F':
|
||||
case 'B':
|
||||
b = va_arg(ap, bignum);
|
||||
if (*p == 'F') {
|
||||
len = va_arg(ap, size_t);
|
||||
count++; /* increase argument count */
|
||||
o.string = ssh_make_padded_bignum_string(b, len);
|
||||
} else {
|
||||
o.string = ssh_make_bignum_string(b);
|
||||
}
|
||||
o.string = ssh_make_bignum_string(b);
|
||||
if(o.string == NULL){
|
||||
rc = SSH_ERROR;
|
||||
break;
|
||||
@@ -1035,11 +1007,7 @@ ssh_buffer_pack_va(struct ssh_buffer_struct *buffer,
|
||||
case 't':
|
||||
cstring = va_arg(ap, char *);
|
||||
len = strlen(cstring);
|
||||
if (len > UINT32_MAX) {
|
||||
rc = SSH_ERROR;
|
||||
break;
|
||||
}
|
||||
rc = ssh_buffer_add_data(buffer, cstring, (uint32_t)len);
|
||||
rc = ssh_buffer_add_data(buffer, cstring, len);
|
||||
cstring = NULL;
|
||||
break;
|
||||
default:
|
||||
@@ -1080,8 +1048,6 @@ ssh_buffer_pack_va(struct ssh_buffer_struct *buffer,
|
||||
* 'P': size_t, void * (len of data, pointer to data)
|
||||
* only pushes data.
|
||||
* 'B': bignum (pushed as SSH string)
|
||||
* 'F': bignum, size_t (bignum, padded to fixed length,
|
||||
* pushed as SSH string)
|
||||
* @returns SSH_OK on success
|
||||
* SSH_ERROR on error
|
||||
* @warning when using 'P' with a constant size (e.g. 8), do not
|
||||
@@ -1221,28 +1187,28 @@ int ssh_buffer_unpack_va(struct ssh_buffer_struct *buffer,
|
||||
if (rlen != 4){
|
||||
break;
|
||||
}
|
||||
u32len = ntohl(u32len);
|
||||
if (u32len > max_len - 1) {
|
||||
len = ntohl(u32len);
|
||||
if (len > max_len - 1) {
|
||||
break;
|
||||
}
|
||||
|
||||
rc = ssh_buffer_validate_length(buffer, u32len);
|
||||
rc = ssh_buffer_validate_length(buffer, len);
|
||||
if (rc != SSH_OK) {
|
||||
break;
|
||||
}
|
||||
|
||||
*o.cstring = malloc(u32len + 1);
|
||||
*o.cstring = malloc(len + 1);
|
||||
if (*o.cstring == NULL){
|
||||
rc = SSH_ERROR;
|
||||
break;
|
||||
}
|
||||
rlen = ssh_buffer_get_data(buffer, *o.cstring, u32len);
|
||||
if (rlen != u32len) {
|
||||
rlen = ssh_buffer_get_data(buffer, *o.cstring, len);
|
||||
if (rlen != len){
|
||||
SAFE_FREE(*o.cstring);
|
||||
rc = SSH_ERROR;
|
||||
break;
|
||||
}
|
||||
(*o.cstring)[u32len] = '\0';
|
||||
(*o.cstring)[len] = '\0';
|
||||
o.cstring = NULL;
|
||||
rc = SSH_OK;
|
||||
break;
|
||||
@@ -1267,7 +1233,7 @@ int ssh_buffer_unpack_va(struct ssh_buffer_struct *buffer,
|
||||
rc = SSH_ERROR;
|
||||
break;
|
||||
}
|
||||
rlen = ssh_buffer_get_data(buffer, *o.data, (uint32_t)len);
|
||||
rlen = ssh_buffer_get_data(buffer, *o.data, len);
|
||||
if (rlen != len){
|
||||
SAFE_FREE(*o.data);
|
||||
rc = SSH_ERROR;
|
||||
|
||||
@@ -24,11 +24,11 @@
|
||||
#include "config.h"
|
||||
|
||||
#include "libssh/callbacks.h"
|
||||
#include "libssh/misc.h"
|
||||
#include "libssh/session.h"
|
||||
#include "libssh/misc.h"
|
||||
|
||||
#define is_callback_valid(session, cb) \
|
||||
(cb->size > 0 || cb->size <= 1024 * sizeof(void *))
|
||||
(cb->size <= 0 || cb->size > 1024 * sizeof(void *))
|
||||
|
||||
/* LEGACY */
|
||||
static void ssh_legacy_log_callback(int priority,
|
||||
@@ -45,7 +45,8 @@ static void ssh_legacy_log_callback(int priority,
|
||||
log_fn(session, priority, buffer, log_data);
|
||||
}
|
||||
|
||||
void _ssh_remove_legacy_log_cb(void)
|
||||
void
|
||||
_ssh_remove_legacy_log_cb(void)
|
||||
{
|
||||
if (ssh_get_log_callback() == ssh_legacy_log_callback) {
|
||||
_ssh_reset_log_cb();
|
||||
@@ -53,27 +54,26 @@ void _ssh_remove_legacy_log_cb(void)
|
||||
}
|
||||
}
|
||||
|
||||
int ssh_set_callbacks(ssh_session session, ssh_callbacks cb)
|
||||
{
|
||||
if (session == NULL || cb == NULL) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
int ssh_set_callbacks(ssh_session session, ssh_callbacks cb) {
|
||||
if (session == NULL || cb == NULL) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
if (!is_callback_valid(session, cb)) {
|
||||
ssh_set_error(session,
|
||||
SSH_FATAL,
|
||||
"Invalid callback passed in (badly initialized)");
|
||||
return SSH_ERROR;
|
||||
};
|
||||
session->common.callbacks = cb;
|
||||
if (is_callback_valid(session, cb)) {
|
||||
ssh_set_error(session,
|
||||
SSH_FATAL,
|
||||
"Invalid callback passed in (badly initialized)");
|
||||
return SSH_ERROR;
|
||||
};
|
||||
session->common.callbacks = cb;
|
||||
|
||||
/* LEGACY */
|
||||
if (ssh_get_log_callback() == NULL && cb->log_function) {
|
||||
ssh_set_log_callback(ssh_legacy_log_callback);
|
||||
ssh_set_log_userdata(session);
|
||||
}
|
||||
/* LEGACY */
|
||||
if (ssh_get_log_callback() == NULL && cb->log_function) {
|
||||
ssh_set_log_callback(ssh_legacy_log_callback);
|
||||
ssh_set_log_userdata(session);
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ssh_add_set_channel_callbacks(ssh_channel channel,
|
||||
@@ -84,11 +84,11 @@ static int ssh_add_set_channel_callbacks(ssh_channel channel,
|
||||
int rc;
|
||||
|
||||
if (channel == NULL || cb == NULL) {
|
||||
return SSH_ERROR;
|
||||
return SSH_ERROR;
|
||||
}
|
||||
session = channel->session;
|
||||
|
||||
if (!is_callback_valid(session, cb)) {
|
||||
if (is_callback_valid(session, cb)) {
|
||||
ssh_set_error(session,
|
||||
SSH_FATAL,
|
||||
"Invalid callback passed in (badly initialized)");
|
||||
@@ -96,7 +96,7 @@ static int ssh_add_set_channel_callbacks(ssh_channel channel,
|
||||
};
|
||||
if (channel->callbacks == NULL) {
|
||||
channel->callbacks = ssh_list_new();
|
||||
if (channel->callbacks == NULL) {
|
||||
if (channel->callbacks == NULL){
|
||||
ssh_set_error_oom(session);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
@@ -124,12 +124,12 @@ int ssh_remove_channel_callbacks(ssh_channel channel, ssh_channel_callbacks cb)
|
||||
{
|
||||
struct ssh_iterator *it = NULL;
|
||||
|
||||
if (channel == NULL || channel->callbacks == NULL) {
|
||||
if (channel == NULL || channel->callbacks == NULL){
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
it = ssh_list_find(channel->callbacks, cb);
|
||||
if (it == NULL) {
|
||||
if (it == NULL){
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
@@ -138,19 +138,19 @@ int ssh_remove_channel_callbacks(ssh_channel channel, ssh_channel_callbacks cb)
|
||||
return SSH_OK;
|
||||
}
|
||||
|
||||
int ssh_set_server_callbacks(ssh_session session, ssh_server_callbacks cb)
|
||||
{
|
||||
if (session == NULL || cb == NULL) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
if (!is_callback_valid(session, cb)) {
|
||||
int ssh_set_server_callbacks(ssh_session session, ssh_server_callbacks cb){
|
||||
if (session == NULL || cb == NULL) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
if (is_callback_valid(session, cb)) {
|
||||
ssh_set_error(session,
|
||||
SSH_FATAL,
|
||||
"Invalid callback passed in (badly initialized)");
|
||||
return SSH_ERROR;
|
||||
};
|
||||
session->server_callbacks = cb;
|
||||
session->server_callbacks = cb;
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
1705
src/channels.c
1705
src/channels.c
File diff suppressed because it is too large
Load Diff
60
src/client.c
60
src/client.c
@@ -226,7 +226,7 @@ int ssh_send_banner(ssh_session session, int server)
|
||||
terminator);
|
||||
}
|
||||
|
||||
rc = ssh_socket_write(session->socket, buffer, (uint32_t)strlen(buffer));
|
||||
rc = ssh_socket_write(session->socket, buffer, strlen(buffer));
|
||||
if (rc == SSH_ERROR) {
|
||||
goto end;
|
||||
}
|
||||
@@ -235,8 +235,8 @@ int ssh_send_banner(ssh_session session, int server)
|
||||
ssh_pcap_context_write(session->pcap_ctx,
|
||||
SSH_PCAP_DIR_OUT,
|
||||
buffer,
|
||||
(uint32_t)strlen(buffer),
|
||||
(uint32_t)strlen(buffer));
|
||||
strlen(buffer),
|
||||
strlen(buffer));
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -254,52 +254,45 @@ end:
|
||||
*/
|
||||
int dh_handshake(ssh_session session)
|
||||
{
|
||||
int rc = SSH_AGAIN;
|
||||
int rc = SSH_AGAIN;
|
||||
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"dh_handshake_state = %d, kex_type = %d",
|
||||
session->dh_handshake_state,
|
||||
session->next_crypto->kex_type);
|
||||
SSH_LOG(SSH_LOG_TRACE, "dh_handshake_state = %d, kex_type = %d",
|
||||
session->dh_handshake_state, session->next_crypto->kex_type);
|
||||
|
||||
switch (session->dh_handshake_state) {
|
||||
switch (session->dh_handshake_state) {
|
||||
case DH_STATE_INIT:
|
||||
switch (session->next_crypto->kex_type) {
|
||||
switch(session->next_crypto->kex_type){
|
||||
case SSH_KEX_DH_GROUP1_SHA1:
|
||||
case SSH_KEX_DH_GROUP14_SHA1:
|
||||
case SSH_KEX_DH_GROUP14_SHA256:
|
||||
case SSH_KEX_DH_GROUP16_SHA512:
|
||||
case SSH_KEX_DH_GROUP18_SHA512:
|
||||
rc = ssh_client_dh_init(session);
|
||||
break;
|
||||
rc = ssh_client_dh_init(session);
|
||||
break;
|
||||
#ifdef WITH_GEX
|
||||
case SSH_KEX_DH_GEX_SHA1:
|
||||
case SSH_KEX_DH_GEX_SHA256:
|
||||
rc = ssh_client_dhgex_init(session);
|
||||
break;
|
||||
rc = ssh_client_dhgex_init(session);
|
||||
break;
|
||||
#endif /* WITH_GEX */
|
||||
#ifdef HAVE_ECDH
|
||||
case SSH_KEX_ECDH_SHA2_NISTP256:
|
||||
case SSH_KEX_ECDH_SHA2_NISTP384:
|
||||
case SSH_KEX_ECDH_SHA2_NISTP521:
|
||||
rc = ssh_client_ecdh_init(session);
|
||||
break;
|
||||
rc = ssh_client_ecdh_init(session);
|
||||
break;
|
||||
#endif
|
||||
#ifdef HAVE_CURVE25519
|
||||
case SSH_KEX_CURVE25519_SHA256:
|
||||
case SSH_KEX_CURVE25519_SHA256_LIBSSH_ORG:
|
||||
rc = ssh_client_curve25519_init(session);
|
||||
break;
|
||||
#endif
|
||||
#ifdef HAVE_SNTRUP761
|
||||
case SSH_KEX_SNTRUP761X25519_SHA512_OPENSSH_COM:
|
||||
rc = ssh_client_sntrup761x25519_init(session);
|
||||
break;
|
||||
rc = ssh_client_curve25519_init(session);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
rc = SSH_ERROR;
|
||||
}
|
||||
rc = SSH_ERROR;
|
||||
}
|
||||
|
||||
break;
|
||||
break;
|
||||
case DH_STATE_INIT_SENT:
|
||||
/* wait until ssh_packet_dh_reply is called */
|
||||
break;
|
||||
@@ -307,17 +300,15 @@ int dh_handshake(ssh_session session)
|
||||
/* wait until ssh_packet_newkeys is called */
|
||||
break;
|
||||
case DH_STATE_FINISHED:
|
||||
return SSH_OK;
|
||||
return SSH_OK;
|
||||
default:
|
||||
ssh_set_error(session,
|
||||
SSH_FATAL,
|
||||
"Invalid state in dh_handshake(): %d",
|
||||
session->dh_handshake_state);
|
||||
ssh_set_error(session, SSH_FATAL, "Invalid state in dh_handshake(): %d",
|
||||
session->dh_handshake_state);
|
||||
|
||||
return SSH_ERROR;
|
||||
}
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
return rc;
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int ssh_service_request_termination(void *s)
|
||||
@@ -845,6 +836,7 @@ error:
|
||||
session->opts.fd = SSH_INVALID_SOCKET;
|
||||
session->session_state = SSH_SESSION_STATE_DISCONNECTED;
|
||||
session->pending_call_state = SSH_PENDING_CALL_NONE;
|
||||
session->packet_state = PACKET_STATE_INIT;
|
||||
|
||||
while ((it = ssh_list_get_iterator(session->channels)) != NULL) {
|
||||
ssh_channel_do_free(ssh_iterator_value(ssh_channel, it));
|
||||
|
||||
75
src/config.c
75
src/config.c
@@ -1066,13 +1066,11 @@ ssh_config_parse_line(ssh_session session,
|
||||
}
|
||||
break;
|
||||
case SOC_USERNAME:
|
||||
if (session->opts.username == NULL) {
|
||||
p = ssh_config_get_str_tok(&s, NULL);
|
||||
if (p && *parsing) {
|
||||
p = ssh_config_get_str_tok(&s, NULL);
|
||||
if (p && *parsing) {
|
||||
ssh_options_set(session, SSH_OPTIONS_USER, p);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case SOC_IDENTITY:
|
||||
p = ssh_config_get_str_tok(&s, NULL);
|
||||
if (p && *parsing) {
|
||||
@@ -1451,32 +1449,6 @@ ssh_config_parse_line(ssh_session session,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* @brief Parse configuration from a file pointer
|
||||
*
|
||||
* @params[in] session The ssh session
|
||||
* @params[in] fp A valid file pointer
|
||||
* @params[in] global Whether the config is global or not
|
||||
*
|
||||
* @returns 0 on successful parsing the configuration file, -1 on error
|
||||
*/
|
||||
int ssh_config_parse(ssh_session session, FILE *fp, bool global)
|
||||
{
|
||||
char line[MAX_LINE_SIZE] = {0};
|
||||
unsigned int count = 0;
|
||||
int parsing, rv;
|
||||
|
||||
parsing = 1;
|
||||
while (fgets(line, sizeof(line), fp)) {
|
||||
count++;
|
||||
rv = ssh_config_parse_line(session, line, count, &parsing, 0, global);
|
||||
if (rv < 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* @brief Parse configuration file and set the options to the given session
|
||||
*
|
||||
* @params[in] session The ssh session
|
||||
@@ -1486,32 +1458,36 @@ int ssh_config_parse(ssh_session session, FILE *fp, bool global)
|
||||
*/
|
||||
int ssh_config_parse_file(ssh_session session, const char *filename)
|
||||
{
|
||||
FILE *fp = NULL;
|
||||
int rv;
|
||||
char line[MAX_LINE_SIZE] = {0};
|
||||
unsigned int count = 0;
|
||||
FILE *f = NULL;
|
||||
int parsing, rv;
|
||||
bool global = 0;
|
||||
|
||||
fp = fopen(filename, "r");
|
||||
if (fp == NULL) {
|
||||
f = fopen(filename, "r");
|
||||
if (f == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
rv = strcmp(filename, GLOBAL_CLIENT_CONFIG);
|
||||
#ifdef USR_GLOBAL_CLIENT_CONFIG
|
||||
if (rv != 0) {
|
||||
rv = strcmp(filename, USR_GLOBAL_CLIENT_CONFIG);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (rv == 0) {
|
||||
global = true;
|
||||
}
|
||||
|
||||
SSH_LOG(SSH_LOG_PACKET, "Reading configuration data from %s", filename);
|
||||
|
||||
rv = ssh_config_parse(session, fp, global);
|
||||
parsing = 1;
|
||||
while (fgets(line, sizeof(line), f)) {
|
||||
count++;
|
||||
rv = ssh_config_parse_line(session, line, count, &parsing, 0, global);
|
||||
if (rv < 0) {
|
||||
fclose(f);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
return rv;
|
||||
fclose(f);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* @brief Parse configuration string and set the options to the given session
|
||||
@@ -1526,8 +1502,7 @@ int ssh_config_parse_string(ssh_session session, const char *input)
|
||||
{
|
||||
char line[MAX_LINE_SIZE] = {0};
|
||||
const char *c = input, *line_start = input;
|
||||
unsigned int line_num = 0;
|
||||
size_t line_len;
|
||||
unsigned int line_num = 0, line_len;
|
||||
int parsing, rv;
|
||||
|
||||
SSH_LOG(SSH_LOG_DEBUG, "Reading configuration data from string:");
|
||||
@@ -1549,10 +1524,8 @@ int ssh_config_parse_string(ssh_session session, const char *input)
|
||||
}
|
||||
line_len = c - line_start;
|
||||
if (line_len > MAX_LINE_SIZE - 1) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Line %u too long: %zu characters",
|
||||
line_num,
|
||||
line_len);
|
||||
SSH_LOG(SSH_LOG_TRACE, "Line %u too long: %u characters",
|
||||
line_num, line_len);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
memcpy(line, line_start, line_len);
|
||||
|
||||
@@ -209,8 +209,7 @@ socket_t ssh_connect_host_nonblocking(ssh_session session, const char *host,
|
||||
bind_itr != NULL;
|
||||
bind_itr = bind_itr->ai_next)
|
||||
{
|
||||
rc = bind(s, bind_itr->ai_addr, bind_itr->ai_addrlen);
|
||||
if (rc < 0) {
|
||||
if (bind(s, bind_itr->ai_addr, bind_itr->ai_addrlen) < 0) {
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
"Binding local address: %s",
|
||||
ssh_strerror(errno, err_msg, SSH_ERRNO_MSG_MAX));
|
||||
|
||||
@@ -166,7 +166,7 @@ int ssh_connector_set_out_channel(ssh_connector connector,
|
||||
|
||||
/* Fallback to default value for invalid flags */
|
||||
if (!(flags & SSH_CONNECTOR_STDOUT) && !(flags & SSH_CONNECTOR_STDERR)) {
|
||||
connector->in_flags = SSH_CONNECTOR_STDOUT;
|
||||
connector->out_flags = SSH_CONNECTOR_STDOUT;
|
||||
}
|
||||
|
||||
return ssh_add_channel_callbacks(channel, &connector->out_channel_cb);
|
||||
@@ -264,17 +264,17 @@ static void ssh_connector_fd_in_cb(ssh_connector connector)
|
||||
}
|
||||
connector->in_available = 1; /* Don't poll on it */
|
||||
return;
|
||||
} else if (r > 0) {
|
||||
} else if (r> 0) {
|
||||
/* loop around ssh_channel_write in case our window reduced due to a race */
|
||||
while (total != r){
|
||||
if (connector->out_flags & SSH_CONNECTOR_STDOUT) {
|
||||
w = ssh_channel_write(connector->out_channel,
|
||||
buffer + total,
|
||||
(uint32_t)(r - total));
|
||||
r - total);
|
||||
} else {
|
||||
w = ssh_channel_write_stderr(connector->out_channel,
|
||||
buffer + total,
|
||||
(uint32_t)(r - total));
|
||||
r - total);
|
||||
}
|
||||
if (w == SSH_ERROR) {
|
||||
return;
|
||||
@@ -294,7 +294,7 @@ static void ssh_connector_fd_in_cb(ssh_connector connector)
|
||||
while (total < r) {
|
||||
w = ssh_connector_fd_write(connector,
|
||||
buffer + total,
|
||||
(uint32_t)(r - total));
|
||||
r - total);
|
||||
if (w < 0) {
|
||||
ssh_connector_except(connector, connector->out_fd);
|
||||
return;
|
||||
@@ -340,9 +340,8 @@ ssh_connector_fd_out_cb(ssh_connector connector)
|
||||
} else if (r > 0) {
|
||||
/* loop around write in case the write blocks even for CHUNKSIZE bytes */
|
||||
while (total != r) {
|
||||
w = ssh_connector_fd_write(connector,
|
||||
buffer + total,
|
||||
(uint32_t)(r - total));
|
||||
w = ssh_connector_fd_write(connector, buffer + total,
|
||||
r - total);
|
||||
if (w < 0) {
|
||||
ssh_connector_except(connector, connector->out_fd);
|
||||
return;
|
||||
@@ -382,15 +381,13 @@ ssh_connector_fd_out_cb(ssh_connector connector)
|
||||
*
|
||||
* @returns 0
|
||||
*/
|
||||
static int ssh_connector_fd_cb(ssh_poll_handle p,
|
||||
static int ssh_connector_fd_cb(UNUSED_PARAM(ssh_poll_handle p),
|
||||
socket_t fd,
|
||||
int revents,
|
||||
void *userdata)
|
||||
{
|
||||
ssh_connector connector = userdata;
|
||||
|
||||
(void)p;
|
||||
|
||||
if (revents & POLLERR) {
|
||||
ssh_connector_except(connector, fd);
|
||||
} else if((revents & (POLLIN|POLLHUP)) && fd == connector->in_fd) {
|
||||
@@ -420,7 +417,7 @@ static int ssh_connector_fd_cb(ssh_poll_handle p,
|
||||
* @returns Amount of data bytes consumed
|
||||
*/
|
||||
static int ssh_connector_channel_data_cb(ssh_session session,
|
||||
ssh_channel channel,
|
||||
UNUSED_PARAM(ssh_channel channel),
|
||||
void *data,
|
||||
uint32_t len,
|
||||
int is_stderr,
|
||||
@@ -430,10 +427,6 @@ static int ssh_connector_channel_data_cb(ssh_session session,
|
||||
int w;
|
||||
uint32_t window;
|
||||
|
||||
(void) session;
|
||||
(void) channel;
|
||||
(void) is_stderr;
|
||||
|
||||
SSH_LOG(SSH_LOG_TRACE,"connector data on channel");
|
||||
|
||||
if (is_stderr && !(connector->in_flags & SSH_CONNECTOR_STDERR)) {
|
||||
@@ -477,11 +470,9 @@ static int ssh_connector_channel_data_cb(ssh_session session,
|
||||
ssh_connector_except_channel(connector, connector->out_channel);
|
||||
}
|
||||
} else if (connector->out_fd != SSH_INVALID_SOCKET) {
|
||||
ssize_t ws = ssh_connector_fd_write(connector, data, len);
|
||||
if (ws < 0) {
|
||||
w = ssh_connector_fd_write(connector, data, len);
|
||||
if (w < 0)
|
||||
ssh_connector_except(connector, connector->out_fd);
|
||||
}
|
||||
w = (int)ws;
|
||||
} else {
|
||||
ssh_set_error(session, SSH_FATAL, "output socket or channel closed");
|
||||
return SSH_ERROR;
|
||||
@@ -513,10 +504,11 @@ static int ssh_connector_channel_data_cb(ssh_session session,
|
||||
*
|
||||
* @returns Amount of data bytes consumed
|
||||
*/
|
||||
static int ssh_connector_channel_write_wontblock_cb(ssh_session session,
|
||||
ssh_channel channel,
|
||||
uint32_t bytes,
|
||||
void *userdata)
|
||||
static int
|
||||
ssh_connector_channel_write_wontblock_cb(ssh_session session,
|
||||
UNUSED_PARAM(ssh_channel channel),
|
||||
uint32_t bytes,
|
||||
void *userdata)
|
||||
{
|
||||
ssh_connector connector = userdata;
|
||||
uint8_t buffer[CHUNKSIZE];
|
||||
|
||||
340
src/curve25519.c
340
src/curve25519.c
@@ -26,43 +26,119 @@
|
||||
#include "libssh/curve25519.h"
|
||||
#ifdef HAVE_CURVE25519
|
||||
|
||||
#include "libssh/bignum.h"
|
||||
#ifdef WITH_NACL
|
||||
#include "nacl/crypto_scalarmult_curve25519.h"
|
||||
#endif
|
||||
|
||||
#include "libssh/ssh2.h"
|
||||
#include "libssh/buffer.h"
|
||||
#include "libssh/priv.h"
|
||||
#include "libssh/session.h"
|
||||
#include "libssh/crypto.h"
|
||||
#include "libssh/dh.h"
|
||||
#include "libssh/pki.h"
|
||||
#include "libssh/priv.h"
|
||||
#include "libssh/session.h"
|
||||
#include "libssh/ssh2.h"
|
||||
#include "libssh/bignum.h"
|
||||
|
||||
#ifdef HAVE_LIBCRYPTO
|
||||
#include <openssl/err.h>
|
||||
#endif
|
||||
|
||||
static SSH_PACKET_CALLBACK(ssh_packet_client_curve25519_reply);
|
||||
|
||||
static ssh_packet_callback dh_client_callbacks[] = {
|
||||
ssh_packet_client_curve25519_reply,
|
||||
ssh_packet_client_curve25519_reply
|
||||
};
|
||||
|
||||
static struct ssh_packet_callbacks_struct ssh_curve25519_client_callbacks = {
|
||||
.start = SSH2_MSG_KEX_ECDH_REPLY,
|
||||
.n_callbacks = 1,
|
||||
.callbacks = dh_client_callbacks,
|
||||
.user = NULL,
|
||||
.user = NULL
|
||||
};
|
||||
|
||||
int ssh_curve25519_create_k(ssh_session session, ssh_curve25519_pubkey k)
|
||||
static int ssh_curve25519_init(ssh_session session)
|
||||
{
|
||||
int rc;
|
||||
#ifdef HAVE_LIBCRYPTO
|
||||
EVP_PKEY_CTX *pctx = NULL;
|
||||
EVP_PKEY *pkey = NULL;
|
||||
size_t pubkey_len = CURVE25519_PUBKEY_SIZE;
|
||||
size_t pkey_len = CURVE25519_PRIVKEY_SIZE;
|
||||
|
||||
#ifdef DEBUG_CRYPTO
|
||||
ssh_log_hexdump("Session server cookie",
|
||||
session->next_crypto->server_kex.cookie,
|
||||
16);
|
||||
ssh_log_hexdump("Session client cookie",
|
||||
session->next_crypto->client_kex.cookie,
|
||||
16);
|
||||
#endif
|
||||
pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_X25519, NULL);
|
||||
if (pctx == NULL) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Failed to initialize X25519 context: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
rc = curve25519_do_create_k(session, k);
|
||||
return rc;
|
||||
rc = EVP_PKEY_keygen_init(pctx);
|
||||
if (rc != 1) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Failed to initialize X25519 keygen: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
EVP_PKEY_CTX_free(pctx);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
rc = EVP_PKEY_keygen(pctx, &pkey);
|
||||
EVP_PKEY_CTX_free(pctx);
|
||||
if (rc != 1) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Failed to generate X25519 keys: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
if (session->server) {
|
||||
rc = EVP_PKEY_get_raw_public_key(pkey,
|
||||
session->next_crypto->curve25519_server_pubkey,
|
||||
&pubkey_len);
|
||||
} else {
|
||||
rc = EVP_PKEY_get_raw_public_key(pkey,
|
||||
session->next_crypto->curve25519_client_pubkey,
|
||||
&pubkey_len);
|
||||
}
|
||||
|
||||
if (rc != 1) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Failed to get X25519 raw public key: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
EVP_PKEY_free(pkey);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
rc = EVP_PKEY_get_raw_private_key(pkey,
|
||||
session->next_crypto->curve25519_privkey,
|
||||
&pkey_len);
|
||||
if (rc != 1) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Failed to get X25519 raw private key: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
EVP_PKEY_free(pkey);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
EVP_PKEY_free(pkey);
|
||||
#else
|
||||
rc = ssh_get_random(session->next_crypto->curve25519_privkey,
|
||||
CURVE25519_PRIVKEY_SIZE, 1);
|
||||
if (rc != 1) {
|
||||
ssh_set_error(session, SSH_FATAL, "PRNG error");
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
if (session->server) {
|
||||
crypto_scalarmult_base(session->next_crypto->curve25519_server_pubkey,
|
||||
session->next_crypto->curve25519_privkey);
|
||||
} else {
|
||||
crypto_scalarmult_base(session->next_crypto->curve25519_client_pubkey,
|
||||
session->next_crypto->curve25519_privkey);
|
||||
}
|
||||
#endif /* HAVE_LIBCRYPTO */
|
||||
|
||||
return SSH_OK;
|
||||
}
|
||||
|
||||
/** @internal
|
||||
@@ -104,120 +180,193 @@ void ssh_client_curve25519_remove_callbacks(ssh_session session)
|
||||
static int ssh_curve25519_build_k(ssh_session session)
|
||||
{
|
||||
ssh_curve25519_pubkey k;
|
||||
int rc;
|
||||
|
||||
rc = ssh_curve25519_create_k(session, k);
|
||||
if (rc != SSH_OK) {
|
||||
return rc;
|
||||
#ifdef HAVE_LIBCRYPTO
|
||||
EVP_PKEY_CTX *pctx = NULL;
|
||||
EVP_PKEY *pkey = NULL, *pubkey = NULL;
|
||||
size_t shared_key_len = sizeof(k);
|
||||
int rc, ret = SSH_ERROR;
|
||||
|
||||
pkey = EVP_PKEY_new_raw_private_key(EVP_PKEY_X25519, NULL,
|
||||
session->next_crypto->curve25519_privkey,
|
||||
CURVE25519_PRIVKEY_SIZE);
|
||||
if (pkey == NULL) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Failed to create X25519 EVP_PKEY: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
bignum_bin2bn(k,
|
||||
CURVE25519_PUBKEY_SIZE,
|
||||
&session->next_crypto->shared_secret);
|
||||
pctx = EVP_PKEY_CTX_new(pkey, NULL);
|
||||
if (pctx == NULL) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Failed to initialize X25519 context: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = EVP_PKEY_derive_init(pctx);
|
||||
if (rc != 1) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Failed to initialize X25519 key derivation: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (session->server) {
|
||||
pubkey = EVP_PKEY_new_raw_public_key(EVP_PKEY_X25519, NULL,
|
||||
session->next_crypto->curve25519_client_pubkey,
|
||||
CURVE25519_PUBKEY_SIZE);
|
||||
} else {
|
||||
pubkey = EVP_PKEY_new_raw_public_key(EVP_PKEY_X25519, NULL,
|
||||
session->next_crypto->curve25519_server_pubkey,
|
||||
CURVE25519_PUBKEY_SIZE);
|
||||
}
|
||||
if (pubkey == NULL) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Failed to create X25519 public key EVP_PKEY: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = EVP_PKEY_derive_set_peer(pctx, pubkey);
|
||||
if (rc != 1) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Failed to set peer X25519 public key: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = EVP_PKEY_derive(pctx, k, &shared_key_len);
|
||||
if (rc != 1) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Failed to derive X25519 shared secret: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
goto out;
|
||||
}
|
||||
ret = SSH_OK;
|
||||
out:
|
||||
EVP_PKEY_free(pkey);
|
||||
EVP_PKEY_free(pubkey);
|
||||
EVP_PKEY_CTX_free(pctx);
|
||||
if (ret == SSH_ERROR) {
|
||||
return ret;
|
||||
}
|
||||
#else
|
||||
if (session->server) {
|
||||
crypto_scalarmult(k, session->next_crypto->curve25519_privkey,
|
||||
session->next_crypto->curve25519_client_pubkey);
|
||||
} else {
|
||||
crypto_scalarmult(k, session->next_crypto->curve25519_privkey,
|
||||
session->next_crypto->curve25519_server_pubkey);
|
||||
}
|
||||
#endif /* HAVE_LIBCRYPTO */
|
||||
|
||||
bignum_bin2bn(k, CURVE25519_PUBKEY_SIZE, &session->next_crypto->shared_secret);
|
||||
if (session->next_crypto->shared_secret == NULL) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_CRYPTO
|
||||
ssh_log_hexdump("Session server cookie",
|
||||
session->next_crypto->server_kex.cookie, 16);
|
||||
ssh_log_hexdump("Session client cookie",
|
||||
session->next_crypto->client_kex.cookie, 16);
|
||||
ssh_print_bignum("Shared secret key", session->next_crypto->shared_secret);
|
||||
#endif
|
||||
|
||||
return SSH_OK;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** @internal
|
||||
* @brief parses a SSH_MSG_KEX_ECDH_REPLY packet and sends back
|
||||
* a SSH_MSG_NEWKEYS
|
||||
*/
|
||||
static SSH_PACKET_CALLBACK(ssh_packet_client_curve25519_reply)
|
||||
{
|
||||
ssh_string q_s_string = NULL;
|
||||
ssh_string pubkey_blob = NULL;
|
||||
ssh_string signature = NULL;
|
||||
int rc;
|
||||
(void)type;
|
||||
(void)user;
|
||||
static SSH_PACKET_CALLBACK(ssh_packet_client_curve25519_reply){
|
||||
ssh_string q_s_string = NULL;
|
||||
ssh_string pubkey_blob = NULL;
|
||||
ssh_string signature = NULL;
|
||||
int rc;
|
||||
(void)type;
|
||||
(void)user;
|
||||
|
||||
ssh_client_curve25519_remove_callbacks(session);
|
||||
ssh_client_curve25519_remove_callbacks(session);
|
||||
|
||||
pubkey_blob = ssh_buffer_get_ssh_string(packet);
|
||||
if (pubkey_blob == NULL) {
|
||||
ssh_set_error(session, SSH_FATAL, "No public key in packet");
|
||||
goto error;
|
||||
}
|
||||
pubkey_blob = ssh_buffer_get_ssh_string(packet);
|
||||
if (pubkey_blob == NULL) {
|
||||
ssh_set_error(session,SSH_FATAL, "No public key in packet");
|
||||
goto error;
|
||||
}
|
||||
|
||||
rc = ssh_dh_import_next_pubkey_blob(session, pubkey_blob);
|
||||
SSH_STRING_FREE(pubkey_blob);
|
||||
if (rc != 0) {
|
||||
ssh_set_error(session, SSH_FATAL, "Failed to import next public key");
|
||||
goto error;
|
||||
}
|
||||
rc = ssh_dh_import_next_pubkey_blob(session, pubkey_blob);
|
||||
SSH_STRING_FREE(pubkey_blob);
|
||||
if (rc != 0) {
|
||||
ssh_set_error(session,
|
||||
SSH_FATAL,
|
||||
"Failed to import next public key");
|
||||
goto error;
|
||||
}
|
||||
|
||||
q_s_string = ssh_buffer_get_ssh_string(packet);
|
||||
if (q_s_string == NULL) {
|
||||
ssh_set_error(session, SSH_FATAL, "No Q_S ECC point in packet");
|
||||
goto error;
|
||||
}
|
||||
if (ssh_string_len(q_s_string) != CURVE25519_PUBKEY_SIZE) {
|
||||
ssh_set_error(session,
|
||||
SSH_FATAL,
|
||||
"Incorrect size for server Curve25519 public key: %zu",
|
||||
ssh_string_len(q_s_string));
|
||||
SSH_STRING_FREE(q_s_string);
|
||||
goto error;
|
||||
}
|
||||
memcpy(session->next_crypto->curve25519_server_pubkey,
|
||||
ssh_string_data(q_s_string),
|
||||
CURVE25519_PUBKEY_SIZE);
|
||||
SSH_STRING_FREE(q_s_string);
|
||||
q_s_string = ssh_buffer_get_ssh_string(packet);
|
||||
if (q_s_string == NULL) {
|
||||
ssh_set_error(session,SSH_FATAL, "No Q_S ECC point in packet");
|
||||
goto error;
|
||||
}
|
||||
if (ssh_string_len(q_s_string) != CURVE25519_PUBKEY_SIZE){
|
||||
ssh_set_error(session, SSH_FATAL, "Incorrect size for server Curve25519 public key: %d",
|
||||
(int)ssh_string_len(q_s_string));
|
||||
SSH_STRING_FREE(q_s_string);
|
||||
goto error;
|
||||
}
|
||||
memcpy(session->next_crypto->curve25519_server_pubkey, ssh_string_data(q_s_string), CURVE25519_PUBKEY_SIZE);
|
||||
SSH_STRING_FREE(q_s_string);
|
||||
|
||||
signature = ssh_buffer_get_ssh_string(packet);
|
||||
if (signature == NULL) {
|
||||
ssh_set_error(session, SSH_FATAL, "No signature in packet");
|
||||
goto error;
|
||||
}
|
||||
session->next_crypto->dh_server_signature = signature;
|
||||
signature = NULL; /* ownership changed */
|
||||
/* TODO: verify signature now instead of waiting for NEWKEYS */
|
||||
if (ssh_curve25519_build_k(session) < 0) {
|
||||
ssh_set_error(session, SSH_FATAL, "Cannot build k number");
|
||||
goto error;
|
||||
}
|
||||
signature = ssh_buffer_get_ssh_string(packet);
|
||||
if (signature == NULL) {
|
||||
ssh_set_error(session, SSH_FATAL, "No signature in packet");
|
||||
goto error;
|
||||
}
|
||||
session->next_crypto->dh_server_signature = signature;
|
||||
signature=NULL; /* ownership changed */
|
||||
/* TODO: verify signature now instead of waiting for NEWKEYS */
|
||||
if (ssh_curve25519_build_k(session) < 0) {
|
||||
ssh_set_error(session, SSH_FATAL, "Cannot build k number");
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Send the MSG_NEWKEYS */
|
||||
rc = ssh_packet_send_newkeys(session);
|
||||
if (rc == SSH_ERROR) {
|
||||
goto error;
|
||||
}
|
||||
session->dh_handshake_state = DH_STATE_NEWKEYS_SENT;
|
||||
/* Send the MSG_NEWKEYS */
|
||||
rc = ssh_packet_send_newkeys(session);
|
||||
if (rc == SSH_ERROR) {
|
||||
goto error;
|
||||
}
|
||||
session->dh_handshake_state = DH_STATE_NEWKEYS_SENT;
|
||||
|
||||
return SSH_PACKET_USED;
|
||||
return SSH_PACKET_USED;
|
||||
|
||||
error:
|
||||
session->session_state = SSH_SESSION_STATE_ERROR;
|
||||
return SSH_PACKET_USED;
|
||||
session->session_state=SSH_SESSION_STATE_ERROR;
|
||||
return SSH_PACKET_USED;
|
||||
}
|
||||
|
||||
#ifdef WITH_SERVER
|
||||
|
||||
static SSH_PACKET_CALLBACK(ssh_packet_server_curve25519_init);
|
||||
|
||||
static ssh_packet_callback dh_server_callbacks[] = {
|
||||
ssh_packet_server_curve25519_init,
|
||||
static ssh_packet_callback dh_server_callbacks[]= {
|
||||
ssh_packet_server_curve25519_init
|
||||
};
|
||||
|
||||
static struct ssh_packet_callbacks_struct ssh_curve25519_server_callbacks = {
|
||||
.start = SSH2_MSG_KEX_ECDH_INIT,
|
||||
.n_callbacks = 1,
|
||||
.callbacks = dh_server_callbacks,
|
||||
.user = NULL,
|
||||
.user = NULL
|
||||
};
|
||||
|
||||
/** @internal
|
||||
* @brief sets up the curve25519-sha256@libssh.org kex callbacks
|
||||
*/
|
||||
void ssh_server_curve25519_init(ssh_session session)
|
||||
{
|
||||
void ssh_server_curve25519_init(ssh_session session){
|
||||
/* register the packet callbacks */
|
||||
ssh_packet_set_callbacks(session, &ssh_curve25519_server_callbacks);
|
||||
}
|
||||
@@ -225,8 +374,7 @@ void ssh_server_curve25519_init(ssh_session session)
|
||||
/** @brief Parse a SSH_MSG_KEXDH_INIT packet (server) and send a
|
||||
* SSH_MSG_KEXDH_REPLY
|
||||
*/
|
||||
static SSH_PACKET_CALLBACK(ssh_packet_server_curve25519_init)
|
||||
{
|
||||
static SSH_PACKET_CALLBACK(ssh_packet_server_curve25519_init){
|
||||
/* ECDH keys */
|
||||
ssh_string q_c_string = NULL;
|
||||
ssh_string q_s_string = NULL;
|
||||
@@ -245,10 +393,10 @@ static SSH_PACKET_CALLBACK(ssh_packet_server_curve25519_init)
|
||||
/* Extract the client pubkey from the init packet */
|
||||
q_c_string = ssh_buffer_get_ssh_string(packet);
|
||||
if (q_c_string == NULL) {
|
||||
ssh_set_error(session, SSH_FATAL, "No Q_C ECC point in packet");
|
||||
ssh_set_error(session,SSH_FATAL, "No Q_C ECC point in packet");
|
||||
goto error;
|
||||
}
|
||||
if (ssh_string_len(q_c_string) != CURVE25519_PUBKEY_SIZE) {
|
||||
if (ssh_string_len(q_c_string) != CURVE25519_PUBKEY_SIZE){
|
||||
ssh_set_error(session,
|
||||
SSH_FATAL,
|
||||
"Incorrect size for server Curve25519 public key: %zu",
|
||||
@@ -257,8 +405,7 @@ static SSH_PACKET_CALLBACK(ssh_packet_server_curve25519_init)
|
||||
}
|
||||
|
||||
memcpy(session->next_crypto->curve25519_client_pubkey,
|
||||
ssh_string_data(q_c_string),
|
||||
CURVE25519_PUBKEY_SIZE);
|
||||
ssh_string_data(q_c_string), CURVE25519_PUBKEY_SIZE);
|
||||
SSH_STRING_FREE(q_c_string);
|
||||
|
||||
/* Build server's key pair */
|
||||
@@ -300,7 +447,8 @@ static SSH_PACKET_CALLBACK(ssh_packet_server_curve25519_init)
|
||||
}
|
||||
|
||||
/* add host's public key */
|
||||
rc = ssh_buffer_add_ssh_string(session->out_buffer, server_pubkey_blob);
|
||||
rc = ssh_buffer_add_ssh_string(session->out_buffer,
|
||||
server_pubkey_blob);
|
||||
SSH_STRING_FREE(server_pubkey_blob);
|
||||
if (rc < 0) {
|
||||
ssh_set_error_oom(session);
|
||||
@@ -361,7 +509,7 @@ error:
|
||||
SSH_STRING_FREE(q_c_string);
|
||||
SSH_STRING_FREE(q_s_string);
|
||||
ssh_buffer_reinit(session->out_buffer);
|
||||
session->session_state = SSH_SESSION_STATE_ERROR;
|
||||
session->session_state=SSH_SESSION_STATE_ERROR;
|
||||
return SSH_PACKET_USED;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,158 +0,0 @@
|
||||
/*
|
||||
* curve25519_crypto.c - Curve25519 ECDH functions for key exchange (OpenSSL)
|
||||
*
|
||||
* This file is part of the SSH Library
|
||||
*
|
||||
* Copyright (c) 2013-2023 by Aris Adamantiadis <aris@badcode.be>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "libssh/curve25519.h"
|
||||
|
||||
#include "libssh/crypto.h"
|
||||
#include "libssh/priv.h"
|
||||
#include "libssh/session.h"
|
||||
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/evp.h>
|
||||
|
||||
int ssh_curve25519_init(ssh_session session)
|
||||
{
|
||||
ssh_curve25519_pubkey *pubkey_loc = NULL;
|
||||
EVP_PKEY_CTX *pctx = NULL;
|
||||
EVP_PKEY *pkey = NULL;
|
||||
size_t pubkey_len = CURVE25519_PUBKEY_SIZE;
|
||||
int rc;
|
||||
|
||||
if (session->server) {
|
||||
pubkey_loc = &session->next_crypto->curve25519_server_pubkey;
|
||||
} else {
|
||||
pubkey_loc = &session->next_crypto->curve25519_client_pubkey;
|
||||
}
|
||||
|
||||
pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_X25519, NULL);
|
||||
if (pctx == NULL) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Failed to initialize X25519 context: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
rc = EVP_PKEY_keygen_init(pctx);
|
||||
if (rc != 1) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Failed to initialize X25519 keygen: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
EVP_PKEY_CTX_free(pctx);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
rc = EVP_PKEY_keygen(pctx, &pkey);
|
||||
EVP_PKEY_CTX_free(pctx);
|
||||
if (rc != 1) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Failed to generate X25519 keys: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
rc = EVP_PKEY_get_raw_public_key(pkey, *pubkey_loc, &pubkey_len);
|
||||
if (rc != 1) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Failed to get X25519 raw public key: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
EVP_PKEY_free(pkey);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
session->next_crypto->curve25519_privkey = pkey;
|
||||
pkey = NULL;
|
||||
|
||||
return SSH_OK;
|
||||
}
|
||||
|
||||
int curve25519_do_create_k(ssh_session session, ssh_curve25519_pubkey k)
|
||||
{
|
||||
ssh_curve25519_pubkey *peer_pubkey_loc = NULL;
|
||||
int rc, ret = SSH_ERROR;
|
||||
EVP_PKEY_CTX *pctx = NULL;
|
||||
EVP_PKEY *pkey = NULL, *pubkey = NULL;
|
||||
size_t shared_key_len = CURVE25519_PUBKEY_SIZE;
|
||||
|
||||
if (session->server) {
|
||||
peer_pubkey_loc = &session->next_crypto->curve25519_client_pubkey;
|
||||
} else {
|
||||
peer_pubkey_loc = &session->next_crypto->curve25519_server_pubkey;
|
||||
}
|
||||
|
||||
pkey = session->next_crypto->curve25519_privkey;
|
||||
if (pkey == NULL) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Failed to create X25519 EVP_PKEY: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
pctx = EVP_PKEY_CTX_new(pkey, NULL);
|
||||
if (pctx == NULL) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Failed to initialize X25519 context: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = EVP_PKEY_derive_init(pctx);
|
||||
if (rc != 1) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Failed to initialize X25519 key derivation: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
goto out;
|
||||
}
|
||||
|
||||
pubkey = EVP_PKEY_new_raw_public_key(EVP_PKEY_X25519,
|
||||
NULL,
|
||||
*peer_pubkey_loc,
|
||||
CURVE25519_PUBKEY_SIZE);
|
||||
if (pubkey == NULL) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Failed to create X25519 public key EVP_PKEY: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = EVP_PKEY_derive_set_peer(pctx, pubkey);
|
||||
if (rc != 1) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Failed to set peer X25519 public key: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = EVP_PKEY_derive(pctx, k, &shared_key_len);
|
||||
if (rc != 1) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Failed to derive X25519 shared secret: %s",
|
||||
ERR_error_string(ERR_get_error(), NULL));
|
||||
goto out;
|
||||
}
|
||||
ret = SSH_OK;
|
||||
|
||||
out:
|
||||
EVP_PKEY_free(pubkey);
|
||||
EVP_PKEY_CTX_free(pctx);
|
||||
return ret;
|
||||
}
|
||||
@@ -1,73 +0,0 @@
|
||||
/*
|
||||
* curve25519_fallback.c - Curve25519 ECDH functions for key exchange
|
||||
*
|
||||
* This file is part of the SSH Library
|
||||
*
|
||||
* Copyright (c) 2013-2023 by Aris Adamantiadis <aris@badcode.be>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "libssh/curve25519.h"
|
||||
|
||||
#include "libssh/crypto.h"
|
||||
#include "libssh/priv.h"
|
||||
#include "libssh/session.h"
|
||||
|
||||
#ifdef WITH_NACL
|
||||
#include "nacl/crypto_scalarmult_curve25519.h"
|
||||
#endif
|
||||
|
||||
int ssh_curve25519_init(ssh_session session)
|
||||
{
|
||||
ssh_curve25519_pubkey *pubkey_loc = NULL;
|
||||
int rc;
|
||||
|
||||
if (session->server) {
|
||||
pubkey_loc = &session->next_crypto->curve25519_server_pubkey;
|
||||
} else {
|
||||
pubkey_loc = &session->next_crypto->curve25519_client_pubkey;
|
||||
}
|
||||
|
||||
rc = ssh_get_random(session->next_crypto->curve25519_privkey,
|
||||
CURVE25519_PRIVKEY_SIZE,
|
||||
1);
|
||||
if (rc != 1) {
|
||||
ssh_set_error(session, SSH_FATAL, "PRNG error");
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
crypto_scalarmult_base(*pubkey_loc,
|
||||
session->next_crypto->curve25519_privkey);
|
||||
|
||||
return SSH_OK;
|
||||
}
|
||||
|
||||
int curve25519_do_create_k(ssh_session session, ssh_curve25519_pubkey k)
|
||||
{
|
||||
ssh_curve25519_pubkey *peer_pubkey_loc = NULL;
|
||||
|
||||
if (session->server) {
|
||||
peer_pubkey_loc = &session->next_crypto->curve25519_client_pubkey;
|
||||
} else {
|
||||
peer_pubkey_loc = &session->next_crypto->curve25519_server_pubkey;
|
||||
}
|
||||
|
||||
crypto_scalarmult(k,
|
||||
session->next_crypto->curve25519_privkey,
|
||||
*peer_pubkey_loc);
|
||||
return SSH_OK;
|
||||
}
|
||||
@@ -1,199 +0,0 @@
|
||||
/*
|
||||
* curve25519_gcrypt.c - Curve25519 ECDH functions for key exchange (Gcrypt)
|
||||
*
|
||||
* This file is part of the SSH Library
|
||||
*
|
||||
* Copyright (c) 2013-2023 by Aris Adamantiadis <aris@badcode.be>
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "libssh/curve25519.h"
|
||||
|
||||
#include "libssh/buffer.h"
|
||||
#include "libssh/crypto.h"
|
||||
#include "libssh/priv.h"
|
||||
#include "libssh/session.h"
|
||||
|
||||
#include <gcrypt.h>
|
||||
|
||||
int ssh_curve25519_init(ssh_session session)
|
||||
{
|
||||
ssh_curve25519_pubkey *pubkey_loc = NULL;
|
||||
gcry_error_t gcry_err;
|
||||
gcry_sexp_t param = NULL, keypair_sexp = NULL;
|
||||
ssh_string pubkey = NULL;
|
||||
const char *pubkey_data = NULL;
|
||||
int ret = SSH_ERROR;
|
||||
|
||||
if (session->server) {
|
||||
pubkey_loc = &session->next_crypto->curve25519_server_pubkey;
|
||||
} else {
|
||||
pubkey_loc = &session->next_crypto->curve25519_client_pubkey;
|
||||
}
|
||||
|
||||
gcry_err =
|
||||
gcry_sexp_build(¶m, NULL, "(genkey (ecdh (curve Curve25519)))");
|
||||
if (gcry_err != GPG_ERR_NO_ERROR) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Failed to create keypair sexp: %s",
|
||||
gcry_strerror(gcry_err));
|
||||
goto out;
|
||||
}
|
||||
|
||||
gcry_err = gcry_pk_genkey(&keypair_sexp, param);
|
||||
if (gcry_err != GPG_ERR_NO_ERROR) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Failed to generate keypair: %s",
|
||||
gcry_strerror(gcry_err));
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Extract the public key */
|
||||
pubkey = ssh_sexp_extract_mpi(keypair_sexp,
|
||||
"q",
|
||||
GCRYMPI_FMT_USG,
|
||||
GCRYMPI_FMT_STD);
|
||||
if (pubkey == NULL) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Failed to extract public key: %s",
|
||||
gcry_strerror(gcry_err));
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Store the public key in the session */
|
||||
/* The first byte should be 0x40 indicating that the point is compressed, so
|
||||
* we skip storing it */
|
||||
pubkey_data = (char *)ssh_string_data(pubkey);
|
||||
if (ssh_string_len(pubkey) != CURVE25519_PUBKEY_SIZE + 1 ||
|
||||
pubkey_data[0] != 0x40) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Invalid public key with length: %zu",
|
||||
ssh_string_len(pubkey));
|
||||
goto out;
|
||||
}
|
||||
|
||||
memcpy(*pubkey_loc, pubkey_data + 1, CURVE25519_PUBKEY_SIZE);
|
||||
|
||||
/* Store the private key */
|
||||
session->next_crypto->curve25519_privkey = keypair_sexp;
|
||||
keypair_sexp = NULL;
|
||||
ret = SSH_OK;
|
||||
|
||||
out:
|
||||
ssh_string_burn(pubkey);
|
||||
SSH_STRING_FREE(pubkey);
|
||||
gcry_sexp_release(param);
|
||||
gcry_sexp_release(keypair_sexp);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int curve25519_do_create_k(ssh_session session, ssh_curve25519_pubkey k)
|
||||
{
|
||||
ssh_curve25519_pubkey *peer_pubkey_loc = NULL;
|
||||
gcry_error_t gcry_err;
|
||||
gcry_sexp_t pubkey_sexp = NULL, privkey_data_sexp = NULL,
|
||||
result_sexp = NULL;
|
||||
ssh_string shared_secret = NULL, privkey = NULL;
|
||||
char *shared_secret_data = NULL;
|
||||
int ret = SSH_ERROR;
|
||||
|
||||
if (session->server) {
|
||||
peer_pubkey_loc = &session->next_crypto->curve25519_client_pubkey;
|
||||
} else {
|
||||
peer_pubkey_loc = &session->next_crypto->curve25519_server_pubkey;
|
||||
}
|
||||
|
||||
gcry_err = gcry_sexp_build(
|
||||
&pubkey_sexp,
|
||||
NULL,
|
||||
"(key-data(public-key (ecdh (curve Curve25519) (q %b))))",
|
||||
CURVE25519_PUBKEY_SIZE,
|
||||
*peer_pubkey_loc);
|
||||
if (gcry_err != GPG_ERR_NO_ERROR) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Failed to create peer public key sexp: %s",
|
||||
gcry_strerror(gcry_err));
|
||||
goto out;
|
||||
}
|
||||
|
||||
privkey = ssh_sexp_extract_mpi(session->next_crypto->curve25519_privkey,
|
||||
"d",
|
||||
GCRYMPI_FMT_USG,
|
||||
GCRYMPI_FMT_STD);
|
||||
if (privkey == NULL) {
|
||||
SSH_LOG(SSH_LOG_TRACE, "Failed to extract private key");
|
||||
goto out;
|
||||
}
|
||||
|
||||
gcry_err = gcry_sexp_build(&privkey_data_sexp,
|
||||
NULL,
|
||||
"(data(flags raw)(value %b))",
|
||||
ssh_string_len(privkey),
|
||||
ssh_string_data(privkey));
|
||||
if (gcry_err != GPG_ERR_NO_ERROR) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Failed to create private key sexp: %s",
|
||||
gcry_strerror(gcry_err));
|
||||
goto out;
|
||||
}
|
||||
|
||||
gcry_err = gcry_pk_encrypt(&result_sexp, privkey_data_sexp, pubkey_sexp);
|
||||
if (gcry_err != GPG_ERR_NO_ERROR) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Failed to compute shared secret: %s",
|
||||
gcry_strerror(gcry_err));
|
||||
goto out;
|
||||
}
|
||||
|
||||
shared_secret = ssh_sexp_extract_mpi(result_sexp,
|
||||
"s",
|
||||
GCRYMPI_FMT_USG,
|
||||
GCRYMPI_FMT_USG);
|
||||
if (shared_secret == NULL) {
|
||||
SSH_LOG(SSH_LOG_TRACE, "Failed to extract shared secret");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Copy the shared secret to the output buffer */
|
||||
/* The first byte should be 0x40 indicating that it is a compressed point,
|
||||
* so we skip it */
|
||||
shared_secret_data = (char *)ssh_string_data(shared_secret);
|
||||
if (ssh_string_len(shared_secret) != CURVE25519_PUBKEY_SIZE + 1 ||
|
||||
shared_secret_data[0] != 0x40) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Invalid shared secret with length: %zu",
|
||||
ssh_string_len(shared_secret));
|
||||
goto out;
|
||||
}
|
||||
|
||||
memcpy(k, shared_secret_data + 1, CURVE25519_PUBKEY_SIZE);
|
||||
|
||||
ret = SSH_OK;
|
||||
gcry_sexp_release(session->next_crypto->curve25519_privkey);
|
||||
session->next_crypto->curve25519_privkey = NULL;
|
||||
|
||||
out:
|
||||
ssh_string_burn(shared_secret);
|
||||
SSH_STRING_FREE(shared_secret);
|
||||
ssh_string_burn(privkey);
|
||||
SSH_STRING_FREE(privkey);
|
||||
gcry_sexp_release(privkey_data_sexp);
|
||||
gcry_sexp_release(pubkey_sexp);
|
||||
gcry_sexp_release(result_sexp);
|
||||
return ret;
|
||||
}
|
||||
@@ -1,189 +0,0 @@
|
||||
/*
|
||||
* curve25519_mbedcrypto.c - Curve25519 ECDH functions for key exchange
|
||||
* (MbedTLS)
|
||||
*
|
||||
* This file is part of the SSH Library
|
||||
*
|
||||
* Copyright (c) 2013-2023 by Aris Adamantiadis <aris@badcode.be>
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "libssh/curve25519.h"
|
||||
|
||||
#include "libssh/crypto.h"
|
||||
#include "libssh/priv.h"
|
||||
#include "libssh/session.h"
|
||||
#include "mbedcrypto-compat.h"
|
||||
|
||||
#include <mbedtls/ecdh.h>
|
||||
#include <mbedtls/error.h>
|
||||
|
||||
int ssh_curve25519_init(ssh_session session)
|
||||
{
|
||||
ssh_curve25519_pubkey *pubkey_loc = NULL;
|
||||
mbedtls_ecdh_context ecdh_ctx;
|
||||
mbedtls_ecdh_params *ecdh_params = NULL;
|
||||
mbedtls_ctr_drbg_context *ctr_drbg = NULL;
|
||||
int rc, ret = SSH_ERROR;
|
||||
char error_buf[128];
|
||||
|
||||
if (session->server) {
|
||||
pubkey_loc = &session->next_crypto->curve25519_server_pubkey;
|
||||
} else {
|
||||
pubkey_loc = &session->next_crypto->curve25519_client_pubkey;
|
||||
}
|
||||
|
||||
ctr_drbg = ssh_get_mbedtls_ctr_drbg_context();
|
||||
|
||||
mbedtls_ecdh_init(&ecdh_ctx);
|
||||
rc = mbedtls_ecdh_setup(&ecdh_ctx, MBEDTLS_ECP_DP_CURVE25519);
|
||||
if (rc != 0) {
|
||||
mbedtls_strerror(rc, error_buf, sizeof(error_buf));
|
||||
SSH_LOG(SSH_LOG_TRACE, "Failed to setup X25519 context: %s", error_buf);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ecdh_params = &MBEDTLS_ECDH_PARAMS(ecdh_ctx);
|
||||
|
||||
rc = mbedtls_ecdh_gen_public(&ecdh_params->MBEDTLS_ECDH_PRIVATE(grp),
|
||||
&ecdh_params->MBEDTLS_ECDH_PRIVATE(d),
|
||||
&ecdh_params->MBEDTLS_ECDH_PRIVATE(Q),
|
||||
mbedtls_ctr_drbg_random,
|
||||
ctr_drbg);
|
||||
if (rc != 0) {
|
||||
mbedtls_strerror(rc, error_buf, sizeof(error_buf));
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Failed to generate X25519 keypair: %s",
|
||||
error_buf);
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = mbedtls_mpi_write_binary_le(&ecdh_params->MBEDTLS_ECDH_PRIVATE(d),
|
||||
session->next_crypto->curve25519_privkey,
|
||||
CURVE25519_PRIVKEY_SIZE);
|
||||
if (rc != 0) {
|
||||
mbedtls_strerror(rc, error_buf, sizeof(error_buf));
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Failed to write X25519 private key: %s",
|
||||
error_buf);
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = mbedtls_mpi_write_binary_le(
|
||||
&ecdh_params->MBEDTLS_ECDH_PRIVATE(Q).MBEDTLS_ECDH_PRIVATE(X),
|
||||
*pubkey_loc,
|
||||
CURVE25519_PUBKEY_SIZE);
|
||||
if (rc != 0) {
|
||||
mbedtls_strerror(rc, error_buf, sizeof(error_buf));
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Failed to write X25519 public key: %s",
|
||||
error_buf);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = SSH_OK;
|
||||
|
||||
out:
|
||||
mbedtls_ecdh_free(&ecdh_ctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int curve25519_do_create_k(ssh_session session, ssh_curve25519_pubkey k)
|
||||
{
|
||||
ssh_curve25519_pubkey *peer_pubkey_loc = NULL;
|
||||
int rc, ret = SSH_ERROR;
|
||||
mbedtls_ecdh_context ecdh_ctx;
|
||||
mbedtls_ecdh_params *ecdh_params = NULL;
|
||||
mbedtls_ctr_drbg_context *ctr_drbg = NULL;
|
||||
char error_buf[128];
|
||||
|
||||
if (session->server) {
|
||||
peer_pubkey_loc = &session->next_crypto->curve25519_client_pubkey;
|
||||
} else {
|
||||
peer_pubkey_loc = &session->next_crypto->curve25519_server_pubkey;
|
||||
}
|
||||
|
||||
ctr_drbg = ssh_get_mbedtls_ctr_drbg_context();
|
||||
|
||||
mbedtls_ecdh_init(&ecdh_ctx);
|
||||
rc = mbedtls_ecdh_setup(&ecdh_ctx, MBEDTLS_ECP_DP_CURVE25519);
|
||||
if (rc != 0) {
|
||||
mbedtls_strerror(rc, error_buf, sizeof(error_buf));
|
||||
SSH_LOG(SSH_LOG_TRACE, "Failed to setup X25519 context: %s", error_buf);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ecdh_params = &MBEDTLS_ECDH_PARAMS(ecdh_ctx);
|
||||
|
||||
rc = mbedtls_mpi_read_binary_le(&ecdh_params->MBEDTLS_ECDH_PRIVATE(d),
|
||||
session->next_crypto->curve25519_privkey,
|
||||
CURVE25519_PRIVKEY_SIZE);
|
||||
if (rc != 0) {
|
||||
mbedtls_strerror(rc, error_buf, sizeof(error_buf));
|
||||
SSH_LOG(SSH_LOG_TRACE, "Failed to read private key: %s", error_buf);
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = mbedtls_mpi_read_binary_le(
|
||||
&ecdh_params->MBEDTLS_ECDH_PRIVATE(Qp).MBEDTLS_ECDH_PRIVATE(X),
|
||||
*peer_pubkey_loc,
|
||||
CURVE25519_PUBKEY_SIZE);
|
||||
if (rc != 0) {
|
||||
mbedtls_strerror(rc, error_buf, sizeof(error_buf));
|
||||
SSH_LOG(SSH_LOG_TRACE, "Failed to read peer public key: %s", error_buf);
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = mbedtls_mpi_lset(
|
||||
&ecdh_params->MBEDTLS_ECDH_PRIVATE(Qp).MBEDTLS_ECDH_PRIVATE(Z),
|
||||
1);
|
||||
if (rc != 0) {
|
||||
mbedtls_strerror(rc, error_buf, sizeof(error_buf));
|
||||
SSH_LOG(SSH_LOG_TRACE, "Failed to set Z coordinate: %s", error_buf);
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = mbedtls_ecdh_compute_shared(&ecdh_params->MBEDTLS_ECDH_PRIVATE(grp),
|
||||
&ecdh_params->MBEDTLS_ECDH_PRIVATE(z),
|
||||
&ecdh_params->MBEDTLS_ECDH_PRIVATE(Qp),
|
||||
&ecdh_params->MBEDTLS_ECDH_PRIVATE(d),
|
||||
mbedtls_ctr_drbg_random,
|
||||
ctr_drbg);
|
||||
if (rc != 0) {
|
||||
mbedtls_strerror(rc, error_buf, sizeof(error_buf));
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Failed to compute shared secret: %s",
|
||||
error_buf);
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = mbedtls_mpi_write_binary_le(&ecdh_params->MBEDTLS_ECDH_PRIVATE(z),
|
||||
k,
|
||||
CURVE25519_PUBKEY_SIZE);
|
||||
if (rc != 0) {
|
||||
mbedtls_strerror(rc, error_buf, sizeof(error_buf));
|
||||
SSH_LOG(SSH_LOG_TRACE, "Failed to write shared secret: %s", error_buf);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = SSH_OK;
|
||||
|
||||
out:
|
||||
mbedtls_ecdh_free(&ecdh_ctx);
|
||||
return ret;
|
||||
}
|
||||
@@ -416,9 +416,6 @@ static int ssh_retrieve_dhgroup_file(FILE *moduli,
|
||||
do {
|
||||
firstbyte = getc(moduli);
|
||||
} while(firstbyte != '\n' && firstbyte != EOF);
|
||||
if (firstbyte == EOF) {
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (firstbyte == EOF) {
|
||||
@@ -442,9 +439,6 @@ static int ssh_retrieve_dhgroup_file(FILE *moduli,
|
||||
do {
|
||||
firstbyte = getc(moduli);
|
||||
} while(firstbyte != '\n' && firstbyte != EOF);
|
||||
if (firstbyte == EOF) {
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -407,6 +407,11 @@ int ssh_dh_init_common(struct ssh_crypto_struct *crypto)
|
||||
struct dh_ctx *ctx = NULL;
|
||||
int rc;
|
||||
|
||||
/* Cleanup any previously allocated dh_ctx */
|
||||
if (crypto->dh_ctx != NULL) {
|
||||
ssh_dh_cleanup(crypto);
|
||||
}
|
||||
|
||||
ctx = calloc(1, sizeof(*ctx));
|
||||
if (ctx == NULL) {
|
||||
return SSH_ERROR;
|
||||
@@ -592,7 +597,7 @@ int ssh_dh_compute_shared_secret(struct dh_ctx *dh_ctx, int local, int remote,
|
||||
}
|
||||
#endif /* OPENSSL_VERSION_NUMBER */
|
||||
|
||||
*dest = BN_bin2bn(kstring, (int)klen, NULL);
|
||||
*dest = BN_bin2bn(kstring, klen, NULL);
|
||||
if (*dest == NULL) {
|
||||
rc = SSH_ERROR;
|
||||
goto done;
|
||||
|
||||
@@ -237,6 +237,11 @@ int ssh_dh_init_common(struct ssh_crypto_struct *crypto)
|
||||
struct dh_ctx *ctx = NULL;
|
||||
int rc;
|
||||
|
||||
/* Cleanup any previously allocated dh_ctx */
|
||||
if (crypto->dh_ctx != NULL) {
|
||||
ssh_dh_cleanup(crypto);
|
||||
}
|
||||
|
||||
ctx = calloc(1, sizeof(*ctx));
|
||||
if (ctx == NULL) {
|
||||
return SSH_ERROR;
|
||||
|
||||
@@ -191,6 +191,17 @@ static ssh_string ssh_ecdh_generate(ssh_session session)
|
||||
#endif /* OPENSSL_VERSION_NUMBER */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Free any previously allocated privkey */
|
||||
if (session->next_crypto->ecdh_privkey != NULL) {
|
||||
#if OPENSSL_VERSION_NUMBER < 0x30000000L
|
||||
EC_KEY_free(session->next_crypto->ecdh_privkey);
|
||||
#else
|
||||
EVP_PKEY_free(session->next_crypto->ecdh_privkey);
|
||||
#endif
|
||||
session->next_crypto->ecdh_privkey = NULL;
|
||||
}
|
||||
|
||||
session->next_crypto->ecdh_privkey = key;
|
||||
return pubkey_string;
|
||||
}
|
||||
@@ -219,6 +230,7 @@ int ssh_client_ecdh_init(ssh_session session)
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
ssh_string_free(session->next_crypto->ecdh_client_pubkey);
|
||||
session->next_crypto->ecdh_client_pubkey = client_pubkey;
|
||||
|
||||
/* register the packet callbacks */
|
||||
|
||||
@@ -101,8 +101,15 @@ int ssh_client_ecdh_init(ssh_session session)
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Free any previously allocated privkey */
|
||||
if (session->next_crypto->ecdh_privkey != NULL) {
|
||||
gcry_sexp_release(session->next_crypto->ecdh_privkey);
|
||||
session->next_crypto->ecdh_privkey = NULL;
|
||||
}
|
||||
session->next_crypto->ecdh_privkey = key;
|
||||
key = NULL;
|
||||
|
||||
SSH_STRING_FREE(session->next_crypto->ecdh_client_pubkey);
|
||||
session->next_crypto->ecdh_client_pubkey = client_pubkey;
|
||||
client_pubkey = NULL;
|
||||
|
||||
|
||||
@@ -70,6 +70,12 @@ int ssh_client_ecdh_init(ssh_session session)
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
/* Free any previously allocated privkey */
|
||||
if (session->next_crypto->ecdh_privkey != NULL) {
|
||||
mbedtls_ecp_keypair_free(session->next_crypto->ecdh_privkey);
|
||||
SAFE_FREE(session->next_crypto->ecdh_privkey);
|
||||
}
|
||||
|
||||
session->next_crypto->ecdh_privkey = malloc(sizeof(mbedtls_ecp_keypair));
|
||||
if (session->next_crypto->ecdh_privkey == NULL) {
|
||||
return SSH_ERROR;
|
||||
@@ -110,6 +116,7 @@ int ssh_client_ecdh_init(ssh_session session)
|
||||
goto out;
|
||||
}
|
||||
|
||||
SSH_STRING_FREE(session->next_crypto->ecdh_client_pubkey);
|
||||
session->next_crypto->ecdh_client_pubkey = client_pubkey;
|
||||
client_pubkey = NULL;
|
||||
|
||||
|
||||
1060
src/external/sntrup761.c
vendored
1060
src/external/sntrup761.c
vendored
File diff suppressed because it is too large
Load Diff
@@ -63,7 +63,7 @@ static int ssh_gets(const char *prompt, char *buf, size_t len, int verify)
|
||||
fprintf(stdout, "%s", prompt);
|
||||
}
|
||||
fflush(stdout);
|
||||
if (fgets(tmp, (int)len, stdin) == NULL) {
|
||||
if (fgets(tmp, len, stdin) == NULL) {
|
||||
free(tmp);
|
||||
return 0;
|
||||
}
|
||||
@@ -87,7 +87,7 @@ static int ssh_gets(const char *prompt, char *buf, size_t len, int verify)
|
||||
|
||||
fprintf(stdout, "\nVerifying, please re-enter. %s", prompt);
|
||||
fflush(stdout);
|
||||
if (!fgets(key_string, (int)len, stdin)) {
|
||||
if (! fgets(key_string, len, stdin)) {
|
||||
explicit_bzero(key_string, len);
|
||||
SAFE_FREE(key_string);
|
||||
clearerr(stdin);
|
||||
|
||||
130
src/kex.c
130
src/kex.c
@@ -40,7 +40,6 @@
|
||||
#include "libssh/ssh2.h"
|
||||
#include "libssh/string.h"
|
||||
#include "libssh/curve25519.h"
|
||||
#include "libssh/sntrup761.h"
|
||||
#include "libssh/knownhosts.h"
|
||||
#include "libssh/misc.h"
|
||||
#include "libssh/pki.h"
|
||||
@@ -96,12 +95,6 @@
|
||||
#define CURVE25519 ""
|
||||
#endif /* HAVE_CURVE25519 */
|
||||
|
||||
#ifdef HAVE_SNTRUP761
|
||||
#define SNTRUP761X25519 "sntrup761x25519-sha512@openssh.com,"
|
||||
#else
|
||||
#define SNTRUP761X25519 ""
|
||||
#endif /* HAVE_SNTRUP761 */
|
||||
|
||||
#ifdef HAVE_ECC
|
||||
#define ECDH "ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,"
|
||||
#define EC_HOSTKEYS "ecdsa-sha2-nistp521," \
|
||||
@@ -166,7 +159,6 @@
|
||||
|
||||
#define DEFAULT_KEY_EXCHANGE \
|
||||
CURVE25519 \
|
||||
SNTRUP761X25519 \
|
||||
ECDH \
|
||||
"diffie-hellman-group18-sha512,diffie-hellman-group16-sha512," \
|
||||
GEX_SHA256 \
|
||||
@@ -275,58 +267,38 @@ static const char *ssh_kex_descriptions[] = {
|
||||
NULL
|
||||
};
|
||||
|
||||
const char *ssh_kex_get_default_methods(enum ssh_kex_types_e type)
|
||||
const char *ssh_kex_get_default_methods(uint32_t algo)
|
||||
{
|
||||
if (type >= SSH_KEX_METHODS) {
|
||||
if (algo >= SSH_KEX_METHODS) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return default_methods[type];
|
||||
return default_methods[algo];
|
||||
}
|
||||
const char *ssh_kex_get_supported_method(enum ssh_kex_types_e type)
|
||||
|
||||
const char *ssh_kex_get_supported_method(uint32_t algo)
|
||||
{
|
||||
if (type >= SSH_KEX_METHODS) {
|
||||
if (algo >= SSH_KEX_METHODS) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return supported_methods[type];
|
||||
return supported_methods[algo];
|
||||
}
|
||||
|
||||
const char *ssh_kex_get_description(enum ssh_kex_types_e type)
|
||||
{
|
||||
if (type >= SSH_KEX_METHODS) {
|
||||
return NULL;
|
||||
}
|
||||
const char *ssh_kex_get_description(uint32_t algo) {
|
||||
if (algo >= SSH_KEX_METHODS) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ssh_kex_descriptions[type];
|
||||
return ssh_kex_descriptions[algo];
|
||||
}
|
||||
|
||||
const char *ssh_kex_get_fips_methods(enum ssh_kex_types_e type)
|
||||
{
|
||||
if (type >= SSH_KEX_METHODS) {
|
||||
return NULL;
|
||||
}
|
||||
const char *ssh_kex_get_fips_methods(uint32_t algo) {
|
||||
if (algo >= SSH_KEX_METHODS) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return fips_methods[type];
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get a list of supported algorithms of a given type. This respects the
|
||||
* FIPS mode status.
|
||||
*
|
||||
* @param[in] type The type of the algorithm to query (SSH_KEX, SSH_MAC_C_S,
|
||||
* ...).
|
||||
*
|
||||
* @return The list of supported methods as comma-separated string, or NULL for
|
||||
* unknown type.
|
||||
*/
|
||||
const char *ssh_get_supported_methods(enum ssh_kex_types_e type)
|
||||
{
|
||||
if (ssh_fips_mode()) {
|
||||
return ssh_kex_get_fips_methods(type);
|
||||
} else {
|
||||
return ssh_kex_get_supported_method(type);
|
||||
}
|
||||
return fips_methods[algo];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -922,8 +894,6 @@ kex_select_kex_type(const char *kex)
|
||||
return SSH_KEX_CURVE25519_SHA256_LIBSSH_ORG;
|
||||
} else if (strcmp(kex, "curve25519-sha256") == 0) {
|
||||
return SSH_KEX_CURVE25519_SHA256;
|
||||
} else if (strcmp(kex, "sntrup761x25519-sha512@openssh.com") == 0) {
|
||||
return SSH_KEX_SNTRUP761X25519_SHA512_OPENSSH_COM;
|
||||
}
|
||||
/* should not happen. We should be getting only valid names at this stage */
|
||||
return 0;
|
||||
@@ -963,11 +933,6 @@ static void revert_kex_callbacks(ssh_session session)
|
||||
case SSH_KEX_CURVE25519_SHA256_LIBSSH_ORG:
|
||||
ssh_client_curve25519_remove_callbacks(session);
|
||||
break;
|
||||
#endif
|
||||
#ifdef HAVE_SNTRUP761
|
||||
case SSH_KEX_SNTRUP761X25519_SHA512_OPENSSH_COM:
|
||||
ssh_client_sntrup761x25519_remove_callbacks(session);
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -1375,7 +1340,6 @@ int ssh_make_sessionid(ssh_session session)
|
||||
|
||||
buf = ssh_buffer_new();
|
||||
if (buf == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -1384,9 +1348,6 @@ int ssh_make_sessionid(ssh_session session)
|
||||
session->clientbanner,
|
||||
session->serverbanner);
|
||||
if (rc == SSH_ERROR) {
|
||||
ssh_set_error(session,
|
||||
SSH_FATAL,
|
||||
"Failed to pack client and server banner");
|
||||
goto error;
|
||||
}
|
||||
|
||||
@@ -1400,9 +1361,6 @@ int ssh_make_sessionid(ssh_session session)
|
||||
|
||||
rc = ssh_dh_get_next_server_publickey_blob(session, &server_pubkey_blob);
|
||||
if (rc != SSH_OK) {
|
||||
ssh_set_error(session,
|
||||
SSH_FATAL,
|
||||
"Failed to get next server pubkey blob");
|
||||
goto error;
|
||||
}
|
||||
|
||||
@@ -1417,9 +1375,6 @@ int ssh_make_sessionid(ssh_session session)
|
||||
server_pubkey_blob);
|
||||
SSH_STRING_FREE(server_pubkey_blob);
|
||||
if (rc != SSH_OK){
|
||||
ssh_set_error(session,
|
||||
SSH_FATAL,
|
||||
"Failed to pack hashes and pubkey blob");
|
||||
goto error;
|
||||
}
|
||||
|
||||
@@ -1444,7 +1399,6 @@ int ssh_make_sessionid(ssh_session session)
|
||||
client_pubkey,
|
||||
server_pubkey);
|
||||
if (rc != SSH_OK) {
|
||||
ssh_set_error(session, SSH_FATAL, "Failed to pack DH pubkeys");
|
||||
goto error;
|
||||
}
|
||||
#if defined(HAVE_LIBCRYPTO) && OPENSSL_VERSION_NUMBER >= 0x30000000L
|
||||
@@ -1480,7 +1434,6 @@ int ssh_make_sessionid(ssh_session session)
|
||||
client_pubkey,
|
||||
server_pubkey);
|
||||
if (rc != SSH_OK) {
|
||||
ssh_set_error(session, SSH_FATAL, "Failed to pack DH GEX params");
|
||||
goto error;
|
||||
}
|
||||
#if defined(HAVE_LIBCRYPTO) && OPENSSL_VERSION_NUMBER >= 0x30000000L
|
||||
@@ -1503,7 +1456,6 @@ int ssh_make_sessionid(ssh_session session)
|
||||
session->next_crypto->ecdh_client_pubkey,
|
||||
session->next_crypto->ecdh_server_pubkey);
|
||||
if (rc != SSH_OK) {
|
||||
ssh_set_error(session, SSH_FATAL, "Failed to pack ECDH pubkeys");
|
||||
goto error;
|
||||
}
|
||||
break;
|
||||
@@ -1521,47 +1473,13 @@ int ssh_make_sessionid(ssh_session session)
|
||||
session->next_crypto->curve25519_server_pubkey);
|
||||
|
||||
if (rc != SSH_OK) {
|
||||
ssh_set_error(session,
|
||||
SSH_FATAL,
|
||||
"Failed to pack Curve25519 pubkeys");
|
||||
goto error;
|
||||
}
|
||||
break;
|
||||
#endif /* HAVE_CURVE25519 */
|
||||
#ifdef HAVE_SNTRUP761
|
||||
case SSH_KEX_SNTRUP761X25519_SHA512_OPENSSH_COM:
|
||||
rc = ssh_buffer_pack(buf,
|
||||
"dPPdPP",
|
||||
SNTRUP761_PUBLICKEY_SIZE + CURVE25519_PUBKEY_SIZE,
|
||||
(size_t)SNTRUP761_PUBLICKEY_SIZE,
|
||||
session->next_crypto->sntrup761_client_pubkey,
|
||||
(size_t)CURVE25519_PUBKEY_SIZE,
|
||||
session->next_crypto->curve25519_client_pubkey,
|
||||
SNTRUP761_CIPHERTEXT_SIZE + CURVE25519_PUBKEY_SIZE,
|
||||
(size_t)SNTRUP761_CIPHERTEXT_SIZE,
|
||||
session->next_crypto->sntrup761_ciphertext,
|
||||
(size_t)CURVE25519_PUBKEY_SIZE,
|
||||
session->next_crypto->curve25519_server_pubkey);
|
||||
|
||||
if (rc != SSH_OK) {
|
||||
ssh_set_error(session,
|
||||
SSH_FATAL,
|
||||
"Failed to pack SNTRU Prime params");
|
||||
goto error;
|
||||
}
|
||||
break;
|
||||
#endif /* HAVE_SNTRUP761 */
|
||||
}
|
||||
if (session->next_crypto->kex_type == SSH_KEX_SNTRUP761X25519_SHA512_OPENSSH_COM) {
|
||||
rc = ssh_buffer_pack(buf,
|
||||
"F",
|
||||
session->next_crypto->shared_secret,
|
||||
SHA512_DIGEST_LEN);
|
||||
} else {
|
||||
rc = ssh_buffer_pack(buf, "B", session->next_crypto->shared_secret);
|
||||
}
|
||||
rc = ssh_buffer_pack(buf, "B", session->next_crypto->shared_secret);
|
||||
if (rc != SSH_OK) {
|
||||
ssh_set_error(session, SSH_FATAL, "Failed to pack shared secret");
|
||||
goto error;
|
||||
}
|
||||
|
||||
@@ -1569,6 +1487,8 @@ int ssh_make_sessionid(ssh_session session)
|
||||
ssh_log_hexdump("hash buffer", ssh_buffer_get(buf), ssh_buffer_get_len(buf));
|
||||
#endif
|
||||
|
||||
/* Set rc for the following switch statement in case we goto error. */
|
||||
rc = SSH_ERROR;
|
||||
switch (session->next_crypto->kex_type) {
|
||||
case SSH_KEX_DH_GROUP1_SHA1:
|
||||
case SSH_KEX_DH_GROUP14_SHA1:
|
||||
@@ -1616,7 +1536,6 @@ int ssh_make_sessionid(ssh_session session)
|
||||
case SSH_KEX_DH_GROUP16_SHA512:
|
||||
case SSH_KEX_DH_GROUP18_SHA512:
|
||||
case SSH_KEX_ECDH_SHA2_NISTP521:
|
||||
case SSH_KEX_SNTRUP761X25519_SHA512_OPENSSH_COM:
|
||||
session->next_crypto->digest_len = SHA512_DIGEST_LENGTH;
|
||||
session->next_crypto->digest_type = SSH_KDF_SHA512;
|
||||
session->next_crypto->secret_hash = malloc(session->next_crypto->digest_len);
|
||||
@@ -1629,6 +1548,7 @@ int ssh_make_sessionid(ssh_session session)
|
||||
session->next_crypto->secret_hash);
|
||||
break;
|
||||
}
|
||||
|
||||
/* During the first kex, secret hash and session ID are equal. However, after
|
||||
* a key re-exchange, a new secret hash is calculated. This hash will not replace
|
||||
* but complement existing session id.
|
||||
@@ -1637,6 +1557,7 @@ int ssh_make_sessionid(ssh_session session)
|
||||
session->next_crypto->session_id = malloc(session->next_crypto->digest_len);
|
||||
if (session->next_crypto->session_id == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
rc = SSH_ERROR;
|
||||
goto error;
|
||||
}
|
||||
memcpy(session->next_crypto->session_id, session->next_crypto->secret_hash,
|
||||
@@ -1753,12 +1674,7 @@ int ssh_generate_session_keys(ssh_session session)
|
||||
size_t intkey_srv_to_cli_len = 0;
|
||||
int rc = -1;
|
||||
|
||||
if (session->next_crypto->kex_type == SSH_KEX_SNTRUP761X25519_SHA512_OPENSSH_COM) {
|
||||
k_string = ssh_make_padded_bignum_string(crypto->shared_secret,
|
||||
SHA512_DIGEST_LEN);
|
||||
} else {
|
||||
k_string = ssh_make_bignum_string(crypto->shared_secret);
|
||||
}
|
||||
k_string = ssh_make_bignum_string(crypto->shared_secret);
|
||||
if (k_string == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
goto error;
|
||||
|
||||
@@ -171,7 +171,7 @@ static int known_hosts_read_line(FILE *fp,
|
||||
size_t *buf_len,
|
||||
size_t *lineno)
|
||||
{
|
||||
while (fgets(buf, (int)buf_size, fp) != NULL) {
|
||||
while (fgets(buf, buf_size, fp) != NULL) {
|
||||
size_t len;
|
||||
if (buf[0] == '\0') {
|
||||
continue;
|
||||
@@ -376,25 +376,23 @@ struct ssh_list *ssh_known_hosts_get_algorithms(ssh_session session)
|
||||
}
|
||||
}
|
||||
|
||||
host_port = ssh_session_get_host_port(session);
|
||||
if (host_port == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
list = ssh_list_new();
|
||||
if (list == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
SAFE_FREE(host_port);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
host_port = ssh_session_get_host_port(session);
|
||||
if (host_port == NULL) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
rc = ssh_known_hosts_read_entries(host_port,
|
||||
session->opts.knownhosts,
|
||||
&entry_list);
|
||||
if (rc != 0) {
|
||||
ssh_list_free(entry_list);
|
||||
ssh_list_free(list);
|
||||
return NULL;
|
||||
SAFE_FREE(host_port);
|
||||
goto error;
|
||||
}
|
||||
|
||||
rc = ssh_known_hosts_read_entries(host_port,
|
||||
@@ -402,21 +400,16 @@ struct ssh_list *ssh_known_hosts_get_algorithms(ssh_session session)
|
||||
&entry_list);
|
||||
SAFE_FREE(host_port);
|
||||
if (rc != 0) {
|
||||
ssh_list_free(entry_list);
|
||||
ssh_list_free(list);
|
||||
return NULL;
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (entry_list == NULL) {
|
||||
ssh_list_free(list);
|
||||
return NULL;
|
||||
goto error;
|
||||
}
|
||||
|
||||
count = ssh_list_count(entry_list);
|
||||
if (count == 0) {
|
||||
ssh_list_free(list);
|
||||
ssh_list_free(entry_list);
|
||||
return NULL;
|
||||
goto error;
|
||||
}
|
||||
|
||||
for (it = ssh_list_get_iterator(entry_list);
|
||||
@@ -460,6 +453,7 @@ struct ssh_list *ssh_known_hosts_get_algorithms(ssh_session session)
|
||||
|
||||
return list;
|
||||
error:
|
||||
ssh_list_free(entry_list);
|
||||
ssh_list_free(list);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -349,7 +349,7 @@ HMACCTX hmac_init(const void *key, size_t len, enum ssh_hmac_e type)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pkey = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL, key, (int)len);
|
||||
pkey = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL, key, len);
|
||||
if (pkey == NULL) {
|
||||
goto error;
|
||||
}
|
||||
@@ -635,7 +635,7 @@ evp_cipher_aead_encrypt(struct ssh_cipher_struct *cipher,
|
||||
(unsigned char *)out + aadlen,
|
||||
&tmplen,
|
||||
(unsigned char *)in + aadlen,
|
||||
(int)(len - aadlen));
|
||||
(int)len - aadlen);
|
||||
outlen = tmplen;
|
||||
if (rc != 1 || outlen != (int)len - aadlen) {
|
||||
SSH_LOG(SSH_LOG_TRACE, "EVP_EncryptUpdate failed");
|
||||
@@ -653,7 +653,7 @@ evp_cipher_aead_encrypt(struct ssh_cipher_struct *cipher,
|
||||
|
||||
rc = EVP_CIPHER_CTX_ctrl(cipher->ctx,
|
||||
EVP_CTRL_GCM_GET_TAG,
|
||||
(int)authlen,
|
||||
authlen,
|
||||
(unsigned char *)tag);
|
||||
if (rc != 1) {
|
||||
SSH_LOG(SSH_LOG_TRACE, "EVP_CTRL_GCM_GET_TAG failed");
|
||||
@@ -691,7 +691,7 @@ evp_cipher_aead_decrypt(struct ssh_cipher_struct *cipher,
|
||||
/* set tag for authentication */
|
||||
rc = EVP_CIPHER_CTX_ctrl(cipher->ctx,
|
||||
EVP_CTRL_GCM_SET_TAG,
|
||||
(int)authlen,
|
||||
authlen,
|
||||
(unsigned char *)complete_packet + aadlen + encrypted_size);
|
||||
if (rc == 0) {
|
||||
SSH_LOG(SSH_LOG_TRACE, "EVP_CTRL_GCM_SET_TAG failed");
|
||||
@@ -716,7 +716,7 @@ evp_cipher_aead_decrypt(struct ssh_cipher_struct *cipher,
|
||||
(unsigned char *)out,
|
||||
&outlen,
|
||||
(unsigned char *)complete_packet + aadlen,
|
||||
(int)encrypted_size /* already subtracted aadlen */);
|
||||
encrypted_size /* already subtracted aadlen */);
|
||||
if (rc != 1) {
|
||||
SSH_LOG(SSH_LOG_TRACE, "EVP_DecryptUpdate failed");
|
||||
return SSH_ERROR;
|
||||
@@ -998,7 +998,7 @@ chacha20_poly1305_aead_decrypt_length(struct ssh_cipher_struct *cipher,
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
rv = EVP_CipherUpdate(ctx->header_evp, out, &outlen, in, (int)len);
|
||||
rv = EVP_CipherUpdate(ctx->header_evp, out, &outlen, in, len);
|
||||
if (rv != 1 || outlen != sizeof(uint32_t)) {
|
||||
SSH_LOG(SSH_LOG_TRACE, "EVP_CipherUpdate failed");
|
||||
return SSH_ERROR;
|
||||
@@ -1085,11 +1085,9 @@ chacha20_poly1305_aead_decrypt(struct ssh_cipher_struct *cipher,
|
||||
}
|
||||
|
||||
/* Decrypt the message */
|
||||
rv = EVP_CipherUpdate(ctx->main_evp,
|
||||
out,
|
||||
&len,
|
||||
rv = EVP_CipherUpdate(ctx->main_evp, out, &len,
|
||||
(uint8_t *)complete_packet + sizeof(uint32_t),
|
||||
(int)encrypted_size);
|
||||
encrypted_size);
|
||||
if (rv != 1) {
|
||||
SSH_LOG(SSH_LOG_TRACE, "EVP_CipherUpdate failed");
|
||||
goto out;
|
||||
@@ -1156,7 +1154,7 @@ chacha20_poly1305_aead_encrypt(struct ssh_cipher_struct *cipher,
|
||||
out_packet->payload,
|
||||
&outlen,
|
||||
in_packet->payload,
|
||||
(int)(len - sizeof(uint32_t)));
|
||||
len - sizeof(uint32_t));
|
||||
if (ret != 1) {
|
||||
SSH_LOG(SSH_LOG_TRACE, "EVP_CipherUpdate failed");
|
||||
return;
|
||||
@@ -1588,12 +1586,6 @@ int evp_dup_ecdsa_pkey(const ssh_key key, ssh_key new_key, int demote)
|
||||
{
|
||||
return evp_dup_pkey("EC", key, demote, new_key);
|
||||
}
|
||||
|
||||
int evp_dup_ed25519_pkey(const ssh_key key, ssh_key new_key, int demote)
|
||||
{
|
||||
return evp_dup_pkey("ED25519", key, demote, new_key);
|
||||
}
|
||||
|
||||
#endif /* OPENSSL_VERSION_NUMBER */
|
||||
|
||||
ssh_string
|
||||
|
||||
@@ -966,8 +966,7 @@ int ssh_crypto_init(void)
|
||||
gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN);
|
||||
|
||||
if (!gcry_control(GCRYCTL_INITIALIZATION_FINISHED_P, 0)) {
|
||||
gcry_control(GCRYCTL_USE_SECURE_RNDPOOL);
|
||||
gcry_control(GCRYCTL_INIT_SECMEM, 32768, 0);
|
||||
gcry_control(GCRYCTL_INIT_SECMEM, 4096);
|
||||
gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0);
|
||||
}
|
||||
|
||||
|
||||
@@ -481,16 +481,3 @@ LIBSSH_4_10_0 # Released
|
||||
ssh_pki_export_privkey_file_format;
|
||||
ssh_request_no_more_sessions;
|
||||
} LIBSSH_4_9_0;
|
||||
|
||||
LIBSSH_AFTER_4_10_0
|
||||
{
|
||||
global:
|
||||
sftp_get_users_groups_by_id;
|
||||
sftp_name_id_map_free;
|
||||
sftp_name_id_map_new;
|
||||
ssh_get_supported_methods;
|
||||
sshsig_sign;
|
||||
sshsig_verify;
|
||||
ssh_string_cmp;
|
||||
} LIBSSH_4_10_0;
|
||||
|
||||
|
||||
10
src/log.c
10
src/log.c
@@ -59,22 +59,22 @@ static int current_timestring(int hires, char *buf, size_t len)
|
||||
{
|
||||
char tbuf[64];
|
||||
struct timeval tv;
|
||||
struct tm tm, *tm_ptr = NULL;
|
||||
struct tm *tm;
|
||||
time_t t;
|
||||
|
||||
gettimeofday(&tv, NULL);
|
||||
t = (time_t) tv.tv_sec;
|
||||
|
||||
tm_ptr = localtime_r(&t, &tm);
|
||||
if (tm_ptr == NULL) {
|
||||
tm = localtime(&t);
|
||||
if (tm == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (hires) {
|
||||
strftime(tbuf, sizeof(tbuf), "%Y/%m/%d %H:%M:%S", &tm);
|
||||
strftime(tbuf, sizeof(tbuf) - 1, "%Y/%m/%d %H:%M:%S", tm);
|
||||
snprintf(buf, len, "%s.%06ld", tbuf, (long)tv.tv_usec);
|
||||
} else {
|
||||
strftime(tbuf, sizeof(tbuf), "%Y/%m/%d %H:%M:%S", &tm);
|
||||
strftime(tbuf, sizeof(tbuf) - 1, "%Y/%m/%d %H:%M:%S", tm);
|
||||
snprintf(buf, len, "%s", tbuf);
|
||||
}
|
||||
|
||||
|
||||
@@ -205,10 +205,8 @@ int match_pattern_list(const char *string, const char *pattern,
|
||||
* Returns -1 if negation matches, 1 if there is a positive match, 0 if there
|
||||
* is no match at all.
|
||||
*/
|
||||
int
|
||||
match_hostname(const char *host, const char *pattern, size_t len)
|
||||
{
|
||||
return match_pattern_list(host, pattern, len, 1);
|
||||
int match_hostname(const char *host, const char *pattern, unsigned int len) {
|
||||
return match_pattern_list(host, pattern, len, 1);
|
||||
}
|
||||
|
||||
#ifndef _WIN32
|
||||
|
||||
@@ -5,17 +5,13 @@
|
||||
* v3 defines the version inside build_info.h so if it isn't defined
|
||||
* in version.h we should have v3
|
||||
*/
|
||||
#include <mbedtls/cipher.h>
|
||||
#include <mbedtls/version.h>
|
||||
|
||||
#ifndef MBEDTLS_VERSION_MAJOR
|
||||
#include <mbedtls/build_info.h>
|
||||
#endif /* MBEDTLS_VERSION_MAJOR */
|
||||
|
||||
#include <mbedtls/cipher.h>
|
||||
#ifdef MBEDTLS_VERSION_MAJOR
|
||||
#if MBEDTLS_VERSION_MAJOR < 3
|
||||
|
||||
static inline size_t
|
||||
mbedtls_cipher_info_get_key_bitlen(const mbedtls_cipher_info_t *info)
|
||||
static inline size_t mbedtls_cipher_info_get_key_bitlen(
|
||||
const mbedtls_cipher_info_t *info)
|
||||
{
|
||||
if (info == NULL) {
|
||||
return 0;
|
||||
@@ -23,8 +19,8 @@ mbedtls_cipher_info_get_key_bitlen(const mbedtls_cipher_info_t *info)
|
||||
return info->key_bitlen;
|
||||
}
|
||||
|
||||
static inline size_t
|
||||
mbedtls_cipher_info_get_iv_size(const mbedtls_cipher_info_t *info)
|
||||
static inline size_t mbedtls_cipher_info_get_iv_size(
|
||||
const mbedtls_cipher_info_t *info)
|
||||
{
|
||||
if (info == NULL) {
|
||||
return 0;
|
||||
@@ -33,24 +29,11 @@ mbedtls_cipher_info_get_iv_size(const mbedtls_cipher_info_t *info)
|
||||
}
|
||||
|
||||
#define MBEDTLS_PRIVATE(X) X
|
||||
|
||||
#ifdef HAVE_MBEDTLS_CURVE25519
|
||||
#include <mbedtls/ecdh.h>
|
||||
|
||||
#define MBEDTLS_ECDH_PRIVATE(X) X
|
||||
#define MBEDTLS_ECDH_PARAMS(X) X
|
||||
typedef mbedtls_ecdh_context mbedtls_ecdh_params;
|
||||
#endif /* HAVE_MBEDTLS_CURVE25519 */
|
||||
|
||||
#else /* MBEDTLS_VERSION_MAJOR < 3 */
|
||||
|
||||
#ifdef HAVE_MBEDTLS_CURVE25519
|
||||
#include <mbedtls/ecdh.h>
|
||||
|
||||
#define MBEDTLS_ECDH_PRIVATE(X) MBEDTLS_PRIVATE(X)
|
||||
#define MBEDTLS_ECDH_PARAMS(X) X.MBEDTLS_PRIVATE(ctx).MBEDTLS_PRIVATE(mbed_ecdh)
|
||||
typedef mbedtls_ecdh_context_mbed mbedtls_ecdh_params;
|
||||
#endif /* HAVE_MBEDTLS_CURVE25519 */
|
||||
|
||||
#endif /* MBEDTLS_VERSION_MAJOR < 3 */
|
||||
#else /* MBEDTLS_VERSION_MAJOR */
|
||||
#include <mbedtls/build_info.h>
|
||||
#if MBEDTLS_VERSION_MAJOR < 3
|
||||
#define MBEDTLS_PRIVATE(X) X
|
||||
#endif /* MBEDTLS_VERSION_MAJOR < 3 */
|
||||
#endif /* MBEDTLS_VERSION_MAJOR */
|
||||
#endif /* MBEDCRYPTO_COMPAT_H */
|
||||
|
||||
651
src/messages.c
651
src/messages.c
@@ -204,35 +204,8 @@ static int ssh_execute_server_request(ssh_session session, ssh_message msg)
|
||||
ssh_message_reply_default(msg);
|
||||
}
|
||||
|
||||
return SSH_OK;
|
||||
#define CB channel_open_request_direct_tcpip_function
|
||||
} else if (msg->channel_request_open.type == SSH_CHANNEL_DIRECT_TCPIP &&
|
||||
ssh_callbacks_exists(session->server_callbacks, CB)) {
|
||||
struct ssh_channel_request_open *rq = &msg->channel_request_open;
|
||||
channel = session->server_callbacks->CB(session,
|
||||
rq->destination,
|
||||
rq->destination_port,
|
||||
rq->originator,
|
||||
rq->originator_port,
|
||||
session->server_callbacks->userdata);
|
||||
#undef CB
|
||||
if (channel != NULL) {
|
||||
rc = ssh_message_channel_request_open_reply_accept_channel(
|
||||
msg,
|
||||
channel);
|
||||
if (rc != SSH_OK) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Failed to send reply for accepting a channel "
|
||||
"open");
|
||||
}
|
||||
return SSH_OK;
|
||||
} else {
|
||||
ssh_message_reply_default(msg);
|
||||
}
|
||||
|
||||
return SSH_OK;
|
||||
}
|
||||
|
||||
break;
|
||||
case SSH_REQUEST_CHANNEL:
|
||||
channel = msg->channel_request.channel;
|
||||
@@ -546,36 +519,30 @@ static void ssh_message_queue(ssh_session session, ssh_message message)
|
||||
*
|
||||
* @returns The head message or NULL if it doesn't exist.
|
||||
*/
|
||||
ssh_message ssh_message_pop_head(ssh_session session)
|
||||
{
|
||||
ssh_message msg = NULL;
|
||||
struct ssh_iterator *i = NULL;
|
||||
|
||||
if (session->ssh_message_list == NULL)
|
||||
return NULL;
|
||||
|
||||
i = ssh_list_get_iterator(session->ssh_message_list);
|
||||
if (i != NULL) {
|
||||
msg = ssh_iterator_value(ssh_message, i);
|
||||
ssh_list_remove(session->ssh_message_list, i);
|
||||
}
|
||||
return msg;
|
||||
ssh_message ssh_message_pop_head(ssh_session session){
|
||||
ssh_message msg=NULL;
|
||||
struct ssh_iterator *i = NULL;
|
||||
if(session->ssh_message_list == NULL)
|
||||
return NULL;
|
||||
i=ssh_list_get_iterator(session->ssh_message_list);
|
||||
if(i != NULL){
|
||||
msg=ssh_iterator_value(ssh_message,i);
|
||||
ssh_list_remove(session->ssh_message_list,i);
|
||||
}
|
||||
return msg;
|
||||
}
|
||||
|
||||
/* Returns 1 if there is a message available */
|
||||
static int ssh_message_termination(void *s)
|
||||
{
|
||||
ssh_session session = s;
|
||||
struct ssh_iterator *it = NULL;
|
||||
|
||||
if (session->session_state == SSH_SESSION_STATE_ERROR)
|
||||
return 1;
|
||||
|
||||
it = ssh_list_get_iterator(session->ssh_message_list);
|
||||
if (!it)
|
||||
return 0;
|
||||
else
|
||||
return 1;
|
||||
static int ssh_message_termination(void *s){
|
||||
ssh_session session = s;
|
||||
struct ssh_iterator *it = NULL;
|
||||
if(session->session_state == SSH_SESSION_STATE_ERROR)
|
||||
return 1;
|
||||
it = ssh_list_get_iterator(session->ssh_message_list);
|
||||
if(!it)
|
||||
return 0;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
/**
|
||||
* @brief Retrieve a SSH message from a SSH session.
|
||||
@@ -675,7 +642,6 @@ void ssh_message_free(ssh_message msg){
|
||||
SAFE_FREE(msg->auth_request.password);
|
||||
}
|
||||
ssh_key_free(msg->auth_request.pubkey);
|
||||
ssh_key_free(msg->auth_request.server_pubkey);
|
||||
break;
|
||||
case SSH_REQUEST_CHANNEL_OPEN:
|
||||
SAFE_FREE(msg->channel_request_open.originator);
|
||||
@@ -767,12 +733,11 @@ error:
|
||||
static ssh_buffer ssh_msg_userauth_build_digest(ssh_session session,
|
||||
ssh_message msg,
|
||||
const char *service,
|
||||
ssh_string algo,
|
||||
const char *method)
|
||||
ssh_string algo)
|
||||
{
|
||||
struct ssh_crypto_struct *crypto = NULL;
|
||||
ssh_buffer buffer = NULL;
|
||||
ssh_string str = NULL;
|
||||
ssh_string str=NULL;
|
||||
int rc;
|
||||
|
||||
crypto = ssh_packet_get_current_crypto(session, SSH_DIRECTION_IN);
|
||||
@@ -798,10 +763,10 @@ static ssh_buffer ssh_msg_userauth_build_digest(ssh_session session,
|
||||
SSH2_MSG_USERAUTH_REQUEST, /* type */
|
||||
msg->auth_request.username,
|
||||
service,
|
||||
method,
|
||||
"publickey", /* method */
|
||||
1, /* has to be signed (true) */
|
||||
ssh_string_get_char(algo), /* pubkey algorithm */
|
||||
str); /* public key as a blob */
|
||||
str); /* public key as a blob */
|
||||
|
||||
SSH_STRING_FREE(str);
|
||||
if (rc != SSH_OK) {
|
||||
@@ -810,25 +775,6 @@ static ssh_buffer ssh_msg_userauth_build_digest(ssh_session session,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Add server public key for hostbound extension */
|
||||
if (strcmp(method, "publickey-hostbound-v00@openssh.com") == 0 &&
|
||||
msg->auth_request.server_pubkey != NULL) {
|
||||
|
||||
rc = ssh_pki_export_pubkey_blob(msg->auth_request.server_pubkey, &str);
|
||||
if (rc < 0) {
|
||||
SSH_BUFFER_FREE(buffer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
rc = ssh_buffer_add_ssh_string(buffer, str);
|
||||
SSH_STRING_FREE(str);
|
||||
if (rc < 0) {
|
||||
ssh_set_error_oom(session);
|
||||
SSH_BUFFER_FREE(buffer);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
@@ -838,334 +784,263 @@ static ssh_buffer ssh_msg_userauth_build_digest(ssh_session session,
|
||||
* @brief Handle a SSH_MSG_MSG_USERAUTH_REQUEST packet and queue a
|
||||
* SSH Message
|
||||
*/
|
||||
SSH_PACKET_CALLBACK(ssh_packet_userauth_request)
|
||||
{
|
||||
ssh_message msg = NULL;
|
||||
ssh_signature sig = NULL;
|
||||
char *service = NULL;
|
||||
char *method = NULL;
|
||||
int cmp;
|
||||
int rc;
|
||||
SSH_PACKET_CALLBACK(ssh_packet_userauth_request){
|
||||
ssh_message msg = NULL;
|
||||
ssh_signature sig = NULL;
|
||||
char *service = NULL;
|
||||
char *method = NULL;
|
||||
int cmp;
|
||||
int rc;
|
||||
|
||||
(void)user;
|
||||
(void)type;
|
||||
(void)user;
|
||||
(void)type;
|
||||
|
||||
msg = ssh_message_new(session);
|
||||
if (msg == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
goto error;
|
||||
msg = ssh_message_new(session);
|
||||
if (msg == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
goto error;
|
||||
}
|
||||
msg->type = SSH_REQUEST_AUTH;
|
||||
rc = ssh_buffer_unpack(packet,
|
||||
"sss",
|
||||
&msg->auth_request.username,
|
||||
&service,
|
||||
&method);
|
||||
|
||||
if (rc != SSH_OK) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
SSH_LOG(SSH_LOG_PACKET,
|
||||
"Auth request for service %s, method %s for user '%s'",
|
||||
service, method,
|
||||
msg->auth_request.username);
|
||||
|
||||
cmp = strcmp(service, "ssh-connection");
|
||||
if (cmp != 0) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Invalid service request: %s",
|
||||
service);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (strcmp(method, "none") == 0) {
|
||||
msg->auth_request.method = SSH_AUTH_METHOD_NONE;
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (strcmp(method, "password") == 0) {
|
||||
uint8_t tmp;
|
||||
|
||||
msg->auth_request.method = SSH_AUTH_METHOD_PASSWORD;
|
||||
rc = ssh_buffer_unpack(packet, "bs", &tmp, &msg->auth_request.password);
|
||||
if (rc != SSH_OK) {
|
||||
goto error;
|
||||
}
|
||||
msg->type = SSH_REQUEST_AUTH;
|
||||
rc = ssh_buffer_unpack(packet,
|
||||
"sss",
|
||||
&msg->auth_request.username,
|
||||
&service,
|
||||
&method);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (strcmp(method, "keyboard-interactive") == 0) {
|
||||
ssh_string lang = NULL;
|
||||
ssh_string submethods = NULL;
|
||||
|
||||
msg->auth_request.method = SSH_AUTH_METHOD_INTERACTIVE;
|
||||
lang = ssh_buffer_get_ssh_string(packet);
|
||||
if (lang == NULL) {
|
||||
goto error;
|
||||
}
|
||||
/* from the RFC 4256
|
||||
* 3.1. Initial Exchange
|
||||
* "The language tag is deprecated and SHOULD be the empty string."
|
||||
*/
|
||||
SSH_STRING_FREE(lang);
|
||||
|
||||
submethods = ssh_buffer_get_ssh_string(packet);
|
||||
if (submethods == NULL) {
|
||||
goto error;
|
||||
}
|
||||
/* from the RFC 4256
|
||||
* 3.1. Initial Exchange
|
||||
* "One possible implementation strategy of the submethods field on the
|
||||
* server is that, unless the user may use multiple different
|
||||
* submethods, the server ignores this field."
|
||||
*/
|
||||
SSH_STRING_FREE(submethods);
|
||||
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (strcmp(method, "publickey") == 0) {
|
||||
ssh_string algo = NULL;
|
||||
ssh_string pubkey_blob = NULL;
|
||||
uint8_t has_sign;
|
||||
|
||||
msg->auth_request.method = SSH_AUTH_METHOD_PUBLICKEY;
|
||||
SAFE_FREE(method);
|
||||
rc = ssh_buffer_unpack(packet, "bSS",
|
||||
&has_sign,
|
||||
&algo,
|
||||
&pubkey_blob
|
||||
);
|
||||
|
||||
if (rc != SSH_OK) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
rc = ssh_pki_import_pubkey_blob(pubkey_blob, &msg->auth_request.pubkey);
|
||||
SSH_STRING_FREE(pubkey_blob);
|
||||
pubkey_blob = NULL;
|
||||
if (rc < 0) {
|
||||
SSH_STRING_FREE(algo);
|
||||
algo = NULL;
|
||||
goto error;
|
||||
}
|
||||
msg->auth_request.signature_state = SSH_PUBLICKEY_STATE_NONE;
|
||||
msg->auth_request.sigtype = strdup(ssh_string_get_char(algo));
|
||||
if (msg->auth_request.sigtype == NULL) {
|
||||
msg->auth_request.signature_state = SSH_PUBLICKEY_STATE_ERROR;
|
||||
SSH_STRING_FREE(algo);
|
||||
algo = NULL;
|
||||
goto error;
|
||||
}
|
||||
|
||||
SSH_LOG(SSH_LOG_PACKET,
|
||||
"Auth request for service %s, method %s for user '%s'",
|
||||
service,
|
||||
method,
|
||||
msg->auth_request.username);
|
||||
// has a valid signature ?
|
||||
if(has_sign) {
|
||||
ssh_string sig_blob = NULL;
|
||||
ssh_buffer digest = NULL;
|
||||
|
||||
cmp = strcmp(service, "ssh-connection");
|
||||
if (cmp != 0) {
|
||||
SSH_LOG(SSH_LOG_TRACE, "Invalid service request: %s", service);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (strcmp(method, "none") == 0) {
|
||||
msg->auth_request.method = SSH_AUTH_METHOD_NONE;
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (strcmp(method, "password") == 0) {
|
||||
uint8_t tmp;
|
||||
|
||||
msg->auth_request.method = SSH_AUTH_METHOD_PASSWORD;
|
||||
rc = ssh_buffer_unpack(packet, "bs", &tmp, &msg->auth_request.password);
|
||||
if (rc != SSH_OK) {
|
||||
goto error;
|
||||
}
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (strcmp(method, "keyboard-interactive") == 0) {
|
||||
ssh_string lang = NULL;
|
||||
ssh_string submethods = NULL;
|
||||
|
||||
msg->auth_request.method = SSH_AUTH_METHOD_INTERACTIVE;
|
||||
lang = ssh_buffer_get_ssh_string(packet);
|
||||
if (lang == NULL) {
|
||||
goto error;
|
||||
}
|
||||
/* from the RFC 4256
|
||||
* 3.1. Initial Exchange
|
||||
* "The language tag is deprecated and SHOULD be the empty string."
|
||||
*/
|
||||
SSH_STRING_FREE(lang);
|
||||
|
||||
submethods = ssh_buffer_get_ssh_string(packet);
|
||||
if (submethods == NULL) {
|
||||
goto error;
|
||||
}
|
||||
/* from the RFC 4256
|
||||
* 3.1. Initial Exchange
|
||||
* "One possible implementation strategy of the submethods field on the
|
||||
* server is that, unless the user may use multiple different
|
||||
* submethods, the server ignores this field."
|
||||
*/
|
||||
SSH_STRING_FREE(submethods);
|
||||
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (strcmp(method, "publickey") == 0 ||
|
||||
strcmp(method, "publickey-hostbound-v00@openssh.com") == 0) {
|
||||
ssh_string algo = NULL;
|
||||
ssh_string pubkey_blob = NULL;
|
||||
ssh_string server_pubkey_blob = NULL;
|
||||
uint8_t has_sign;
|
||||
|
||||
msg->auth_request.method = SSH_AUTH_METHOD_PUBLICKEY;
|
||||
|
||||
rc = ssh_buffer_unpack(packet, "bSS", &has_sign, &algo, &pubkey_blob);
|
||||
|
||||
if (rc != SSH_OK) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
cmp = strcmp(method, "publickey-hostbound-v00@openssh.com");
|
||||
if (cmp == 0) {
|
||||
server_pubkey_blob = ssh_buffer_get_ssh_string(packet);
|
||||
if (server_pubkey_blob == NULL) {
|
||||
SSH_STRING_FREE(pubkey_blob);
|
||||
SSH_STRING_FREE(algo);
|
||||
goto error;
|
||||
}
|
||||
|
||||
rc = ssh_pki_import_pubkey_blob(server_pubkey_blob,
|
||||
&msg->auth_request.server_pubkey);
|
||||
SSH_STRING_FREE(server_pubkey_blob);
|
||||
|
||||
if (rc < 0) {
|
||||
SSH_STRING_FREE(pubkey_blob);
|
||||
SSH_STRING_FREE(algo);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
rc = ssh_pki_import_pubkey_blob(pubkey_blob, &msg->auth_request.pubkey);
|
||||
SSH_STRING_FREE(pubkey_blob);
|
||||
pubkey_blob = NULL;
|
||||
if (rc < 0) {
|
||||
SSH_STRING_FREE(algo);
|
||||
algo = NULL;
|
||||
goto error;
|
||||
}
|
||||
msg->auth_request.signature_state = SSH_PUBLICKEY_STATE_NONE;
|
||||
msg->auth_request.sigtype = strdup(ssh_string_get_char(algo));
|
||||
if (msg->auth_request.sigtype == NULL) {
|
||||
sig_blob = ssh_buffer_get_ssh_string(packet);
|
||||
if(sig_blob == NULL) {
|
||||
SSH_LOG(SSH_LOG_PACKET, "Invalid signature packet from peer");
|
||||
msg->auth_request.signature_state = SSH_PUBLICKEY_STATE_ERROR;
|
||||
SSH_STRING_FREE(algo);
|
||||
algo = NULL;
|
||||
goto error;
|
||||
}
|
||||
|
||||
// has a valid signature ?
|
||||
if (has_sign) {
|
||||
ssh_string sig_blob = NULL;
|
||||
ssh_buffer digest = NULL;
|
||||
digest = ssh_msg_userauth_build_digest(session, msg, service, algo);
|
||||
SSH_STRING_FREE(algo);
|
||||
algo = NULL;
|
||||
if (digest == NULL) {
|
||||
SSH_STRING_FREE(sig_blob);
|
||||
SSH_LOG(SSH_LOG_PACKET, "Failed to get digest");
|
||||
msg->auth_request.signature_state = SSH_PUBLICKEY_STATE_WRONG;
|
||||
goto error;
|
||||
}
|
||||
|
||||
sig_blob = ssh_buffer_get_ssh_string(packet);
|
||||
if (sig_blob == NULL) {
|
||||
SSH_LOG(SSH_LOG_PACKET, "Invalid signature packet from peer");
|
||||
msg->auth_request.signature_state = SSH_PUBLICKEY_STATE_ERROR;
|
||||
SSH_STRING_FREE(algo);
|
||||
algo = NULL;
|
||||
goto error;
|
||||
}
|
||||
|
||||
digest = ssh_msg_userauth_build_digest(session,
|
||||
msg,
|
||||
service,
|
||||
algo,
|
||||
method);
|
||||
SSH_STRING_FREE(algo);
|
||||
algo = NULL;
|
||||
if (digest == NULL) {
|
||||
SSH_STRING_FREE(sig_blob);
|
||||
SSH_LOG(SSH_LOG_PACKET, "Failed to get digest");
|
||||
msg->auth_request.signature_state = SSH_PUBLICKEY_STATE_WRONG;
|
||||
goto error;
|
||||
}
|
||||
|
||||
rc = ssh_pki_import_signature_blob(sig_blob,
|
||||
msg->auth_request.pubkey,
|
||||
&sig);
|
||||
if (rc == SSH_OK) {
|
||||
/* Check if the signature from client matches server preferences
|
||||
*/
|
||||
if (session->opts.pubkey_accepted_types) {
|
||||
cmp = match_group(session->opts.pubkey_accepted_types,
|
||||
sig->type_c);
|
||||
if (cmp != 1) {
|
||||
ssh_set_error(
|
||||
session,
|
||||
rc = ssh_pki_import_signature_blob(sig_blob,
|
||||
msg->auth_request.pubkey,
|
||||
&sig);
|
||||
if (rc == SSH_OK) {
|
||||
/* Check if the signature from client matches server preferences */
|
||||
if (session->opts.pubkey_accepted_types) {
|
||||
cmp = match_group(session->opts.pubkey_accepted_types,
|
||||
sig->type_c);
|
||||
if (cmp != 1) {
|
||||
ssh_set_error(session,
|
||||
SSH_FATAL,
|
||||
"Public key from client (%s) doesn't match server "
|
||||
"preference (%s)",
|
||||
sig->type_c,
|
||||
session->opts.pubkey_accepted_types);
|
||||
rc = SSH_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
if (rc == SSH_OK) {
|
||||
rc = ssh_pki_signature_verify(session,
|
||||
sig,
|
||||
msg->auth_request.pubkey,
|
||||
ssh_buffer_get(digest),
|
||||
ssh_buffer_get_len(digest));
|
||||
rc = SSH_ERROR;
|
||||
}
|
||||
}
|
||||
SSH_STRING_FREE(sig_blob);
|
||||
SSH_BUFFER_FREE(digest);
|
||||
ssh_signature_free(sig);
|
||||
if (rc < 0) {
|
||||
SSH_LOG(SSH_LOG_PACKET,
|
||||
"Received an invalid signature from peer");
|
||||
msg->auth_request.signature_state = SSH_PUBLICKEY_STATE_WRONG;
|
||||
goto error;
|
||||
|
||||
if (rc == SSH_OK) {
|
||||
rc = ssh_pki_signature_verify(session,
|
||||
sig,
|
||||
msg->auth_request.pubkey,
|
||||
ssh_buffer_get(digest),
|
||||
ssh_buffer_get_len(digest));
|
||||
}
|
||||
|
||||
SSH_LOG(SSH_LOG_PACKET, "Valid signature received");
|
||||
|
||||
cmp = strcmp(method, "publickey-hostbound-v00@openssh.com");
|
||||
if (cmp == 0) {
|
||||
ssh_key server_key = NULL;
|
||||
|
||||
if (msg->auth_request.server_pubkey == NULL) {
|
||||
SSH_LOG(SSH_LOG_PACKET,
|
||||
"Server public key not provided by client");
|
||||
msg->auth_request.signature_state =
|
||||
SSH_PUBLICKEY_STATE_WRONG;
|
||||
goto error;
|
||||
}
|
||||
|
||||
rc = ssh_get_server_publickey(session, &server_key);
|
||||
if (rc != SSH_OK) {
|
||||
SSH_LOG(SSH_LOG_PACKET,
|
||||
"Failed to get server public key for hostbound "
|
||||
"verification");
|
||||
msg->auth_request.signature_state =
|
||||
SSH_PUBLICKEY_STATE_ERROR;
|
||||
ssh_key_free(server_key);
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (ssh_key_cmp(server_key,
|
||||
msg->auth_request.server_pubkey,
|
||||
SSH_KEY_CMP_PUBLIC) != 0) {
|
||||
SSH_LOG(SSH_LOG_PACKET,
|
||||
"Server public key doesn't match the one provided "
|
||||
"by client");
|
||||
msg->auth_request.signature_state =
|
||||
SSH_PUBLICKEY_STATE_WRONG;
|
||||
ssh_key_free(server_key);
|
||||
goto error;
|
||||
}
|
||||
ssh_key_free(server_key);
|
||||
}
|
||||
|
||||
msg->auth_request.signature_state = SSH_PUBLICKEY_STATE_VALID;
|
||||
}
|
||||
SSH_STRING_FREE(sig_blob);
|
||||
SSH_BUFFER_FREE(digest);
|
||||
ssh_signature_free(sig);
|
||||
if (rc < 0) {
|
||||
SSH_LOG(
|
||||
SSH_LOG_PACKET,
|
||||
"Received an invalid signature from peer");
|
||||
msg->auth_request.signature_state = SSH_PUBLICKEY_STATE_WRONG;
|
||||
goto error;
|
||||
}
|
||||
|
||||
SAFE_FREE(method);
|
||||
SSH_STRING_FREE(algo);
|
||||
goto end;
|
||||
SSH_LOG(SSH_LOG_PACKET, "Valid signature received");
|
||||
|
||||
msg->auth_request.signature_state = SSH_PUBLICKEY_STATE_VALID;
|
||||
}
|
||||
SSH_STRING_FREE(algo);
|
||||
goto end;
|
||||
}
|
||||
#ifdef WITH_GSSAPI
|
||||
if (strcmp(method, "gssapi-with-mic") == 0) {
|
||||
uint32_t n_oid;
|
||||
ssh_string *oids = NULL;
|
||||
ssh_string oid = NULL;
|
||||
char *hexa = NULL;
|
||||
int i;
|
||||
ssh_buffer_get_u32(packet, &n_oid);
|
||||
n_oid = ntohl(n_oid);
|
||||
if (n_oid > 100) {
|
||||
ssh_set_error(
|
||||
session,
|
||||
SSH_FATAL,
|
||||
"USERAUTH_REQUEST: gssapi-with-mic OID count too big (%d)",
|
||||
n_oid);
|
||||
goto error;
|
||||
}
|
||||
SSH_LOG(SSH_LOG_PACKET, "gssapi: %d OIDs", n_oid);
|
||||
oids = calloc(n_oid, sizeof(ssh_string));
|
||||
if (oids == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
goto error;
|
||||
}
|
||||
for (i = 0; i < (int)n_oid; ++i) {
|
||||
oid = ssh_buffer_get_ssh_string(packet);
|
||||
if (oid == NULL) {
|
||||
for (i = i - 1; i >= 0; --i) {
|
||||
SAFE_FREE(oids[i]);
|
||||
}
|
||||
SAFE_FREE(oids);
|
||||
ssh_set_error(session,
|
||||
SSH_LOG_PACKET,
|
||||
"USERAUTH_REQUEST: gssapi-with-mic missing OID");
|
||||
goto error;
|
||||
}
|
||||
oids[i] = oid;
|
||||
if (session->common.log_verbosity >= SSH_LOG_PACKET) {
|
||||
hexa = ssh_get_hexa(ssh_string_data(oid), ssh_string_len(oid));
|
||||
SSH_LOG(SSH_LOG_PACKET, "gssapi: OID %d: %s", i, hexa);
|
||||
SAFE_FREE(hexa);
|
||||
}
|
||||
}
|
||||
ssh_gssapi_handle_userauth(session,
|
||||
msg->auth_request.username,
|
||||
n_oid,
|
||||
oids);
|
||||
if (strcmp(method, "gssapi-with-mic") == 0) {
|
||||
uint32_t n_oid;
|
||||
ssh_string *oids = NULL;
|
||||
ssh_string oid = NULL;
|
||||
char *hexa = NULL;
|
||||
int i;
|
||||
ssh_buffer_get_u32(packet, &n_oid);
|
||||
n_oid=ntohl(n_oid);
|
||||
if(n_oid > 100){
|
||||
ssh_set_error(session, SSH_FATAL, "USERAUTH_REQUEST: gssapi-with-mic OID count too big (%d)",n_oid);
|
||||
goto error;
|
||||
}
|
||||
SSH_LOG(SSH_LOG_PACKET, "gssapi: %d OIDs", n_oid);
|
||||
oids = calloc(n_oid, sizeof(ssh_string));
|
||||
if (oids == NULL){
|
||||
ssh_set_error_oom(session);
|
||||
goto error;
|
||||
}
|
||||
for (i=0;i<(int) n_oid;++i){
|
||||
oid=ssh_buffer_get_ssh_string(packet);
|
||||
if(oid == NULL){
|
||||
for(i=i-1;i>=0;--i){
|
||||
SAFE_FREE(oids[i]);
|
||||
}
|
||||
SAFE_FREE(oids);
|
||||
ssh_set_error(session, SSH_LOG_PACKET, "USERAUTH_REQUEST: gssapi-with-mic missing OID");
|
||||
goto error;
|
||||
}
|
||||
oids[i] = oid;
|
||||
if(session->common.log_verbosity >= SSH_LOG_PACKET){
|
||||
hexa = ssh_get_hexa(ssh_string_data(oid), ssh_string_len(oid));
|
||||
SSH_LOG(SSH_LOG_PACKET,"gssapi: OID %d: %s",i, hexa);
|
||||
SAFE_FREE(hexa);
|
||||
}
|
||||
}
|
||||
ssh_gssapi_handle_userauth(session, msg->auth_request.username, n_oid, oids);
|
||||
|
||||
for (i = 0; i < (int)n_oid; ++i) {
|
||||
SAFE_FREE(oids[i]);
|
||||
}
|
||||
SAFE_FREE(oids);
|
||||
/* bypass the message queue thing */
|
||||
SAFE_FREE(service);
|
||||
SAFE_FREE(method);
|
||||
SSH_MESSAGE_FREE(msg);
|
||||
for(i=0;i<(int)n_oid;++i){
|
||||
SAFE_FREE(oids[i]);
|
||||
}
|
||||
SAFE_FREE(oids);
|
||||
/* bypass the message queue thing */
|
||||
SAFE_FREE(service);
|
||||
SAFE_FREE(method);
|
||||
SSH_MESSAGE_FREE(msg);
|
||||
|
||||
return SSH_PACKET_USED;
|
||||
}
|
||||
return SSH_PACKET_USED;
|
||||
}
|
||||
#endif
|
||||
|
||||
msg->auth_request.method = SSH_AUTH_METHOD_UNKNOWN;
|
||||
SAFE_FREE(method);
|
||||
goto end;
|
||||
msg->auth_request.method = SSH_AUTH_METHOD_UNKNOWN;
|
||||
SAFE_FREE(method);
|
||||
goto end;
|
||||
error:
|
||||
SAFE_FREE(service);
|
||||
SAFE_FREE(method);
|
||||
SAFE_FREE(service);
|
||||
SAFE_FREE(method);
|
||||
|
||||
SSH_MESSAGE_FREE(msg);
|
||||
SSH_MESSAGE_FREE(msg);
|
||||
|
||||
return SSH_PACKET_USED;
|
||||
return SSH_PACKET_USED;
|
||||
end:
|
||||
SAFE_FREE(service);
|
||||
SAFE_FREE(method);
|
||||
SAFE_FREE(service);
|
||||
SAFE_FREE(method);
|
||||
|
||||
ssh_message_queue(session, msg);
|
||||
ssh_message_queue(session,msg);
|
||||
|
||||
return SSH_PACKET_USED;
|
||||
return SSH_PACKET_USED;
|
||||
}
|
||||
|
||||
#endif /* WITH_SERVER */
|
||||
@@ -1426,9 +1301,7 @@ end:
|
||||
*
|
||||
* @returns SSH_OK on success, SSH_ERROR if an error occurred.
|
||||
*/
|
||||
int ssh_message_channel_request_open_reply_accept_channel(ssh_message msg,
|
||||
ssh_channel chan)
|
||||
{
|
||||
int ssh_message_channel_request_open_reply_accept_channel(ssh_message msg, ssh_channel chan) {
|
||||
ssh_session session = NULL;
|
||||
int rc;
|
||||
|
||||
@@ -1479,25 +1352,25 @@ int ssh_message_channel_request_open_reply_accept_channel(ssh_message msg,
|
||||
*
|
||||
* @returns NULL in case of error
|
||||
*/
|
||||
ssh_channel ssh_message_channel_request_open_reply_accept(ssh_message msg)
|
||||
{
|
||||
ssh_channel chan = NULL;
|
||||
int rc;
|
||||
ssh_channel ssh_message_channel_request_open_reply_accept(ssh_message msg) {
|
||||
ssh_channel chan = NULL;
|
||||
int rc;
|
||||
|
||||
if (msg == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
if (msg == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
chan = ssh_channel_new(msg->session);
|
||||
if (chan == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
rc = ssh_message_channel_request_open_reply_accept_channel(msg, chan);
|
||||
if (rc < 0) {
|
||||
ssh_channel_free(chan);
|
||||
chan = NULL;
|
||||
}
|
||||
return chan;
|
||||
|
||||
chan = ssh_channel_new(msg->session);
|
||||
if (chan == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
rc = ssh_message_channel_request_open_reply_accept_channel(msg, chan);
|
||||
if (rc < 0) {
|
||||
ssh_channel_free(chan);
|
||||
chan = NULL;
|
||||
}
|
||||
return chan;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
126
src/misc.c
126
src/misc.c
@@ -178,35 +178,6 @@ int ssh_gettimeofday(struct timeval *__p, void *__t)
|
||||
return (0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
* @brief Convert time in seconds since the Epoch to broken-down local time
|
||||
*
|
||||
* This is a helper used to provide localtime_r() like function interface
|
||||
* on Windows.
|
||||
*
|
||||
* @param timer Pointer to a location storing the time_t which
|
||||
* represents the time in seconds since the Epoch.
|
||||
*
|
||||
* @param result Pointer to a location where the broken-down time
|
||||
* (expressed as local time) should be stored.
|
||||
*
|
||||
* @returns A pointer to the structure pointed to by the parameter
|
||||
* <tt>result</tt> on success, NULL on error with the errno
|
||||
* set to indicate the error.
|
||||
*/
|
||||
struct tm *ssh_localtime(const time_t *timer, struct tm *result)
|
||||
{
|
||||
errno_t rc;
|
||||
rc = localtime_s(result, timer);
|
||||
if (rc != 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
char *ssh_get_local_username(void)
|
||||
{
|
||||
DWORD size = 0;
|
||||
@@ -430,22 +401,22 @@ int ssh_is_ipaddr(const char *str)
|
||||
|
||||
char *ssh_lowercase(const char* str)
|
||||
{
|
||||
char *new = NULL, *p = NULL;
|
||||
char *new = NULL, *p = NULL;
|
||||
|
||||
if (str == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
if (str == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
new = strdup(str);
|
||||
if (new == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
new = strdup(str);
|
||||
if (new == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (p = new; *p; p++) {
|
||||
*p = tolower(*p);
|
||||
}
|
||||
for (p = new; *p; p++) {
|
||||
*p = tolower(*p);
|
||||
}
|
||||
|
||||
return new;
|
||||
return new;
|
||||
}
|
||||
|
||||
char *ssh_hostport(const char *host, int port)
|
||||
@@ -865,32 +836,32 @@ int ssh_list_prepend(struct ssh_list *list, const void *data)
|
||||
|
||||
void ssh_list_remove(struct ssh_list *list, struct ssh_iterator *iterator)
|
||||
{
|
||||
struct ssh_iterator *ptr = NULL, *prev = NULL;
|
||||
struct ssh_iterator *ptr = NULL, *prev = NULL;
|
||||
|
||||
if (list == NULL) {
|
||||
return;
|
||||
}
|
||||
if (list == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
prev = NULL;
|
||||
ptr = list->root;
|
||||
while (ptr && ptr != iterator) {
|
||||
prev = ptr;
|
||||
ptr = ptr->next;
|
||||
}
|
||||
if (!ptr) {
|
||||
/* we did not find the element */
|
||||
return;
|
||||
}
|
||||
/* unlink it */
|
||||
if (prev)
|
||||
prev->next = ptr->next;
|
||||
/* if iterator was the head */
|
||||
if (list->root == iterator)
|
||||
list->root = iterator->next;
|
||||
/* if iterator was the tail */
|
||||
if (list->end == iterator)
|
||||
list->end = prev;
|
||||
SAFE_FREE(iterator);
|
||||
prev=NULL;
|
||||
ptr=list->root;
|
||||
while(ptr && ptr != iterator){
|
||||
prev=ptr;
|
||||
ptr=ptr->next;
|
||||
}
|
||||
if(!ptr){
|
||||
/* we did not find the element */
|
||||
return;
|
||||
}
|
||||
/* unlink it */
|
||||
if(prev)
|
||||
prev->next=ptr->next;
|
||||
/* if iterator was the head */
|
||||
if(list->root == iterator)
|
||||
list->root=iterator->next;
|
||||
/* if iterator was the tail */
|
||||
if(list->end == iterator)
|
||||
list->end = prev;
|
||||
SAFE_FREE(iterator);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1619,27 +1590,6 @@ void explicit_bzero(void *s, size_t n)
|
||||
}
|
||||
#endif /* !HAVE_EXPLICIT_BZERO */
|
||||
|
||||
/**
|
||||
* @brief Securely free memory by overwriting it before deallocation
|
||||
*
|
||||
* Overwrites the memory region with zeros before calling free() to prevent
|
||||
* sensitive data from remaining in memory after deallocation.
|
||||
*
|
||||
* @param[in] ptr Pointer to the memory region to securely free.
|
||||
* Can be NULL (no operation performed).
|
||||
* @param[in] len Length of the memory region in bytes.
|
||||
*
|
||||
*/
|
||||
void burn_free(void *ptr, size_t len)
|
||||
{
|
||||
if (ptr == NULL || len == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
explicit_bzero(ptr, len);
|
||||
free(ptr);
|
||||
}
|
||||
|
||||
#if !defined(HAVE_STRNDUP)
|
||||
char *strndup(const char *s, size_t n)
|
||||
{
|
||||
@@ -1852,7 +1802,7 @@ int ssh_quote_file_name(const char *file_name, char *buf, size_t buf_len)
|
||||
/* Put the string terminator */
|
||||
*dst = '\0';
|
||||
|
||||
return (int)(dst - buf);
|
||||
return dst - buf;
|
||||
|
||||
error:
|
||||
return SSH_ERROR;
|
||||
@@ -1898,7 +1848,7 @@ int ssh_newline_vis(const char *string, char *buf, size_t buf_len)
|
||||
}
|
||||
*out = '\0';
|
||||
|
||||
return (int)(out - buf);
|
||||
return out - buf;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
105
src/options.c
105
src/options.c
@@ -1814,8 +1814,6 @@ int ssh_options_getopt(ssh_session session, int *argcptr, char **argv)
|
||||
*
|
||||
* @param filename The options file to use, if NULL the default
|
||||
* ~/.ssh/config and /etc/ssh/ssh_config will be used.
|
||||
* If complied with support for hermetic-usr,
|
||||
* /usr/etc/ssh/ssh_config will be used last.
|
||||
*
|
||||
* @return 0 on success, < 0 on error.
|
||||
*
|
||||
@@ -1823,63 +1821,48 @@ int ssh_options_getopt(ssh_session session, int *argcptr, char **argv)
|
||||
*/
|
||||
int ssh_options_parse_config(ssh_session session, const char *filename)
|
||||
{
|
||||
char *expanded_filename = NULL;
|
||||
int r;
|
||||
FILE *fp = NULL;
|
||||
char *expanded_filename = NULL;
|
||||
int r;
|
||||
|
||||
if (session == NULL) {
|
||||
return -1;
|
||||
}
|
||||
if (session->opts.host == NULL) {
|
||||
ssh_set_error_invalid(session);
|
||||
return -1;
|
||||
}
|
||||
if (session == NULL) {
|
||||
return -1;
|
||||
}
|
||||
if (session->opts.host == NULL) {
|
||||
ssh_set_error_invalid(session);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (session->opts.sshdir == NULL) {
|
||||
r = ssh_options_set(session, SSH_OPTIONS_SSH_DIR, NULL);
|
||||
if (r < 0) {
|
||||
ssh_set_error_oom(session);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (session->opts.sshdir == NULL) {
|
||||
r = ssh_options_set(session, SSH_OPTIONS_SSH_DIR, NULL);
|
||||
if (r < 0) {
|
||||
ssh_set_error_oom(session);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* set default filename */
|
||||
if (filename == NULL) {
|
||||
expanded_filename = ssh_path_expand_escape(session, "%d/config");
|
||||
} else {
|
||||
expanded_filename = ssh_path_expand_escape(session, filename);
|
||||
}
|
||||
if (expanded_filename == NULL) {
|
||||
return -1;
|
||||
}
|
||||
/* set default filename */
|
||||
if (filename == NULL) {
|
||||
expanded_filename = ssh_path_expand_escape(session, "%d/config");
|
||||
} else {
|
||||
expanded_filename = ssh_path_expand_escape(session, filename);
|
||||
}
|
||||
if (expanded_filename == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
r = ssh_config_parse_file(session, expanded_filename);
|
||||
if (r < 0) {
|
||||
goto out;
|
||||
}
|
||||
if (filename == NULL) {
|
||||
if ((fp = fopen(GLOBAL_CLIENT_CONFIG, "r")) != NULL) {
|
||||
filename = GLOBAL_CLIENT_CONFIG;
|
||||
#ifdef USR_GLOBAL_CLIENT_CONFIG
|
||||
} else if ((fp = fopen(USR_GLOBAL_CLIENT_CONFIG, "r")) != NULL) {
|
||||
filename = USR_GLOBAL_CLIENT_CONFIG;
|
||||
#endif
|
||||
}
|
||||
r = ssh_config_parse_file(session, expanded_filename);
|
||||
if (r < 0) {
|
||||
goto out;
|
||||
}
|
||||
if (filename == NULL) {
|
||||
r = ssh_config_parse_file(session, GLOBAL_CLIENT_CONFIG);
|
||||
}
|
||||
|
||||
if (fp) {
|
||||
SSH_LOG(SSH_LOG_PACKET,
|
||||
"Reading configuration data from %s",
|
||||
filename);
|
||||
r = ssh_config_parse(session, fp, true);
|
||||
fclose(fp);
|
||||
}
|
||||
}
|
||||
|
||||
/* Do not process the default configuration as part of connection again */
|
||||
session->opts.config_processed = true;
|
||||
/* Do not process the default configuration as part of connection again */
|
||||
session->opts.config_processed = true;
|
||||
out:
|
||||
free(expanded_filename);
|
||||
return r;
|
||||
free(expanded_filename);
|
||||
return r;
|
||||
}
|
||||
|
||||
int ssh_options_apply(ssh_session session)
|
||||
@@ -2285,9 +2268,6 @@ ssh_bind_options_set(ssh_bind sshbind,
|
||||
SSH_FATAL,
|
||||
"The host key size %d is too small.",
|
||||
ssh_key_size(key));
|
||||
if (type != SSH_BIND_OPTIONS_IMPORT_KEY) {
|
||||
SSH_KEY_FREE(key);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
key_type = ssh_key_type(key);
|
||||
@@ -2333,11 +2313,6 @@ ssh_bind_options_set(ssh_bind sshbind,
|
||||
ssh_key_free(key);
|
||||
return -1;
|
||||
}
|
||||
} else if (type == SSH_BIND_OPTIONS_IMPORT_KEY_STR) {
|
||||
if (bind_key_loc == NULL) {
|
||||
ssh_key_free(key);
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
if (bind_key_loc == NULL) {
|
||||
return -1;
|
||||
@@ -2731,13 +2706,7 @@ int ssh_bind_options_parse_config(ssh_bind sshbind, const char *filename)
|
||||
/* If the global default configuration hasn't been processed yet, process it
|
||||
* before the provided configuration. */
|
||||
if (!(sshbind->config_processed)) {
|
||||
if (ssh_file_readaccess_ok(GLOBAL_BIND_CONFIG)) {
|
||||
rc = ssh_bind_config_parse_file(sshbind, GLOBAL_BIND_CONFIG);
|
||||
#ifdef USR_GLOBAL_BIND_CONFIG
|
||||
} else {
|
||||
rc = ssh_bind_config_parse_file(sshbind, USR_GLOBAL_BIND_CONFIG);
|
||||
#endif
|
||||
}
|
||||
rc = ssh_bind_config_parse_file(sshbind, GLOBAL_BIND_CONFIG);
|
||||
if (rc != 0) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
20
src/packet.c
20
src/packet.c
@@ -294,6 +294,7 @@ static enum ssh_packet_filter_result_e ssh_packet_incoming_filter(ssh_session se
|
||||
* or session_state == SSH_SESSION_STATE_INITIAL_KEX
|
||||
* - dh_handshake_state == DH_STATE_INIT
|
||||
* or dh_handshake_state == DH_STATE_INIT_SENT (re-exchange)
|
||||
* or dh_handshake_state == DH_STATE_REQUEST_SENT (dh-gex)
|
||||
* or dh_handshake_state == DH_STATE_FINISHED (re-exchange)
|
||||
*
|
||||
* Transitions:
|
||||
@@ -313,6 +314,7 @@ static enum ssh_packet_filter_result_e ssh_packet_incoming_filter(ssh_session se
|
||||
|
||||
if ((session->dh_handshake_state != DH_STATE_INIT) &&
|
||||
(session->dh_handshake_state != DH_STATE_INIT_SENT) &&
|
||||
(session->dh_handshake_state != DH_STATE_REQUEST_SENT) &&
|
||||
(session->dh_handshake_state != DH_STATE_FINISHED))
|
||||
{
|
||||
rc = SSH_PACKET_DENIED;
|
||||
@@ -1158,7 +1160,7 @@ ssh_packet_socket_callback(const void *data, size_t receivedlen, void *user)
|
||||
uint32_t lenfield_blocksize = 8;
|
||||
size_t current_macsize = 0;
|
||||
uint8_t *ptr = NULL;
|
||||
ssize_t to_be_read;
|
||||
long to_be_read;
|
||||
int rc;
|
||||
uint8_t *cleartext_packet = NULL;
|
||||
uint8_t *packet_second_block = NULL;
|
||||
@@ -1268,7 +1270,7 @@ ssh_packet_socket_callback(const void *data, size_t receivedlen, void *user)
|
||||
/* remote sshd sends invalid sizes? */
|
||||
ssh_set_error(session,
|
||||
SSH_FATAL,
|
||||
"Given numbers of bytes left to be read < 0 (%zd)!",
|
||||
"Given numbers of bytes left to be read < 0 (%ld)!",
|
||||
to_be_read);
|
||||
goto error;
|
||||
}
|
||||
@@ -1286,7 +1288,7 @@ ssh_packet_socket_callback(const void *data, size_t receivedlen, void *user)
|
||||
/* give up, not enough data in buffer */
|
||||
SSH_LOG(SSH_LOG_PACKET,
|
||||
"packet: partial packet (read len) "
|
||||
"[len=%" PRIu32 ", receivedlen=%zu, to_be_read=%zd]",
|
||||
"[len=%" PRIu32 ", receivedlen=%zu, to_be_read=%ld]",
|
||||
packet_len,
|
||||
receivedlen,
|
||||
to_be_read);
|
||||
@@ -1300,7 +1302,7 @@ ssh_packet_socket_callback(const void *data, size_t receivedlen, void *user)
|
||||
/* remaining encrypted bytes from the packet, MAC not included */
|
||||
packet_remaining = packet_len - (packet_offset - sizeof(uint32_t));
|
||||
cleartext_packet = ssh_buffer_allocate(session->in_buffer,
|
||||
(uint32_t)packet_remaining);
|
||||
packet_remaining);
|
||||
if (cleartext_packet == NULL) {
|
||||
goto error;
|
||||
}
|
||||
@@ -1476,7 +1478,6 @@ ssh_packet_socket_callback(const void *data, size_t receivedlen, void *user)
|
||||
|
||||
session->packet_state = PACKET_STATE_INIT;
|
||||
if (processed < receivedlen) {
|
||||
size_t num;
|
||||
/* Handle a potential packet left in socket buffer */
|
||||
SSH_LOG(SSH_LOG_PACKET,
|
||||
"Processing %zu bytes left in socket buffer",
|
||||
@@ -1484,10 +1485,9 @@ ssh_packet_socket_callback(const void *data, size_t receivedlen, void *user)
|
||||
|
||||
ptr = ((uint8_t*)data) + processed;
|
||||
|
||||
num = ssh_packet_socket_callback(ptr,
|
||||
receivedlen - processed,
|
||||
user);
|
||||
processed += num;
|
||||
rc = ssh_packet_socket_callback(ptr, receivedlen - processed,
|
||||
user);
|
||||
processed += rc;
|
||||
}
|
||||
|
||||
ok = ssh_packet_need_rekey(session, 0);
|
||||
@@ -1856,7 +1856,7 @@ static int packet_send2(ssh_session session)
|
||||
if (hmac != NULL) {
|
||||
rc = ssh_buffer_add_data(session->out_buffer,
|
||||
hmac,
|
||||
(uint32_t)hmac_digest_len(hmac_type));
|
||||
hmac_digest_len(hmac_type));
|
||||
if (rc < 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
@@ -291,6 +291,7 @@ SSH_PACKET_CALLBACK(ssh_packet_ext_info)
|
||||
for (i = 0; i < nr_extensions; i++) {
|
||||
char *name = NULL;
|
||||
char *value = NULL;
|
||||
int cmp;
|
||||
|
||||
rc = ssh_buffer_unpack(packet, "ss", &name, &value);
|
||||
if (rc != SSH_OK) {
|
||||
@@ -298,7 +299,8 @@ SSH_PACKET_CALLBACK(ssh_packet_ext_info)
|
||||
return SSH_PACKET_USED;
|
||||
}
|
||||
|
||||
if (strcmp(name, "server-sig-algs") == 0) {
|
||||
cmp = strcmp(name, "server-sig-algs");
|
||||
if (cmp == 0) {
|
||||
/* TODO check for NULL bytes */
|
||||
SSH_LOG(SSH_LOG_PACKET, "Extension: %s=<%s>", name, value);
|
||||
|
||||
@@ -311,9 +313,6 @@ SSH_PACKET_CALLBACK(ssh_packet_ext_info)
|
||||
if (rc == 1) {
|
||||
session->extensions |= SSH_EXT_SIG_RSA_SHA256;
|
||||
}
|
||||
} else if (strcmp(name, "publickey-hostbound@openssh.com") == 0) {
|
||||
SSH_LOG(SSH_LOG_PACKET, "Extension: %s=<%s>", name, value);
|
||||
session->extensions |= SSH_EXT_PUBLICKEY_HOSTBOUND;
|
||||
} else {
|
||||
SSH_LOG(SSH_LOG_PACKET, "Unknown extension: %s", name);
|
||||
}
|
||||
|
||||
@@ -126,10 +126,11 @@ ssh_pcap_file ssh_pcap_file_new(void)
|
||||
{
|
||||
struct ssh_pcap_file_struct *pcap = NULL;
|
||||
|
||||
pcap = calloc(1, sizeof(struct ssh_pcap_file_struct));
|
||||
pcap = malloc(sizeof(struct ssh_pcap_file_struct));
|
||||
if (pcap == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
ZERO_STRUCTP(pcap);
|
||||
|
||||
return pcap;
|
||||
}
|
||||
@@ -295,13 +296,12 @@ void ssh_pcap_file_free(ssh_pcap_file pcap)
|
||||
*/
|
||||
ssh_pcap_context ssh_pcap_context_new(ssh_session session)
|
||||
{
|
||||
ssh_pcap_context ctx = NULL;
|
||||
|
||||
ctx = calloc(1, sizeof(struct ssh_pcap_context_struct));
|
||||
ssh_pcap_context ctx = (struct ssh_pcap_context_struct *)malloc(sizeof(struct ssh_pcap_context_struct));
|
||||
if (ctx == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
return NULL;
|
||||
}
|
||||
ZERO_STRUCTP(ctx);
|
||||
ctx->session = session;
|
||||
return ctx;
|
||||
}
|
||||
|
||||
@@ -155,7 +155,7 @@ static int pki_private_key_decrypt(ssh_string blob,
|
||||
}
|
||||
rc = ssh_buffer_add_data(buffer,
|
||||
ssh_string_data(kdfoptions),
|
||||
(uint32_t)ssh_string_len(kdfoptions));
|
||||
ssh_string_len(kdfoptions));
|
||||
if (rc != SSH_ERROR){
|
||||
rc = ssh_buffer_unpack(buffer, "Sd", &salt, &rounds);
|
||||
}
|
||||
@@ -339,7 +339,7 @@ ssh_pki_openssh_import(const char *text_key,
|
||||
ssh_buffer_set_secure(privkey_buffer);
|
||||
ssh_buffer_add_data(privkey_buffer,
|
||||
ssh_string_data(privkeys),
|
||||
(uint32_t)ssh_string_len(privkeys));
|
||||
ssh_string_len(privkeys));
|
||||
|
||||
rc = ssh_buffer_unpack(privkey_buffer, "dd", &checkint1, &checkint2);
|
||||
if (rc == SSH_ERROR || checkint1 != checkint2) {
|
||||
|
||||
1220
src/pki_crypto.c
1220
src/pki_crypto.c
File diff suppressed because it is too large
Load Diff
@@ -28,205 +28,6 @@
|
||||
#include "libssh/ed25519.h"
|
||||
#include "libssh/buffer.h"
|
||||
|
||||
int pki_pubkey_build_ed25519(ssh_key key, ssh_string pubkey)
|
||||
{
|
||||
if (ssh_string_len(pubkey) != ED25519_KEY_LEN) {
|
||||
SSH_LOG(SSH_LOG_TRACE, "Invalid ed25519 key len");
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
key->ed25519_pubkey = malloc(ED25519_KEY_LEN);
|
||||
if (key->ed25519_pubkey == NULL) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
memcpy(key->ed25519_pubkey, ssh_string_data(pubkey), ED25519_KEY_LEN);
|
||||
|
||||
return SSH_OK;
|
||||
}
|
||||
|
||||
int pki_privkey_build_ed25519(ssh_key key,
|
||||
ssh_string pubkey,
|
||||
ssh_string privkey)
|
||||
{
|
||||
if (ssh_string_len(pubkey) != ED25519_KEY_LEN ||
|
||||
ssh_string_len(privkey) != (2 * ED25519_KEY_LEN)) {
|
||||
SSH_LOG(SSH_LOG_TRACE, "Invalid ed25519 key len");
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
/* In the internal implementation, the private key is the concatenation of
|
||||
* the private seed with the public key. */
|
||||
key->ed25519_privkey = malloc(2 * ED25519_KEY_LEN);
|
||||
if (key->ed25519_privkey == NULL) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
key->ed25519_pubkey = malloc(ED25519_KEY_LEN);
|
||||
if (key->ed25519_pubkey == NULL) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
memcpy(key->ed25519_privkey, ssh_string_data(privkey), 2 * ED25519_KEY_LEN);
|
||||
memcpy(key->ed25519_pubkey, ssh_string_data(pubkey), ED25519_KEY_LEN);
|
||||
|
||||
return SSH_OK;
|
||||
|
||||
error:
|
||||
SAFE_FREE(key->ed25519_privkey);
|
||||
SAFE_FREE(key->ed25519_pubkey);
|
||||
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
* @brief Compare ed25519 keys if they are equal.
|
||||
*
|
||||
* @param[in] k1 The first key to compare.
|
||||
*
|
||||
* @param[in] k2 The second key to compare.
|
||||
*
|
||||
* @param[in] what What part or type of the key do you want to compare.
|
||||
*
|
||||
* @return 0 if equal, 1 if not.
|
||||
*/
|
||||
int
|
||||
pki_ed25519_key_cmp(const ssh_key k1, const ssh_key k2, enum ssh_keycmp_e what)
|
||||
{
|
||||
int cmp;
|
||||
|
||||
switch (what) {
|
||||
case SSH_KEY_CMP_PRIVATE:
|
||||
if (k1->ed25519_privkey == NULL || k2->ed25519_privkey == NULL) {
|
||||
return 1;
|
||||
}
|
||||
/* In the internal implementation, the private key is the concatenation
|
||||
* of the private seed with the public key. */
|
||||
cmp = memcmp(k1->ed25519_privkey,
|
||||
k2->ed25519_privkey,
|
||||
2 * ED25519_KEY_LEN);
|
||||
if (cmp != 0) {
|
||||
return 1;
|
||||
}
|
||||
FALL_THROUGH;
|
||||
case SSH_KEY_CMP_PUBLIC:
|
||||
if (k1->ed25519_pubkey == NULL || k2->ed25519_pubkey == NULL) {
|
||||
return 1;
|
||||
}
|
||||
cmp = memcmp(k1->ed25519_pubkey, k2->ed25519_pubkey, ED25519_KEY_LEN);
|
||||
if (cmp != 0) {
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case SSH_KEY_CMP_CERTIFICATE:
|
||||
/* handled globally */
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
* @brief Duplicate an Ed25519 key
|
||||
*
|
||||
* @param[out] new Pre-initialized ssh_key structure
|
||||
*
|
||||
* @param[in] key Key to copy
|
||||
*
|
||||
* @return SSH_ERROR on error, SSH_OK on success
|
||||
*/
|
||||
int pki_ed25519_key_dup(ssh_key new_key, const ssh_key key)
|
||||
{
|
||||
if (key->ed25519_privkey == NULL && key->ed25519_pubkey == NULL) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
if (key->ed25519_privkey != NULL) {
|
||||
/* In the internal implementation, the private key is the concatenation
|
||||
* of the private seed with the public key. */
|
||||
new_key->ed25519_privkey = malloc(2 * ED25519_KEY_LEN);
|
||||
if (new_key->ed25519_privkey == NULL) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
memcpy(new_key->ed25519_privkey,
|
||||
key->ed25519_privkey,
|
||||
2 * ED25519_KEY_LEN);
|
||||
}
|
||||
|
||||
if (key->ed25519_pubkey != NULL) {
|
||||
new_key->ed25519_pubkey = malloc(ED25519_KEY_LEN);
|
||||
if (new_key->ed25519_pubkey == NULL) {
|
||||
SAFE_FREE(new_key->ed25519_privkey);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
memcpy(new_key->ed25519_pubkey, key->ed25519_pubkey, ED25519_KEY_LEN);
|
||||
}
|
||||
|
||||
return SSH_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
* @brief Outputs an Ed25519 public key in a blob buffer.
|
||||
*
|
||||
* @param[out] buffer Output buffer
|
||||
*
|
||||
* @param[in] key Key to output
|
||||
*
|
||||
* @return SSH_ERROR on error, SSH_OK on success
|
||||
*/
|
||||
int pki_ed25519_public_key_to_blob(ssh_buffer buffer, ssh_key key)
|
||||
{
|
||||
int rc;
|
||||
|
||||
if (key->ed25519_pubkey == NULL) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
rc = ssh_buffer_pack(buffer,
|
||||
"dP",
|
||||
(uint32_t)ED25519_KEY_LEN,
|
||||
(size_t)ED25519_KEY_LEN,
|
||||
key->ed25519_pubkey);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/** @internal
|
||||
* @brief exports a ed25519 private key to a string blob.
|
||||
* @param[in] privkey private key to convert
|
||||
* @param[out] buffer buffer to write the blob in.
|
||||
* @returns SSH_OK on success
|
||||
*/
|
||||
int pki_ed25519_private_key_to_blob(ssh_buffer buffer, const ssh_key privkey)
|
||||
{
|
||||
int rc;
|
||||
|
||||
if (privkey->type != SSH_KEYTYPE_ED25519) {
|
||||
SSH_LOG(SSH_LOG_TRACE, "Type %s not supported", privkey->type_c);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
if (privkey->ed25519_privkey == NULL || privkey->ed25519_pubkey == NULL) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
rc = ssh_buffer_pack(buffer,
|
||||
"dPdPP",
|
||||
(uint32_t)ED25519_KEY_LEN,
|
||||
(size_t)ED25519_KEY_LEN,
|
||||
privkey->ed25519_pubkey,
|
||||
(uint32_t)(2 * ED25519_KEY_LEN),
|
||||
(size_t)ED25519_KEY_LEN,
|
||||
privkey->ed25519_privkey,
|
||||
(size_t)ED25519_KEY_LEN,
|
||||
privkey->ed25519_pubkey);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int pki_key_generate_ed25519(ssh_key key)
|
||||
{
|
||||
int rc;
|
||||
|
||||
@@ -27,6 +27,213 @@
|
||||
#include "libssh/pki_priv.h"
|
||||
#include "libssh/buffer.h"
|
||||
|
||||
int pki_privkey_build_ed25519(ssh_key key,
|
||||
ssh_string pubkey,
|
||||
ssh_string privkey)
|
||||
{
|
||||
if (ssh_string_len(pubkey) != ED25519_KEY_LEN ||
|
||||
ssh_string_len(privkey) != (2 * ED25519_KEY_LEN))
|
||||
{
|
||||
SSH_LOG(SSH_LOG_TRACE, "Invalid ed25519 key len");
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
#ifdef HAVE_LIBCRYPTO
|
||||
/* In OpenSSL implementation, the private key is the original private seed,
|
||||
* without the public key. */
|
||||
key->ed25519_privkey = malloc(ED25519_KEY_LEN);
|
||||
#else
|
||||
/* In the internal implementation, the private key is the concatenation of
|
||||
* the private seed with the public key. */
|
||||
key->ed25519_privkey = malloc(2 * ED25519_KEY_LEN);
|
||||
#endif
|
||||
if (key->ed25519_privkey == NULL) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
key->ed25519_pubkey = malloc(ED25519_KEY_LEN);
|
||||
if (key->ed25519_pubkey == NULL) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
#ifdef HAVE_LIBCRYPTO
|
||||
memcpy(key->ed25519_privkey, ssh_string_data(privkey),
|
||||
ED25519_KEY_LEN);
|
||||
#else
|
||||
memcpy(key->ed25519_privkey, ssh_string_data(privkey),
|
||||
2 * ED25519_KEY_LEN);
|
||||
#endif
|
||||
memcpy(key->ed25519_pubkey, ssh_string_data(pubkey),
|
||||
ED25519_KEY_LEN);
|
||||
|
||||
return SSH_OK;
|
||||
|
||||
error:
|
||||
SAFE_FREE(key->ed25519_privkey);
|
||||
SAFE_FREE(key->ed25519_pubkey);
|
||||
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
* @brief Compare ed25519 keys if they are equal.
|
||||
*
|
||||
* @param[in] k1 The first key to compare.
|
||||
*
|
||||
* @param[in] k2 The second key to compare.
|
||||
*
|
||||
* @param[in] what What part or type of the key do you want to compare.
|
||||
*
|
||||
* @return 0 if equal, 1 if not.
|
||||
*/
|
||||
int pki_ed25519_key_cmp(const ssh_key k1,
|
||||
const ssh_key k2,
|
||||
enum ssh_keycmp_e what)
|
||||
{
|
||||
int cmp;
|
||||
|
||||
switch(what) {
|
||||
case SSH_KEY_CMP_PRIVATE:
|
||||
if (k1->ed25519_privkey == NULL || k2->ed25519_privkey == NULL) {
|
||||
return 1;
|
||||
}
|
||||
#ifdef HAVE_LIBCRYPTO
|
||||
/* In OpenSSL implementation, the private key is the original private
|
||||
* seed, without the public key. */
|
||||
cmp = memcmp(k1->ed25519_privkey, k2->ed25519_privkey, ED25519_KEY_LEN);
|
||||
#else
|
||||
/* In the internal implementation, the private key is the concatenation
|
||||
* of the private seed with the public key. */
|
||||
cmp = memcmp(k1->ed25519_privkey, k2->ed25519_privkey,
|
||||
2 * ED25519_KEY_LEN);
|
||||
#endif
|
||||
if (cmp != 0) {
|
||||
return 1;
|
||||
}
|
||||
FALL_THROUGH;
|
||||
case SSH_KEY_CMP_PUBLIC:
|
||||
if (k1->ed25519_pubkey == NULL || k2->ed25519_pubkey == NULL) {
|
||||
return 1;
|
||||
}
|
||||
cmp = memcmp(k1->ed25519_pubkey, k2->ed25519_pubkey, ED25519_KEY_LEN);
|
||||
if (cmp != 0) {
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case SSH_KEY_CMP_CERTIFICATE:
|
||||
/* handled globally */
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
* @brief Duplicate an Ed25519 key
|
||||
*
|
||||
* @param[out] new Pre-initialized ssh_key structure
|
||||
*
|
||||
* @param[in] key Key to copy
|
||||
*
|
||||
* @return SSH_ERROR on error, SSH_OK on success
|
||||
*/
|
||||
int pki_ed25519_key_dup(ssh_key new_key, const ssh_key key)
|
||||
{
|
||||
if (key->ed25519_privkey == NULL && key->ed25519_pubkey == NULL) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
if (key->ed25519_privkey != NULL) {
|
||||
#ifdef HAVE_LIBCRYPTO
|
||||
/* In OpenSSL implementation, the private key is the original private
|
||||
* seed, without the public key. */
|
||||
new_key->ed25519_privkey = malloc(ED25519_KEY_LEN);
|
||||
#else
|
||||
/* In the internal implementation, the private key is the concatenation
|
||||
* of the private seed with the public key. */
|
||||
new_key->ed25519_privkey = malloc(2 * ED25519_KEY_LEN);
|
||||
#endif
|
||||
if (new_key->ed25519_privkey == NULL) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
#ifdef HAVE_LIBCRYPTO
|
||||
memcpy(new_key->ed25519_privkey, key->ed25519_privkey, ED25519_KEY_LEN);
|
||||
#else
|
||||
memcpy(new_key->ed25519_privkey, key->ed25519_privkey, 2 * ED25519_KEY_LEN);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (key->ed25519_pubkey != NULL) {
|
||||
new_key->ed25519_pubkey = malloc(ED25519_KEY_LEN);
|
||||
if (new_key->ed25519_pubkey == NULL) {
|
||||
SAFE_FREE(new_key->ed25519_privkey);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
memcpy(new_key->ed25519_pubkey, key->ed25519_pubkey, ED25519_KEY_LEN);
|
||||
}
|
||||
|
||||
return SSH_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
* @brief Outputs an Ed25519 public key in a blob buffer.
|
||||
*
|
||||
* @param[out] buffer Output buffer
|
||||
*
|
||||
* @param[in] key Key to output
|
||||
*
|
||||
* @return SSH_ERROR on error, SSH_OK on success
|
||||
*/
|
||||
int pki_ed25519_public_key_to_blob(ssh_buffer buffer, ssh_key key)
|
||||
{
|
||||
int rc;
|
||||
|
||||
if (key->ed25519_pubkey == NULL){
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
rc = ssh_buffer_pack(buffer,
|
||||
"dP",
|
||||
(uint32_t)ED25519_KEY_LEN,
|
||||
(size_t)ED25519_KEY_LEN, key->ed25519_pubkey);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/** @internal
|
||||
* @brief exports a ed25519 private key to a string blob.
|
||||
* @param[in] privkey private key to convert
|
||||
* @param[out] buffer buffer to write the blob in.
|
||||
* @returns SSH_OK on success
|
||||
*/
|
||||
int pki_ed25519_private_key_to_blob(ssh_buffer buffer, const ssh_key privkey)
|
||||
{
|
||||
int rc;
|
||||
|
||||
if (privkey->type != SSH_KEYTYPE_ED25519) {
|
||||
SSH_LOG(SSH_LOG_TRACE, "Type %s not supported", privkey->type_c);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
if (privkey->ed25519_privkey == NULL ||
|
||||
privkey->ed25519_pubkey == NULL) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
rc = ssh_buffer_pack(buffer,
|
||||
"dPdPP",
|
||||
(uint32_t)ED25519_KEY_LEN,
|
||||
(size_t)ED25519_KEY_LEN, privkey->ed25519_pubkey,
|
||||
(uint32_t)(2 * ED25519_KEY_LEN),
|
||||
(size_t)ED25519_KEY_LEN, privkey->ed25519_privkey,
|
||||
(size_t)ED25519_KEY_LEN, privkey->ed25519_pubkey);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
|
||||
2151
src/pki_gcrypt.c
2151
src/pki_gcrypt.c
File diff suppressed because it is too large
Load Diff
@@ -380,11 +380,19 @@ ssh_key pki_key_dup(const ssh_key key, int demote)
|
||||
mbedtls_mpi Q;
|
||||
#endif
|
||||
|
||||
new = pki_key_dup_common_init(key, demote);
|
||||
new = ssh_key_new();
|
||||
if (new == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
new->type = key->type;
|
||||
new->type_c = key->type_c;
|
||||
if (demote) {
|
||||
new->flags = SSH_KEY_FLAG_PUBLIC;
|
||||
} else {
|
||||
new->flags = key->flags;
|
||||
}
|
||||
|
||||
#if MBEDTLS_VERSION_MAJOR > 2
|
||||
mbedtls_mpi_init(&N);
|
||||
mbedtls_mpi_init(&E);
|
||||
@@ -504,7 +512,6 @@ ssh_key pki_key_dup(const ssh_key key, int demote)
|
||||
case SSH_KEYTYPE_ECDSA_P256:
|
||||
case SSH_KEYTYPE_ECDSA_P384:
|
||||
case SSH_KEYTYPE_ECDSA_P521:
|
||||
case SSH_KEYTYPE_SK_ECDSA:
|
||||
new->ecdsa_nid = key->ecdsa_nid;
|
||||
|
||||
new->ecdsa = malloc(sizeof(mbedtls_ecdsa_context));
|
||||
@@ -515,8 +522,7 @@ ssh_key pki_key_dup(const ssh_key key, int demote)
|
||||
|
||||
mbedtls_ecdsa_init(new->ecdsa);
|
||||
|
||||
if ((demote && ssh_key_is_private(key)) ||
|
||||
is_sk_key_type(key->type)) {
|
||||
if (demote && ssh_key_is_private(key)) {
|
||||
rc = mbedtls_ecp_copy(&new->ecdsa->MBEDTLS_PRIVATE(Q),
|
||||
&key->ecdsa->MBEDTLS_PRIVATE(Q));
|
||||
if (rc != 0) {
|
||||
@@ -534,7 +540,6 @@ ssh_key pki_key_dup(const ssh_key key, int demote)
|
||||
|
||||
break;
|
||||
case SSH_KEYTYPE_ED25519:
|
||||
case SSH_KEYTYPE_SK_ED25519:
|
||||
rc = pki_ed25519_key_dup(new, key);
|
||||
if (rc != SSH_OK) {
|
||||
goto fail;
|
||||
@@ -763,8 +768,7 @@ int pki_key_compare(const ssh_key k1, const ssh_key k2, enum ssh_keycmp_e what)
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (what == SSH_KEY_CMP_PRIVATE &&
|
||||
k1->type != SSH_KEYTYPE_SK_ECDSA) {
|
||||
if (what == SSH_KEY_CMP_PRIVATE) {
|
||||
if (mbedtls_mpi_cmp_mpi(&ecdsa1->MBEDTLS_PRIVATE(d),
|
||||
&ecdsa2->MBEDTLS_PRIVATE(d)))
|
||||
{
|
||||
@@ -778,7 +782,7 @@ int pki_key_compare(const ssh_key k1, const ssh_key k2, enum ssh_keycmp_e what)
|
||||
case SSH_KEYTYPE_ED25519:
|
||||
case SSH_KEYTYPE_SK_ED25519:
|
||||
/* ed25519 keys handled globally */
|
||||
rc = 0;
|
||||
rc = 1;
|
||||
break;
|
||||
default:
|
||||
rc = 1;
|
||||
@@ -1066,7 +1070,7 @@ ssh_string pki_key_to_blob(const ssh_key key, enum ssh_key_e type)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (type == SSH_KEY_PRIVATE && key->type != SSH_KEYTYPE_SK_ECDSA) {
|
||||
if (type == SSH_KEY_PRIVATE) {
|
||||
d = ssh_make_bignum_string(&key->ecdsa->MBEDTLS_PRIVATE(d));
|
||||
|
||||
if (d == NULL) {
|
||||
@@ -1078,14 +1082,7 @@ ssh_string pki_key_to_blob(const ssh_key key, enum ssh_key_e type)
|
||||
if (rc < 0) {
|
||||
goto out;
|
||||
}
|
||||
} else if (type == SSH_KEY_PRIVATE &&
|
||||
key->type == SSH_KEYTYPE_SK_ECDSA) {
|
||||
rc = pki_buffer_pack_sk_priv_data(buffer, key);
|
||||
if (rc != SSH_OK) {
|
||||
goto out;
|
||||
}
|
||||
} else if (type == SSH_KEY_PUBLIC &&
|
||||
key->type == SSH_KEYTYPE_SK_ECDSA) {
|
||||
} else if (key->type == SSH_KEYTYPE_SK_ECDSA) {
|
||||
/* public key can contain certificate sk information */
|
||||
rc = ssh_buffer_add_ssh_string(buffer, key->sk_application);
|
||||
if (rc < 0) {
|
||||
@@ -1108,21 +1105,9 @@ ssh_string pki_key_to_blob(const ssh_key key, enum ssh_key_e type)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (key->type == SSH_KEYTYPE_SK_ED25519) {
|
||||
rc = pki_ed25519_public_key_to_blob(buffer, key);
|
||||
if (rc == SSH_ERROR) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = pki_buffer_pack_sk_priv_data(buffer, key);
|
||||
if (rc == SSH_ERROR) {
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
rc = pki_ed25519_private_key_to_blob(buffer, key);
|
||||
if (rc == SSH_ERROR) {
|
||||
goto out;
|
||||
}
|
||||
rc = pki_ed25519_private_key_to_blob(buffer, key);
|
||||
if (rc == SSH_ERROR) {
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -1234,11 +1219,6 @@ ssh_string pki_signature_to_blob(const ssh_signature sig)
|
||||
case SSH_KEYTYPE_ED25519:
|
||||
sig_blob = pki_ed25519_signature_to_blob(sig);
|
||||
break;
|
||||
case SSH_KEYTYPE_SK_ECDSA:
|
||||
case SSH_KEYTYPE_SK_ED25519:
|
||||
/* For SK keys, signature data is already in raw_sig */
|
||||
sig_blob = ssh_string_copy(sig->raw_sig);
|
||||
break;
|
||||
default:
|
||||
SSH_LOG(SSH_LOG_TRACE, "Unknown signature key type: %s",
|
||||
sig->type_c);
|
||||
@@ -1822,6 +1802,7 @@ int pki_privkey_build_ecdsa(ssh_key key, int nid, ssh_string e, ssh_string exp)
|
||||
mbedtls_ecp_point Q;
|
||||
|
||||
key->ecdsa_nid = nid;
|
||||
key->type_c = pki_key_ecdsa_nid_to_name(nid);
|
||||
|
||||
key->ecdsa = malloc(sizeof(mbedtls_ecdsa_context));
|
||||
if (key->ecdsa == NULL) {
|
||||
@@ -1889,6 +1870,7 @@ int pki_pubkey_build_ecdsa(ssh_key key, int nid, ssh_string e)
|
||||
mbedtls_ecp_point Q;
|
||||
|
||||
key->ecdsa_nid = nid;
|
||||
key->type_c = pki_key_ecdsa_nid_to_name(nid);
|
||||
|
||||
key->ecdsa = malloc(sizeof(mbedtls_ecdsa_context));
|
||||
if (key->ecdsa == NULL) {
|
||||
|
||||
51
src/poll.c
51
src/poll.c
@@ -422,7 +422,7 @@ void ssh_poll_set_events(ssh_poll_handle p, short events)
|
||||
{
|
||||
p->events = events;
|
||||
if (p->ctx != NULL) {
|
||||
if (p->lock_cnt == 0) {
|
||||
if (!ssh_poll_is_locked(p)) {
|
||||
p->ctx->pollfds[p->x.idx].events = events;
|
||||
} else if (!(p->ctx->pollfds[p->x.idx].events & POLLOUT)) {
|
||||
/* if locked, allow only setting POLLOUT to prevent recursive
|
||||
@@ -560,30 +560,29 @@ void ssh_poll_ctx_free(ssh_poll_ctx ctx)
|
||||
|
||||
static int ssh_poll_ctx_resize(ssh_poll_ctx ctx, size_t new_size)
|
||||
{
|
||||
ssh_poll_handle *pollptrs = NULL;
|
||||
ssh_pollfd_t *pollfds = NULL;
|
||||
ssh_poll_handle *pollptrs = NULL;
|
||||
ssh_pollfd_t *pollfds = NULL;
|
||||
|
||||
pollptrs = realloc(ctx->pollptrs, sizeof(ssh_poll_handle) * new_size);
|
||||
pollptrs = realloc(ctx->pollptrs, sizeof(ssh_poll_handle) * new_size);
|
||||
if (pollptrs == NULL) {
|
||||
return -1;
|
||||
}
|
||||
ctx->pollptrs = pollptrs;
|
||||
|
||||
pollfds = realloc(ctx->pollfds, sizeof(ssh_pollfd_t) * new_size);
|
||||
if (pollfds == NULL) {
|
||||
pollptrs = realloc(ctx->pollptrs, sizeof(ssh_poll_handle) * ctx->polls_allocated);
|
||||
if (pollptrs == NULL) {
|
||||
return -1;
|
||||
}
|
||||
ctx->pollptrs = pollptrs;
|
||||
return -1;
|
||||
}
|
||||
|
||||
pollfds = realloc(ctx->pollfds, sizeof(ssh_pollfd_t) * new_size);
|
||||
if (pollfds == NULL) {
|
||||
pollptrs = realloc(ctx->pollptrs,
|
||||
sizeof(ssh_poll_handle) * ctx->polls_allocated);
|
||||
if (pollptrs == NULL) {
|
||||
return -1;
|
||||
}
|
||||
ctx->pollptrs = pollptrs;
|
||||
return -1;
|
||||
}
|
||||
ctx->pollfds = pollfds;
|
||||
ctx->polls_allocated = new_size;
|
||||
|
||||
ctx->pollfds = pollfds;
|
||||
ctx->polls_allocated = new_size;
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -670,6 +669,20 @@ void ssh_poll_ctx_remove(ssh_poll_ctx ctx, ssh_poll_handle p)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns if a poll object is locked.
|
||||
*
|
||||
* @param p Pointer to an already allocated poll object.
|
||||
* @returns true if the poll object is locked; false otherwise.
|
||||
*/
|
||||
bool ssh_poll_is_locked(ssh_poll_handle p)
|
||||
{
|
||||
if (p == NULL) {
|
||||
return false;
|
||||
}
|
||||
return p->lock_cnt > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Poll all the sockets associated through a poll object with a
|
||||
* poll context. If any of the events are set after the poll, the
|
||||
@@ -704,7 +717,7 @@ int ssh_poll_ctx_dopoll(ssh_poll_ctx ctx, int timeout)
|
||||
* output buffer */
|
||||
for (i = 0; i < ctx->polls_used; i++) {
|
||||
/* The lock allows only POLLOUT events: drop the rest */
|
||||
if (ctx->pollptrs[i]->lock_cnt > 0) {
|
||||
if (ssh_poll_is_locked(ctx->pollptrs[i])) {
|
||||
ctx->pollfds[i].events &= POLLOUT;
|
||||
}
|
||||
}
|
||||
|
||||
17
src/server.c
17
src/server.c
@@ -230,13 +230,11 @@ static int ssh_server_send_extensions(ssh_session session)
|
||||
}
|
||||
|
||||
rc = ssh_buffer_pack(session->out_buffer,
|
||||
"bdssss",
|
||||
"bdss",
|
||||
SSH2_MSG_EXT_INFO,
|
||||
2, /* nr. of extensions */
|
||||
1, /* nr. of extensions */
|
||||
"server-sig-algs",
|
||||
hostkey_algorithms,
|
||||
"publickey-hostbound@openssh.com",
|
||||
"0");
|
||||
hostkey_algorithms);
|
||||
if (rc != SSH_OK) {
|
||||
goto error;
|
||||
}
|
||||
@@ -485,8 +483,8 @@ static size_t callback_receive_banner(const void *data, size_t len, void *user)
|
||||
ssh_pcap_context_write(session->pcap_ctx,
|
||||
SSH_PCAP_DIR_IN,
|
||||
buffer,
|
||||
(uint32_t)(i + 1),
|
||||
(uint32_t)(i + 1));
|
||||
i + 1,
|
||||
i + 1);
|
||||
}
|
||||
#endif
|
||||
if (buffer[i] == '\r') {
|
||||
@@ -497,6 +495,11 @@ static size_t callback_receive_banner(const void *data, size_t len, void *user)
|
||||
buffer[i] = '\0';
|
||||
|
||||
str = strdup(buffer);
|
||||
if (str == NULL) {
|
||||
session->session_state = SSH_SESSION_STATE_ERROR;
|
||||
ssh_set_error_oom(session);
|
||||
return 0;
|
||||
}
|
||||
/* number of bytes read */
|
||||
processed = i + 1;
|
||||
session->clientbanner = str;
|
||||
|
||||
269
src/session.c
269
src/session.c
@@ -26,10 +26,6 @@
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <winsock2.h>
|
||||
#endif
|
||||
|
||||
#include "libssh/priv.h"
|
||||
#include "libssh/libssh.h"
|
||||
#include "libssh/crypto.h"
|
||||
@@ -413,10 +409,10 @@ const char* ssh_get_clientbanner(ssh_session session) {
|
||||
* @return Returns the server banner string or NULL.
|
||||
*/
|
||||
const char* ssh_get_serverbanner(ssh_session session) {
|
||||
if (!session) {
|
||||
return NULL;
|
||||
}
|
||||
return session->serverbanner;
|
||||
if(!session) {
|
||||
return NULL;
|
||||
}
|
||||
return session->serverbanner;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -433,34 +429,28 @@ const char* ssh_get_kex_algo(ssh_session session) {
|
||||
}
|
||||
|
||||
switch (session->current_crypto->kex_type) {
|
||||
case SSH_KEX_DH_GROUP1_SHA1:
|
||||
return "diffie-hellman-group1-sha1";
|
||||
case SSH_KEX_DH_GROUP14_SHA1:
|
||||
return "diffie-hellman-group14-sha1";
|
||||
case SSH_KEX_DH_GROUP14_SHA256:
|
||||
return "diffie-hellman-group14-sha256";
|
||||
case SSH_KEX_DH_GROUP16_SHA512:
|
||||
return "diffie-hellman-group16-sha512";
|
||||
case SSH_KEX_DH_GROUP18_SHA512:
|
||||
return "diffie-hellman-group18-sha512";
|
||||
case SSH_KEX_ECDH_SHA2_NISTP256:
|
||||
return "ecdh-sha2-nistp256";
|
||||
case SSH_KEX_ECDH_SHA2_NISTP384:
|
||||
return "ecdh-sha2-nistp384";
|
||||
case SSH_KEX_ECDH_SHA2_NISTP521:
|
||||
return "ecdh-sha2-nistp521";
|
||||
case SSH_KEX_CURVE25519_SHA256:
|
||||
return "curve25519-sha256";
|
||||
case SSH_KEX_CURVE25519_SHA256_LIBSSH_ORG:
|
||||
return "curve25519-sha256@libssh.org";
|
||||
case SSH_KEX_SNTRUP761X25519_SHA512_OPENSSH_COM:
|
||||
return "sntrup761x25519-sha512@openssh.com";
|
||||
#ifdef WITH_GEX
|
||||
case SSH_KEX_DH_GEX_SHA1:
|
||||
return "diffie-hellman-group-exchange-sha1";
|
||||
case SSH_KEX_DH_GEX_SHA256:
|
||||
return "diffie-hellman-group-exchange-sha256";
|
||||
#endif /* WITH_GEX */
|
||||
case SSH_KEX_DH_GROUP1_SHA1:
|
||||
return "diffie-hellman-group1-sha1";
|
||||
case SSH_KEX_DH_GROUP14_SHA1:
|
||||
return "diffie-hellman-group14-sha1";
|
||||
case SSH_KEX_DH_GROUP14_SHA256:
|
||||
return "diffie-hellman-group14-sha256";
|
||||
case SSH_KEX_DH_GROUP16_SHA512:
|
||||
return "diffie-hellman-group16-sha512";
|
||||
case SSH_KEX_DH_GROUP18_SHA512:
|
||||
return "diffie-hellman-group18-sha512";
|
||||
case SSH_KEX_ECDH_SHA2_NISTP256:
|
||||
return "ecdh-sha2-nistp256";
|
||||
case SSH_KEX_ECDH_SHA2_NISTP384:
|
||||
return "ecdh-sha2-nistp384";
|
||||
case SSH_KEX_ECDH_SHA2_NISTP521:
|
||||
return "ecdh-sha2-nistp521";
|
||||
case SSH_KEX_CURVE25519_SHA256:
|
||||
return "curve25519-sha256";
|
||||
case SSH_KEX_CURVE25519_SHA256_LIBSSH_ORG:
|
||||
return "curve25519-sha256@libssh.org";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
@@ -946,41 +936,16 @@ int ssh_get_version(ssh_session session) {
|
||||
* @param user is a pointer to session
|
||||
*/
|
||||
void ssh_socket_exception_callback(int code, int errno_code, void *user){
|
||||
ssh_session session = (ssh_session)user;
|
||||
ssh_session session=(ssh_session)user;
|
||||
|
||||
SSH_LOG(SSH_LOG_RARE,
|
||||
"Socket exception callback: %d (%d)",
|
||||
code,
|
||||
errno_code);
|
||||
SSH_LOG(SSH_LOG_RARE,"Socket exception callback: %d (%d)",code, errno_code);
|
||||
session->session_state = SSH_SESSION_STATE_ERROR;
|
||||
if (errno_code == 0 && code == SSH_SOCKET_EXCEPTION_EOF) {
|
||||
ssh_set_error(session, SSH_FATAL, "Socket error: disconnected");
|
||||
#ifdef _WIN32
|
||||
} else if (errno_code == WSAENETDOWN) {
|
||||
ssh_set_error(session, SSH_FATAL, "Socket error: network down");
|
||||
} else if (errno_code == WSAENETUNREACH) {
|
||||
ssh_set_error(session, SSH_FATAL, "Socket error: network unreachable");
|
||||
} else if (errno_code == WSAENETRESET) {
|
||||
ssh_set_error(session, SSH_FATAL, "Socket error: network reset");
|
||||
} else if (errno_code == WSAECONNABORTED) {
|
||||
ssh_set_error(session, SSH_FATAL, "Socket error: connection aborted");
|
||||
} else if (errno_code == WSAECONNRESET) {
|
||||
ssh_set_error(session,
|
||||
SSH_FATAL,
|
||||
"Socket error: connection reset by peer");
|
||||
} else if (errno_code == WSAETIMEDOUT) {
|
||||
ssh_set_error(session, SSH_FATAL, "Socket error: connection timed out");
|
||||
} else if (errno_code == WSAECONNREFUSED) {
|
||||
ssh_set_error(session, SSH_FATAL, "Socket error: connection refused");
|
||||
} else if (errno_code == WSAEHOSTUNREACH) {
|
||||
ssh_set_error(session, SSH_FATAL, "Socket error: host unreachable");
|
||||
#endif
|
||||
} else {
|
||||
char err_msg[SSH_ERRNO_MSG_MAX] = {0};
|
||||
ssh_set_error(session,
|
||||
SSH_FATAL,
|
||||
"Socket error: %s",
|
||||
ssh_strerror(errno_code, err_msg, SSH_ERRNO_MSG_MAX));
|
||||
ssh_set_error(session, SSH_FATAL, "Socket error: %s",
|
||||
ssh_strerror(errno_code, err_msg, SSH_ERRNO_MSG_MAX));
|
||||
}
|
||||
|
||||
session->ssh_connection_callback(session);
|
||||
@@ -1267,108 +1232,110 @@ int ssh_get_publickey_hash(const ssh_key key,
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case SSH_PUBLICKEY_HASH_SHA1: {
|
||||
SHACTX ctx = NULL;
|
||||
case SSH_PUBLICKEY_HASH_SHA1:
|
||||
{
|
||||
SHACTX ctx = NULL;
|
||||
|
||||
h = calloc(1, SHA_DIGEST_LEN);
|
||||
if (h == NULL) {
|
||||
rc = -1;
|
||||
goto out;
|
||||
}
|
||||
h = calloc(1, SHA_DIGEST_LEN);
|
||||
if (h == NULL) {
|
||||
rc = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ctx = sha1_init();
|
||||
if (ctx == NULL) {
|
||||
free(h);
|
||||
rc = -1;
|
||||
goto out;
|
||||
}
|
||||
ctx = sha1_init();
|
||||
if (ctx == NULL) {
|
||||
free(h);
|
||||
rc = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = sha1_update(ctx, ssh_string_data(blob), ssh_string_len(blob));
|
||||
if (rc != SSH_OK) {
|
||||
free(h);
|
||||
sha1_ctx_free(ctx);
|
||||
goto out;
|
||||
}
|
||||
rc = sha1_final(h, ctx);
|
||||
if (rc != SSH_OK) {
|
||||
free(h);
|
||||
goto out;
|
||||
}
|
||||
rc = sha1_update(ctx, ssh_string_data(blob), ssh_string_len(blob));
|
||||
if (rc != SSH_OK) {
|
||||
free(h);
|
||||
sha1_ctx_free(ctx);
|
||||
goto out;
|
||||
}
|
||||
rc = sha1_final(h, ctx);
|
||||
if (rc != SSH_OK) {
|
||||
free(h);
|
||||
goto out;
|
||||
}
|
||||
|
||||
*hlen = SHA_DIGEST_LEN;
|
||||
*hlen = SHA_DIGEST_LEN;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SSH_PUBLICKEY_HASH_SHA256: {
|
||||
SHA256CTX ctx = NULL;
|
||||
case SSH_PUBLICKEY_HASH_SHA256:
|
||||
{
|
||||
SHA256CTX ctx = NULL;
|
||||
|
||||
h = calloc(1, SHA256_DIGEST_LEN);
|
||||
if (h == NULL) {
|
||||
rc = -1;
|
||||
goto out;
|
||||
}
|
||||
h = calloc(1, SHA256_DIGEST_LEN);
|
||||
if (h == NULL) {
|
||||
rc = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ctx = sha256_init();
|
||||
if (ctx == NULL) {
|
||||
free(h);
|
||||
rc = -1;
|
||||
goto out;
|
||||
}
|
||||
ctx = sha256_init();
|
||||
if (ctx == NULL) {
|
||||
free(h);
|
||||
rc = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = sha256_update(ctx, ssh_string_data(blob), ssh_string_len(blob));
|
||||
if (rc != SSH_OK) {
|
||||
free(h);
|
||||
sha256_ctx_free(ctx);
|
||||
goto out;
|
||||
}
|
||||
rc = sha256_final(h, ctx);
|
||||
if (rc != SSH_OK) {
|
||||
free(h);
|
||||
goto out;
|
||||
}
|
||||
rc = sha256_update(ctx, ssh_string_data(blob), ssh_string_len(blob));
|
||||
if (rc != SSH_OK) {
|
||||
free(h);
|
||||
sha256_ctx_free(ctx);
|
||||
goto out;
|
||||
}
|
||||
rc = sha256_final(h, ctx);
|
||||
if (rc != SSH_OK) {
|
||||
free(h);
|
||||
goto out;
|
||||
}
|
||||
|
||||
*hlen = SHA256_DIGEST_LEN;
|
||||
*hlen = SHA256_DIGEST_LEN;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SSH_PUBLICKEY_HASH_MD5: {
|
||||
MD5CTX ctx = NULL;
|
||||
case SSH_PUBLICKEY_HASH_MD5:
|
||||
{
|
||||
MD5CTX ctx = NULL;
|
||||
|
||||
/* In FIPS mode, we cannot use MD5 */
|
||||
if (ssh_fips_mode()) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"In FIPS mode MD5 is not allowed."
|
||||
"Try using SSH_PUBLICKEY_HASH_SHA256");
|
||||
rc = SSH_ERROR;
|
||||
goto out;
|
||||
}
|
||||
/* In FIPS mode, we cannot use MD5 */
|
||||
if (ssh_fips_mode()) {
|
||||
SSH_LOG(SSH_LOG_TRACE, "In FIPS mode MD5 is not allowed."
|
||||
"Try using SSH_PUBLICKEY_HASH_SHA256");
|
||||
rc = SSH_ERROR;
|
||||
goto out;
|
||||
}
|
||||
|
||||
h = calloc(1, MD5_DIGEST_LEN);
|
||||
if (h == NULL) {
|
||||
rc = -1;
|
||||
goto out;
|
||||
}
|
||||
h = calloc(1, MD5_DIGEST_LEN);
|
||||
if (h == NULL) {
|
||||
rc = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ctx = md5_init();
|
||||
if (ctx == NULL) {
|
||||
free(h);
|
||||
rc = -1;
|
||||
goto out;
|
||||
}
|
||||
ctx = md5_init();
|
||||
if (ctx == NULL) {
|
||||
free(h);
|
||||
rc = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = md5_update(ctx, ssh_string_data(blob), ssh_string_len(blob));
|
||||
if (rc != SSH_OK) {
|
||||
free(h);
|
||||
md5_ctx_free(ctx);
|
||||
goto out;
|
||||
}
|
||||
rc = md5_final(h, ctx);
|
||||
if (rc != SSH_OK) {
|
||||
free(h);
|
||||
goto out;
|
||||
}
|
||||
rc = md5_update(ctx, ssh_string_data(blob), ssh_string_len(blob));
|
||||
if (rc != SSH_OK) {
|
||||
free(h);
|
||||
md5_ctx_free(ctx);
|
||||
goto out;
|
||||
}
|
||||
rc = md5_final(h, ctx);
|
||||
if (rc != SSH_OK) {
|
||||
free(h);
|
||||
goto out;
|
||||
}
|
||||
|
||||
*hlen = MD5_DIGEST_LEN;
|
||||
*hlen = MD5_DIGEST_LEN;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
rc = -1;
|
||||
goto out;
|
||||
|
||||
1107
src/sftp.c
1107
src/sftp.c
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user