mirror of
https://github.com/libssh2/libssh2.git
synced 2025-08-08 19:02:07 +03:00
Merge remote-tracking branch 'upstream/master' into shellfish
# Conflicts: # buildconf # configure.ac # include/libssh2.h
This commit is contained in:
4
.github/stale.yml
vendored
4
.github/stale.yml
vendored
@@ -1,7 +1,7 @@
|
|||||||
# Number of days of inactivity before an issue becomes stale
|
# Number of days of inactivity before an issue becomes stale
|
||||||
daysUntilStale: 90
|
daysUntilStale: 120
|
||||||
# Number of days of inactivity before a stale issue is closed
|
# Number of days of inactivity before a stale issue is closed
|
||||||
daysUntilClose: 21
|
daysUntilClose: 30
|
||||||
# Issues with these labels will never be considered stale
|
# Issues with these labels will never be considered stale
|
||||||
exemptLabels:
|
exemptLabels:
|
||||||
- pinned
|
- pinned
|
||||||
|
67
.github/workflows/appveyor.yml
vendored
Normal file
67
.github/workflows/appveyor.yml
vendored
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
# Copyright (c) 2021 Marc Hoersken
|
||||||
|
# All rights reserved.
|
||||||
|
#
|
||||||
|
# Redistribution and use in source and binary forms, with or without
|
||||||
|
# modification, are permitted provided that the following conditions are met:
|
||||||
|
#
|
||||||
|
# * Redistributions of source code must retain the above copyright notice, this
|
||||||
|
# list of conditions and the following disclaimer.
|
||||||
|
#
|
||||||
|
# * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
# this list of conditions and the following disclaimer in the documentation
|
||||||
|
# and/or other materials provided with the distribution.
|
||||||
|
#
|
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
|
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
name: AppVeyor Docker Bridge
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
ssh_host:
|
||||||
|
required: true
|
||||||
|
ssh_port:
|
||||||
|
required: true
|
||||||
|
ssh_user:
|
||||||
|
required: true
|
||||||
|
ssh_forward:
|
||||||
|
required: true
|
||||||
|
ssh_hostkey:
|
||||||
|
required: true
|
||||||
|
ssh_privkey:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
daemon:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
timeout-minutes: 60
|
||||||
|
steps:
|
||||||
|
- name: Setup SSH client configuration
|
||||||
|
run: |
|
||||||
|
cd ~
|
||||||
|
mkdir .ssh
|
||||||
|
chmod 0700 .ssh
|
||||||
|
echo "ServerAliveInterval 45" > .ssh/config
|
||||||
|
echo "Host ${{ github.event.inputs.ssh_host }}" >> .ssh/config
|
||||||
|
echo "${{ github.event.inputs.ssh_forward }}" | sed 's/,/\n/g' | sed 's/^/\tRemoteForward /g' >> .ssh/config
|
||||||
|
chmod 0600 .ssh/config
|
||||||
|
cat .ssh/config
|
||||||
|
echo "${{ github.event.inputs.ssh_host }} ${{ github.event.inputs.ssh_hostkey }}" | sed 's/,/\n${{ github.event.inputs.ssh_host }} /g' > .ssh/known_hosts
|
||||||
|
chmod 0600 .ssh/known_hosts
|
||||||
|
cat .ssh/known_hosts
|
||||||
|
echo "${{ github.event.inputs.ssh_privkey }}" | sed 's/,/\n/g' > .ssh/id_rsa
|
||||||
|
chmod 0600 .ssh/id_rsa
|
||||||
|
|
||||||
|
# we sleep explicitly to allow the remote system to kill the sleep process
|
||||||
|
- name: Connect to AppVeyor and sleep
|
||||||
|
run: |
|
||||||
|
ssh -v -p ${{ github.event.inputs.ssh_port }} ${{ github.event.inputs.ssh_user }}@${{ github.event.inputs.ssh_host }} sleep 1h
|
105
.github/workflows/ci.yml
vendored
Normal file
105
.github/workflows/ci.yml
vendored
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
name: CI
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ master ]
|
||||||
|
pull_request:
|
||||||
|
branches: [ master ]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
style-check:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: Check Style
|
||||||
|
run: ./ci/checksrc.sh
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
compiler: [gcc, clang]
|
||||||
|
address_size: [64]
|
||||||
|
crypto_backend: [OpenSSL, Libgcrypt, mbedTLS]
|
||||||
|
build_shared_libs: [OFF, ON]
|
||||||
|
enable_zlib_compression: [OFF, ON]
|
||||||
|
b: [cmake]
|
||||||
|
include:
|
||||||
|
- compiler: gcc
|
||||||
|
address_size: 64
|
||||||
|
crypto_backend: OpenSSL
|
||||||
|
build_shared_libs: OFF
|
||||||
|
enable_zlib_compression: OFF
|
||||||
|
b: configure
|
||||||
|
- compiler: clang
|
||||||
|
address_size: 64
|
||||||
|
crypto_backend: OpenSSL
|
||||||
|
build_shared_libs: OFF
|
||||||
|
enable_zlib_compression: OFF
|
||||||
|
b: configure
|
||||||
|
env:
|
||||||
|
CC: ${{ matrix.compiler }}
|
||||||
|
CC_FOR_BUILD: ${{ matrix.compiler }}
|
||||||
|
CRYPTO_BACKEND: ${{ matrix.crypto_backend }}
|
||||||
|
BUILD_SHARED_LIBS: ${{ matrix.build_shared_libs }}
|
||||||
|
ENABLE_ZLIB_COMPRESSION: ${{ matrix.enable_zlib_compression }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: Install 32 Bit Dependencies
|
||||||
|
if: ${{ matrix.address_size == 32 }}
|
||||||
|
run: |
|
||||||
|
sudo dpkg --add-architecture i386
|
||||||
|
sudo apt-get update -qq
|
||||||
|
sudo apt-get install -y gcc-multilib
|
||||||
|
sudo apt-get install -y libssl-dev:i386 libgcrypt20-dev:i386 zlib1g-dev:i386 build-essential gcc-multilib
|
||||||
|
sudo dpkg --purge --force-depends gcc-multilib
|
||||||
|
sudo dpkg --purge --force-depends libssl-dev
|
||||||
|
echo "TOOLCHAIN_OPTION=-DCMAKE_TOOLCHAIN_FILE=../cmake/Toolchain-Linux-32.cmake" >> $GITHUB_ENV
|
||||||
|
- name: Install 64 Bit Dependencies
|
||||||
|
if: ${{ matrix.address_size == 64 }}
|
||||||
|
run: |
|
||||||
|
sudo apt-get install -y libssl-dev
|
||||||
|
sudo apt-get install -y libgcrypt-dev
|
||||||
|
- name: Install mbedTLS Dependencies
|
||||||
|
if: ${{ matrix.crypto_backend == 'mbedTLS' }}
|
||||||
|
run: |
|
||||||
|
MBEDTLSVER=mbedtls-2.7.0
|
||||||
|
curl -L https://github.com/ARMmbed/mbedtls/archive/$MBEDTLSVER.tar.gz | tar -xzf -
|
||||||
|
cd mbedtls-$MBEDTLSVER
|
||||||
|
cmake $TOOLCHAIN_OPTION -DUSE_SHARED_MBEDTLS_LIBRARY=ON -DCMAKE_INSTALL_PREFIX:PATH=../usr .
|
||||||
|
make -j3 install
|
||||||
|
cd ..
|
||||||
|
echo "LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$PWD/usr/lib" >> $GITHUB_ENV
|
||||||
|
echo "TOOLCHAIN_OPTION=$TOOLCHAIN_OPTION -DCMAKE_PREFIX_PATH=$PWD/usr" >> $GITHUB_ENV
|
||||||
|
- name: Build with Configure
|
||||||
|
if: ${{ matrix.b == 'configure' }}
|
||||||
|
run: |
|
||||||
|
autoreconf -fi
|
||||||
|
./configure --enable-debug --enable-werror
|
||||||
|
make
|
||||||
|
make check
|
||||||
|
- name: Build with CMake
|
||||||
|
if: ${{ matrix.b == 'cmake' }}
|
||||||
|
run: |
|
||||||
|
mkdir bin
|
||||||
|
cd bin
|
||||||
|
cmake $TOOLCHAIN_OPTION -DCRYPTO_BACKEND=$CRYPTO_BACKEND -DBUILD_SHARED_LIBS=$BUILD_SHARED_LIBS -DENABLE_ZLIB_COMPRESSION=$ENABLE_ZLIB_COMPRESSION ..
|
||||||
|
cmake --build .
|
||||||
|
pushd ../tests
|
||||||
|
docker build -t libssh2/openssh_server openssh_server
|
||||||
|
popd
|
||||||
|
CTEST_OUTPUT_ON_FAILURE=1 cmake --build . --target test
|
||||||
|
cmake --build . --target package
|
||||||
|
fuzzer:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
compiler: [gcc, clang]
|
||||||
|
env:
|
||||||
|
CC: ${{ matrix.compiler }}
|
||||||
|
CC_FOR_BUILD: ${{ matrix.compiler }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: Run Fuzzer
|
||||||
|
run: GIT_REF=$GITHUB_REF ./ci/ossfuzz.sh
|
1
.gitignore
vendored
1
.gitignore
vendored
@@ -35,3 +35,4 @@ tags
|
|||||||
libssh2.pc
|
libssh2.pc
|
||||||
TAGS
|
TAGS
|
||||||
*~
|
*~
|
||||||
|
.DS_Store
|
||||||
|
21
.travis.yml
21
.travis.yml
@@ -46,10 +46,12 @@ compiler:
|
|||||||
|
|
||||||
addons:
|
addons:
|
||||||
chrome: stable
|
chrome: stable
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- name: "Check style"
|
||||||
|
script: ./ci/checksrc.sh
|
||||||
|
|
||||||
env:
|
env:
|
||||||
matrix:
|
|
||||||
- B=style
|
|
||||||
- ADDRESS_SIZE=64 CRYPTO_BACKEND=OpenSSL BUILD_SHARED_LIBS=OFF ENABLE_ZLIB_COMPRESSION=OFF B=configure
|
- ADDRESS_SIZE=64 CRYPTO_BACKEND=OpenSSL BUILD_SHARED_LIBS=OFF ENABLE_ZLIB_COMPRESSION=OFF B=configure
|
||||||
- ADDRESS_SIZE=64 CRYPTO_BACKEND=OpenSSL BUILD_SHARED_LIBS=OFF ENABLE_ZLIB_COMPRESSION=OFF B=cmake
|
- ADDRESS_SIZE=64 CRYPTO_BACKEND=OpenSSL BUILD_SHARED_LIBS=OFF ENABLE_ZLIB_COMPRESSION=OFF B=cmake
|
||||||
- ADDRESS_SIZE=64 CRYPTO_BACKEND=OpenSSL BUILD_SHARED_LIBS=ON ENABLE_ZLIB_COMPRESSION=OFF B=cmake
|
- ADDRESS_SIZE=64 CRYPTO_BACKEND=OpenSSL BUILD_SHARED_LIBS=ON ENABLE_ZLIB_COMPRESSION=OFF B=cmake
|
||||||
@@ -75,6 +77,7 @@ env:
|
|||||||
- ADDRESS_SIZE=32 CRYPTO_BACKEND=mbedTLS BUILD_SHARED_LIBS=ON ENABLE_ZLIB_COMPRESSION=OFF B=cmake
|
- ADDRESS_SIZE=32 CRYPTO_BACKEND=mbedTLS BUILD_SHARED_LIBS=ON ENABLE_ZLIB_COMPRESSION=OFF B=cmake
|
||||||
- ADDRESS_SIZE=32 CRYPTO_BACKEND=mbedTLS BUILD_SHARED_LIBS=OFF ENABLE_ZLIB_COMPRESSION=ON B=cmake
|
- ADDRESS_SIZE=32 CRYPTO_BACKEND=mbedTLS BUILD_SHARED_LIBS=OFF ENABLE_ZLIB_COMPRESSION=ON B=cmake
|
||||||
- ADDRESS_SIZE=32 CRYPTO_BACKEND=mbedTLS BUILD_SHARED_LIBS=ON ENABLE_ZLIB_COMPRESSION=ON B=cmake
|
- ADDRESS_SIZE=32 CRYPTO_BACKEND=mbedTLS BUILD_SHARED_LIBS=ON ENABLE_ZLIB_COMPRESSION=ON B=cmake
|
||||||
|
- B=fuzzer
|
||||||
|
|
||||||
before_install:
|
before_install:
|
||||||
- if [ $ADDRESS_SIZE = '32' ]; then sudo dpkg --add-architecture i386; fi
|
- if [ $ADDRESS_SIZE = '32' ]; then sudo dpkg --add-architecture i386; fi
|
||||||
@@ -86,7 +89,7 @@ before_install:
|
|||||||
- if [ $ADDRESS_SIZE = '64' ]; then sudo apt-get install -y libgcrypt11-dev; fi
|
- if [ $ADDRESS_SIZE = '64' ]; then sudo apt-get install -y libgcrypt11-dev; fi
|
||||||
- if [ $ADDRESS_SIZE = '32' ]; then export TOOLCHAIN_OPTION="-DCMAKE_TOOLCHAIN_FILE=../cmake/Toolchain-Linux-32.cmake"; fi
|
- if [ $ADDRESS_SIZE = '32' ]; then export TOOLCHAIN_OPTION="-DCMAKE_TOOLCHAIN_FILE=../cmake/Toolchain-Linux-32.cmake"; fi
|
||||||
- if [ $CRYPTO_BACKEND = 'mbedTLS' ]; then
|
- if [ $CRYPTO_BACKEND = 'mbedTLS' ]; then
|
||||||
MBEDTLSVER=mbedtls-2.4.0;
|
MBEDTLSVER=mbedtls-2.7.0;
|
||||||
curl -L https://github.com/ARMmbed/mbedtls/archive/$MBEDTLSVER.tar.gz | tar -xzf -;
|
curl -L https://github.com/ARMmbed/mbedtls/archive/$MBEDTLSVER.tar.gz | tar -xzf -;
|
||||||
cd mbedtls-$MBEDTLSVER;
|
cd mbedtls-$MBEDTLSVER;
|
||||||
cmake $TOOLCHAIN_OPTION -DUSE_SHARED_MBEDTLS_LIBRARY=ON -DCMAKE_INSTALL_PREFIX:PATH=../usr .;
|
cmake $TOOLCHAIN_OPTION -DUSE_SHARED_MBEDTLS_LIBRARY=ON -DCMAKE_INSTALL_PREFIX:PATH=../usr .;
|
||||||
@@ -99,10 +102,6 @@ before_install:
|
|||||||
install:
|
install:
|
||||||
|
|
||||||
script:
|
script:
|
||||||
- |
|
|
||||||
if [ "$B" = "style" ]; then
|
|
||||||
perl src/checksrc.pl -i4 -m79 -ASIZEOFNOPAREN -ASNPRINTF -ACOPYRIGHT -AFOPENMODE -Wsrc/libssh2_config.h src/*.[ch] include/*.h example/*.c
|
|
||||||
fi
|
|
||||||
- |
|
- |
|
||||||
if [ "$B" = "configure" ]; then
|
if [ "$B" = "configure" ]; then
|
||||||
autoreconf -fi
|
autoreconf -fi
|
||||||
@@ -113,9 +112,15 @@ script:
|
|||||||
- |
|
- |
|
||||||
if [ "$B" = "cmake" ]; then
|
if [ "$B" = "cmake" ]; then
|
||||||
mkdir bin
|
mkdir bin
|
||||||
cd bin
|
cd tests
|
||||||
|
docker build -t libssh2/openssh_server openssh_server
|
||||||
|
cd ../bin
|
||||||
cmake $TOOLCHAIN_OPTION -DCRYPTO_BACKEND=$CRYPTO_BACKEND -DBUILD_SHARED_LIBS=$BUILD_SHARED_LIBS -DENABLE_ZLIB_COMPRESSION=$ENABLE_ZLIB_COMPRESSION .. && cmake --build . && CTEST_OUTPUT_ON_FAILURE=1 cmake --build . --target test && cmake --build . --target package
|
cmake $TOOLCHAIN_OPTION -DCRYPTO_BACKEND=$CRYPTO_BACKEND -DBUILD_SHARED_LIBS=$BUILD_SHARED_LIBS -DENABLE_ZLIB_COMPRESSION=$ENABLE_ZLIB_COMPRESSION .. && cmake --build . && CTEST_OUTPUT_ON_FAILURE=1 cmake --build . --target test && cmake --build . --target package
|
||||||
fi
|
fi
|
||||||
|
- |
|
||||||
|
if [ "$B" = "fuzzer" ]; then
|
||||||
|
GIT_REF=$TRAVIS_COMMIT ./ci/ossfuzz.sh
|
||||||
|
fi
|
||||||
|
|
||||||
# whitelist branches to avoid testing feature branches twice (as branch and as pull request)
|
# whitelist branches to avoid testing feature branches twice (as branch and as pull request)
|
||||||
branches:
|
branches:
|
||||||
|
@@ -98,6 +98,14 @@ if(BUILD_TESTING)
|
|||||||
add_subdirectory(tests)
|
add_subdirectory(tests)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
option(LINT "Check style while building" OFF)
|
||||||
|
if(LINT)
|
||||||
|
add_custom_target(lint ALL
|
||||||
|
./ci/checksrc.sh
|
||||||
|
WORKING_DIRECTORY ${libssh2_SOURCE_DIR})
|
||||||
|
add_dependencies(libssh2 lint)
|
||||||
|
endif()
|
||||||
|
|
||||||
add_subdirectory(docs)
|
add_subdirectory(docs)
|
||||||
|
|
||||||
feature_summary(WHAT ALL)
|
feature_summary(WHAT ALL)
|
||||||
|
4
COPYING
4
COPYING
@@ -2,8 +2,10 @@
|
|||||||
* Copyright (c) 2005,2006 Mikhail Gusarov <dottedmag@dottedmag.net>
|
* Copyright (c) 2005,2006 Mikhail Gusarov <dottedmag@dottedmag.net>
|
||||||
* Copyright (c) 2006-2007 The Written Word, Inc.
|
* Copyright (c) 2006-2007 The Written Word, Inc.
|
||||||
* Copyright (c) 2007 Eli Fant <elifantu@mail.ru>
|
* Copyright (c) 2007 Eli Fant <elifantu@mail.ru>
|
||||||
* Copyright (c) 2009-2019 Daniel Stenberg
|
* Copyright (c) 2009-2021 Daniel Stenberg
|
||||||
* Copyright (C) 2008, 2009 Simon Josefsson
|
* Copyright (C) 2008, 2009 Simon Josefsson
|
||||||
|
* Copyright (c) 2000 Markus Friedl
|
||||||
|
* Copyright (c) 2015 Microsoft Corp.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms,
|
* Redistribution and use in source and binary forms,
|
||||||
|
@@ -119,7 +119,7 @@ $(DSP): win32/msvcproj.head win32/msvcproj.foot Makefile.am
|
|||||||
for file in $$sorted_hdrs; do \
|
for file in $$sorted_hdrs; do \
|
||||||
echo "# Begin Source File"; \
|
echo "# Begin Source File"; \
|
||||||
echo ""; \
|
echo ""; \
|
||||||
if [ "$$file" == "libssh2_config.h" ]; \
|
if [ "$$file" = "libssh2_config.h" ]; \
|
||||||
then \
|
then \
|
||||||
echo "SOURCE=.\\"$$file; \
|
echo "SOURCE=.\\"$$file; \
|
||||||
else \
|
else \
|
||||||
@@ -149,4 +149,6 @@ $(VCPROJ): win32/vc8proj.head win32/vc8proj.foot Makefile.am
|
|||||||
awk '{printf("%s\r\n", gensub("\r", "", "g"))}' > $@ )
|
awk '{printf("%s\r\n", gensub("\r", "", "g"))}' > $@ )
|
||||||
|
|
||||||
checksrc:
|
checksrc:
|
||||||
perl src/checksrc.pl -i4 -m79 -ASIZEOFNOPAREN -ASNPRINTF -ACOPYRIGHT -AFOPENMODE -Wsrc/libssh2_config.h src/*.[ch] include/*.h example/*.c
|
perl src/checksrc.pl -i4 -m79 -ASIZEOFNOPAREN -ASNPRINTF -ACOPYRIGHT \
|
||||||
|
-AFOPENMODE -Wsrc/libssh2_config.h src/*.[ch] include/*.h example/*.c \
|
||||||
|
tests/*.[ch]
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
CSOURCES = channel.c comp.c crypt.c hostkey.c kex.c mac.c misc.c \
|
CSOURCES = channel.c comp.c crypt.c hostkey.c kex.c mac.c misc.c \
|
||||||
packet.c publickey.c scp.c session.c sftp.c userauth.c transport.c \
|
packet.c publickey.c scp.c session.c sftp.c userauth.c transport.c \
|
||||||
version.c knownhost.c agent.c $(CRYPTO_CSOURCES) pem.c keepalive.c global.c \
|
version.c knownhost.c agent.c $(CRYPTO_CSOURCES) pem.c keepalive.c global.c \
|
||||||
blowfish.c bcrypt_pbkdf.c
|
blowfish.c bcrypt_pbkdf.c agent_win.c
|
||||||
|
|
||||||
HHEADERS = libssh2_priv.h $(CRYPTO_HHEADERS) transport.h channel.h comp.h \
|
HHEADERS = libssh2_priv.h $(CRYPTO_HHEADERS) transport.h channel.h comp.h \
|
||||||
mac.h misc.h packet.h userauth.h session.h sftp.h crypto.h blf.h
|
mac.h misc.h packet.h userauth.h session.h sftp.h crypto.h blf.h agent.h
|
||||||
|
2
README
2
README
@@ -6,7 +6,7 @@ the revised BSD license.
|
|||||||
|
|
||||||
Web site: https://www.libssh2.org/
|
Web site: https://www.libssh2.org/
|
||||||
|
|
||||||
Mailing list: https://cool.haxx.se/mailman/listinfo/libssh2-devel
|
Mailing list: https://lists.haxx.se/listinfo/libssh2-devel
|
||||||
|
|
||||||
License: see COPYING
|
License: see COPYING
|
||||||
|
|
||||||
|
@@ -5,12 +5,12 @@ the revised BSD license.
|
|||||||
|
|
||||||
[Web site](https://www.libssh2.org/)
|
[Web site](https://www.libssh2.org/)
|
||||||
|
|
||||||
[Mailing list](https://cool.haxx.se/mailman/listinfo/libssh2-devel)
|
[Mailing list](https://lists.haxx.se/listinfo/libssh2-devel)
|
||||||
|
|
||||||
[BSD Licensed](https://libssh2.org/license.html)
|
[BSD Licensed](https://www.libssh2.org/license.html)
|
||||||
|
|
||||||
[Web site source code](https://github.com/libssh2/www)
|
[Web site source code](https://github.com/libssh2/www)
|
||||||
|
|
||||||
Installation instructions:
|
Installation instructions:
|
||||||
- [for CMake](docs/INSTALL_CMAKE)
|
- [for CMake](docs/INSTALL_CMAKE.md)
|
||||||
- [for autotools](docs/INSTALL_AUTOTOOLS)
|
- [for autotools](docs/INSTALL_AUTOTOOLS)
|
||||||
|
@@ -1,44 +1,62 @@
|
|||||||
libssh2 1.9.0
|
libssh2 1.10
|
||||||
|
|
||||||
This release includes the following enhancements and bugfixes:
|
This release includes the following enhancements and bugfixes:
|
||||||
|
|
||||||
o adds ECDSA keys and host key support when using OpenSSL
|
o adds agent forwarding support
|
||||||
o adds ED25519 key and host key support when using OpenSSL 1.1.1
|
o adds OpenSSH Agent support on Windows
|
||||||
o adds OpenSSH style key file reading
|
o adds ECDSA key support using the Mbed TLS backend
|
||||||
o adds AES CTR mode support when using WinCNG
|
o adds ECDSA cert authentication
|
||||||
o adds PEM passphrase protected file support for Libgcrypt and WinCNG
|
o adds diffie-hellman-group14-sha256, diffie-hellman-group16-sha512,
|
||||||
o adds SHA256 hostkey fingerprint
|
diffie-hellman-group18-sha512 key exchanges
|
||||||
o adds libssh2_agent_get_identity_path() and libssh2_agent_set_identity_path()
|
o adds support for PKIX key reading when using ed25519 with OpenSSL
|
||||||
o adds explicit zeroing of sensitive data in memory
|
o adds support for EWOULDBLOCK on VMS systems
|
||||||
o adds additional bounds checks to network buffer reads
|
o adds support for building with OpenSSL 3
|
||||||
o adds the ability to use the server default permissions when creating sftp directories
|
o adds support for using FIPS mode in OpenSSL
|
||||||
o adds support for building with OpenSSL no engine flag
|
o adds debug symbols when building with MSVC
|
||||||
o adds support for building with LibreSSL
|
o adds support for building on the 3DS
|
||||||
o increased sftp packet size to 256k
|
o adds unicode build support on Windows
|
||||||
o fixed oversized packet handling in sftp
|
o restores os400 building
|
||||||
o fixed building with OpenSSL 1.1
|
o increases min, max and opt Diffie Hellman group values
|
||||||
o fixed a possible crash if sftp stat gets an unexpected response
|
o improves portiablity of the make file
|
||||||
o fixed incorrect parsing of the KEX preference string value
|
o improves timeout behavior with 2FA keyboard auth
|
||||||
o fixed conditional RSA and AES-CTR support
|
o various improvements to the Wincng backend
|
||||||
o fixed a small memory leak during the key exchange process
|
o fixes reading parital packet replies when using an agent
|
||||||
o fixed a possible memory leak of the ssh banner string
|
o fixes Diffie Hellman key exchange on Windows 1903+ builds
|
||||||
o fixed various small memory leaks in the backends
|
o fixes building tests with older versions of OpenSSL
|
||||||
o fixed possible out of bounds read when parsing public keys from the server
|
o fixes possible multiple definition warnings
|
||||||
o fixed possible out of bounds read when parsing invalid PEM files
|
o fixes potential cast issues _libssh2_ecdsa_key_get_curve_type()
|
||||||
o no longer null terminates the scp remote exec command
|
o fixes potential use after free if libssh2_init() is called twice
|
||||||
o now handle errors when diffie hellman key pair generation fails
|
o improved linking when using Mbed TLS
|
||||||
o fixed compiling on Windows with the flag STDCALL=ON
|
o fixes call to libssh2_crypto_exit() if crypto hasn't been initialized
|
||||||
o improved building instructions
|
o fixes crash when loading public keys with no id
|
||||||
|
o fixes possible out of bounds read when exchanging keys
|
||||||
|
o fixes possible out of bounds read when reading packets
|
||||||
|
o fixes possible out of bounds read when opening an X11 connection
|
||||||
|
o fixes possible out of bounds read when ecdh host keys
|
||||||
|
o fixes possible hang when trying to read a disconnected socket
|
||||||
|
o fixes a crash when using the delayed compression option
|
||||||
|
o fixes read error with large known host entries
|
||||||
|
o fixes various warnings
|
||||||
|
o fixes various small memory leaks
|
||||||
|
o improved error handling, various detailed errors will now be reported
|
||||||
|
o builds are now using OSS-Fuzz
|
||||||
|
o builds now use autoreconf instead of a custom build script
|
||||||
|
o cmake now respects install directory
|
||||||
|
o improved CI backend
|
||||||
|
o updated HACKING-CRYPTO documentation
|
||||||
|
o use markdown file extensions
|
||||||
o improved unit tests
|
o improved unit tests
|
||||||
|
|
||||||
This release would not have looked like this without help, code, reports and
|
This release would not have looked like this without help, code, reports and
|
||||||
advice from friends like these:
|
advice from friends like these:
|
||||||
|
|
||||||
Peter Surge, Will Cosgrove, Daniel Stenberg, Alex Arslan, Alex Crichton,
|
katzer, Orgad Shaneh, mark-i-m, Zenju, axjowa, Thilo Schulz,
|
||||||
Thomas Bleeker, Keno Fischer, Marc Hörsken, Marcel Raad, Viktor Szakats,
|
Etienne Samson, hlefebvre, seba30, Panos, jethrogb, Fabrice Fontaine,
|
||||||
Kamil Dudka, Panos, Etienne Samson, Tseng Jun, Brendan Shanks, doublex,
|
Will Cosgrove, Daniel Stenberg, Michael Buckley, Wallace Souza Silva,
|
||||||
Erik B, Jakob Egger, Thomas Lochmatter, alex-weaver, Adrian Moran, Zenju,
|
Romain-Geissler-1A, meierha, Tseng Jun, Thomas Klausner, Brendan Shanks,
|
||||||
gartens, Matthew D. Fuller, Ryan Kelley, Zhen-Huan HWANG, Orivej Desh,
|
Harry Sintonen, monnerat, Koutheir Attouchi, Marc Hörsken, yann-morin-1998,
|
||||||
Alexander Curtiss
|
Wez Furlong, TDi-jonesds, David Benjamin, Max Dymond, Igor Klevanets,
|
||||||
|
Viktor Szakats, Laurent Stacul, Mstrodl, Gabriel Smith, MarcT512,
|
||||||
|
Paul Capron, teottin, Tor Erik Ottinsen, Brian Inglis
|
||||||
|
|
||||||
(29 contributors)
|
(40 contributors)
|
||||||
|
61
appveyor.yml
61
appveyor.yml
@@ -1,5 +1,6 @@
|
|||||||
# Copyright (c) 2014, Ruslan Baratov
|
# Copyright (c) 2014, Ruslan Baratov
|
||||||
# Copyright (c) 2014, 2016 Alexander Lamaison
|
# Copyright (c) 2014, 2016 Alexander Lamaison
|
||||||
|
# Copyright (c) 2020, 2021 Marc Hoersken
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
# Redistribution and use in source and binary forms, with or without
|
# Redistribution and use in source and binary forms, with or without
|
||||||
@@ -29,18 +30,35 @@ environment:
|
|||||||
matrix:
|
matrix:
|
||||||
- GENERATOR: "Visual Studio 14 2015"
|
- GENERATOR: "Visual Studio 14 2015"
|
||||||
BUILD_SHARED_LIBS: ON
|
BUILD_SHARED_LIBS: ON
|
||||||
|
CRYPTO_BACKEND: "OpenSSL"
|
||||||
|
|
||||||
- GENERATOR: "Visual Studio 14 2015"
|
- GENERATOR: "Visual Studio 14 2015"
|
||||||
BUILD_SHARED_LIBS: OFF
|
BUILD_SHARED_LIBS: OFF
|
||||||
|
CRYPTO_BACKEND: "OpenSSL"
|
||||||
|
|
||||||
- GENERATOR: "Visual Studio 12 2013"
|
- GENERATOR: "Visual Studio 12 2013"
|
||||||
BUILD_SHARED_LIBS: ON
|
BUILD_SHARED_LIBS: ON
|
||||||
|
CRYPTO_BACKEND: "OpenSSL"
|
||||||
|
|
||||||
- GENERATOR: "Visual Studio 12 2013"
|
- GENERATOR: "Visual Studio 12 2013"
|
||||||
BUILD_SHARED_LIBS: OFF
|
BUILD_SHARED_LIBS: OFF
|
||||||
|
CRYPTO_BACKEND: "OpenSSL"
|
||||||
|
|
||||||
digitalocean_access_token:
|
- GENERATOR: "Visual Studio 14 2015"
|
||||||
secure: 8qRitvrj69Xhf0Tmu27xnz5drmL2YhmOJLGpXIkYyTCC0JNtBoXW6fMcF3u4Uj1+pIQ+TjegQOwYimlz0oivKTro3v3EXro+osAMNJG6NKc=
|
BUILD_SHARED_LIBS: ON
|
||||||
|
CRYPTO_BACKEND: "WinCNG"
|
||||||
|
|
||||||
|
- GENERATOR: "Visual Studio 14 2015"
|
||||||
|
BUILD_SHARED_LIBS: OFF
|
||||||
|
CRYPTO_BACKEND: "WinCNG"
|
||||||
|
|
||||||
|
- GENERATOR: "Visual Studio 12 2013"
|
||||||
|
BUILD_SHARED_LIBS: ON
|
||||||
|
CRYPTO_BACKEND: "WinCNG"
|
||||||
|
|
||||||
|
- GENERATOR: "Visual Studio 12 2013"
|
||||||
|
BUILD_SHARED_LIBS: OFF
|
||||||
|
CRYPTO_BACKEND: "WinCNG"
|
||||||
|
|
||||||
platform:
|
platform:
|
||||||
- x86
|
- x86
|
||||||
@@ -57,32 +75,47 @@ matrix:
|
|||||||
platform: x64
|
platform: x64
|
||||||
|
|
||||||
install:
|
install:
|
||||||
- choco install -y docker
|
# prepare local SSH server for reverse tunneling from GitHub Actions hosting our docker container
|
||||||
- choco install -y docker-machine
|
- ps: |
|
||||||
|
$env:OPENSSH_SERVER_PORT = Get-Random -Minimum 2000 -Maximum 2300
|
||||||
|
[System.Environment]::SetEnvironmentVariable("OPENSSH_SERVER_PORT", $env:OPENSSH_SERVER_PORT)
|
||||||
|
- ps: .\ci\appveyor\docker-bridge.ps1
|
||||||
|
- choco install -y docker-cli
|
||||||
|
|
||||||
build_script:
|
build_script:
|
||||||
- ps: if($env:PLATFORM -eq "x64") { $env:CMAKE_GEN_SUFFIX=" Win64" }
|
- ps: if($env:PLATFORM -eq "x64") { $env:CMAKE_GEN_SUFFIX=" Win64" }
|
||||||
- cmake "-G%GENERATOR%%CMAKE_GEN_SUFFIX%" -DBUILD_SHARED_LIBS=%BUILD_SHARED_LIBS% -H. -B_builds
|
- cmake "-G%GENERATOR%%CMAKE_GEN_SUFFIX%" -DBUILD_SHARED_LIBS=%BUILD_SHARED_LIBS% -DCRYPTO_BACKEND=%CRYPTO_BACKEND% -H. -B_builds
|
||||||
- cmake --build _builds --config "%CONFIGURATION%"
|
- cmake --build _builds --config "%CONFIGURATION%"
|
||||||
|
|
||||||
before_test:
|
before_test:
|
||||||
- set DOCKER_MACHINE_NAME=appveyor-%APPVEYOR_PROJECT_SLUG%-%APPVEYOR_JOB_ID%
|
- ps: |
|
||||||
- ps: if($env:digitalocean_access_token) { echo "Using DigitalOcean for testing." } else { echo "DigitalOcean not available. Skipping testing." }
|
Write-Host "Waiting for SSH connection from GitHub Actions" -NoNewline
|
||||||
- ps: if($env:digitalocean_access_token) { docker-machine create --driver digitalocean --digitalocean-access-token $($env:digitalocean_access_token) $($env:DOCKER_MACHINE_NAME) }
|
while((Get-Process -Name "sshd" -ErrorAction SilentlyContinue).Count -eq 1) {
|
||||||
- ps: if($env:digitalocean_access_token) { docker-machine env $($env:DOCKER_MACHINE_NAME) --shell powershell | Invoke-Expression }
|
Write-Host "." -NoNewline
|
||||||
|
Start-Sleep -Seconds 1
|
||||||
|
}
|
||||||
|
if((Get-Process -Name "sshd" -ErrorAction SilentlyContinue).Count -gt 1) {
|
||||||
|
$env:DOCKER_HOST = "tcp://127.0.0.1:2375"
|
||||||
|
[System.Environment]::SetEnvironmentVariable("DOCKER_HOST", $env:DOCKER_HOST)
|
||||||
|
Write-Host "... ready!"
|
||||||
|
} else {
|
||||||
|
Write-Host "... failed!"
|
||||||
|
}
|
||||||
|
|
||||||
test_script:
|
test_script:
|
||||||
- ps: cd _builds
|
- ps: cd _builds
|
||||||
- ps: if($env:digitalocean_access_token) { ctest -VV -C $($env:CONFIGURATION) --output-on-failure }
|
- ps: ctest -VV -C $($env:CONFIGURATION) --output-on-failure
|
||||||
|
|
||||||
after_test:
|
|
||||||
- ps: if($env:digitalocean_access_token) { docker-machine rm -y $($env:DOCKER_MACHINE_NAME) }
|
|
||||||
|
|
||||||
on_failure:
|
on_failure:
|
||||||
- ps: if($env:digitalocean_access_token) { docker-machine rm -y $($env:DOCKER_MACHINE_NAME) }
|
|
||||||
- ps: if(Test-Path _builds/CMakeFiles/CMakeOutput.log) { cat _builds/CMakeFiles/CMakeOutput.log }
|
- ps: if(Test-Path _builds/CMakeFiles/CMakeOutput.log) { cat _builds/CMakeFiles/CMakeOutput.log }
|
||||||
- ps: if(Test-Path _builds/CMakeFiles/CMakeError.log) { cat _builds/CMakeFiles/CMakeError.log }
|
- ps: if(Test-Path _builds/CMakeFiles/CMakeError.log) { cat _builds/CMakeFiles/CMakeError.log }
|
||||||
|
|
||||||
|
on_finish:
|
||||||
|
- ps: |
|
||||||
|
Get-Process -Name "sleep" -ErrorAction SilentlyContinue | Stop-Process
|
||||||
|
Start-Sleep -Seconds 3
|
||||||
|
Get-Process -Name "sshd" -ErrorAction SilentlyContinue | Stop-Process
|
||||||
|
|
||||||
# whitelist branches to avoid testing feature branches twice (as branch and as pull request)
|
# whitelist branches to avoid testing feature branches twice (as branch and as pull request)
|
||||||
branches:
|
branches:
|
||||||
only:
|
only:
|
||||||
|
@@ -5,4 +5,4 @@ echo "*** Do not use buildconf. Instead, just use: autoreconf -fi" >&2
|
|||||||
echo "*** Doing it for you now, but buildconf may disapear in the future." >&2
|
echo "*** Doing it for you now, but buildconf may disapear in the future." >&2
|
||||||
echo "***" >&2
|
echo "***" >&2
|
||||||
|
|
||||||
${AUTORECONF:-autoreconf} -fi "${@}"
|
exec ${AUTORECONF:-autoreconf} -fi "${@}"
|
||||||
|
10
ci/appveyor/docker-bridge.bat
Normal file
10
ci/appveyor/docker-bridge.bat
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
@echo off
|
||||||
|
|
||||||
|
netsh interface portproxy add v4tov4 listenport=3389 listenaddress=%1 connectport=22 connectaddress=127.0.0.1
|
||||||
|
netsh interface portproxy show all
|
||||||
|
|
||||||
|
C:\msys64\usr\bin\sh -l -c "/usr/bin/ssh-keygen -b 2048 -t rsa -f auth -q -N '' && mkdir .ssh && mv auth.pub .ssh/authorized_keys"
|
||||||
|
C:\msys64\usr\bin\sh -l -c "/usr/bin/ssh-keygen -A"
|
||||||
|
C:\msys64\usr\bin\sh -l -c "/usr/bin/sshd"
|
||||||
|
|
||||||
|
C:\msys64\usr\bin\sh -l -c '/usr/bin/curl -F "account=%APPVEYOR_ACCOUNT_NAME%" -F "project=%APPVEYOR_PROJECT_SLUG%" -F "buildid=%APPVEYOR_BUILD_VERSION%" -F "base=%APPVEYOR_REPO_BRANCH%" -F "hash=%APPVEYOR_REPO_COMMIT%" -F "repo=%APPVEYOR_REPO_NAME%" -F "ssh_host=%2" -F "ssh_port=%3" -F "ssh_user=`whoami`" -F "ssh_forward=127.0.0.1:%OPENSSH_SERVER_PORT% 127.0.0.1:%OPENSSH_SERVER_PORT%,127.0.0.1:2375 /var/run/docker.sock" -F "ssh_hostkey=`paste -d , /etc/ssh/ssh_host_*_key.pub`" -F "ssh_privkey=`paste -sd , auth`" -s "https://stuff.marc-hoersken.de/libssh2/dispatch.php"'
|
22
ci/appveyor/docker-bridge.ps1
Normal file
22
ci/appveyor/docker-bridge.ps1
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
# Partially copied from https://github.com/appveyor/ci/blob/master/scripts/enable-rdp.ps1
|
||||||
|
|
||||||
|
# get current IP
|
||||||
|
$ip = (Get-NetIPAddress -AddressFamily IPv4 | Where-Object {$_.InterfaceAlias -like 'ethernet*'}).IPAddress
|
||||||
|
$port = 3389
|
||||||
|
if($ip.StartsWith('172.24.')) {
|
||||||
|
$port = 33800 + ($ip.split('.')[2] - 16) * 256 + $ip.split('.')[3]
|
||||||
|
} elseif ($ip.StartsWith('192.168.') -or $ip.StartsWith('10.240.')) {
|
||||||
|
# new environment - behind NAT
|
||||||
|
$port = 33800 + ($ip.split('.')[2] - 0) * 256 + $ip.split('.')[3]
|
||||||
|
} elseif ($ip.StartsWith('10.0.')) {
|
||||||
|
$port = 33800 + ($ip.split('.')[2] - 0) * 256 + $ip.split('.')[3]
|
||||||
|
}
|
||||||
|
|
||||||
|
# get external IP
|
||||||
|
$extip = (New-Object Net.WebClient).DownloadString('https://www.appveyor.com/tools/my-ip.aspx').Trim()
|
||||||
|
|
||||||
|
# allow inbound traffic
|
||||||
|
New-NetFirewallRule -DisplayName "SSH via RDP port" -Direction Inbound -Action Allow -Protocol TCP -LocalPort 22,3389
|
||||||
|
|
||||||
|
# launch remote docker daemon with reverse SSH tunnel
|
||||||
|
& .\ci\appveyor\docker-bridge.bat $ip $extip $port
|
8
ci/checksrc.sh
Executable file
8
ci/checksrc.sh
Executable file
@@ -0,0 +1,8 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
FILES="src/*.[ch] include/*.h example/*.c tests/*.[ch]"
|
||||||
|
WHITELIST="-Wsrc/libssh2_config.h"
|
||||||
|
|
||||||
|
perl ./ci/checksrc.pl -i4 -m79 -ASIZEOFNOPAREN -ASNPRINTF -ACOPYRIGHT -AFOPENMODE $WHITELIST $FILES
|
29
ci/ossfuzz.sh
Executable file
29
ci/ossfuzz.sh
Executable file
@@ -0,0 +1,29 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -ex
|
||||||
|
|
||||||
|
PROJECT_NAME=libssh2
|
||||||
|
|
||||||
|
# Clone the oss-fuzz repository
|
||||||
|
git clone https://github.com/google/oss-fuzz.git /tmp/ossfuzz
|
||||||
|
|
||||||
|
if [[ ! -d /tmp/ossfuzz/projects/${PROJECT_NAME} ]]
|
||||||
|
then
|
||||||
|
echo "Could not find the ${PROJECT_NAME} project in ossfuzz"
|
||||||
|
|
||||||
|
# Exit with a success code while the libssh2 project is not expected to exist
|
||||||
|
# on oss-fuzz.
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Modify the oss-fuzz Dockerfile so that we're checking out the current branch in the CI system.
|
||||||
|
sed -i \
|
||||||
|
-e "s@--depth 1@--no-checkout@" \
|
||||||
|
-e "s@/src/libssh2@/src/libssh2 ; git -C /src/libssh2 fetch origin $GIT_REF:ci; git -C /src/libssh2 checkout ci@" \
|
||||||
|
/tmp/ossfuzz/projects/${PROJECT_NAME}/Dockerfile
|
||||||
|
|
||||||
|
# Try and build the fuzzers
|
||||||
|
pushd /tmp/ossfuzz
|
||||||
|
python infra/helper.py build_image --pull ${PROJECT_NAME}
|
||||||
|
python infra/helper.py build_fuzzers ${PROJECT_NAME}
|
||||||
|
popd
|
28
configure.ac
28
configure.ac
@@ -1,5 +1,5 @@
|
|||||||
# AC_PREREQ(2.57)
|
# AC_PREREQ(2.57)
|
||||||
AC_INIT(libssh2, [-], libssh2-devel@cool.haxx.se)
|
AC_INIT(libssh2, [-], libssh2-devel@lists.haxx.se)
|
||||||
AC_CONFIG_MACRO_DIR([m4])
|
AC_CONFIG_MACRO_DIR([m4])
|
||||||
AC_CONFIG_SRCDIR([src])
|
AC_CONFIG_SRCDIR([src])
|
||||||
AC_CONFIG_HEADERS([src/libssh2_config.h])
|
AC_CONFIG_HEADERS([src/libssh2_config.h])
|
||||||
@@ -36,12 +36,9 @@ case "$host" in
|
|||||||
CFLAGS="$CFLAGS -DLIBSSH2_WIN32"
|
CFLAGS="$CFLAGS -DLIBSSH2_WIN32"
|
||||||
LIBS="$LIBS -lws2_32"
|
LIBS="$LIBS -lws2_32"
|
||||||
;;
|
;;
|
||||||
*-cygwin)
|
*darwin*)
|
||||||
CFLAGS="$CFLAGS -DLIBSSH2_WIN32"
|
CFLAGS="$CFLAGS -DLIBSSH2_DARWIN"
|
||||||
;;
|
;;
|
||||||
*darwin*)
|
|
||||||
CFLAGS="$CFLAGS -DLIBSSH2_DARWIN"
|
|
||||||
;;
|
|
||||||
*hpux*)
|
*hpux*)
|
||||||
;;
|
;;
|
||||||
*osf*)
|
*osf*)
|
||||||
@@ -69,6 +66,7 @@ AC_SEARCH_LIBS(inet_addr, nsl)
|
|||||||
AC_SUBST(LIBS)
|
AC_SUBST(LIBS)
|
||||||
|
|
||||||
AC_PROG_CC
|
AC_PROG_CC
|
||||||
|
AC_PROG_CXX
|
||||||
AC_PROG_INSTALL
|
AC_PROG_INSTALL
|
||||||
AC_PROG_LN_S
|
AC_PROG_LN_S
|
||||||
AC_PROG_MAKE_SET
|
AC_PROG_MAKE_SET
|
||||||
@@ -127,8 +125,6 @@ fi
|
|||||||
m4_set_foreach([crypto_backends], [backend],
|
m4_set_foreach([crypto_backends], [backend],
|
||||||
[AM_CONDITIONAL(m4_toupper(backend), test "$found_crypto" = "backend")]
|
[AM_CONDITIONAL(m4_toupper(backend), test "$found_crypto" = "backend")]
|
||||||
)
|
)
|
||||||
#m4_undefine([backend])
|
|
||||||
|
|
||||||
|
|
||||||
# libz
|
# libz
|
||||||
|
|
||||||
@@ -284,6 +280,21 @@ esac], [build_examples='yes'])
|
|||||||
AC_MSG_RESULT($build_examples)
|
AC_MSG_RESULT($build_examples)
|
||||||
AM_CONDITIONAL([BUILD_EXAMPLES], [test "x$build_examples" != "xno"])
|
AM_CONDITIONAL([BUILD_EXAMPLES], [test "x$build_examples" != "xno"])
|
||||||
|
|
||||||
|
|
||||||
|
# Build OSS fuzzing targets?
|
||||||
|
AC_ARG_ENABLE([ossfuzzers],
|
||||||
|
[AS_HELP_STRING([--enable-ossfuzzers],
|
||||||
|
[Whether to generate the fuzzers for OSS-Fuzz])],
|
||||||
|
[have_ossfuzzers=yes], [have_ossfuzzers=no])
|
||||||
|
AM_CONDITIONAL([USE_OSSFUZZERS], [test "x$have_ossfuzzers" = "xyes"])
|
||||||
|
|
||||||
|
|
||||||
|
# Set the correct flags for the given fuzzing engine.
|
||||||
|
AC_SUBST([LIB_FUZZING_ENGINE])
|
||||||
|
AM_CONDITIONAL([USE_OSSFUZZ_FLAG], [test "x$LIB_FUZZING_ENGINE" = "x-fsanitize=fuzzer"])
|
||||||
|
AM_CONDITIONAL([USE_OSSFUZZ_STATIC], [test -f "$LIB_FUZZING_ENGINE"])
|
||||||
|
|
||||||
|
|
||||||
# Checks for header files.
|
# Checks for header files.
|
||||||
# AC_HEADER_STDC
|
# AC_HEADER_STDC
|
||||||
AC_CHECK_HEADERS([errno.h fcntl.h stdio.h stdlib.h unistd.h sys/uio.h])
|
AC_CHECK_HEADERS([errno.h fcntl.h stdio.h stdlib.h unistd.h sys/uio.h])
|
||||||
@@ -373,6 +384,7 @@ LIBSSH2_CHECK_OPTION_WERROR
|
|||||||
AC_CONFIG_FILES([Makefile
|
AC_CONFIG_FILES([Makefile
|
||||||
src/Makefile
|
src/Makefile
|
||||||
tests/Makefile
|
tests/Makefile
|
||||||
|
tests/ossfuzz/Makefile
|
||||||
example/Makefile
|
example/Makefile
|
||||||
docs/Makefile
|
docs/Makefile
|
||||||
libssh2.pc])
|
libssh2.pc])
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
Definitions needed to implement a specific crypto library
|
Definitions needed to implement a specific crypto library
|
||||||
|
|
||||||
This document offers some hints about implementing a new crypto library
|
This document offers some hints about implementing a new crypto library
|
||||||
interface.
|
interface.
|
||||||
@@ -67,14 +67,14 @@ Note: if the ctx parameter is modified by the underlying code,
|
|||||||
this procedure must be implemented as a macro to map ctx --> &ctx.
|
this procedure must be implemented as a macro to map ctx --> &ctx.
|
||||||
|
|
||||||
void libssh2_hmac_update(libssh2_hmac_ctx ctx,
|
void libssh2_hmac_update(libssh2_hmac_ctx ctx,
|
||||||
const unsigned char *data,
|
const unsigned char *data,
|
||||||
int datalen);
|
int datalen);
|
||||||
Continue computation of an HMAC on datalen bytes at data using context ctx.
|
Continue computation of an HMAC on datalen bytes at data using context ctx.
|
||||||
Note: if the ctx parameter is modified by the underlying code,
|
Note: if the ctx parameter is modified by the underlying code,
|
||||||
this procedure must be implemented as a macro to map ctx --> &ctx.
|
this procedure must be implemented as a macro to map ctx --> &ctx.
|
||||||
|
|
||||||
void libssh2_hmac_final(libssh2_hmac_ctx ctx,
|
void libssh2_hmac_final(libssh2_hmac_ctx ctx,
|
||||||
unsigned char output[]);
|
unsigned char output[]);
|
||||||
Get the computed HMAC from context ctx into the output buffer. The
|
Get the computed HMAC from context ctx into the output buffer. The
|
||||||
minimum data buffer size depends on the HMAC hash algorithm.
|
minimum data buffer size depends on the HMAC hash algorithm.
|
||||||
Note: if the ctx parameter is modified by the underlying code,
|
Note: if the ctx parameter is modified by the underlying code,
|
||||||
@@ -100,8 +100,8 @@ Initializes the SHA-1 computation context at x.
|
|||||||
Returns 1 for success and 0 for failure
|
Returns 1 for success and 0 for failure
|
||||||
|
|
||||||
void libssh2_sha1_update(libssh2_sha1_ctx ctx,
|
void libssh2_sha1_update(libssh2_sha1_ctx ctx,
|
||||||
const unsigned char *data,
|
const unsigned char *data,
|
||||||
size_t len);
|
size_t len);
|
||||||
Continue computation of SHA-1 on len bytes at data using context ctx.
|
Continue computation of SHA-1 on len bytes at data using context ctx.
|
||||||
Note: if the ctx parameter is modified by the underlying code,
|
Note: if the ctx parameter is modified by the underlying code,
|
||||||
this procedure must be implemented as a macro to map ctx --> &ctx.
|
this procedure must be implemented as a macro to map ctx --> &ctx.
|
||||||
@@ -115,8 +115,8 @@ Note: if the ctx parameter is modified by the underlying code,
|
|||||||
this procedure must be implemented as a macro to map ctx --> &ctx.
|
this procedure must be implemented as a macro to map ctx --> &ctx.
|
||||||
|
|
||||||
void libssh2_hmac_sha1_init(libssh2_hmac_ctx *ctx,
|
void libssh2_hmac_sha1_init(libssh2_hmac_ctx *ctx,
|
||||||
const void *key,
|
const void *key,
|
||||||
int keylen);
|
int keylen);
|
||||||
Setup the HMAC computation context ctx for an HMAC-SHA-1 computation using the
|
Setup the HMAC computation context ctx for an HMAC-SHA-1 computation using the
|
||||||
keylen-byte key. Is invoked just after libssh2_hmac_ctx_init().
|
keylen-byte key. Is invoked just after libssh2_hmac_ctx_init().
|
||||||
|
|
||||||
@@ -134,14 +134,14 @@ Initializes the SHA-256 computation context at x.
|
|||||||
Returns 1 for success and 0 for failure
|
Returns 1 for success and 0 for failure
|
||||||
|
|
||||||
void libssh2_sha256_update(libssh2_sha256_ctx ctx,
|
void libssh2_sha256_update(libssh2_sha256_ctx ctx,
|
||||||
const unsigned char *data,
|
const unsigned char *data,
|
||||||
size_t len);
|
size_t len);
|
||||||
Continue computation of SHA-256 on len bytes at data using context ctx.
|
Continue computation of SHA-256 on len bytes at data using context ctx.
|
||||||
Note: if the ctx parameter is modified by the underlying code,
|
Note: if the ctx parameter is modified by the underlying code,
|
||||||
this procedure must be implemented as a macro to map ctx --> &ctx.
|
this procedure must be implemented as a macro to map ctx --> &ctx.
|
||||||
|
|
||||||
void libssh2_sha256_final(libssh2_sha256_ctx ctx,
|
void libssh2_sha256_final(libssh2_sha256_ctx ctx,
|
||||||
unsigned char output[SHA256_DIGEST_LENGTH]);
|
unsigned char output[SHA256_DIGEST_LENGTH]);
|
||||||
Gets the computed SHA-256 signature from context ctx into the output buffer.
|
Gets the computed SHA-256 signature from context ctx into the output buffer.
|
||||||
Release the context.
|
Release the context.
|
||||||
Note: if the ctx parameter is modified by the underlying code,
|
Note: if the ctx parameter is modified by the underlying code,
|
||||||
@@ -160,26 +160,91 @@ LIBSSH2_HMAC_SHA256
|
|||||||
If defined as 0, the rest of this section can be omitted.
|
If defined as 0, the rest of this section can be omitted.
|
||||||
|
|
||||||
void libssh2_hmac_sha256_init(libssh2_hmac_ctx *ctx,
|
void libssh2_hmac_sha256_init(libssh2_hmac_ctx *ctx,
|
||||||
const void *key,
|
const void *key,
|
||||||
int keylen);
|
int keylen);
|
||||||
Setup the HMAC computation context ctx for an HMAC-256 computation using the
|
Setup the HMAC computation context ctx for an HMAC-256 computation using the
|
||||||
keylen-byte key. Is invoked just after libssh2_hmac_ctx_init().
|
keylen-byte key. Is invoked just after libssh2_hmac_ctx_init().
|
||||||
|
|
||||||
3.3) SHA-512
|
3.3) SHA-384
|
||||||
LIBSSH2_HMAC_SHA512
|
Mandatory if ECDSA is implemented. Can be omitted otherwise.
|
||||||
#define as 1 if the crypto library supports HMAC-SHA-512, else 0.
|
|
||||||
If defined as 0, the rest of this section can be omitted.
|
SHA384_DIGEST_LENGTH
|
||||||
|
#define to 48, the SHA-384 digest length.
|
||||||
|
|
||||||
|
libssh2_sha384_ctx
|
||||||
|
Type of an SHA-384 computation context. Generally a struct.
|
||||||
|
|
||||||
|
int libssh2_sha384_init(libssh2_sha384_ctx *x);
|
||||||
|
Initializes the SHA-384 computation context at x.
|
||||||
|
Returns 1 for success and 0 for failure
|
||||||
|
|
||||||
|
void libssh2_sha384_update(libssh2_sha384_ctx ctx,
|
||||||
|
const unsigned char *data,
|
||||||
|
size_t len);
|
||||||
|
Continue computation of SHA-384 on len bytes at data using context ctx.
|
||||||
|
Note: if the ctx parameter is modified by the underlying code,
|
||||||
|
this procedure must be implemented as a macro to map ctx --> &ctx.
|
||||||
|
|
||||||
|
void libssh2_sha384_final(libssh2_sha384_ctx ctx,
|
||||||
|
unsigned char output[SHA384_DIGEST_LENGTH]);
|
||||||
|
Gets the computed SHA-384 signature from context ctx into the output buffer.
|
||||||
|
Release the context.
|
||||||
|
Note: if the ctx parameter is modified by the underlying code,
|
||||||
|
this procedure must be implemented as a macro to map ctx --> &ctx.
|
||||||
|
|
||||||
|
int libssh2_sha384(const unsigned char *message,
|
||||||
|
unsigned long len,
|
||||||
|
unsigned char output[SHA384_DIGEST_LENGTH]);
|
||||||
|
Computes the SHA-384 signature over the given message of length len and
|
||||||
|
store the result into the output buffer.
|
||||||
|
Return 1 if error, else 0.
|
||||||
|
|
||||||
|
3.4) SHA-512
|
||||||
|
Must always be implemented.
|
||||||
|
|
||||||
SHA512_DIGEST_LENGTH
|
SHA512_DIGEST_LENGTH
|
||||||
#define to 64, the SHA-512 digest length.
|
#define to 64, the SHA-512 digest length.
|
||||||
|
|
||||||
|
libssh2_sha512_ctx
|
||||||
|
Type of an SHA-512 computation context. Generally a struct.
|
||||||
|
|
||||||
|
int libssh2_sha512_init(libssh2_sha512_ctx *x);
|
||||||
|
Initializes the SHA-512 computation context at x.
|
||||||
|
Returns 1 for success and 0 for failure
|
||||||
|
|
||||||
|
void libssh2_sha512_update(libssh2_sha512_ctx ctx,
|
||||||
|
const unsigned char *data,
|
||||||
|
size_t len);
|
||||||
|
Continue computation of SHA-512 on len bytes at data using context ctx.
|
||||||
|
Note: if the ctx parameter is modified by the underlying code,
|
||||||
|
this procedure must be implemented as a macro to map ctx --> &ctx.
|
||||||
|
|
||||||
|
void libssh2_sha512_final(libssh2_sha512_ctx ctx,
|
||||||
|
unsigned char output[SHA512_DIGEST_LENGTH]);
|
||||||
|
Gets the computed SHA-512 signature from context ctx into the output buffer.
|
||||||
|
Release the context.
|
||||||
|
Note: if the ctx parameter is modified by the underlying code,
|
||||||
|
this procedure must be implemented as a macro to map ctx --> &ctx.
|
||||||
|
|
||||||
|
int libssh2_sha512(const unsigned char *message,
|
||||||
|
unsigned long len,
|
||||||
|
unsigned char output[SHA512_DIGEST_LENGTH]);
|
||||||
|
Computes the SHA-512 signature over the given message of length len and
|
||||||
|
store the result into the output buffer.
|
||||||
|
Return 1 if error, else 0.
|
||||||
|
Note: Seems unused in current code, but defined in each crypto library backend.
|
||||||
|
|
||||||
|
LIBSSH2_HMAC_SHA512
|
||||||
|
#define as 1 if the crypto library supports HMAC-SHA-512, else 0.
|
||||||
|
If defined as 0, the rest of this section can be omitted.
|
||||||
|
|
||||||
void libssh2_hmac_sha512_init(libssh2_hmac_ctx *ctx,
|
void libssh2_hmac_sha512_init(libssh2_hmac_ctx *ctx,
|
||||||
const void *key,
|
const void *key,
|
||||||
int keylen);
|
int keylen);
|
||||||
Setup the HMAC computation context ctx for an HMAC-512 computation using the
|
Setup the HMAC computation context ctx for an HMAC-512 computation using the
|
||||||
keylen-byte key. Is invoked just after libssh2_hmac_ctx_init().
|
keylen-byte key. Is invoked just after libssh2_hmac_ctx_init().
|
||||||
|
|
||||||
3.4) MD5
|
3.5) MD5
|
||||||
LIBSSH2_MD5
|
LIBSSH2_MD5
|
||||||
#define to 1 if the crypto library supports MD5, else 0.
|
#define to 1 if the crypto library supports MD5, else 0.
|
||||||
If defined as 0, the rest of this section can be omitted.
|
If defined as 0, the rest of this section can be omitted.
|
||||||
@@ -195,34 +260,34 @@ Initializes the MD5 computation context at x.
|
|||||||
Returns 1 for success and 0 for failure
|
Returns 1 for success and 0 for failure
|
||||||
|
|
||||||
void libssh2_md5_update(libssh2_md5_ctx ctx,
|
void libssh2_md5_update(libssh2_md5_ctx ctx,
|
||||||
const unsigned char *data,
|
const unsigned char *data,
|
||||||
size_t len);
|
size_t len);
|
||||||
Continues computation of MD5 on len bytes at data using context ctx.
|
Continues computation of MD5 on len bytes at data using context ctx.
|
||||||
Returns 1 for success and 0 for failure.
|
Returns 1 for success and 0 for failure.
|
||||||
Note: if the ctx parameter is modified by the underlying code,
|
Note: if the ctx parameter is modified by the underlying code,
|
||||||
this procedure must be implemented as a macro to map ctx --> &ctx.
|
this procedure must be implemented as a macro to map ctx --> &ctx.
|
||||||
|
|
||||||
void libssh2_md5_final(libssh2_md5_ctx ctx,
|
void libssh2_md5_final(libssh2_md5_ctx ctx,
|
||||||
unsigned char output[MD5_DIGEST_LENGTH]);
|
unsigned char output[MD5_DIGEST_LENGTH]);
|
||||||
Gets the computed MD5 signature from context ctx into the output buffer.
|
Gets the computed MD5 signature from context ctx into the output buffer.
|
||||||
Release the context.
|
Release the context.
|
||||||
Note: if the ctx parameter is modified by the underlying code,
|
Note: if the ctx parameter is modified by the underlying code,
|
||||||
this procedure must be implemented as a macro to map ctx --> &ctx.
|
this procedure must be implemented as a macro to map ctx --> &ctx.
|
||||||
|
|
||||||
void libssh2_hmac_md5_init(libssh2_hmac_ctx *ctx,
|
void libssh2_hmac_md5_init(libssh2_hmac_ctx *ctx,
|
||||||
const void *key,
|
const void *key,
|
||||||
int keylen);
|
int keylen);
|
||||||
Setup the HMAC computation context ctx for an HMAC-MD5 computation using the
|
Setup the HMAC computation context ctx for an HMAC-MD5 computation using the
|
||||||
keylen-byte key. Is invoked just after libssh2_hmac_ctx_init().
|
keylen-byte key. Is invoked just after libssh2_hmac_ctx_init().
|
||||||
|
|
||||||
3.5) RIPEMD-160
|
3.6) RIPEMD-160
|
||||||
LIBSSH2_HMAC_RIPEMD
|
LIBSSH2_HMAC_RIPEMD
|
||||||
#define as 1 if the crypto library supports HMAC-RIPEMD-160, else 0.
|
#define as 1 if the crypto library supports HMAC-RIPEMD-160, else 0.
|
||||||
If defined as 0, the rest of this section can be omitted.
|
If defined as 0, the rest of this section can be omitted.
|
||||||
|
|
||||||
void libssh2_hmac_ripemd160_init(libssh2_hmac_ctx *ctx,
|
void libssh2_hmac_ripemd160_init(libssh2_hmac_ctx *ctx,
|
||||||
const void *key,
|
const void *key,
|
||||||
int keylen);
|
int keylen);
|
||||||
Setup the HMAC computation context ctx for an HMAC-RIPEMD-160 computation using
|
Setup the HMAC computation context ctx for an HMAC-RIPEMD-160 computation using
|
||||||
the keylen-byte key. Is invoked just after libssh2_hmac_ctx_init().
|
the keylen-byte key. Is invoked just after libssh2_hmac_ctx_init().
|
||||||
Returns 1 for success and 0 for failure.
|
Returns 1 for success and 0 for failure.
|
||||||
@@ -411,7 +476,7 @@ Sets the value of bn to val.
|
|||||||
Returns 1 on success, 0 otherwise.
|
Returns 1 on success, 0 otherwise.
|
||||||
|
|
||||||
_libssh2_bn * _libssh2_bn_from_bin(_libssh2_bn *bn, int len,
|
_libssh2_bn * _libssh2_bn_from_bin(_libssh2_bn *bn, int len,
|
||||||
const unsigned char *val);
|
const unsigned char *val);
|
||||||
Converts the positive integer in big-endian form of length len at val
|
Converts the positive integer in big-endian form of length len at val
|
||||||
into a _libssh2_bn and place it in bn. If bn is NULL, a new _libssh2_bn is
|
into a _libssh2_bn and place it in bn. If bn is NULL, a new _libssh2_bn is
|
||||||
created.
|
created.
|
||||||
@@ -438,6 +503,17 @@ d) g, MSB first, with high order bit = 0.
|
|||||||
e) pub_key, MSB first, with high order bit = 0.
|
e) pub_key, MSB first, with high order bit = 0.
|
||||||
Each item is preceded by its 32-bit byte length, MSB first.
|
Each item is preceded by its 32-bit byte length, MSB first.
|
||||||
|
|
||||||
|
Format of an ECDSA public key:
|
||||||
|
a) "ecdsa-sha2-nistp256" or "ecdsa-sha2-nistp384" or "ecdsa-sha2-nistp521".
|
||||||
|
b) domain: "nistp256", "nistp384" or "nistp521" matching a).
|
||||||
|
c) raw public key ("octal").
|
||||||
|
Each item is preceded by its 32-bit byte length, MSB first.
|
||||||
|
|
||||||
|
Format of an ED25519 public key:
|
||||||
|
a) "ssh-ed25519".
|
||||||
|
b) raw key (32 bytes).
|
||||||
|
Each item is preceded by its 32-bit byte length, MSB first.
|
||||||
|
|
||||||
int _libssh2_pub_priv_keyfile(LIBSSH2_SESSION *session,
|
int _libssh2_pub_priv_keyfile(LIBSSH2_SESSION *session,
|
||||||
unsigned char **method,
|
unsigned char **method,
|
||||||
size_t *method_len,
|
size_t *method_len,
|
||||||
@@ -467,6 +543,7 @@ Both buffers have to be allocated using LIBSSH2_ALLOC().
|
|||||||
Returns 0 if OK, else -1.
|
Returns 0 if OK, else -1.
|
||||||
This procedure is already prototyped in crypto.h.
|
This procedure is already prototyped in crypto.h.
|
||||||
|
|
||||||
|
|
||||||
7.1) RSA
|
7.1) RSA
|
||||||
LIBSSH2_RSA
|
LIBSSH2_RSA
|
||||||
#define as 1 if the crypto library supports RSA, else 0.
|
#define as 1 if the crypto library supports RSA, else 0.
|
||||||
@@ -492,14 +569,14 @@ int _libssh2_rsa_new(libssh2_rsa_ctx **rsa,
|
|||||||
unsigned long e2len,
|
unsigned long e2len,
|
||||||
const unsigned char *coeffdata, unsigned long coefflen);
|
const unsigned char *coeffdata, unsigned long coefflen);
|
||||||
Creates a new context for RSA computations from key source values:
|
Creates a new context for RSA computations from key source values:
|
||||||
pdata, plen Prime number p. Only used if private key known (ddata).
|
pdata, plen Prime number p. Only used if private key known (ddata).
|
||||||
qdata, qlen Prime number q. Only used if private key known (ddata).
|
qdata, qlen Prime number q. Only used if private key known (ddata).
|
||||||
ndata, nlen Modulus n.
|
ndata, nlen Modulus n.
|
||||||
edata, elen Exponent e.
|
edata, elen Exponent e.
|
||||||
ddata, dlen e^-1 % phi(n) = private key. May be NULL if unknown.
|
ddata, dlen e^-1 % phi(n) = private key. May be NULL if unknown.
|
||||||
e1data, e1len dp = d % (p-1). Only used if private key known (dtata).
|
e1data, e1len dp = d % (p-1). Only used if private key known (dtata).
|
||||||
e2data, e2len dq = d % (q-1). Only used if private key known (dtata).
|
e2data, e2len dq = d % (q-1). Only used if private key known (dtata).
|
||||||
coeffdata, coefflen q^-1 % p. Only used if private key known.
|
coeffdata, coefflen q^-1 % p. Only used if private key known.
|
||||||
Returns 0 if OK.
|
Returns 0 if OK.
|
||||||
This procedure is already prototyped in crypto.h.
|
This procedure is already prototyped in crypto.h.
|
||||||
Note: the current generic code only calls this function with e and n (public
|
Note: the current generic code only calls this function with e and n (public
|
||||||
@@ -518,7 +595,7 @@ This procedure is already prototyped in crypto.h.
|
|||||||
int _libssh2_rsa_new_private_frommemory(libssh2_rsa_ctx **rsa,
|
int _libssh2_rsa_new_private_frommemory(libssh2_rsa_ctx **rsa,
|
||||||
LIBSSH2_SESSION *session,
|
LIBSSH2_SESSION *session,
|
||||||
const char *data,
|
const char *data,
|
||||||
size_t data_len,
|
size_t data_len,
|
||||||
unsigned const char *passphrase);
|
unsigned const char *passphrase);
|
||||||
Gets an RSA private key from data into a new RSA context.
|
Gets an RSA private key from data into a new RSA context.
|
||||||
Must call _libssh2_init_if_needed().
|
Must call _libssh2_init_if_needed().
|
||||||
@@ -529,15 +606,15 @@ int _libssh2_rsa_sha1_verify(libssh2_rsa_ctx *rsa,
|
|||||||
const unsigned char *sig,
|
const unsigned char *sig,
|
||||||
unsigned long sig_len,
|
unsigned long sig_len,
|
||||||
const unsigned char *m, unsigned long m_len);
|
const unsigned char *m, unsigned long m_len);
|
||||||
Verify (sig, siglen) signature of (m, m_len) using an SHA-1 hash and the
|
Verify (sig, sig_len) signature of (m, m_len) using an SHA-1 hash and the
|
||||||
RSA context.
|
RSA context.
|
||||||
Return 0 if OK, else -1.
|
Return 0 if OK, else -1.
|
||||||
This procedure is already prototyped in crypto.h.
|
This procedure is already prototyped in crypto.h.
|
||||||
|
|
||||||
int _libssh2_rsa_sha1_signv(LIBSSH2_SESSION *session,
|
int _libssh2_rsa_sha1_signv(LIBSSH2_SESSION *session,
|
||||||
unsigned char **sig, size_t *siglen,
|
unsigned char **sig, size_t *siglen,
|
||||||
int count, const struct iovec vector[],
|
int count, const struct iovec vector[],
|
||||||
libssh2_rsa_ctx *ctx);
|
libssh2_rsa_ctx *ctx);
|
||||||
RSA signs the SHA-1 hash computed over the count data chunks in vector.
|
RSA signs the SHA-1 hash computed over the count data chunks in vector.
|
||||||
Signature is stored at (sig, siglen).
|
Signature is stored at (sig, siglen).
|
||||||
Signature buffer must be allocated from the given session.
|
Signature buffer must be allocated from the given session.
|
||||||
@@ -581,11 +658,11 @@ int _libssh2_dsa_new(libssh2_dsa_ctx **dsa,
|
|||||||
unsigned long ylen,
|
unsigned long ylen,
|
||||||
const unsigned char *x, unsigned long x_len);
|
const unsigned char *x, unsigned long x_len);
|
||||||
Creates a new context for DSA computations from source key values:
|
Creates a new context for DSA computations from source key values:
|
||||||
pdata, plen Prime number p. Only used if private key known (ddata).
|
pdata, plen Prime number p. Only used if private key known (ddata).
|
||||||
qdata, qlen Prime number q. Only used if private key known (ddata).
|
qdata, qlen Prime number q. Only used if private key known (ddata).
|
||||||
gdata, glen G number.
|
gdata, glen G number.
|
||||||
ydata, ylen Public key.
|
ydata, ylen Public key.
|
||||||
xdata, xlen Private key. Only taken if xlen non-zero.
|
xdata, xlen Private key. Only taken if xlen non-zero.
|
||||||
Returns 0 if OK.
|
Returns 0 if OK.
|
||||||
This procedure is already prototyped in crypto.h.
|
This procedure is already prototyped in crypto.h.
|
||||||
|
|
||||||
@@ -601,7 +678,7 @@ This procedure is already prototyped in crypto.h.
|
|||||||
int _libssh2_dsa_new_private_frommemory(libssh2_dsa_ctx **dsa,
|
int _libssh2_dsa_new_private_frommemory(libssh2_dsa_ctx **dsa,
|
||||||
LIBSSH2_SESSION *session,
|
LIBSSH2_SESSION *session,
|
||||||
const char *data,
|
const char *data,
|
||||||
size_t data_len,
|
size_t data_len,
|
||||||
unsigned const char *passphrase);
|
unsigned const char *passphrase);
|
||||||
Gets a DSA private key from the data_len-bytes data into a new DSA context.
|
Gets a DSA private key from the data_len-bytes data into a new DSA context.
|
||||||
Must call _libssh2_init_if_needed().
|
Must call _libssh2_init_if_needed().
|
||||||
@@ -627,6 +704,191 @@ void _libssh2_dsa_free(libssh2_dsa_ctx *dsactx);
|
|||||||
Releases the DSA computation context at dsactx.
|
Releases the DSA computation context at dsactx.
|
||||||
|
|
||||||
|
|
||||||
|
7.3) ECDSA
|
||||||
|
LIBSSH2_ECDSA
|
||||||
|
#define as 1 if the crypto library supports ECDSA, else 0.
|
||||||
|
If defined as 0, _libssh2_ec_key should be defined as void and the rest of
|
||||||
|
this section can be omitted.
|
||||||
|
|
||||||
|
EC_MAX_POINT_LEN
|
||||||
|
Maximum point length. Usually defined as ((528 * 2 / 8) + 1) (= 133).
|
||||||
|
|
||||||
|
libssh2_ecdsa_ctx
|
||||||
|
Type of an ECDSA computation context. Generally a struct.
|
||||||
|
|
||||||
|
_libssh2_ec_key
|
||||||
|
Type of an elliptic curve key.
|
||||||
|
|
||||||
|
libssh2_curve_type
|
||||||
|
An enum type defining curve types. Current supported identifiers are:
|
||||||
|
LIBSSH2_EC_CURVE_NISTP256
|
||||||
|
LIBSSH2_EC_CURVE_NISTP384
|
||||||
|
LIBSSH2_EC_CURVE_NISTP521
|
||||||
|
|
||||||
|
int _libssh2_ecdsa_create_key(_libssh2_ec_key **out_private_key,
|
||||||
|
unsigned char **out_public_key_octal,
|
||||||
|
size_t *out_public_key_octal_len,
|
||||||
|
libssh2_curve_type curve_type);
|
||||||
|
Create a new ECDSA private key of type curve_type and return it at
|
||||||
|
out_private_key. If out_public_key_octal is not NULL, store an allocated
|
||||||
|
pointer to the associated public key in "octal" form in it and its length
|
||||||
|
at out_public_key_octal_len.
|
||||||
|
Return 0 if OK, else -1.
|
||||||
|
This procedure is already prototyped in crypto.h.
|
||||||
|
|
||||||
|
int _libssh2_ecdsa_new_private(libssh2_ecdsa_ctx **ec_ctx,
|
||||||
|
LIBSSH2_SESSION * session,
|
||||||
|
const char *filename,
|
||||||
|
unsigned const char *passphrase);
|
||||||
|
Reads an ECDSA private key from PEM file filename into a new ECDSA context.
|
||||||
|
Must call _libssh2_init_if_needed().
|
||||||
|
Return 0 if OK, else -1.
|
||||||
|
This procedure is already prototyped in crypto.h.
|
||||||
|
|
||||||
|
int _libssh2_ecdsa_new_private_frommemory(libssh2_ecdsa_ctx ** ec_ctx,
|
||||||
|
LIBSSH2_SESSION * session,
|
||||||
|
const char *filedata,
|
||||||
|
size_t filedata_len,
|
||||||
|
unsigned const char *passphrase);
|
||||||
|
Builds an ECDSA private key from PEM data at filedata of length filedata_len
|
||||||
|
into a new ECDSA context stored at ec_ctx.
|
||||||
|
Must call _libssh2_init_if_needed().
|
||||||
|
Return 0 if OK, else -1.
|
||||||
|
This procedure is already prototyped in crypto.h.
|
||||||
|
|
||||||
|
int _libssh2_ecdsa_curve_name_with_octal_new(libssh2_ecdsa_ctx **ecdsactx,
|
||||||
|
const unsigned char *k,
|
||||||
|
size_t k_len,
|
||||||
|
libssh2_curve_type type);
|
||||||
|
Stores at ecdsactx a new ECDSA context associated with the given curve type
|
||||||
|
and with "octal" form public key (k, k_len).
|
||||||
|
Return 0 if OK, else -1.
|
||||||
|
This procedure is already prototyped in crypto.h.
|
||||||
|
|
||||||
|
int _libssh2_ecdsa_new_openssh_private(libssh2_ecdsa_ctx **ec_ctx,
|
||||||
|
LIBSSH2_SESSION * session,
|
||||||
|
const char *filename,
|
||||||
|
unsigned const char *passphrase);
|
||||||
|
Reads a PEM-encoded ECDSA private key from file filename encrypted with
|
||||||
|
passphrase and stores at ec_ctx a new ECDSA context for it.
|
||||||
|
Return 0 if OK, else -1.
|
||||||
|
Currently used only from openssl backend (ought to be private).
|
||||||
|
This procedure is already prototyped in crypto.h.
|
||||||
|
|
||||||
|
int _libssh2_ecdsa_sign(LIBSSH2_SESSION *session, libssh2_ecdsa_ctx *ec_ctx,
|
||||||
|
const unsigned char *hash, unsigned long hash_len,
|
||||||
|
unsigned char **signature, size_t *signature_len);
|
||||||
|
ECDSA signs the (hash, hashlen) hash bytes and stores the allocated
|
||||||
|
signature at (signature, signature_len). Hash algorithm used should be
|
||||||
|
SHA-256, SHA-384 or SHA-512 depending on type stored in ECDSA context at ec_ctx.
|
||||||
|
Signature buffer must be allocated from the given session.
|
||||||
|
Returns 0 if OK, else -1.
|
||||||
|
This procedure is already prototyped in crypto.h.
|
||||||
|
|
||||||
|
int _libssh2_ecdsa_verify(libssh2_ecdsa_ctx *ctx,
|
||||||
|
const unsigned char *r, size_t r_len,
|
||||||
|
const unsigned char *s, size_t s_len,
|
||||||
|
const unsigned char *m, size_t m_len);
|
||||||
|
Verify the ECDSA signature made of (r, r_len) and (s, s_len) of (m, m_len)
|
||||||
|
using the hash algorithm configured in the ECDSA context ctx.
|
||||||
|
Return 0 if OK, else -1.
|
||||||
|
This procedure is already prototyped in crypto.h.
|
||||||
|
|
||||||
|
libssh2_curve_type _libssh2_ecdsa_get_curve_type(libssh2_ecdsa_ctx *ecdsactx);
|
||||||
|
Returns the curve type associated with given context.
|
||||||
|
This procedure is already prototyped in crypto.h.
|
||||||
|
|
||||||
|
int _libssh2_ecdsa_curve_type_from_name(const char *name,
|
||||||
|
libssh2_curve_type *out_type);
|
||||||
|
Stores in out_type the curve type matching string name of the form
|
||||||
|
"ecdsa-sha2-nistpxxx".
|
||||||
|
Return 0 if OK, else -1.
|
||||||
|
Currently used only from openssl backend (ought to be private).
|
||||||
|
This procedure is already prototyped in crypto.h.
|
||||||
|
|
||||||
|
void _libssh2_ecdsa_free(libssh2_ecdsa_ctx *ecdsactx);
|
||||||
|
Releases the ECDSA computation context at ecdsactx.
|
||||||
|
|
||||||
|
|
||||||
|
7.4) ED25519
|
||||||
|
LIBSSH2_ED25519
|
||||||
|
#define as 1 if the crypto library supports ED25519, else 0.
|
||||||
|
If defined as 0, the rest of this section can be omitted.
|
||||||
|
|
||||||
|
|
||||||
|
libssh2_ed25519_ctx
|
||||||
|
Type of an ED25519 computation context. Generally a struct.
|
||||||
|
|
||||||
|
int _libssh2_curve25519_new(LIBSSH2_SESSION *session, libssh2_ed25519_ctx **ctx,
|
||||||
|
uint8_t **out_public_key,
|
||||||
|
uint8_t **out_private_key);
|
||||||
|
Generates an ED25519 key pair, stores a pointer to them at out_private_key
|
||||||
|
and out_public_key respectively and stores at ctx a new ED25519 context for
|
||||||
|
this key.
|
||||||
|
Argument ctx, out_private_key and out_public key may be NULL to disable storing
|
||||||
|
the corresponding value.
|
||||||
|
Length of each key is LIBSSH2_ED25519_KEY_LEN (32 bytes).
|
||||||
|
Key buffers are allocated and should be released by caller after use.
|
||||||
|
Returns 0 if OK, else -1.
|
||||||
|
This procedure is already prototyped in crypto.h.
|
||||||
|
|
||||||
|
int _libssh2_ed25519_new_private(libssh2_ed25519_ctx **ed_ctx,
|
||||||
|
LIBSSH2_SESSION *session,
|
||||||
|
const char *filename,
|
||||||
|
const uint8_t *passphrase);
|
||||||
|
Reads an ED25519 private key from PEM file filename into a new ED25519 context.
|
||||||
|
Must call _libssh2_init_if_needed().
|
||||||
|
Return 0 if OK, else -1.
|
||||||
|
This procedure is already prototyped in crypto.h.
|
||||||
|
|
||||||
|
int _libssh2_ed25519_new_public(libssh2_ed25519_ctx **ed_ctx,
|
||||||
|
LIBSSH2_SESSION *session,
|
||||||
|
const unsigned char *raw_pub_key,
|
||||||
|
const uint8_t key_len);
|
||||||
|
Stores at ed_ctx a new ED25519 key context for raw public key (raw_pub_key,
|
||||||
|
key_len).
|
||||||
|
Return 0 if OK, else -1.
|
||||||
|
This procedure is already prototyped in crypto.h.
|
||||||
|
|
||||||
|
int _libssh2_ed25519_new_private_frommemory(libssh2_ed25519_ctx **ed_ctx,
|
||||||
|
LIBSSH2_SESSION *session,
|
||||||
|
const char *filedata,
|
||||||
|
size_t filedata_len,
|
||||||
|
unsigned const char *passphrase);
|
||||||
|
Builds an ED25519 private key from PEM data at filedata of length filedata_len
|
||||||
|
into a new ED25519 context stored at ed_ctx.
|
||||||
|
Must call _libssh2_init_if_needed().
|
||||||
|
Return 0 if OK, else -1.
|
||||||
|
This procedure is already prototyped in crypto.h.
|
||||||
|
|
||||||
|
int _libssh2_ed25519_sign(libssh2_ed25519_ctx *ctx, LIBSSH2_SESSION *session,
|
||||||
|
uint8_t **out_sig, size_t *out_sig_len,
|
||||||
|
const uint8_t *message, size_t message_len);
|
||||||
|
ED25519 signs the (message, message_len) bytes and stores the allocated
|
||||||
|
signature at (sig, sig_len).
|
||||||
|
Signature buffer is allocated from the given session.
|
||||||
|
Returns 0 if OK, else -1.
|
||||||
|
This procedure is already prototyped in crypto.h.
|
||||||
|
|
||||||
|
int _libssh2_ed25519_verify(libssh2_ed25519_ctx *ctx, const uint8_t *s,
|
||||||
|
size_t s_len, const uint8_t *m, size_t m_len);
|
||||||
|
Verify (s, s_len) signature of (m, m_len) using the given ED25519 context.
|
||||||
|
Return 0 if OK, else -1.
|
||||||
|
This procedure is already prototyped in crypto.h.
|
||||||
|
|
||||||
|
int _libssh2_curve25519_gen_k(_libssh2_bn **k,
|
||||||
|
uint8_t private_key[LIBSSH2_ED25519_KEY_LEN],
|
||||||
|
uint8_t srvr_public_key[LIBSSH2_ED25519_KEY_LEN]);
|
||||||
|
Computes a shared ED25519 secret key from the given raw server public key and
|
||||||
|
raw client public key and stores it as a big number in *k. Big number should
|
||||||
|
have been initialized before calling this function.
|
||||||
|
Returns 0 if OK, else -1.
|
||||||
|
This procedure is already prototyped in crypto.h.
|
||||||
|
|
||||||
|
void _libssh2_ed25519_free(libssh2_ed25519_ctx *ed25519ctx);
|
||||||
|
Releases the ED25519 computation context at ed25519ctx.
|
||||||
|
|
||||||
|
|
||||||
8) Miscellaneous
|
8) Miscellaneous
|
||||||
|
|
||||||
void libssh2_prepare_iovec(struct iovec *vector, unsigned int len);
|
void libssh2_prepare_iovec(struct iovec *vector, unsigned int len);
|
||||||
@@ -635,5 +897,6 @@ In example, this is needed to preset unused structure slacks on platforms
|
|||||||
requiring it.
|
requiring it.
|
||||||
If this is not needed, it should be defined as an empty macro.
|
If this is not needed, it should be defined as an empty macro.
|
||||||
|
|
||||||
void _libssh2_random(unsigned char *buf, int len);
|
int _libssh2_random(unsigned char *buf, int len);
|
||||||
Store len random bytes at buf.
|
Store len random bytes at buf.
|
||||||
|
Returns 0 if OK, else -1.
|
@@ -20,10 +20,12 @@ Getting started
|
|||||||
If you are happy with the default options, make a new build directory,
|
If you are happy with the default options, make a new build directory,
|
||||||
change to it, configure the build environment and build the project:
|
change to it, configure the build environment and build the project:
|
||||||
|
|
||||||
|
```
|
||||||
mkdir bin
|
mkdir bin
|
||||||
cd bin
|
cd bin
|
||||||
cmake ..
|
cmake ..
|
||||||
cmake --build .
|
cmake --build .
|
||||||
|
```
|
||||||
|
|
||||||
libssh2 will be built as a static library and will use any
|
libssh2 will be built as a static library and will use any
|
||||||
cryptography library available. The library binary will be put in
|
cryptography library available. The library binary will be put in
|
||||||
@@ -40,6 +42,11 @@ pass the options to CMake on the command line:
|
|||||||
|
|
||||||
The following options are available:
|
The following options are available:
|
||||||
|
|
||||||
|
* `LINT=ON`
|
||||||
|
|
||||||
|
Enables running the source code linter when building. Can be `ON` or `OFF`.
|
||||||
|
|
||||||
|
|
||||||
* `BUILD_SHARED_LIBS=OFF`
|
* `BUILD_SHARED_LIBS=OFF`
|
||||||
|
|
||||||
Determines whether libssh2 is built as a static library or as a
|
Determines whether libssh2 is built as a static library or as a
|
||||||
@@ -119,20 +126,27 @@ Tests
|
|||||||
To test the build, run the appropriate test target for your build
|
To test the build, run the appropriate test target for your build
|
||||||
system. For example:
|
system. For example:
|
||||||
|
|
||||||
|
```
|
||||||
cmake --build . --target test
|
cmake --build . --target test
|
||||||
|
```
|
||||||
or
|
or
|
||||||
|
```
|
||||||
cmake --build . --target RUN_TESTS
|
cmake --build . --target RUN_TESTS
|
||||||
|
```
|
||||||
|
|
||||||
How do I use libssh2 in my project if my project doesn't use CMake?
|
How do I use libssh2 in my project if my project doesn't use CMake?
|
||||||
-------------------------------------------------------------------
|
-------------------------------------------------------------------
|
||||||
|
|
||||||
If you are not using CMake for your own project, install libssh2
|
If you are not using CMake for your own project, install libssh2
|
||||||
|
```
|
||||||
cmake <libssh2 source location>
|
cmake <libssh2 source location>
|
||||||
cmake --build .
|
cmake --build .
|
||||||
cmake --build . --target install
|
cmake --build . --target install
|
||||||
|
```
|
||||||
or
|
or
|
||||||
|
```
|
||||||
cmake --build . --target INSTALL
|
cmake --build . --target INSTALL
|
||||||
|
```
|
||||||
|
|
||||||
and then specify the install location to your project in the normal
|
and then specify the install location to your project in the normal
|
||||||
way for your build environment. If you don't like the default install
|
way for your build environment. If you don't like the default install
|
@@ -1,7 +1,7 @@
|
|||||||
# $Id: Makefile.am,v 1.37 2009/03/26 15:41:15 bagder Exp $
|
# $Id: Makefile.am,v 1.37 2009/03/26 15:41:15 bagder Exp $
|
||||||
|
|
||||||
EXTRA_DIST = template.3 BINDINGS INSTALL_AUTOTOOLS INSTALL_CMAKE HACKING TODO \
|
EXTRA_DIST = template.3 BINDINGS INSTALL_AUTOTOOLS INSTALL_CMAKE.md HACKING TODO \
|
||||||
AUTHORS CMakeLists.txt HACKING.CRYPTO SECURITY.md
|
AUTHORS CMakeLists.txt HACKING-CRYPTO SECURITY.md
|
||||||
|
|
||||||
dist_man_MANS = \
|
dist_man_MANS = \
|
||||||
libssh2_agent_connect.3 \
|
libssh2_agent_connect.3 \
|
||||||
|
@@ -32,11 +32,43 @@ function returns 0, the packet will be accepted nonetheless.
|
|||||||
.IP LIBSSH2_CALLBACK_X11
|
.IP LIBSSH2_CALLBACK_X11
|
||||||
Called when an X11 connection has been accepted
|
Called when an X11 connection has been accepted
|
||||||
.IP LIBSSH2_CALLBACK_SEND
|
.IP LIBSSH2_CALLBACK_SEND
|
||||||
Called when libssh2 wants to send some data on the connection.
|
Called when libssh2 wants to send data on the connection. Can be set to a
|
||||||
Can be set to a custom function to handle I/O your own way.
|
custom function to handle I/O your own way.
|
||||||
|
|
||||||
|
The prototype of the callback:
|
||||||
|
|
||||||
|
.nf
|
||||||
|
ssize_t sendcb(libssh2_socket_t sockfd, const void *buffer,
|
||||||
|
size_t length, int flags, void **abstract);
|
||||||
|
.fi
|
||||||
|
|
||||||
|
\fBsockfd\fP is the socket to write to, \fBbuffer\fP points to the data to
|
||||||
|
send, \fBlength\fP is the size of the data, \fBflags\fP is the flags that
|
||||||
|
would've been used to a \fIsend()\fP call and \fBabstract\fP is a pointer to
|
||||||
|
the abstract pointer set in the \fIlibssh2_session_init_ex(3)\fP call.
|
||||||
|
|
||||||
|
The callback returns the number of bytes sent, or -1 for error. The special
|
||||||
|
return code \fB-EAGAIN\fP can be returned to signal that the send was aborted
|
||||||
|
to prevent getting blocked and it needs to be called again.
|
||||||
.IP LIBSSH2_CALLBACK_RECV
|
.IP LIBSSH2_CALLBACK_RECV
|
||||||
Called when libssh2 wants to receive some data from the connection.
|
Called when libssh2 wants to read data from the connection. Can be set to a
|
||||||
Can be set to a custom function to handle I/O your own way.
|
custom function to handle I/O your own way.
|
||||||
|
|
||||||
|
The prototype of the callback:
|
||||||
|
|
||||||
|
.nf
|
||||||
|
ssize_t recvcb(libssh2_socket_t sockfd, void *buffer,
|
||||||
|
size_t length, int flags, void **abstract);
|
||||||
|
.fi
|
||||||
|
|
||||||
|
\fBsockfd\fP is the socket to read from, \fBbuffer\fP where to store received
|
||||||
|
data into, \fBlength\fP is the size of the buffer, \fBflags\fP is the flags
|
||||||
|
that would've been used to a \fIrecv()\fP call and \fBabstract\fP is a pointer
|
||||||
|
to the abstract pointer set in the \fIlibssh2_session_init_ex(3)\fP call.
|
||||||
|
|
||||||
|
The callback returns the number of bytes read, or -1 for error. The special
|
||||||
|
return code \fB-EAGAIN\fP can be returned to signal that the read was aborted
|
||||||
|
to prevent getting blocked and it needs to be called again.
|
||||||
.SH RETURN VALUE
|
.SH RETURN VALUE
|
||||||
Pointer to previous callback handler. Returns NULL if no prior callback
|
Pointer to previous callback handler. Returns NULL if no prior callback
|
||||||
handler was set or the callback type was unknown.
|
handler was set or the callback type was unknown.
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/* Copyright (c) 2004-2009, Sara Golemon <sarag@libssh2.org>
|
/* Copyright (c) 2004-2009, Sara Golemon <sarag@libssh2.org>
|
||||||
* Copyright (c) 2009-2015 Daniel Stenberg
|
* Copyright (c) 2009-2021 Daniel Stenberg
|
||||||
* Copyright (c) 2010 Simon Josefsson <simon@josefsson.org>
|
* Copyright (c) 2010 Simon Josefsson <simon@josefsson.org>
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
@@ -40,19 +40,19 @@
|
|||||||
#ifndef LIBSSH2_H
|
#ifndef LIBSSH2_H
|
||||||
#define LIBSSH2_H 1
|
#define LIBSSH2_H 1
|
||||||
|
|
||||||
#define LIBSSH2_COPYRIGHT "2004-2019 The libssh2 project and its contributors."
|
#define LIBSSH2_COPYRIGHT "2004-2021 The libssh2 project and its contributors."
|
||||||
|
|
||||||
/* We use underscore instead of dash when appending DEV in dev versions just
|
/* We use underscore instead of dash when appending DEV in dev versions just
|
||||||
to make the BANNER define (used by src/session.c) be a valid SSH
|
to make the BANNER define (used by src/session.c) be a valid SSH
|
||||||
banner. Release versions have no appended strings and may of course not
|
banner. Release versions have no appended strings and may of course not
|
||||||
have dashes either. */
|
have dashes either. */
|
||||||
#define LIBSSH2_VERSION "1.9.0_DEV"
|
#define LIBSSH2_VERSION "1.10.1_DEV"
|
||||||
|
|
||||||
/* The numeric version number is also available "in parts" by using these
|
/* The numeric version number is also available "in parts" by using these
|
||||||
defines: */
|
defines: */
|
||||||
#define LIBSSH2_VERSION_MAJOR 1
|
#define LIBSSH2_VERSION_MAJOR 1
|
||||||
#define LIBSSH2_VERSION_MINOR 9
|
#define LIBSSH2_VERSION_MINOR 10
|
||||||
#define LIBSSH2_VERSION_PATCH 0
|
#define LIBSSH2_VERSION_PATCH 1
|
||||||
|
|
||||||
/* This is the numeric version of the libssh2 version number, meant for easier
|
/* This is the numeric version of the libssh2 version number, meant for easier
|
||||||
parsing and comparions by programs. The LIBSSH2_VERSION_NUM define will
|
parsing and comparions by programs. The LIBSSH2_VERSION_NUM define will
|
||||||
@@ -69,7 +69,7 @@
|
|||||||
and it is always a greater number in a more recent release. It makes
|
and it is always a greater number in a more recent release. It makes
|
||||||
comparisons with greater than and less than work.
|
comparisons with greater than and less than work.
|
||||||
*/
|
*/
|
||||||
#define LIBSSH2_VERSION_NUM 0x010900
|
#define LIBSSH2_VERSION_NUM 0x010a01
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This is the date and time when the full source package was created. The
|
* This is the date and time when the full source package was created. The
|
||||||
@@ -235,9 +235,11 @@ typedef off_t libssh2_struct_stat_size;
|
|||||||
|
|
||||||
/* Default generate and safe prime sizes for
|
/* Default generate and safe prime sizes for
|
||||||
diffie-hellman-group-exchange-sha1 */
|
diffie-hellman-group-exchange-sha1 */
|
||||||
#define LIBSSH2_DH_GEX_MINGROUP 1024
|
#define LIBSSH2_DH_GEX_MINGROUP 2048
|
||||||
#define LIBSSH2_DH_GEX_OPTGROUP 1536
|
#define LIBSSH2_DH_GEX_OPTGROUP 4096
|
||||||
#define LIBSSH2_DH_GEX_MAXGROUP 2048
|
#define LIBSSH2_DH_GEX_MAXGROUP 8192
|
||||||
|
|
||||||
|
#define LIBSSH2_DH_MAX_MODULUS_BITS 16384
|
||||||
|
|
||||||
/* Defaults for pty requests */
|
/* Defaults for pty requests */
|
||||||
#define LIBSSH2_TERM_WIDTH 80
|
#define LIBSSH2_TERM_WIDTH 80
|
||||||
@@ -503,7 +505,8 @@ typedef struct _LIBSSH2_POLLFD {
|
|||||||
#define LIBSSH2_ERROR_KNOWN_HOSTS -46
|
#define LIBSSH2_ERROR_KNOWN_HOSTS -46
|
||||||
#define LIBSSH2_ERROR_CHANNEL_WINDOW_FULL -47
|
#define LIBSSH2_ERROR_CHANNEL_WINDOW_FULL -47
|
||||||
#define LIBSSH2_ERROR_KEYFILE_AUTH_FAILED -48
|
#define LIBSSH2_ERROR_KEYFILE_AUTH_FAILED -48
|
||||||
#define LIBSSH2_ERROR_MISSING_AUTH_BANNER -49
|
#define LIBSSH2_ERROR_RANDGEN -49
|
||||||
|
#define LIBSSH2_ERROR_MISSING_AUTH_BANNER -50
|
||||||
|
|
||||||
/* this is a define to provide the old (<= 1.2.7) name */
|
/* this is a define to provide the old (<= 1.2.7) name */
|
||||||
#define LIBSSH2_ERROR_BANNER_NONE LIBSSH2_ERROR_BANNER_RECV
|
#define LIBSSH2_ERROR_BANNER_NONE LIBSSH2_ERROR_BANNER_RECV
|
||||||
|
@@ -189,30 +189,30 @@ struct _LIBSSH2_SFTP_STATVFS {
|
|||||||
#define LIBSSH2_FXF_EXCL 0x00000020
|
#define LIBSSH2_FXF_EXCL 0x00000020
|
||||||
|
|
||||||
/* SFTP Status Codes (returned by libssh2_sftp_last_error() ) */
|
/* SFTP Status Codes (returned by libssh2_sftp_last_error() ) */
|
||||||
#define LIBSSH2_FX_OK 0
|
#define LIBSSH2_FX_OK 0UL
|
||||||
#define LIBSSH2_FX_EOF 1
|
#define LIBSSH2_FX_EOF 1UL
|
||||||
#define LIBSSH2_FX_NO_SUCH_FILE 2
|
#define LIBSSH2_FX_NO_SUCH_FILE 2UL
|
||||||
#define LIBSSH2_FX_PERMISSION_DENIED 3
|
#define LIBSSH2_FX_PERMISSION_DENIED 3UL
|
||||||
#define LIBSSH2_FX_FAILURE 4
|
#define LIBSSH2_FX_FAILURE 4UL
|
||||||
#define LIBSSH2_FX_BAD_MESSAGE 5
|
#define LIBSSH2_FX_BAD_MESSAGE 5UL
|
||||||
#define LIBSSH2_FX_NO_CONNECTION 6
|
#define LIBSSH2_FX_NO_CONNECTION 6UL
|
||||||
#define LIBSSH2_FX_CONNECTION_LOST 7
|
#define LIBSSH2_FX_CONNECTION_LOST 7UL
|
||||||
#define LIBSSH2_FX_OP_UNSUPPORTED 8
|
#define LIBSSH2_FX_OP_UNSUPPORTED 8UL
|
||||||
#define LIBSSH2_FX_INVALID_HANDLE 9
|
#define LIBSSH2_FX_INVALID_HANDLE 9UL
|
||||||
#define LIBSSH2_FX_NO_SUCH_PATH 10
|
#define LIBSSH2_FX_NO_SUCH_PATH 10UL
|
||||||
#define LIBSSH2_FX_FILE_ALREADY_EXISTS 11
|
#define LIBSSH2_FX_FILE_ALREADY_EXISTS 11UL
|
||||||
#define LIBSSH2_FX_WRITE_PROTECT 12
|
#define LIBSSH2_FX_WRITE_PROTECT 12UL
|
||||||
#define LIBSSH2_FX_NO_MEDIA 13
|
#define LIBSSH2_FX_NO_MEDIA 13UL
|
||||||
#define LIBSSH2_FX_NO_SPACE_ON_FILESYSTEM 14
|
#define LIBSSH2_FX_NO_SPACE_ON_FILESYSTEM 14UL
|
||||||
#define LIBSSH2_FX_QUOTA_EXCEEDED 15
|
#define LIBSSH2_FX_QUOTA_EXCEEDED 15UL
|
||||||
#define LIBSSH2_FX_UNKNOWN_PRINCIPLE 16 /* Initial mis-spelling */
|
#define LIBSSH2_FX_UNKNOWN_PRINCIPLE 16UL /* Initial mis-spelling */
|
||||||
#define LIBSSH2_FX_UNKNOWN_PRINCIPAL 16
|
#define LIBSSH2_FX_UNKNOWN_PRINCIPAL 16UL
|
||||||
#define LIBSSH2_FX_LOCK_CONFlICT 17 /* Initial mis-spelling */
|
#define LIBSSH2_FX_LOCK_CONFlICT 17UL /* Initial mis-spelling */
|
||||||
#define LIBSSH2_FX_LOCK_CONFLICT 17
|
#define LIBSSH2_FX_LOCK_CONFLICT 17UL
|
||||||
#define LIBSSH2_FX_DIR_NOT_EMPTY 18
|
#define LIBSSH2_FX_DIR_NOT_EMPTY 18UL
|
||||||
#define LIBSSH2_FX_NOT_A_DIRECTORY 19
|
#define LIBSSH2_FX_NOT_A_DIRECTORY 19UL
|
||||||
#define LIBSSH2_FX_INVALID_FILENAME 20
|
#define LIBSSH2_FX_INVALID_FILENAME 20UL
|
||||||
#define LIBSSH2_FX_LINK_LOOP 21
|
#define LIBSSH2_FX_LINK_LOOP 21UL
|
||||||
|
|
||||||
/* Returned by any function that would block during a read/write operation */
|
/* Returned by any function that would block during a read/write operation */
|
||||||
#define LIBSSH2SFTP_EAGAIN LIBSSH2_ERROR_EAGAIN
|
#define LIBSSH2SFTP_EAGAIN LIBSSH2_ERROR_EAGAIN
|
||||||
|
@@ -230,7 +230,7 @@
|
|||||||
#define PACKAGE "libssh2"
|
#define PACKAGE "libssh2"
|
||||||
|
|
||||||
/* Define to the address where bug reports for this package should be sent. */
|
/* Define to the address where bug reports for this package should be sent. */
|
||||||
#define PACKAGE_BUGREPORT "libssh2-devel@cool.haxx.se"
|
#define PACKAGE_BUGREPORT "libssh2-devel@lists.haxx.se"
|
||||||
|
|
||||||
/* Define to the full name of this package. */
|
/* Define to the full name of this package. */
|
||||||
#define PACKAGE_NAME "libssh2"
|
#define PACKAGE_NAME "libssh2"
|
||||||
|
@@ -176,6 +176,7 @@ include(GNUInstallDirs)
|
|||||||
set(SOURCES
|
set(SOURCES
|
||||||
${CRYPTO_SOURCES}
|
${CRYPTO_SOURCES}
|
||||||
agent.c
|
agent.c
|
||||||
|
agent_win.c
|
||||||
blf.h
|
blf.h
|
||||||
bcrypt_pbkdf.c
|
bcrypt_pbkdf.c
|
||||||
blowfish.c
|
blowfish.c
|
||||||
@@ -397,7 +398,7 @@ set(RUNTIME_DEPENDENCIES ${_RUNTIME_DEPENDENCIES} CACHE INTERNAL
|
|||||||
## During package installation, install Libssh2Config.cmake
|
## During package installation, install Libssh2Config.cmake
|
||||||
install(EXPORT Libssh2Config
|
install(EXPORT Libssh2Config
|
||||||
NAMESPACE Libssh2::
|
NAMESPACE Libssh2::
|
||||||
DESTINATION lib/cmake/libssh2)
|
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/libssh2)
|
||||||
|
|
||||||
## During build, register directly from build tree
|
## During build, register directly from build tree
|
||||||
# create Libssh2Config.cmake
|
# create Libssh2Config.cmake
|
||||||
@@ -429,4 +430,4 @@ write_basic_package_version_file(
|
|||||||
COMPATIBILITY SameMajorVersion)
|
COMPATIBILITY SameMajorVersion)
|
||||||
install(
|
install(
|
||||||
FILES ${CMAKE_CURRENT_BINARY_DIR}/Libssh2ConfigVersion.cmake
|
FILES ${CMAKE_CURRENT_BINARY_DIR}/Libssh2ConfigVersion.cmake
|
||||||
DESTINATION lib/cmake/libssh2)
|
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/libssh2)
|
||||||
|
119
src/agent.c
119
src/agent.c
@@ -38,6 +38,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "libssh2_priv.h"
|
#include "libssh2_priv.h"
|
||||||
|
#include "agent.h"
|
||||||
#include "misc.h"
|
#include "misc.h"
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#ifdef HAVE_SYS_UN_H
|
#ifdef HAVE_SYS_UN_H
|
||||||
@@ -50,6 +51,9 @@
|
|||||||
#endif
|
#endif
|
||||||
#include "userauth.h"
|
#include "userauth.h"
|
||||||
#include "session.h"
|
#include "session.h"
|
||||||
|
#ifdef WIN32
|
||||||
|
#include <stdlib.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Requests from client to agent for protocol 1 key operations */
|
/* Requests from client to agent for protocol 1 key operations */
|
||||||
#define SSH_AGENTC_REQUEST_RSA_IDENTITIES 1
|
#define SSH_AGENTC_REQUEST_RSA_IDENTITIES 1
|
||||||
@@ -90,58 +94,6 @@
|
|||||||
#define SSH_AGENT_CONSTRAIN_LIFETIME 1
|
#define SSH_AGENT_CONSTRAIN_LIFETIME 1
|
||||||
#define SSH_AGENT_CONSTRAIN_CONFIRM 2
|
#define SSH_AGENT_CONSTRAIN_CONFIRM 2
|
||||||
|
|
||||||
/* non-blocking mode on agent connection is not yet implemented, but
|
|
||||||
for future use. */
|
|
||||||
typedef enum {
|
|
||||||
agent_NB_state_init = 0,
|
|
||||||
agent_NB_state_request_created,
|
|
||||||
agent_NB_state_request_length_sent,
|
|
||||||
agent_NB_state_request_sent,
|
|
||||||
agent_NB_state_response_length_received,
|
|
||||||
agent_NB_state_response_received
|
|
||||||
} agent_nonblocking_states;
|
|
||||||
|
|
||||||
typedef struct agent_transaction_ctx {
|
|
||||||
unsigned char *request;
|
|
||||||
size_t request_len;
|
|
||||||
unsigned char *response;
|
|
||||||
size_t response_len;
|
|
||||||
agent_nonblocking_states state;
|
|
||||||
} *agent_transaction_ctx_t;
|
|
||||||
|
|
||||||
typedef int (*agent_connect_func)(LIBSSH2_AGENT *agent);
|
|
||||||
typedef int (*agent_transact_func)(LIBSSH2_AGENT *agent,
|
|
||||||
agent_transaction_ctx_t transctx);
|
|
||||||
typedef int (*agent_disconnect_func)(LIBSSH2_AGENT *agent);
|
|
||||||
|
|
||||||
struct agent_publickey {
|
|
||||||
struct list_node node;
|
|
||||||
|
|
||||||
/* this is the struct we expose externally */
|
|
||||||
struct libssh2_agent_publickey external;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct agent_ops {
|
|
||||||
agent_connect_func connect;
|
|
||||||
agent_transact_func transact;
|
|
||||||
agent_disconnect_func disconnect;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct _LIBSSH2_AGENT
|
|
||||||
{
|
|
||||||
LIBSSH2_SESSION *session; /* the session this "belongs to" */
|
|
||||||
|
|
||||||
libssh2_socket_t fd;
|
|
||||||
|
|
||||||
struct agent_ops *ops;
|
|
||||||
|
|
||||||
struct agent_transaction_ctx transctx;
|
|
||||||
struct agent_publickey *identity;
|
|
||||||
struct list_head head; /* list of public keys */
|
|
||||||
|
|
||||||
char *identity_agent_path; /* Path to a custom identity agent socket */
|
|
||||||
};
|
|
||||||
|
|
||||||
#ifdef PF_UNIX
|
#ifdef PF_UNIX
|
||||||
static int
|
static int
|
||||||
agent_connect_unix(LIBSSH2_AGENT *agent)
|
agent_connect_unix(LIBSSH2_AGENT *agent)
|
||||||
@@ -175,6 +127,38 @@ agent_connect_unix(LIBSSH2_AGENT *agent)
|
|||||||
return LIBSSH2_ERROR_NONE;
|
return LIBSSH2_ERROR_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define RECV_SEND_ALL(func, socket, buffer, length, flags, abstract) \
|
||||||
|
int rc; \
|
||||||
|
size_t finished = 0; \
|
||||||
|
\
|
||||||
|
while(finished < length) { \
|
||||||
|
rc = func(socket, \
|
||||||
|
(char *)buffer + finished, length - finished, \
|
||||||
|
flags, abstract); \
|
||||||
|
if(rc < 0) \
|
||||||
|
return rc; \
|
||||||
|
\
|
||||||
|
finished += rc; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
return finished;
|
||||||
|
|
||||||
|
static ssize_t _send_all(LIBSSH2_SEND_FUNC(func), libssh2_socket_t socket,
|
||||||
|
const void *buffer, size_t length,
|
||||||
|
int flags, void **abstract)
|
||||||
|
{
|
||||||
|
RECV_SEND_ALL(func, socket, buffer, length, flags, abstract);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t _recv_all(LIBSSH2_RECV_FUNC(func), libssh2_socket_t socket,
|
||||||
|
void *buffer, size_t length,
|
||||||
|
int flags, void **abstract)
|
||||||
|
{
|
||||||
|
RECV_SEND_ALL(func, socket, buffer, length, flags, abstract);
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef RECV_SEND_ALL
|
||||||
|
|
||||||
static int
|
static int
|
||||||
agent_transact_unix(LIBSSH2_AGENT *agent, agent_transaction_ctx_t transctx)
|
agent_transact_unix(LIBSSH2_AGENT *agent, agent_transaction_ctx_t transctx)
|
||||||
{
|
{
|
||||||
@@ -184,7 +168,8 @@ agent_transact_unix(LIBSSH2_AGENT *agent, agent_transaction_ctx_t transctx)
|
|||||||
/* Send the length of the request */
|
/* Send the length of the request */
|
||||||
if(transctx->state == agent_NB_state_request_created) {
|
if(transctx->state == agent_NB_state_request_created) {
|
||||||
_libssh2_htonu32(buf, transctx->request_len);
|
_libssh2_htonu32(buf, transctx->request_len);
|
||||||
rc = LIBSSH2_SEND_FD(agent->session, agent->fd, buf, sizeof buf, 0);
|
rc = _send_all(agent->session->send, agent->fd,
|
||||||
|
buf, sizeof buf, 0, &agent->session->abstract);
|
||||||
if(rc == -EAGAIN)
|
if(rc == -EAGAIN)
|
||||||
return LIBSSH2_ERROR_EAGAIN;
|
return LIBSSH2_ERROR_EAGAIN;
|
||||||
else if(rc < 0)
|
else if(rc < 0)
|
||||||
@@ -195,8 +180,8 @@ agent_transact_unix(LIBSSH2_AGENT *agent, agent_transaction_ctx_t transctx)
|
|||||||
|
|
||||||
/* Send the request body */
|
/* Send the request body */
|
||||||
if(transctx->state == agent_NB_state_request_length_sent) {
|
if(transctx->state == agent_NB_state_request_length_sent) {
|
||||||
rc = LIBSSH2_SEND_FD(agent->session, agent->fd, transctx->request,
|
rc = _send_all(agent->session->send, agent->fd, transctx->request,
|
||||||
transctx->request_len, 0);
|
transctx->request_len, 0, &agent->session->abstract);
|
||||||
if(rc == -EAGAIN)
|
if(rc == -EAGAIN)
|
||||||
return LIBSSH2_ERROR_EAGAIN;
|
return LIBSSH2_ERROR_EAGAIN;
|
||||||
else if(rc < 0)
|
else if(rc < 0)
|
||||||
@@ -207,7 +192,8 @@ agent_transact_unix(LIBSSH2_AGENT *agent, agent_transaction_ctx_t transctx)
|
|||||||
|
|
||||||
/* Receive the length of a response */
|
/* Receive the length of a response */
|
||||||
if(transctx->state == agent_NB_state_request_sent) {
|
if(transctx->state == agent_NB_state_request_sent) {
|
||||||
rc = LIBSSH2_RECV_FD(agent->session, agent->fd, buf, sizeof buf, 0);
|
rc = _recv_all(agent->session->recv, agent->fd,
|
||||||
|
buf, sizeof buf, 0, &agent->session->abstract);
|
||||||
if(rc < 0) {
|
if(rc < 0) {
|
||||||
if(rc == -EAGAIN)
|
if(rc == -EAGAIN)
|
||||||
return LIBSSH2_ERROR_EAGAIN;
|
return LIBSSH2_ERROR_EAGAIN;
|
||||||
@@ -225,8 +211,8 @@ agent_transact_unix(LIBSSH2_AGENT *agent, agent_transaction_ctx_t transctx)
|
|||||||
|
|
||||||
/* Receive the response body */
|
/* Receive the response body */
|
||||||
if(transctx->state == agent_NB_state_response_length_received) {
|
if(transctx->state == agent_NB_state_response_length_received) {
|
||||||
rc = LIBSSH2_RECV_FD(agent->session, agent->fd, transctx->response,
|
rc = _recv_all(agent->session->recv, agent->fd, transctx->response,
|
||||||
transctx->response_len, 0);
|
transctx->response_len, 0, &agent->session->abstract);
|
||||||
if(rc < 0) {
|
if(rc < 0) {
|
||||||
if(rc == -EAGAIN)
|
if(rc == -EAGAIN)
|
||||||
return LIBSSH2_ERROR_EAGAIN;
|
return LIBSSH2_ERROR_EAGAIN;
|
||||||
@@ -274,7 +260,7 @@ static int
|
|||||||
agent_connect_pageant(LIBSSH2_AGENT *agent)
|
agent_connect_pageant(LIBSSH2_AGENT *agent)
|
||||||
{
|
{
|
||||||
HWND hwnd;
|
HWND hwnd;
|
||||||
hwnd = FindWindow("Pageant", "Pageant");
|
hwnd = FindWindowA("Pageant", "Pageant");
|
||||||
if(!hwnd)
|
if(!hwnd)
|
||||||
return _libssh2_error(agent->session, LIBSSH2_ERROR_AGENT_PROTOCOL,
|
return _libssh2_error(agent->session, LIBSSH2_ERROR_AGENT_PROTOCOL,
|
||||||
"failed connecting agent");
|
"failed connecting agent");
|
||||||
@@ -297,15 +283,15 @@ agent_transact_pageant(LIBSSH2_AGENT *agent, agent_transaction_ctx_t transctx)
|
|||||||
return _libssh2_error(agent->session, LIBSSH2_ERROR_INVAL,
|
return _libssh2_error(agent->session, LIBSSH2_ERROR_INVAL,
|
||||||
"illegal input");
|
"illegal input");
|
||||||
|
|
||||||
hwnd = FindWindow("Pageant", "Pageant");
|
hwnd = FindWindowA("Pageant", "Pageant");
|
||||||
if(!hwnd)
|
if(!hwnd)
|
||||||
return _libssh2_error(agent->session, LIBSSH2_ERROR_AGENT_PROTOCOL,
|
return _libssh2_error(agent->session, LIBSSH2_ERROR_AGENT_PROTOCOL,
|
||||||
"found no pageant");
|
"found no pageant");
|
||||||
|
|
||||||
snprintf(mapname, sizeof(mapname),
|
snprintf(mapname, sizeof(mapname),
|
||||||
"PageantRequest%08x%c", (unsigned)GetCurrentThreadId(), '\0');
|
"PageantRequest%08x%c", (unsigned)GetCurrentThreadId(), '\0');
|
||||||
filemap = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE,
|
filemap = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE,
|
||||||
0, PAGEANT_MAX_MSGLEN, mapname);
|
0, PAGEANT_MAX_MSGLEN, mapname);
|
||||||
|
|
||||||
if(filemap == NULL || filemap == INVALID_HANDLE_VALUE)
|
if(filemap == NULL || filemap == INVALID_HANDLE_VALUE)
|
||||||
return _libssh2_error(agent->session, LIBSSH2_ERROR_AGENT_PROTOCOL,
|
return _libssh2_error(agent->session, LIBSSH2_ERROR_AGENT_PROTOCOL,
|
||||||
@@ -370,6 +356,7 @@ static struct {
|
|||||||
} supported_backends[] = {
|
} supported_backends[] = {
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
{"Pageant", &agent_ops_pageant},
|
{"Pageant", &agent_ops_pageant},
|
||||||
|
{"OpenSSH", &agent_ops_openssh},
|
||||||
#endif /* WIN32 */
|
#endif /* WIN32 */
|
||||||
#ifdef PF_UNIX
|
#ifdef PF_UNIX
|
||||||
{"Unix", &agent_ops_unix},
|
{"Unix", &agent_ops_unix},
|
||||||
@@ -407,6 +394,7 @@ agent_sign(LIBSSH2_SESSION *session, unsigned char **sig, size_t *sig_len,
|
|||||||
_libssh2_store_u32(&s, 0);
|
_libssh2_store_u32(&s, 0);
|
||||||
|
|
||||||
transctx->request_len = s - transctx->request;
|
transctx->request_len = s - transctx->request;
|
||||||
|
transctx->send_recv_total = 0;
|
||||||
transctx->state = agent_NB_state_request_created;
|
transctx->state = agent_NB_state_request_created;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -507,6 +495,7 @@ agent_list_identities(LIBSSH2_AGENT *agent)
|
|||||||
if(transctx->state == agent_NB_state_init) {
|
if(transctx->state == agent_NB_state_init) {
|
||||||
transctx->request = &c;
|
transctx->request = &c;
|
||||||
transctx->request_len = 1;
|
transctx->request_len = 1;
|
||||||
|
transctx->send_recv_total = 0;
|
||||||
transctx->state = agent_NB_state_request_created;
|
transctx->state = agent_NB_state_request_created;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -683,6 +672,12 @@ libssh2_agent_init(LIBSSH2_SESSION *session)
|
|||||||
agent->identity_agent_path = NULL;
|
agent->identity_agent_path = NULL;
|
||||||
_libssh2_list_init(&agent->head);
|
_libssh2_list_init(&agent->head);
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
agent->pipe = INVALID_HANDLE_VALUE;
|
||||||
|
memset(&agent->overlapped, 0, sizeof(OVERLAPPED));
|
||||||
|
agent->pending_io = FALSE;
|
||||||
|
#endif
|
||||||
|
|
||||||
return agent;
|
return agent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
112
src/agent.h
Normal file
112
src/agent.h
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
#ifndef __LIBSSH2_AGENT_H
|
||||||
|
#define __LIBSSH2_AGENT_H
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2009 by Daiki Ueno
|
||||||
|
* Copyright (C) 2010-2014 by Daniel Stenberg
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms,
|
||||||
|
* with or without modification, are permitted provided
|
||||||
|
* that the following conditions are met:
|
||||||
|
*
|
||||||
|
* Redistributions of source code must retain the above
|
||||||
|
* copyright notice, this list of conditions and the
|
||||||
|
* following disclaimer.
|
||||||
|
*
|
||||||
|
* Redistributions in binary form must reproduce the above
|
||||||
|
* copyright notice, this list of conditions and the following
|
||||||
|
* disclaimer in the documentation and/or other materials
|
||||||
|
* provided with the distribution.
|
||||||
|
*
|
||||||
|
* Neither the name of the copyright holder nor the names
|
||||||
|
* of any other contributors may be used to endorse or
|
||||||
|
* promote products derived from this software without
|
||||||
|
* specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||||
|
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||||
|
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||||
|
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||||
|
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||||
|
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||||
|
* OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "libssh2_priv.h"
|
||||||
|
#include "misc.h"
|
||||||
|
#include "session.h"
|
||||||
|
#ifdef WIN32
|
||||||
|
#include <stdlib.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* non-blocking mode on agent connection is not yet implemented, but
|
||||||
|
for future use. */
|
||||||
|
typedef enum {
|
||||||
|
agent_NB_state_init = 0,
|
||||||
|
agent_NB_state_request_created,
|
||||||
|
agent_NB_state_request_length_sent,
|
||||||
|
agent_NB_state_request_sent,
|
||||||
|
agent_NB_state_response_length_received,
|
||||||
|
agent_NB_state_response_received
|
||||||
|
} agent_nonblocking_states;
|
||||||
|
|
||||||
|
typedef struct agent_transaction_ctx {
|
||||||
|
unsigned char *request;
|
||||||
|
size_t request_len;
|
||||||
|
unsigned char *response;
|
||||||
|
size_t response_len;
|
||||||
|
agent_nonblocking_states state;
|
||||||
|
size_t send_recv_total;
|
||||||
|
} *agent_transaction_ctx_t;
|
||||||
|
|
||||||
|
typedef int (*agent_connect_func)(LIBSSH2_AGENT *agent);
|
||||||
|
typedef int (*agent_transact_func)(LIBSSH2_AGENT *agent,
|
||||||
|
agent_transaction_ctx_t transctx);
|
||||||
|
typedef int (*agent_disconnect_func)(LIBSSH2_AGENT *agent);
|
||||||
|
|
||||||
|
struct agent_publickey {
|
||||||
|
struct list_node node;
|
||||||
|
|
||||||
|
/* this is the struct we expose externally */
|
||||||
|
struct libssh2_agent_publickey external;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct agent_ops {
|
||||||
|
agent_connect_func connect;
|
||||||
|
agent_transact_func transact;
|
||||||
|
agent_disconnect_func disconnect;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _LIBSSH2_AGENT
|
||||||
|
{
|
||||||
|
LIBSSH2_SESSION *session; /* the session this "belongs to" */
|
||||||
|
|
||||||
|
libssh2_socket_t fd;
|
||||||
|
|
||||||
|
struct agent_ops *ops;
|
||||||
|
|
||||||
|
struct agent_transaction_ctx transctx;
|
||||||
|
struct agent_publickey *identity;
|
||||||
|
struct list_head head; /* list of public keys */
|
||||||
|
|
||||||
|
char *identity_agent_path; /* Path to a custom identity agent socket */
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
OVERLAPPED overlapped;
|
||||||
|
HANDLE pipe;
|
||||||
|
BOOL pending_io;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
extern struct agent_ops agent_ops_openssh;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __LIBSSH2_AGENT_H */
|
361
src/agent_win.c
Normal file
361
src/agent_win.c
Normal file
@@ -0,0 +1,361 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2009 by Daiki Ueno
|
||||||
|
* Copyright (C) 2010-2014 by Daniel Stenberg
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms,
|
||||||
|
* with or without modification, are permitted provided
|
||||||
|
* that the following conditions are met:
|
||||||
|
*
|
||||||
|
* Redistributions of source code must retain the above
|
||||||
|
* copyright notice, this list of conditions and the
|
||||||
|
* following disclaimer.
|
||||||
|
*
|
||||||
|
* Redistributions in binary form must reproduce the above
|
||||||
|
* copyright notice, this list of conditions and the following
|
||||||
|
* disclaimer in the documentation and/or other materials
|
||||||
|
* provided with the distribution.
|
||||||
|
*
|
||||||
|
* Neither the name of the copyright holder nor the names
|
||||||
|
* of any other contributors may be used to endorse or
|
||||||
|
* promote products derived from this software without
|
||||||
|
* specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||||
|
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||||
|
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||||
|
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||||
|
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||||
|
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||||
|
* OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "libssh2_priv.h"
|
||||||
|
#include "agent.h"
|
||||||
|
#include "misc.h"
|
||||||
|
#include <errno.h>
|
||||||
|
#ifdef HAVE_SYS_UN_H
|
||||||
|
#include <sys/un.h>
|
||||||
|
#else
|
||||||
|
/* Use the existence of sys/un.h as a test if Unix domain socket is
|
||||||
|
supported. winsock*.h define PF_UNIX/AF_UNIX but do not actually
|
||||||
|
support them. */
|
||||||
|
#undef PF_UNIX
|
||||||
|
#endif
|
||||||
|
#include "userauth.h"
|
||||||
|
#include "session.h"
|
||||||
|
#ifdef WIN32
|
||||||
|
#include <stdlib.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
/* Code to talk to OpenSSH was taken and modified from the Win32 port of
|
||||||
|
* Portable OpenSSH by the PowerShell team. Commit
|
||||||
|
* 8ab565c53f3619d6a1f5ac229e212cad8a52852c of
|
||||||
|
* https://github.com/PowerShell/openssh-portable.git was used as the base,
|
||||||
|
* specificaly the following files:
|
||||||
|
*
|
||||||
|
* - contrib\win32\win32compat\fileio.c
|
||||||
|
* - Structure of agent_connect_openssh from ssh_get_authentication_socket
|
||||||
|
* - Structure of agent_transact_openssh from ssh_request_reply
|
||||||
|
* - contrib\win32\win32compat\wmain_common.c
|
||||||
|
* - Windows equivalent functions for common Unix functions, inlined into
|
||||||
|
* this implementation
|
||||||
|
* - fileio_connect replacing connect
|
||||||
|
* - fileio_read replacing read
|
||||||
|
* - fileio_write replacing write
|
||||||
|
* - fileio_close replacing close
|
||||||
|
*
|
||||||
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
|
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
|
* All rights reserved
|
||||||
|
* Functions for connecting the local authentication agent.
|
||||||
|
*
|
||||||
|
* As far as I am concerned, the code I have written for this software
|
||||||
|
* can be used freely for any purpose. Any derived versions of this
|
||||||
|
* software must be clearly marked as such, and if the derived work is
|
||||||
|
* incompatible with the protocol description in the RFC file, it must be
|
||||||
|
* called by a name other than "ssh" or "Secure Shell".
|
||||||
|
*
|
||||||
|
* SSH2 implementation,
|
||||||
|
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2015 Microsoft Corp.
|
||||||
|
* All rights reserved
|
||||||
|
*
|
||||||
|
* Microsoft openssh win32 port
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define WIN32_OPENSSH_AGENT_SOCK "\\\\.\\pipe\\openssh-ssh-agent"
|
||||||
|
|
||||||
|
static int
|
||||||
|
agent_connect_openssh(LIBSSH2_AGENT *agent)
|
||||||
|
{
|
||||||
|
int ret = LIBSSH2_ERROR_NONE;
|
||||||
|
const char *path;
|
||||||
|
HANDLE pipe = INVALID_HANDLE_VALUE;
|
||||||
|
HANDLE event = NULL;
|
||||||
|
|
||||||
|
path = agent->identity_agent_path;
|
||||||
|
if(!path) {
|
||||||
|
path = getenv("SSH_AUTH_SOCK");
|
||||||
|
if(!path)
|
||||||
|
path = WIN32_OPENSSH_AGENT_SOCK;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(;;) {
|
||||||
|
pipe = CreateFileA(
|
||||||
|
path,
|
||||||
|
GENERIC_READ | GENERIC_WRITE,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
OPEN_EXISTING,
|
||||||
|
/* Non-blocking mode for agent connections is not implemented at
|
||||||
|
* the point this was implemented. The code for Win32 OpenSSH
|
||||||
|
* should support non-blocking IO, but the code calling it doesn't
|
||||||
|
* support it as of yet.
|
||||||
|
* When non-blocking IO is implemented for the surrounding code,
|
||||||
|
* uncomment the following line to enable support within the Win32
|
||||||
|
* OpenSSH code.
|
||||||
|
*/
|
||||||
|
/* FILE_FLAG_OVERLAPPED | */
|
||||||
|
SECURITY_SQOS_PRESENT |
|
||||||
|
SECURITY_IDENTIFICATION,
|
||||||
|
NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
if(pipe != INVALID_HANDLE_VALUE)
|
||||||
|
break;
|
||||||
|
if(GetLastError() != ERROR_PIPE_BUSY)
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* Wait up to 1 second for a pipe instance to become available */
|
||||||
|
if(!WaitNamedPipeA(path, 1000))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(pipe == INVALID_HANDLE_VALUE) {
|
||||||
|
ret = _libssh2_error(agent->session, LIBSSH2_ERROR_AGENT_PROTOCOL,
|
||||||
|
"unable to connect to agent pipe");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(SetHandleInformation(pipe, HANDLE_FLAG_INHERIT, 0) == FALSE) {
|
||||||
|
ret = _libssh2_error(agent->session, LIBSSH2_ERROR_AGENT_PROTOCOL,
|
||||||
|
"unable to set handle information of agent pipe");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
event = CreateEventA(NULL, TRUE, FALSE, NULL);
|
||||||
|
if(event == NULL) {
|
||||||
|
ret = _libssh2_error(agent->session, LIBSSH2_ERROR_AGENT_PROTOCOL,
|
||||||
|
"unable to create async I/O event");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
agent->pipe = pipe;
|
||||||
|
pipe = INVALID_HANDLE_VALUE;
|
||||||
|
agent->overlapped.hEvent = event;
|
||||||
|
event = NULL;
|
||||||
|
agent->fd = 0; /* Mark as the connection has been established */
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
if(event != NULL)
|
||||||
|
CloseHandle(event);
|
||||||
|
if(pipe != INVALID_HANDLE_VALUE)
|
||||||
|
CloseHandle(pipe);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define RECV_SEND_ALL(func, agent, buffer, length, total) \
|
||||||
|
DWORD bytes_transfered; \
|
||||||
|
BOOL ret; \
|
||||||
|
DWORD err; \
|
||||||
|
int rc; \
|
||||||
|
\
|
||||||
|
while(*total < length) { \
|
||||||
|
if(!agent->pending_io) \
|
||||||
|
ret = func(agent->pipe, (char *)buffer + *total, \
|
||||||
|
(DWORD)(length - *total), &bytes_transfered, \
|
||||||
|
&agent->overlapped); \
|
||||||
|
else \
|
||||||
|
ret = GetOverlappedResult(agent->pipe, &agent->overlapped, \
|
||||||
|
&bytes_transfered, FALSE); \
|
||||||
|
\
|
||||||
|
*total += bytes_transfered; \
|
||||||
|
if(!ret) { \
|
||||||
|
err = GetLastError(); \
|
||||||
|
if((!agent->pending_io && ERROR_IO_PENDING == err) \
|
||||||
|
|| (agent->pending_io && ERROR_IO_INCOMPLETE == err)) { \
|
||||||
|
agent->pending_io = TRUE; \
|
||||||
|
return LIBSSH2_ERROR_EAGAIN; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
return LIBSSH2_ERROR_SOCKET_NONE; \
|
||||||
|
} \
|
||||||
|
agent->pending_io = FALSE; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
rc = (int)*total; \
|
||||||
|
*total = 0; \
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
static int
|
||||||
|
win32_openssh_send_all(LIBSSH2_AGENT *agent, void *buffer, size_t length,
|
||||||
|
size_t *send_recv_total)
|
||||||
|
{
|
||||||
|
RECV_SEND_ALL(WriteFile, agent, buffer, length, send_recv_total)
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
win32_openssh_recv_all(LIBSSH2_AGENT *agent, void *buffer, size_t length,
|
||||||
|
size_t *send_recv_total)
|
||||||
|
{
|
||||||
|
RECV_SEND_ALL(ReadFile, agent, buffer, length, send_recv_total)
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef RECV_SEND_ALL
|
||||||
|
|
||||||
|
static int
|
||||||
|
agent_transact_openssh(LIBSSH2_AGENT *agent, agent_transaction_ctx_t transctx)
|
||||||
|
{
|
||||||
|
unsigned char buf[4];
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
/* Send the length of the request */
|
||||||
|
if(transctx->state == agent_NB_state_request_created) {
|
||||||
|
_libssh2_htonu32(buf, (uint32_t)transctx->request_len);
|
||||||
|
rc = win32_openssh_send_all(agent, buf, sizeof buf,
|
||||||
|
&transctx->send_recv_total);
|
||||||
|
if(rc == LIBSSH2_ERROR_EAGAIN)
|
||||||
|
return LIBSSH2_ERROR_EAGAIN;
|
||||||
|
else if(rc < 0)
|
||||||
|
return _libssh2_error(agent->session, LIBSSH2_ERROR_SOCKET_SEND,
|
||||||
|
"agent send failed");
|
||||||
|
transctx->state = agent_NB_state_request_length_sent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Send the request body */
|
||||||
|
if(transctx->state == agent_NB_state_request_length_sent) {
|
||||||
|
rc = win32_openssh_send_all(agent, transctx->request,
|
||||||
|
transctx->request_len,
|
||||||
|
&transctx->send_recv_total);
|
||||||
|
if(rc == LIBSSH2_ERROR_EAGAIN)
|
||||||
|
return LIBSSH2_ERROR_EAGAIN;
|
||||||
|
else if(rc < 0)
|
||||||
|
return _libssh2_error(agent->session, LIBSSH2_ERROR_SOCKET_SEND,
|
||||||
|
"agent send failed");
|
||||||
|
transctx->state = agent_NB_state_request_sent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Receive the length of the body */
|
||||||
|
if(transctx->state == agent_NB_state_request_sent) {
|
||||||
|
rc = win32_openssh_recv_all(agent, buf, sizeof buf,
|
||||||
|
&transctx->send_recv_total);
|
||||||
|
if(rc == LIBSSH2_ERROR_EAGAIN)
|
||||||
|
return LIBSSH2_ERROR_EAGAIN;
|
||||||
|
else if(rc < 0)
|
||||||
|
return _libssh2_error(agent->session, LIBSSH2_ERROR_SOCKET_RECV,
|
||||||
|
"agent recv failed");
|
||||||
|
|
||||||
|
transctx->response_len = _libssh2_ntohu32(buf);
|
||||||
|
transctx->response = LIBSSH2_ALLOC(agent->session,
|
||||||
|
transctx->response_len);
|
||||||
|
if(!transctx->response)
|
||||||
|
return LIBSSH2_ERROR_ALLOC;
|
||||||
|
|
||||||
|
transctx->state = agent_NB_state_response_length_received;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Receive the response body */
|
||||||
|
if(transctx->state == agent_NB_state_response_length_received) {
|
||||||
|
rc = win32_openssh_recv_all(agent, transctx->response,
|
||||||
|
transctx->response_len,
|
||||||
|
&transctx->send_recv_total);
|
||||||
|
if(rc == LIBSSH2_ERROR_EAGAIN)
|
||||||
|
return LIBSSH2_ERROR_EAGAIN;
|
||||||
|
else if(rc < 0)
|
||||||
|
return _libssh2_error(agent->session, LIBSSH2_ERROR_SOCKET_RECV,
|
||||||
|
"agent recv failed");
|
||||||
|
transctx->state = agent_NB_state_response_received;
|
||||||
|
}
|
||||||
|
|
||||||
|
return LIBSSH2_ERROR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
agent_disconnect_openssh(LIBSSH2_AGENT *agent)
|
||||||
|
{
|
||||||
|
if(!CancelIo(agent->pipe))
|
||||||
|
return _libssh2_error(agent->session, LIBSSH2_ERROR_SOCKET_DISCONNECT,
|
||||||
|
"failed to cancel pending IO of agent pipe");
|
||||||
|
if(!CloseHandle(agent->overlapped.hEvent))
|
||||||
|
return _libssh2_error(agent->session, LIBSSH2_ERROR_SOCKET_DISCONNECT,
|
||||||
|
"failed to close handle to async I/O event");
|
||||||
|
agent->overlapped.hEvent = NULL;
|
||||||
|
/* let queued APCs (if any) drain */
|
||||||
|
SleepEx(0, TRUE);
|
||||||
|
if(!CloseHandle(agent->pipe))
|
||||||
|
return _libssh2_error(agent->session, LIBSSH2_ERROR_SOCKET_DISCONNECT,
|
||||||
|
"failed to close handle to agent pipe");
|
||||||
|
|
||||||
|
agent->pipe = INVALID_HANDLE_VALUE;
|
||||||
|
agent->fd = LIBSSH2_INVALID_SOCKET;
|
||||||
|
|
||||||
|
return LIBSSH2_ERROR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct agent_ops agent_ops_openssh = {
|
||||||
|
agent_connect_openssh,
|
||||||
|
agent_transact_openssh,
|
||||||
|
agent_disconnect_openssh
|
||||||
|
};
|
||||||
|
#endif /* WIN32 */
|
@@ -81,7 +81,7 @@ bcrypt_hash(uint8_t *sha2pass, uint8_t *sha2salt, uint8_t *out)
|
|||||||
cdata[i] = Blowfish_stream2word(ciphertext, sizeof(ciphertext),
|
cdata[i] = Blowfish_stream2word(ciphertext, sizeof(ciphertext),
|
||||||
&j);
|
&j);
|
||||||
for(i = 0; i < 64; i++)
|
for(i = 0; i < 64; i++)
|
||||||
blf_enc(&state, cdata, sizeof(cdata) / sizeof(uint64_t));
|
blf_enc(&state, cdata, BCRYPT_BLOCKS / 2);
|
||||||
|
|
||||||
/* copy out */
|
/* copy out */
|
||||||
for(i = 0; i < BCRYPT_BLOCKS; i++) {
|
for(i = 0; i < BCRYPT_BLOCKS; i++) {
|
||||||
@@ -127,7 +127,7 @@ bcrypt_pbkdf(const char *pass, size_t passlen, const uint8_t *salt,
|
|||||||
memcpy(countsalt, salt, saltlen);
|
memcpy(countsalt, salt, saltlen);
|
||||||
|
|
||||||
/* collapse password */
|
/* collapse password */
|
||||||
libssh2_sha512_init(&ctx);
|
(void)libssh2_sha512_init(&ctx);
|
||||||
libssh2_sha512_update(ctx, pass, passlen);
|
libssh2_sha512_update(ctx, pass, passlen);
|
||||||
libssh2_sha512_final(ctx, sha2pass);
|
libssh2_sha512_final(ctx, sha2pass);
|
||||||
|
|
||||||
@@ -139,7 +139,7 @@ bcrypt_pbkdf(const char *pass, size_t passlen, const uint8_t *salt,
|
|||||||
countsalt[saltlen + 3] = count & 0xff;
|
countsalt[saltlen + 3] = count & 0xff;
|
||||||
|
|
||||||
/* first round, salt is salt */
|
/* first round, salt is salt */
|
||||||
libssh2_sha512_init(&ctx);
|
(void)libssh2_sha512_init(&ctx);
|
||||||
libssh2_sha512_update(ctx, countsalt, saltlen + 4);
|
libssh2_sha512_update(ctx, countsalt, saltlen + 4);
|
||||||
libssh2_sha512_final(ctx, sha2salt);
|
libssh2_sha512_final(ctx, sha2salt);
|
||||||
|
|
||||||
@@ -148,7 +148,7 @@ bcrypt_pbkdf(const char *pass, size_t passlen, const uint8_t *salt,
|
|||||||
|
|
||||||
for(i = 1; i < rounds; i++) {
|
for(i = 1; i < rounds; i++) {
|
||||||
/* subsequent rounds, salt is previous output */
|
/* subsequent rounds, salt is previous output */
|
||||||
libssh2_sha512_init(&ctx);
|
(void)libssh2_sha512_init(&ctx);
|
||||||
libssh2_sha512_update(ctx, tmpout, sizeof(tmpout));
|
libssh2_sha512_update(ctx, tmpout, sizeof(tmpout));
|
||||||
libssh2_sha512_final(ctx, sha2salt);
|
libssh2_sha512_final(ctx, sha2salt);
|
||||||
|
|
||||||
|
@@ -1,3 +1,5 @@
|
|||||||
|
#ifndef __LIBSSH2_BLF_H
|
||||||
|
#define __LIBSSH2_BLF_H
|
||||||
/* $OpenBSD: blf.h,v 1.7 2007/03/14 17:59:41 grunk Exp $ */
|
/* $OpenBSD: blf.h,v 1.7 2007/03/14 17:59:41 grunk Exp $ */
|
||||||
/*
|
/*
|
||||||
* Blowfish - a fast block cipher designed by Bruce Schneier
|
* Blowfish - a fast block cipher designed by Bruce Schneier
|
||||||
@@ -31,9 +33,6 @@
|
|||||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _BLF_H_
|
|
||||||
#define _BLF_H_
|
|
||||||
|
|
||||||
#if !defined(HAVE_BCRYPT_PBKDF) && !defined(HAVE_BLH_H)
|
#if !defined(HAVE_BCRYPT_PBKDF) && !defined(HAVE_BLH_H)
|
||||||
|
|
||||||
/* Schneier specifies a maximum key length of 56 bytes.
|
/* Schneier specifies a maximum key length of 56 bytes.
|
||||||
@@ -87,4 +86,4 @@ int bcrypt_pbkdf(const char *pass, size_t passlen, const uint8_t *salt,
|
|||||||
uint8_t *key, size_t keylen, unsigned int rounds);
|
uint8_t *key, size_t keylen, unsigned int rounds);
|
||||||
|
|
||||||
#endif /* !defined(HAVE_BCRYPT_PBKDF) && !defined(HAVE_BLH_H) */
|
#endif /* !defined(HAVE_BCRYPT_PBKDF) && !defined(HAVE_BLH_H) */
|
||||||
#endif /* _BLF_H */
|
#endif /* __LIBSSH2_BLF_H */
|
||||||
|
@@ -1140,6 +1140,8 @@ libssh2_channel_request_auth_agent(LIBSSH2_CHANNEL *channel)
|
|||||||
if(!channel)
|
if(!channel)
|
||||||
return LIBSSH2_ERROR_BAD_USE;
|
return LIBSSH2_ERROR_BAD_USE;
|
||||||
|
|
||||||
|
rc = LIBSSH2_ERROR_CHANNEL_UNKNOWN;
|
||||||
|
|
||||||
/* The current RFC draft for agent forwarding says you're supposed to
|
/* The current RFC draft for agent forwarding says you're supposed to
|
||||||
* send "auth-agent-req," but most SSH servers out there right now
|
* send "auth-agent-req," but most SSH servers out there right now
|
||||||
* actually expect "auth-agent-req@openssh.com", so we try that
|
* actually expect "auth-agent-req@openssh.com", so we try that
|
||||||
@@ -1152,7 +1154,8 @@ libssh2_channel_request_auth_agent(LIBSSH2_CHANNEL *channel)
|
|||||||
|
|
||||||
/* If we failed (but not with EAGAIN), then we move onto
|
/* If we failed (but not with EAGAIN), then we move onto
|
||||||
* the next step to try another request type. */
|
* the next step to try another request type. */
|
||||||
if(rc != 0 && rc != LIBSSH2_ERROR_EAGAIN)
|
if(rc != LIBSSH2_ERROR_NONE &&
|
||||||
|
rc != LIBSSH2_ERROR_EAGAIN)
|
||||||
channel->req_auth_agent_try_state = libssh2_NB_state_sent;
|
channel->req_auth_agent_try_state = libssh2_NB_state_sent;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1163,12 +1166,13 @@ libssh2_channel_request_auth_agent(LIBSSH2_CHANNEL *channel)
|
|||||||
|
|
||||||
/* If we failed without an EAGAIN, then move on with this
|
/* If we failed without an EAGAIN, then move on with this
|
||||||
* state machine. */
|
* state machine. */
|
||||||
if(rc != 0 && rc != LIBSSH2_ERROR_EAGAIN)
|
if(rc != LIBSSH2_ERROR_NONE &&
|
||||||
|
rc != LIBSSH2_ERROR_EAGAIN)
|
||||||
channel->req_auth_agent_try_state = libssh2_NB_state_sent1;
|
channel->req_auth_agent_try_state = libssh2_NB_state_sent1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If things are good, reset the try state. */
|
/* If things are good, reset the try state. */
|
||||||
if(rc == 0)
|
if(rc == LIBSSH2_ERROR_NONE)
|
||||||
channel->req_auth_agent_try_state = libssh2_NB_state_idle;
|
channel->req_auth_agent_try_state = libssh2_NB_state_idle;
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
@@ -1338,7 +1342,11 @@ channel_x11_req(LIBSSH2_CHANNEL *channel, int single_connection,
|
|||||||
border */
|
border */
|
||||||
unsigned char buffer[(LIBSSH2_X11_RANDOM_COOKIE_LEN / 2) + 1];
|
unsigned char buffer[(LIBSSH2_X11_RANDOM_COOKIE_LEN / 2) + 1];
|
||||||
|
|
||||||
_libssh2_random(buffer, LIBSSH2_X11_RANDOM_COOKIE_LEN / 2);
|
if(_libssh2_random(buffer, LIBSSH2_X11_RANDOM_COOKIE_LEN / 2)) {
|
||||||
|
return _libssh2_error(session, LIBSSH2_ERROR_RANDGEN,
|
||||||
|
"Unable to get random bytes "
|
||||||
|
"for x11-req cookie");
|
||||||
|
}
|
||||||
for(i = 0; i < (LIBSSH2_X11_RANDOM_COOKIE_LEN / 2); i++) {
|
for(i = 0; i < (LIBSSH2_X11_RANDOM_COOKIE_LEN / 2); i++) {
|
||||||
snprintf((char *)&s[i*2], 3, "%02X", buffer[i]);
|
snprintf((char *)&s[i*2], 3, "%02X", buffer[i]);
|
||||||
}
|
}
|
||||||
|
@@ -38,7 +38,8 @@
|
|||||||
|
|
||||||
#include "libssh2_priv.h"
|
#include "libssh2_priv.h"
|
||||||
#ifdef LIBSSH2_HAVE_ZLIB
|
#ifdef LIBSSH2_HAVE_ZLIB
|
||||||
# include <zlib.h>
|
#include <zlib.h>
|
||||||
|
#undef compress /* dodge name clash with ZLIB macro */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "comp.h"
|
#include "comp.h"
|
||||||
|
@@ -1,6 +1,5 @@
|
|||||||
#ifndef __LIBSSH2_COMP_H
|
#ifndef __LIBSSH2_COMP_H
|
||||||
#define __LIBSSH2_COMP_H
|
#define __LIBSSH2_COMP_H
|
||||||
|
|
||||||
/* Copyright (C) 2009-2010 by Daniel Stenberg
|
/* Copyright (C) 2009-2010 by Daniel Stenberg
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms,
|
* Redistribution and use in source and binary forms,
|
||||||
|
10
src/crypto.h
10
src/crypto.h
@@ -1,3 +1,5 @@
|
|||||||
|
#ifndef __LIBSSH2_CRYPTO_H
|
||||||
|
#define __LIBSSH2_CRYPTO_H
|
||||||
/* Copyright (C) 2009, 2010 Simon Josefsson
|
/* Copyright (C) 2009, 2010 Simon Josefsson
|
||||||
* Copyright (C) 2006, 2007 The Written Word, Inc. All rights reserved.
|
* Copyright (C) 2006, 2007 The Written Word, Inc. All rights reserved.
|
||||||
* Copyright (C) 2010-2019 Daniel Stenberg
|
* Copyright (C) 2010-2019 Daniel Stenberg
|
||||||
@@ -35,8 +37,6 @@
|
|||||||
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||||
* OF SUCH DAMAGE.
|
* OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
#ifndef LIBSSH2_CRYPTO_H
|
|
||||||
#define LIBSSH2_CRYPTO_H
|
|
||||||
|
|
||||||
#ifdef LIBSSH2_OPENSSL
|
#ifdef LIBSSH2_OPENSSL
|
||||||
#include "openssl.h"
|
#include "openssl.h"
|
||||||
@@ -181,8 +181,8 @@ _libssh2_ecdsa_curve_type_from_name(const char *name,
|
|||||||
#if LIBSSH2_ED25519
|
#if LIBSSH2_ED25519
|
||||||
|
|
||||||
int
|
int
|
||||||
_libssh2_curve25519_new(LIBSSH2_SESSION *session, libssh2_ed25519_ctx **ctx,
|
_libssh2_curve25519_new(LIBSSH2_SESSION *session, uint8_t **out_public_key,
|
||||||
uint8_t **out_public_key, uint8_t **out_private_key);
|
uint8_t **out_private_key);
|
||||||
|
|
||||||
int
|
int
|
||||||
_libssh2_curve25519_gen_k(_libssh2_bn **k,
|
_libssh2_curve25519_gen_k(_libssh2_bn **k,
|
||||||
@@ -245,4 +245,4 @@ int _libssh2_pub_priv_keyfilememory(LIBSSH2_SESSION *session,
|
|||||||
size_t privatekeydata_len,
|
size_t privatekeydata_len,
|
||||||
const char *passphrase);
|
const char *passphrase);
|
||||||
|
|
||||||
#endif
|
#endif /* __LIBSSH2_CRYPTO_H */
|
||||||
|
@@ -211,7 +211,7 @@ hostkey_method_ssh_rsa_signv(LIBSSH2_SESSION * session,
|
|||||||
unsigned char hash[SHA_DIGEST_LENGTH];
|
unsigned char hash[SHA_DIGEST_LENGTH];
|
||||||
libssh2_sha1_ctx ctx;
|
libssh2_sha1_ctx ctx;
|
||||||
|
|
||||||
libssh2_sha1_init(&ctx);
|
(void)libssh2_sha1_init(&ctx);
|
||||||
for(i = 0; i < veccount; i++) {
|
for(i = 0; i < veccount; i++) {
|
||||||
libssh2_sha1_update(ctx, datavec[i].iov_base, datavec[i].iov_len);
|
libssh2_sha1_update(ctx, datavec[i].iov_base, datavec[i].iov_len);
|
||||||
}
|
}
|
||||||
@@ -438,7 +438,7 @@ hostkey_method_ssh_dss_signv(LIBSSH2_SESSION * session,
|
|||||||
|
|
||||||
*signature_len = 2 * SHA_DIGEST_LENGTH;
|
*signature_len = 2 * SHA_DIGEST_LENGTH;
|
||||||
|
|
||||||
libssh2_sha1_init(&ctx);
|
(void)libssh2_sha1_init(&ctx);
|
||||||
for(i = 0; i < veccount; i++) {
|
for(i = 0; i < veccount; i++) {
|
||||||
libssh2_sha1_update(ctx, datavec[i].iov_base, datavec[i].iov_len);
|
libssh2_sha1_update(ctx, datavec[i].iov_base, datavec[i].iov_len);
|
||||||
}
|
}
|
||||||
@@ -647,7 +647,7 @@ hostkey_method_ssh_ecdsa_sig_verify(LIBSSH2_SESSION * session,
|
|||||||
{
|
{
|
||||||
unsigned char *r, *s, *name;
|
unsigned char *r, *s, *name;
|
||||||
size_t r_len, s_len, name_len;
|
size_t r_len, s_len, name_len;
|
||||||
unsigned int len;
|
uint32_t len;
|
||||||
struct string_buf buf;
|
struct string_buf buf;
|
||||||
libssh2_ecdsa_ctx *ctx = (libssh2_ecdsa_ctx *) (*abstract);
|
libssh2_ecdsa_ctx *ctx = (libssh2_ecdsa_ctx *) (*abstract);
|
||||||
|
|
||||||
@@ -683,7 +683,7 @@ hostkey_method_ssh_ecdsa_sig_verify(LIBSSH2_SESSION * session,
|
|||||||
unsigned char hash[SHA##digest_type##_DIGEST_LENGTH]; \
|
unsigned char hash[SHA##digest_type##_DIGEST_LENGTH]; \
|
||||||
libssh2_sha##digest_type##_ctx ctx; \
|
libssh2_sha##digest_type##_ctx ctx; \
|
||||||
int i; \
|
int i; \
|
||||||
libssh2_sha##digest_type##_init(&ctx); \
|
(void)libssh2_sha##digest_type##_init(&ctx); \
|
||||||
for(i = 0; i < veccount; i++) { \
|
for(i = 0; i < veccount; i++) { \
|
||||||
libssh2_sha##digest_type##_update(ctx, datavec[i].iov_base, \
|
libssh2_sha##digest_type##_update(ctx, datavec[i].iov_base, \
|
||||||
datavec[i].iov_len); \
|
datavec[i].iov_len); \
|
||||||
@@ -783,6 +783,42 @@ static const LIBSSH2_HOSTKEY_METHOD hostkey_method_ecdsa_ssh_nistp521 = {
|
|||||||
hostkey_method_ssh_ecdsa_dtor,
|
hostkey_method_ssh_ecdsa_dtor,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const LIBSSH2_HOSTKEY_METHOD hostkey_method_ecdsa_ssh_nistp256_cert = {
|
||||||
|
"ecdsa-sha2-nistp256-cert-v01@openssh.com",
|
||||||
|
SHA256_DIGEST_LENGTH,
|
||||||
|
NULL,
|
||||||
|
hostkey_method_ssh_ecdsa_initPEM,
|
||||||
|
hostkey_method_ssh_ecdsa_initPEMFromMemory,
|
||||||
|
NULL,
|
||||||
|
hostkey_method_ssh_ecdsa_signv,
|
||||||
|
NULL, /* encrypt */
|
||||||
|
hostkey_method_ssh_ecdsa_dtor,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const LIBSSH2_HOSTKEY_METHOD hostkey_method_ecdsa_ssh_nistp384_cert = {
|
||||||
|
"ecdsa-sha2-nistp384-cert-v01@openssh.com",
|
||||||
|
SHA384_DIGEST_LENGTH,
|
||||||
|
NULL,
|
||||||
|
hostkey_method_ssh_ecdsa_initPEM,
|
||||||
|
hostkey_method_ssh_ecdsa_initPEMFromMemory,
|
||||||
|
NULL,
|
||||||
|
hostkey_method_ssh_ecdsa_signv,
|
||||||
|
NULL, /* encrypt */
|
||||||
|
hostkey_method_ssh_ecdsa_dtor,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const LIBSSH2_HOSTKEY_METHOD hostkey_method_ecdsa_ssh_nistp521_cert = {
|
||||||
|
"ecdsa-sha2-nistp521-cert-v01@openssh.com",
|
||||||
|
SHA512_DIGEST_LENGTH,
|
||||||
|
NULL,
|
||||||
|
hostkey_method_ssh_ecdsa_initPEM,
|
||||||
|
hostkey_method_ssh_ecdsa_initPEMFromMemory,
|
||||||
|
NULL,
|
||||||
|
hostkey_method_ssh_ecdsa_signv,
|
||||||
|
NULL, /* encrypt */
|
||||||
|
hostkey_method_ssh_ecdsa_dtor,
|
||||||
|
};
|
||||||
|
|
||||||
#endif /* LIBSSH2_ECDSA */
|
#endif /* LIBSSH2_ECDSA */
|
||||||
|
|
||||||
#if LIBSSH2_ED25519
|
#if LIBSSH2_ED25519
|
||||||
@@ -999,6 +1035,9 @@ static const LIBSSH2_HOSTKEY_METHOD *hostkey_methods[] = {
|
|||||||
&hostkey_method_ecdsa_ssh_nistp256,
|
&hostkey_method_ecdsa_ssh_nistp256,
|
||||||
&hostkey_method_ecdsa_ssh_nistp384,
|
&hostkey_method_ecdsa_ssh_nistp384,
|
||||||
&hostkey_method_ecdsa_ssh_nistp521,
|
&hostkey_method_ecdsa_ssh_nistp521,
|
||||||
|
&hostkey_method_ecdsa_ssh_nistp256_cert,
|
||||||
|
&hostkey_method_ecdsa_ssh_nistp384_cert,
|
||||||
|
&hostkey_method_ecdsa_ssh_nistp521_cert,
|
||||||
#endif
|
#endif
|
||||||
#if LIBSSH2_ED25519
|
#if LIBSSH2_ED25519
|
||||||
&hostkey_method_ssh_ed25519,
|
&hostkey_method_ssh_ed25519,
|
||||||
|
@@ -1,3 +1,5 @@
|
|||||||
|
#ifndef __LIBSSH2_LIBGCRYPT_H
|
||||||
|
#define __LIBSSH2_LIBGCRYPT_H
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2008, 2009, 2010 Simon Josefsson
|
* Copyright (C) 2008, 2009, 2010 Simon Josefsson
|
||||||
* Copyright (C) 2006, 2007, The Written Word, Inc.
|
* Copyright (C) 2006, 2007, The Written Word, Inc.
|
||||||
@@ -66,7 +68,7 @@
|
|||||||
#define EC_MAX_POINT_LEN ((528 * 2 / 8) + 1)
|
#define EC_MAX_POINT_LEN ((528 * 2 / 8) + 1)
|
||||||
|
|
||||||
#define _libssh2_random(buf, len) \
|
#define _libssh2_random(buf, len) \
|
||||||
(gcry_randomize ((buf), (len), GCRY_STRONG_RANDOM), 1)
|
(gcry_randomize ((buf), (len), GCRY_STRONG_RANDOM), 0)
|
||||||
|
|
||||||
#define libssh2_prepare_iovec(vec, len) /* Empty. */
|
#define libssh2_prepare_iovec(vec, len) /* Empty. */
|
||||||
|
|
||||||
@@ -232,3 +234,4 @@ extern int _libssh2_dh_secret(_libssh2_dh_ctx *dhctx, _libssh2_bn *secret,
|
|||||||
_libssh2_bn *f, _libssh2_bn *p);
|
_libssh2_bn *f, _libssh2_bn *p);
|
||||||
extern void _libssh2_dh_dtor(_libssh2_dh_ctx *dhctx);
|
extern void _libssh2_dh_dtor(_libssh2_dh_ctx *dhctx);
|
||||||
|
|
||||||
|
#endif /* __LIBSSH2_LIBGCRYPT_H */
|
||||||
|
@@ -1,3 +1,5 @@
|
|||||||
|
#ifndef __LIBSSH2_PRIV_H
|
||||||
|
#define __LIBSSH2_PRIV_H
|
||||||
/* Copyright (c) 2004-2008, 2010, Sara Golemon <sarag@libssh2.org>
|
/* Copyright (c) 2004-2008, 2010, Sara Golemon <sarag@libssh2.org>
|
||||||
* Copyright (c) 2009-2014 by Daniel Stenberg
|
* Copyright (c) 2009-2014 by Daniel Stenberg
|
||||||
* Copyright (c) 2010 Simon Josefsson
|
* Copyright (c) 2010 Simon Josefsson
|
||||||
@@ -37,9 +39,6 @@
|
|||||||
* OF SUCH DAMAGE.
|
* OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef LIBSSH2_PRIV_H
|
|
||||||
#define LIBSSH2_PRIV_H 1
|
|
||||||
|
|
||||||
#define LIBSSH2_LIBRARY
|
#define LIBSSH2_LIBRARY
|
||||||
#include "libssh2_config.h"
|
#include "libssh2_config.h"
|
||||||
|
|
||||||
@@ -110,14 +109,19 @@
|
|||||||
#define inline __inline
|
#define inline __inline
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Provide iovec / writev on WIN32 platform. */
|
/* 3DS doesn't seem to have iovec */
|
||||||
#ifdef WIN32
|
#if defined(WIN32) || defined(_3DS)
|
||||||
|
|
||||||
struct iovec {
|
struct iovec {
|
||||||
size_t iov_len;
|
size_t iov_len;
|
||||||
void *iov_base;
|
void *iov_base;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Provide iovec / writev on WIN32 platform. */
|
||||||
|
#ifdef WIN32
|
||||||
|
|
||||||
static inline int writev(int sock, struct iovec *iov, int nvecs)
|
static inline int writev(int sock, struct iovec *iov, int nvecs)
|
||||||
{
|
{
|
||||||
DWORD ret;
|
DWORD ret;
|
||||||
@@ -1149,4 +1153,4 @@ endings either CRLF or LF so 't' is appropriate.
|
|||||||
#define FOPEN_APPENDTEXT "a"
|
#define FOPEN_APPENDTEXT "a"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* LIBSSH2_H */
|
#endif /* __LIBSSH2_PRIV_H */
|
||||||
|
@@ -1,6 +1,5 @@
|
|||||||
#ifndef __LIBSSH2_MAC_H
|
#ifndef __LIBSSH2_MAC_H
|
||||||
#define __LIBSSH2_MAC_H
|
#define __LIBSSH2_MAC_H
|
||||||
|
|
||||||
/* Copyright (C) 2009-2010 by Daniel Stenberg
|
/* Copyright (C) 2009-2010 by Daniel Stenberg
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms,
|
* Redistribution and use in source and binary forms,
|
||||||
|
520
src/mbedtls.c
520
src/mbedtls.c
@@ -94,7 +94,7 @@ _libssh2_mbedtls_safe_free(void *buf, int len)
|
|||||||
|
|
||||||
#ifdef LIBSSH2_CLEAR_MEMORY
|
#ifdef LIBSSH2_CLEAR_MEMORY
|
||||||
if(len > 0)
|
if(len > 0)
|
||||||
memset(buf, 0, len);
|
_libssh2_explicit_zero(buf, len);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
mbedtls_free(buf);
|
mbedtls_free(buf);
|
||||||
@@ -730,4 +730,522 @@ _libssh2_dh_dtor(_libssh2_dh_ctx *dhctx)
|
|||||||
*dhctx = NULL;
|
*dhctx = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if LIBSSH2_ECDSA
|
||||||
|
|
||||||
|
/*******************************************************************/
|
||||||
|
/*
|
||||||
|
* mbedTLS backend: ECDSA functions
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* _libssh2_ecdsa_create_key
|
||||||
|
*
|
||||||
|
* Creates a local private key based on input curve
|
||||||
|
* and returns octal value and octal length
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
int
|
||||||
|
_libssh2_mbedtls_ecdsa_create_key(LIBSSH2_SESSION *session,
|
||||||
|
_libssh2_ec_key **privkey,
|
||||||
|
unsigned char **pubkey_oct,
|
||||||
|
size_t *pubkey_oct_len,
|
||||||
|
libssh2_curve_type curve)
|
||||||
|
{
|
||||||
|
size_t plen = 0;
|
||||||
|
|
||||||
|
*privkey = LIBSSH2_ALLOC(session, sizeof(mbedtls_ecp_keypair));
|
||||||
|
|
||||||
|
if(*privkey == NULL)
|
||||||
|
goto failed;
|
||||||
|
|
||||||
|
mbedtls_ecdsa_init(*privkey);
|
||||||
|
|
||||||
|
if(mbedtls_ecdsa_genkey(*privkey, (mbedtls_ecp_group_id)curve,
|
||||||
|
mbedtls_ctr_drbg_random,
|
||||||
|
&_libssh2_mbedtls_ctr_drbg) != 0)
|
||||||
|
goto failed;
|
||||||
|
|
||||||
|
plen = 2 * mbedtls_mpi_size(&(*privkey)->grp.P) + 1;
|
||||||
|
*pubkey_oct = LIBSSH2_ALLOC(session, plen);
|
||||||
|
|
||||||
|
if(*pubkey_oct == NULL)
|
||||||
|
goto failed;
|
||||||
|
|
||||||
|
if(mbedtls_ecp_point_write_binary(&(*privkey)->grp, &(*privkey)->Q,
|
||||||
|
MBEDTLS_ECP_PF_UNCOMPRESSED,
|
||||||
|
pubkey_oct_len, *pubkey_oct, plen) == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
failed:
|
||||||
|
|
||||||
|
_libssh2_mbedtls_ecdsa_free(*privkey);
|
||||||
|
_libssh2_mbedtls_safe_free(*pubkey_oct, plen);
|
||||||
|
*privkey = NULL;
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* _libssh2_ecdsa_curve_name_with_octal_new
|
||||||
|
*
|
||||||
|
* Creates a new public key given an octal string, length and type
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
int
|
||||||
|
_libssh2_mbedtls_ecdsa_curve_name_with_octal_new(libssh2_ecdsa_ctx **ctx,
|
||||||
|
const unsigned char *k,
|
||||||
|
size_t k_len,
|
||||||
|
libssh2_curve_type curve)
|
||||||
|
{
|
||||||
|
*ctx = mbedtls_calloc(1, sizeof(mbedtls_ecp_keypair));
|
||||||
|
|
||||||
|
if(*ctx == NULL)
|
||||||
|
goto failed;
|
||||||
|
|
||||||
|
mbedtls_ecdsa_init(*ctx);
|
||||||
|
|
||||||
|
if(mbedtls_ecp_group_load(&(*ctx)->grp, (mbedtls_ecp_group_id)curve) != 0)
|
||||||
|
goto failed;
|
||||||
|
|
||||||
|
if(mbedtls_ecp_point_read_binary(&(*ctx)->grp, &(*ctx)->Q, k, k_len) != 0)
|
||||||
|
goto failed;
|
||||||
|
|
||||||
|
if(mbedtls_ecp_check_pubkey(&(*ctx)->grp, &(*ctx)->Q) == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
failed:
|
||||||
|
|
||||||
|
_libssh2_mbedtls_ecdsa_free(*ctx);
|
||||||
|
*ctx = NULL;
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* _libssh2_ecdh_gen_k
|
||||||
|
*
|
||||||
|
* Computes the shared secret K given a local private key,
|
||||||
|
* remote public key and length
|
||||||
|
*/
|
||||||
|
|
||||||
|
int
|
||||||
|
_libssh2_mbedtls_ecdh_gen_k(_libssh2_bn **k,
|
||||||
|
_libssh2_ec_key *privkey,
|
||||||
|
const unsigned char *server_pubkey,
|
||||||
|
size_t server_pubkey_len)
|
||||||
|
{
|
||||||
|
mbedtls_ecp_point pubkey;
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
|
if(*k == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
mbedtls_ecp_point_init(&pubkey);
|
||||||
|
|
||||||
|
if(mbedtls_ecp_point_read_binary(&privkey->grp, &pubkey,
|
||||||
|
server_pubkey, server_pubkey_len) != 0) {
|
||||||
|
rc = -1;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(mbedtls_ecdh_compute_shared(&privkey->grp, *k,
|
||||||
|
&pubkey, &privkey->d,
|
||||||
|
mbedtls_ctr_drbg_random,
|
||||||
|
&_libssh2_mbedtls_ctr_drbg) != 0) {
|
||||||
|
rc = -1;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(mbedtls_ecp_check_privkey(&privkey->grp, *k) != 0)
|
||||||
|
rc = -1;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
|
||||||
|
mbedtls_ecp_point_free(&pubkey);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define LIBSSH2_MBEDTLS_ECDSA_VERIFY(digest_type) \
|
||||||
|
{ \
|
||||||
|
unsigned char hsh[SHA##digest_type##_DIGEST_LENGTH]; \
|
||||||
|
\
|
||||||
|
if(libssh2_sha##digest_type(m, m_len, hsh) == 0) { \
|
||||||
|
rc = mbedtls_ecdsa_verify(&ctx->grp, hsh, \
|
||||||
|
SHA##digest_type##_DIGEST_LENGTH, \
|
||||||
|
&ctx->Q, &pr, &ps); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
}
|
||||||
|
|
||||||
|
/* _libssh2_ecdsa_sign
|
||||||
|
*
|
||||||
|
* Verifies the ECDSA signature of a hashed message
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
int
|
||||||
|
_libssh2_mbedtls_ecdsa_verify(libssh2_ecdsa_ctx *ctx,
|
||||||
|
const unsigned char *r, size_t r_len,
|
||||||
|
const unsigned char *s, size_t s_len,
|
||||||
|
const unsigned char *m, size_t m_len)
|
||||||
|
{
|
||||||
|
mbedtls_mpi pr, ps;
|
||||||
|
int rc = -1;
|
||||||
|
|
||||||
|
mbedtls_mpi_init(&pr);
|
||||||
|
mbedtls_mpi_init(&ps);
|
||||||
|
|
||||||
|
if(mbedtls_mpi_read_binary(&pr, r, r_len) != 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if(mbedtls_mpi_read_binary(&ps, s, s_len) != 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
switch(_libssh2_ecdsa_get_curve_type(ctx)) {
|
||||||
|
case LIBSSH2_EC_CURVE_NISTP256:
|
||||||
|
LIBSSH2_MBEDTLS_ECDSA_VERIFY(256);
|
||||||
|
break;
|
||||||
|
case LIBSSH2_EC_CURVE_NISTP384:
|
||||||
|
LIBSSH2_MBEDTLS_ECDSA_VERIFY(384);
|
||||||
|
break;
|
||||||
|
case LIBSSH2_EC_CURVE_NISTP521:
|
||||||
|
LIBSSH2_MBEDTLS_ECDSA_VERIFY(512);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
rc = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
|
||||||
|
mbedtls_mpi_free(&pr);
|
||||||
|
mbedtls_mpi_free(&ps);
|
||||||
|
|
||||||
|
return (rc == 0) ? 0 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
_libssh2_mbedtls_parse_eckey(libssh2_ecdsa_ctx **ctx,
|
||||||
|
mbedtls_pk_context *pkey,
|
||||||
|
LIBSSH2_SESSION *session,
|
||||||
|
const unsigned char *data,
|
||||||
|
size_t data_len,
|
||||||
|
const unsigned char *pwd)
|
||||||
|
{
|
||||||
|
size_t pwd_len;
|
||||||
|
|
||||||
|
pwd_len = pwd ? strlen((const char *) pwd) : 0;
|
||||||
|
|
||||||
|
if(mbedtls_pk_parse_key(pkey, data, data_len, pwd, pwd_len) != 0)
|
||||||
|
goto failed;
|
||||||
|
|
||||||
|
if(mbedtls_pk_get_type(pkey) != MBEDTLS_PK_ECKEY)
|
||||||
|
goto failed;
|
||||||
|
|
||||||
|
*ctx = LIBSSH2_ALLOC(session, sizeof(libssh2_ecdsa_ctx));
|
||||||
|
|
||||||
|
if(*ctx == NULL)
|
||||||
|
goto failed;
|
||||||
|
|
||||||
|
mbedtls_ecdsa_init(*ctx);
|
||||||
|
|
||||||
|
if(mbedtls_ecdsa_from_keypair(*ctx, mbedtls_pk_ec(*pkey)) == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
failed:
|
||||||
|
|
||||||
|
_libssh2_mbedtls_ecdsa_free(*ctx);
|
||||||
|
*ctx = NULL;
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
_libssh2_mbedtls_parse_openssh_key(libssh2_ecdsa_ctx **ctx,
|
||||||
|
LIBSSH2_SESSION *session,
|
||||||
|
const unsigned char *data,
|
||||||
|
size_t data_len,
|
||||||
|
const unsigned char *pwd)
|
||||||
|
{
|
||||||
|
libssh2_curve_type type;
|
||||||
|
unsigned char *name = NULL;
|
||||||
|
struct string_buf *decrypted = NULL;
|
||||||
|
size_t curvelen, exponentlen, pointlen;
|
||||||
|
unsigned char *curve, *exponent, *point_buf;
|
||||||
|
|
||||||
|
if(_libssh2_openssh_pem_parse_memory(session, pwd,
|
||||||
|
(const char *)data, data_len,
|
||||||
|
&decrypted) != 0)
|
||||||
|
goto failed;
|
||||||
|
|
||||||
|
if(_libssh2_get_string(decrypted, &name, NULL) != 0)
|
||||||
|
goto failed;
|
||||||
|
|
||||||
|
if(_libssh2_mbedtls_ecdsa_curve_type_from_name((const char *)name,
|
||||||
|
&type) != 0)
|
||||||
|
goto failed;
|
||||||
|
|
||||||
|
if(_libssh2_get_string(decrypted, &curve, &curvelen) != 0)
|
||||||
|
goto failed;
|
||||||
|
|
||||||
|
if(_libssh2_get_string(decrypted, &point_buf, &pointlen) != 0)
|
||||||
|
goto failed;
|
||||||
|
|
||||||
|
if(_libssh2_get_bignum_bytes(decrypted, &exponent, &exponentlen) != 0)
|
||||||
|
goto failed;
|
||||||
|
|
||||||
|
*ctx = LIBSSH2_ALLOC(session, sizeof(libssh2_ecdsa_ctx));
|
||||||
|
|
||||||
|
if(*ctx == NULL)
|
||||||
|
goto failed;
|
||||||
|
|
||||||
|
mbedtls_ecdsa_init(*ctx);
|
||||||
|
|
||||||
|
if(mbedtls_ecp_group_load(&(*ctx)->grp, (mbedtls_ecp_group_id)type) != 0)
|
||||||
|
goto failed;
|
||||||
|
|
||||||
|
if(mbedtls_mpi_read_binary(&(*ctx)->d, exponent, exponentlen) != 0)
|
||||||
|
goto failed;
|
||||||
|
|
||||||
|
if(mbedtls_ecp_mul(&(*ctx)->grp, &(*ctx)->Q,
|
||||||
|
&(*ctx)->d, &(*ctx)->grp.G,
|
||||||
|
mbedtls_ctr_drbg_random,
|
||||||
|
&_libssh2_mbedtls_ctr_drbg) != 0)
|
||||||
|
goto failed;
|
||||||
|
|
||||||
|
if(mbedtls_ecp_check_privkey(&(*ctx)->grp, &(*ctx)->d) == 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
failed:
|
||||||
|
|
||||||
|
_libssh2_mbedtls_ecdsa_free(*ctx);
|
||||||
|
*ctx = NULL;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
|
||||||
|
if(decrypted) {
|
||||||
|
_libssh2_string_buf_free(session, decrypted);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (*ctx == NULL) ? -1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* _libssh2_ecdsa_new_private
|
||||||
|
*
|
||||||
|
* Creates a new private key given a file path and password
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
int
|
||||||
|
_libssh2_mbedtls_ecdsa_new_private(libssh2_ecdsa_ctx **ctx,
|
||||||
|
LIBSSH2_SESSION *session,
|
||||||
|
const char *filename,
|
||||||
|
const unsigned char *pwd)
|
||||||
|
{
|
||||||
|
mbedtls_pk_context pkey;
|
||||||
|
unsigned char *data;
|
||||||
|
size_t data_len;
|
||||||
|
|
||||||
|
if(mbedtls_pk_load_file(filename, &data, &data_len) != 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
mbedtls_pk_init(&pkey);
|
||||||
|
|
||||||
|
if(_libssh2_mbedtls_parse_eckey(ctx, &pkey, session,
|
||||||
|
data, data_len, pwd) == 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
_libssh2_mbedtls_parse_openssh_key(ctx, session, data, data_len, pwd);
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
|
||||||
|
mbedtls_pk_free(&pkey);
|
||||||
|
|
||||||
|
_libssh2_mbedtls_safe_free(data, data_len);
|
||||||
|
|
||||||
|
return (*ctx == NULL) ? -1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* _libssh2_ecdsa_new_private
|
||||||
|
*
|
||||||
|
* Creates a new private key given a file data and password
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
int
|
||||||
|
_libssh2_mbedtls_ecdsa_new_private_frommemory(libssh2_ecdsa_ctx **ctx,
|
||||||
|
LIBSSH2_SESSION *session,
|
||||||
|
const char *data,
|
||||||
|
size_t data_len,
|
||||||
|
const unsigned char *pwd)
|
||||||
|
{
|
||||||
|
unsigned char *ntdata;
|
||||||
|
mbedtls_pk_context pkey;
|
||||||
|
|
||||||
|
mbedtls_pk_init(&pkey);
|
||||||
|
|
||||||
|
ntdata = LIBSSH2_ALLOC(session, data_len + 1);
|
||||||
|
|
||||||
|
if(ntdata == NULL)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
memcpy(ntdata, data, data_len);
|
||||||
|
|
||||||
|
if(_libssh2_mbedtls_parse_eckey(ctx, &pkey, session,
|
||||||
|
ntdata, data_len + 1, pwd) == 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
_libssh2_mbedtls_parse_openssh_key(ctx, session,
|
||||||
|
ntdata, data_len + 1, pwd);
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
|
||||||
|
mbedtls_pk_free(&pkey);
|
||||||
|
|
||||||
|
_libssh2_mbedtls_safe_free(ntdata, data_len);
|
||||||
|
|
||||||
|
return (*ctx == NULL) ? -1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned char *
|
||||||
|
_libssh2_mbedtls_mpi_write_binary(unsigned char *buf,
|
||||||
|
const mbedtls_mpi *mpi,
|
||||||
|
size_t bytes)
|
||||||
|
{
|
||||||
|
unsigned char *p = buf;
|
||||||
|
|
||||||
|
if(sizeof(&p) / sizeof(p[0]) < 4) {
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
p += 4;
|
||||||
|
*p = 0;
|
||||||
|
|
||||||
|
if(bytes > 0) {
|
||||||
|
mbedtls_mpi_write_binary(mpi, p + 1, bytes - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(bytes > 0 && !(*(p + 1) & 0x80)) {
|
||||||
|
memmove(p, p + 1, --bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
_libssh2_htonu32(p - 4, bytes);
|
||||||
|
|
||||||
|
done:
|
||||||
|
|
||||||
|
return p + bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* _libssh2_ecdsa_sign
|
||||||
|
*
|
||||||
|
* Computes the ECDSA signature of a previously-hashed message
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
int
|
||||||
|
_libssh2_mbedtls_ecdsa_sign(LIBSSH2_SESSION *session,
|
||||||
|
libssh2_ecdsa_ctx *ctx,
|
||||||
|
const unsigned char *hash,
|
||||||
|
unsigned long hash_len,
|
||||||
|
unsigned char **sign,
|
||||||
|
size_t *sign_len)
|
||||||
|
{
|
||||||
|
size_t r_len, s_len, tmp_sign_len = 0;
|
||||||
|
unsigned char *sp, *tmp_sign = NULL;
|
||||||
|
mbedtls_mpi pr, ps;
|
||||||
|
|
||||||
|
mbedtls_mpi_init(&pr);
|
||||||
|
mbedtls_mpi_init(&ps);
|
||||||
|
|
||||||
|
if(mbedtls_ecdsa_sign(&ctx->grp, &pr, &ps, &ctx->d,
|
||||||
|
hash, hash_len,
|
||||||
|
mbedtls_ctr_drbg_random,
|
||||||
|
&_libssh2_mbedtls_ctr_drbg) != 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
r_len = mbedtls_mpi_size(&pr) + 1;
|
||||||
|
s_len = mbedtls_mpi_size(&ps) + 1;
|
||||||
|
tmp_sign_len = r_len + s_len + 8;
|
||||||
|
|
||||||
|
tmp_sign = LIBSSH2_CALLOC(session, tmp_sign_len);
|
||||||
|
|
||||||
|
if(tmp_sign == NULL)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
sp = tmp_sign;
|
||||||
|
sp = _libssh2_mbedtls_mpi_write_binary(sp, &pr, r_len);
|
||||||
|
sp = _libssh2_mbedtls_mpi_write_binary(sp, &ps, s_len);
|
||||||
|
|
||||||
|
*sign_len = (size_t)(sp - tmp_sign);
|
||||||
|
|
||||||
|
*sign = LIBSSH2_CALLOC(session, *sign_len);
|
||||||
|
|
||||||
|
if(*sign == NULL)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
memcpy(*sign, tmp_sign, *sign_len);
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
|
||||||
|
mbedtls_mpi_free(&pr);
|
||||||
|
mbedtls_mpi_free(&ps);
|
||||||
|
|
||||||
|
_libssh2_mbedtls_safe_free(tmp_sign, tmp_sign_len);
|
||||||
|
|
||||||
|
return (*sign == NULL) ? -1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* _libssh2_ecdsa_get_curve_type
|
||||||
|
*
|
||||||
|
* returns key curve type that maps to libssh2_curve_type
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
libssh2_curve_type
|
||||||
|
_libssh2_mbedtls_ecdsa_get_curve_type(libssh2_ecdsa_ctx *ctx)
|
||||||
|
{
|
||||||
|
return (libssh2_curve_type) ctx->grp.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* _libssh2_ecdsa_curve_type_from_name
|
||||||
|
*
|
||||||
|
* returns 0 for success, key curve type that maps to libssh2_curve_type
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
int
|
||||||
|
_libssh2_mbedtls_ecdsa_curve_type_from_name(const char *name,
|
||||||
|
libssh2_curve_type *out_type)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
libssh2_curve_type type;
|
||||||
|
|
||||||
|
if(name == NULL || strlen(name) != 19)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if(strcmp(name, "ecdsa-sha2-nistp256") == 0)
|
||||||
|
type = LIBSSH2_EC_CURVE_NISTP256;
|
||||||
|
else if(strcmp(name, "ecdsa-sha2-nistp384") == 0)
|
||||||
|
type = LIBSSH2_EC_CURVE_NISTP384;
|
||||||
|
else if(strcmp(name, "ecdsa-sha2-nistp521") == 0)
|
||||||
|
type = LIBSSH2_EC_CURVE_NISTP521;
|
||||||
|
else {
|
||||||
|
ret = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ret == 0 && out_type) {
|
||||||
|
*out_type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_libssh2_mbedtls_ecdsa_free(libssh2_ecdsa_ctx *ctx)
|
||||||
|
{
|
||||||
|
mbedtls_ecdsa_free(ctx);
|
||||||
|
mbedtls_free(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* LIBSSH2_ECDSA */
|
||||||
#endif /* LIBSSH2_MBEDTLS */
|
#endif /* LIBSSH2_MBEDTLS */
|
||||||
|
153
src/mbedtls.h
153
src/mbedtls.h
@@ -1,3 +1,5 @@
|
|||||||
|
#ifndef __LIBSSH2_MBEDTLS_H
|
||||||
|
#define __LIBSSH2_MBEDTLS_H
|
||||||
/* Copyright (c) 2016, Art <https://github.com/wildart>
|
/* Copyright (c) 2016, Art <https://github.com/wildart>
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
@@ -43,6 +45,12 @@
|
|||||||
#include <mbedtls/rsa.h>
|
#include <mbedtls/rsa.h>
|
||||||
#include <mbedtls/bignum.h>
|
#include <mbedtls/bignum.h>
|
||||||
#include <mbedtls/cipher.h>
|
#include <mbedtls/cipher.h>
|
||||||
|
#ifdef MBEDTLS_ECDH_C
|
||||||
|
# include <mbedtls/ecdh.h>
|
||||||
|
#endif
|
||||||
|
#ifdef MBEDTLS_ECDSA_C
|
||||||
|
# include <mbedtls/ecdsa.h>
|
||||||
|
#endif
|
||||||
#include <mbedtls/entropy.h>
|
#include <mbedtls/entropy.h>
|
||||||
#include <mbedtls/ctr_drbg.h>
|
#include <mbedtls/ctr_drbg.h>
|
||||||
#include <mbedtls/pk.h>
|
#include <mbedtls/pk.h>
|
||||||
@@ -64,7 +72,11 @@
|
|||||||
|
|
||||||
#define LIBSSH2_RSA 1
|
#define LIBSSH2_RSA 1
|
||||||
#define LIBSSH2_DSA 0
|
#define LIBSSH2_DSA 0
|
||||||
#define LIBSSH2_ECDSA 0
|
#ifdef MBEDTLS_ECDSA_C
|
||||||
|
# define LIBSSH2_ECDSA 1
|
||||||
|
#else
|
||||||
|
# define LIBSSH2_ECDSA 0
|
||||||
|
#endif
|
||||||
#define LIBSSH2_ED25519 0
|
#define LIBSSH2_ED25519 0
|
||||||
|
|
||||||
#define MD5_DIGEST_LENGTH 16
|
#define MD5_DIGEST_LENGTH 16
|
||||||
@@ -75,10 +87,6 @@
|
|||||||
|
|
||||||
#define EC_MAX_POINT_LEN ((528 * 2 / 8) + 1)
|
#define EC_MAX_POINT_LEN ((528 * 2 / 8) + 1)
|
||||||
|
|
||||||
#if LIBSSH2_ECDSA
|
|
||||||
#else
|
|
||||||
#define _libssh2_ec_key void
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*******************************************************************/
|
/*******************************************************************/
|
||||||
/*
|
/*
|
||||||
@@ -208,9 +216,10 @@
|
|||||||
#define libssh2_md5(data, datalen, hash) \
|
#define libssh2_md5(data, datalen, hash) \
|
||||||
_libssh2_mbedtls_hash(data, datalen, MBEDTLS_MD_MD5, hash)
|
_libssh2_mbedtls_hash(data, datalen, MBEDTLS_MD_MD5, hash)
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************/
|
/*******************************************************************/
|
||||||
/*
|
/*
|
||||||
* mbedTLS backend: RSA structure
|
* mbedTLS backend: RSA functions
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define libssh2_rsa_ctx mbedtls_rsa_context
|
#define libssh2_rsa_ctx mbedtls_rsa_context
|
||||||
@@ -239,6 +248,82 @@
|
|||||||
#define _libssh2_rsa_free(rsactx) \
|
#define _libssh2_rsa_free(rsactx) \
|
||||||
_libssh2_mbedtls_rsa_free(rsactx)
|
_libssh2_mbedtls_rsa_free(rsactx)
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************/
|
||||||
|
/*
|
||||||
|
* mbedTLS backend: ECDSA structures
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if LIBSSH2_ECDSA
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
#ifdef MBEDTLS_ECP_DP_SECP256R1_ENABLED
|
||||||
|
LIBSSH2_EC_CURVE_NISTP256 = MBEDTLS_ECP_DP_SECP256R1,
|
||||||
|
#else
|
||||||
|
LIBSSH2_EC_CURVE_NISTP256 = MBEDTLS_ECP_DP_NONE,
|
||||||
|
#endif
|
||||||
|
#ifdef MBEDTLS_ECP_DP_SECP384R1_ENABLED
|
||||||
|
LIBSSH2_EC_CURVE_NISTP384 = MBEDTLS_ECP_DP_SECP384R1,
|
||||||
|
#else
|
||||||
|
LIBSSH2_EC_CURVE_NISTP384 = MBEDTLS_ECP_DP_NONE,
|
||||||
|
#endif
|
||||||
|
#ifdef MBEDTLS_ECP_DP_SECP521R1_ENABLED
|
||||||
|
LIBSSH2_EC_CURVE_NISTP521 = MBEDTLS_ECP_DP_SECP521R1
|
||||||
|
#else
|
||||||
|
LIBSSH2_EC_CURVE_NISTP521 = MBEDTLS_ECP_DP_NONE,
|
||||||
|
#endif
|
||||||
|
} libssh2_curve_type;
|
||||||
|
|
||||||
|
# define _libssh2_ec_key mbedtls_ecp_keypair
|
||||||
|
#else
|
||||||
|
# define _libssh2_ec_key void
|
||||||
|
#endif /* LIBSSH2_ECDSA */
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************/
|
||||||
|
/*
|
||||||
|
* mbedTLS backend: ECDSA functions
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if LIBSSH2_ECDSA
|
||||||
|
|
||||||
|
#define libssh2_ecdsa_ctx mbedtls_ecdsa_context
|
||||||
|
|
||||||
|
#define _libssh2_ecdsa_create_key(session, privkey, pubkey_octal, \
|
||||||
|
pubkey_octal_len, curve) \
|
||||||
|
_libssh2_mbedtls_ecdsa_create_key(session, privkey, pubkey_octal, \
|
||||||
|
pubkey_octal_len, curve)
|
||||||
|
|
||||||
|
#define _libssh2_ecdsa_curve_name_with_octal_new(ctx, k, k_len, curve) \
|
||||||
|
_libssh2_mbedtls_ecdsa_curve_name_with_octal_new(ctx, k, k_len, curve)
|
||||||
|
|
||||||
|
#define _libssh2_ecdh_gen_k(k, privkey, server_pubkey, server_pubkey_len) \
|
||||||
|
_libssh2_mbedtls_ecdh_gen_k(k, privkey, server_pubkey, server_pubkey_len)
|
||||||
|
|
||||||
|
#define _libssh2_ecdsa_verify(ctx, r, r_len, s, s_len, m, m_len) \
|
||||||
|
_libssh2_mbedtls_ecdsa_verify(ctx, r, r_len, s, s_len, m, m_len)
|
||||||
|
|
||||||
|
#define _libssh2_ecdsa_new_private(ctx, session, filename, passphrase) \
|
||||||
|
_libssh2_mbedtls_ecdsa_new_private(ctx, session, filename, passphrase)
|
||||||
|
|
||||||
|
#define _libssh2_ecdsa_new_private_frommemory(ctx, session, filedata, \
|
||||||
|
filedata_len, passphrase) \
|
||||||
|
_libssh2_mbedtls_ecdsa_new_private_frommemory(ctx, session, filedata, \
|
||||||
|
filedata_len, passphrase)
|
||||||
|
|
||||||
|
#define _libssh2_ecdsa_sign(session, ctx, hash, hash_len, sign, sign_len) \
|
||||||
|
_libssh2_mbedtls_ecdsa_sign(session, ctx, hash, hash_len, sign, sign_len)
|
||||||
|
|
||||||
|
#define _libssh2_ecdsa_get_curve_type(ctx) \
|
||||||
|
_libssh2_mbedtls_ecdsa_get_curve_type(ctx)
|
||||||
|
|
||||||
|
#define _libssh2_ecdsa_free(ctx) \
|
||||||
|
_libssh2_mbedtls_ecdsa_free(ctx)
|
||||||
|
|
||||||
|
#endif /* LIBSSH2_ECDSA */
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************/
|
||||||
/*
|
/*
|
||||||
* mbedTLS backend: Key functions
|
* mbedTLS backend: Key functions
|
||||||
*/
|
*/
|
||||||
@@ -251,10 +336,11 @@
|
|||||||
pk, pk_len, pw)
|
pk, pk_len, pw)
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************/
|
/*******************************************************************/
|
||||||
/*
|
/*
|
||||||
* mbedTLS backend: Cipher Context structure
|
* mbedTLS backend: Cipher Context structure
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define _libssh2_cipher_ctx mbedtls_cipher_context_t
|
#define _libssh2_cipher_ctx mbedtls_cipher_context_t
|
||||||
|
|
||||||
#define _libssh2_cipher_type(algo) mbedtls_cipher_type_t algo
|
#define _libssh2_cipher_type(algo) mbedtls_cipher_type_t algo
|
||||||
@@ -270,6 +356,8 @@
|
|||||||
#define _libssh2_cipher_cast5 MBEDTLS_CIPHER_NULL
|
#define _libssh2_cipher_cast5 MBEDTLS_CIPHER_NULL
|
||||||
#define _libssh2_cipher_3des MBEDTLS_CIPHER_DES_EDE3_CBC
|
#define _libssh2_cipher_3des MBEDTLS_CIPHER_DES_EDE3_CBC
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************/
|
||||||
/*
|
/*
|
||||||
* mbedTLS backend: Cipher functions
|
* mbedTLS backend: Cipher functions
|
||||||
*/
|
*/
|
||||||
@@ -329,6 +417,7 @@
|
|||||||
/*
|
/*
|
||||||
* mbedTLS backend: forward declarations
|
* mbedTLS backend: forward declarations
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
_libssh2_mbedtls_init(void);
|
_libssh2_mbedtls_init(void);
|
||||||
|
|
||||||
@@ -434,6 +523,54 @@ _libssh2_mbedtls_pub_priv_keyfilememory(LIBSSH2_SESSION *session,
|
|||||||
const char *privatekeydata,
|
const char *privatekeydata,
|
||||||
size_t privatekeydata_len,
|
size_t privatekeydata_len,
|
||||||
const char *passphrase);
|
const char *passphrase);
|
||||||
|
#if LIBSSH2_ECDSA
|
||||||
|
int
|
||||||
|
_libssh2_mbedtls_ecdsa_create_key(LIBSSH2_SESSION *session,
|
||||||
|
_libssh2_ec_key **privkey,
|
||||||
|
unsigned char **pubkey_octal,
|
||||||
|
size_t *pubkey_octal_len,
|
||||||
|
libssh2_curve_type curve);
|
||||||
|
int
|
||||||
|
_libssh2_mbedtls_ecdsa_curve_name_with_octal_new(libssh2_ecdsa_ctx **ctx,
|
||||||
|
const unsigned char *k,
|
||||||
|
size_t k_len,
|
||||||
|
libssh2_curve_type curve);
|
||||||
|
int
|
||||||
|
_libssh2_mbedtls_ecdh_gen_k(_libssh2_bn **k,
|
||||||
|
_libssh2_ec_key *privkey,
|
||||||
|
const unsigned char *server_pubkey,
|
||||||
|
size_t server_pubkey_len);
|
||||||
|
int
|
||||||
|
_libssh2_mbedtls_ecdsa_verify(libssh2_ecdsa_ctx *ctx,
|
||||||
|
const unsigned char *r, size_t r_len,
|
||||||
|
const unsigned char *s, size_t s_len,
|
||||||
|
const unsigned char *m, size_t m_len);
|
||||||
|
int
|
||||||
|
_libssh2_mbedtls_ecdsa_new_private(libssh2_ecdsa_ctx **ctx,
|
||||||
|
LIBSSH2_SESSION *session,
|
||||||
|
const char *filename,
|
||||||
|
const unsigned char *passphrase);
|
||||||
|
int
|
||||||
|
_libssh2_mbedtls_ecdsa_new_private_frommemory(libssh2_ecdsa_ctx **ctx,
|
||||||
|
LIBSSH2_SESSION *session,
|
||||||
|
const char *filedata,
|
||||||
|
size_t filedata_len,
|
||||||
|
const unsigned char *passphrase);
|
||||||
|
int
|
||||||
|
_libssh2_mbedtls_ecdsa_sign(LIBSSH2_SESSION *session,
|
||||||
|
libssh2_ecdsa_ctx *ctx,
|
||||||
|
const unsigned char *hash,
|
||||||
|
unsigned long hash_len,
|
||||||
|
unsigned char **signature,
|
||||||
|
size_t *signature_len);
|
||||||
|
libssh2_curve_type
|
||||||
|
_libssh2_mbedtls_ecdsa_key_get_curve_type(libssh2_ecdsa_ctx *ctx);
|
||||||
|
int
|
||||||
|
_libssh2_mbedtls_ecdsa_curve_type_from_name(const char *name,
|
||||||
|
libssh2_curve_type *type);
|
||||||
|
void
|
||||||
|
_libssh2_mbedtls_ecdsa_free(libssh2_ecdsa_ctx *ctx);
|
||||||
|
#endif /* LIBSSH2_ECDSA */
|
||||||
|
|
||||||
extern void
|
extern void
|
||||||
_libssh2_dh_init(_libssh2_dh_ctx *dhctx);
|
_libssh2_dh_init(_libssh2_dh_ctx *dhctx);
|
||||||
@@ -445,3 +582,5 @@ _libssh2_dh_secret(_libssh2_dh_ctx *dhctx, _libssh2_bn *secret,
|
|||||||
_libssh2_bn *f, _libssh2_bn *p);
|
_libssh2_bn *f, _libssh2_bn *p);
|
||||||
extern void
|
extern void
|
||||||
_libssh2_dh_dtor(_libssh2_dh_ctx *dhctx);
|
_libssh2_dh_dtor(_libssh2_dh_ctx *dhctx);
|
||||||
|
|
||||||
|
#endif /* __LIBSSH2_MBEDTLS_H */
|
||||||
|
229
src/openssl.c
229
src/openssl.c
@@ -427,10 +427,19 @@ _libssh2_cipher_crypt(_libssh2_cipher_ctx * ctx,
|
|||||||
#else
|
#else
|
||||||
ret = EVP_Cipher(ctx, buf, block, blocksize);
|
ret = EVP_Cipher(ctx, buf, block, blocksize);
|
||||||
#endif
|
#endif
|
||||||
|
#if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3
|
||||||
|
if(ret != -1) {
|
||||||
|
#else
|
||||||
if(ret == 1) {
|
if(ret == 1) {
|
||||||
|
#endif
|
||||||
memcpy(block, buf, blocksize);
|
memcpy(block, buf, blocksize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3
|
||||||
|
return ret != -1 ? 0 : 1;
|
||||||
|
#else
|
||||||
return ret == 1 ? 0 : 1;
|
return ret == 1 ? 0 : 1;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#if LIBSSH2_AES_CTR && !defined(HAVE_EVP_AES_128_CTR)
|
#if LIBSSH2_AES_CTR && !defined(HAVE_EVP_AES_128_CTR)
|
||||||
@@ -445,6 +454,10 @@ typedef struct
|
|||||||
unsigned char ctr[AES_BLOCK_SIZE];
|
unsigned char ctr[AES_BLOCK_SIZE];
|
||||||
} aes_ctr_ctx;
|
} aes_ctr_ctx;
|
||||||
|
|
||||||
|
static EVP_CIPHER * aes_128_ctr_cipher = NULL;
|
||||||
|
static EVP_CIPHER * aes_192_ctr_cipher = NULL;
|
||||||
|
static EVP_CIPHER * aes_256_ctr_cipher = NULL;
|
||||||
|
|
||||||
static int
|
static int
|
||||||
aes_ctr_init(EVP_CIPHER_CTX *ctx, const unsigned char *key,
|
aes_ctr_init(EVP_CIPHER_CTX *ctx, const unsigned char *key,
|
||||||
const unsigned char *iv, int enc) /* init key */
|
const unsigned char *iv, int enc) /* init key */
|
||||||
@@ -589,12 +602,16 @@ const EVP_CIPHER *
|
|||||||
_libssh2_EVP_aes_128_ctr(void)
|
_libssh2_EVP_aes_128_ctr(void)
|
||||||
{
|
{
|
||||||
#ifdef HAVE_OPAQUE_STRUCTS
|
#ifdef HAVE_OPAQUE_STRUCTS
|
||||||
EVP_CIPHER * aes_ctr_cipher;
|
return !aes_128_ctr_cipher ?
|
||||||
return make_ctr_evp(16, &aes_ctr_cipher, NID_aes_128_ctr);
|
make_ctr_evp(16, &aes_128_ctr_cipher, NID_aes_128_ctr) :
|
||||||
|
aes_128_ctr_cipher;
|
||||||
#else
|
#else
|
||||||
static EVP_CIPHER aes_ctr_cipher;
|
static EVP_CIPHER aes_ctr_cipher;
|
||||||
EVP_CIPHER * aes_ctr_cipher_ptr = &aes_ctr_cipher;
|
if(!aes_128_ctr_cipher) {
|
||||||
return make_ctr_evp(16, &aes_ctr_cipher_ptr, 0);
|
aes_128_ctr_cipher = &aes_ctr_cipher;
|
||||||
|
make_ctr_evp(16, &aes_128_ctr_cipher, 0);
|
||||||
|
}
|
||||||
|
return aes_128_ctr_cipher;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -602,12 +619,16 @@ const EVP_CIPHER *
|
|||||||
_libssh2_EVP_aes_192_ctr(void)
|
_libssh2_EVP_aes_192_ctr(void)
|
||||||
{
|
{
|
||||||
#ifdef HAVE_OPAQUE_STRUCTS
|
#ifdef HAVE_OPAQUE_STRUCTS
|
||||||
EVP_CIPHER * aes_ctr_cipher;
|
return !aes_192_ctr_cipher ?
|
||||||
return make_ctr_evp(24, &aes_ctr_cipher, NID_aes_192_ctr);
|
make_ctr_evp(24, &aes_192_ctr_cipher, NID_aes_192_ctr) :
|
||||||
|
aes_192_ctr_cipher;
|
||||||
#else
|
#else
|
||||||
static EVP_CIPHER aes_ctr_cipher;
|
static EVP_CIPHER aes_ctr_cipher;
|
||||||
EVP_CIPHER * aes_ctr_cipher_ptr = &aes_ctr_cipher;
|
if(!aes_192_ctr_cipher) {
|
||||||
return make_ctr_evp(24, &aes_ctr_cipher_ptr, 0);
|
aes_192_ctr_cipher = &aes_ctr_cipher;
|
||||||
|
make_ctr_evp(24, &aes_192_ctr_cipher, 0);
|
||||||
|
}
|
||||||
|
return aes_192_ctr_cipher;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -615,22 +636,20 @@ const EVP_CIPHER *
|
|||||||
_libssh2_EVP_aes_256_ctr(void)
|
_libssh2_EVP_aes_256_ctr(void)
|
||||||
{
|
{
|
||||||
#ifdef HAVE_OPAQUE_STRUCTS
|
#ifdef HAVE_OPAQUE_STRUCTS
|
||||||
EVP_CIPHER * aes_ctr_cipher;
|
return !aes_256_ctr_cipher ?
|
||||||
return make_ctr_evp(32, &aes_ctr_cipher, NID_aes_256_ctr);
|
make_ctr_evp(32, &aes_256_ctr_cipher, NID_aes_256_ctr) :
|
||||||
|
aes_256_ctr_cipher;
|
||||||
#else
|
#else
|
||||||
static EVP_CIPHER aes_ctr_cipher;
|
static EVP_CIPHER aes_ctr_cipher;
|
||||||
EVP_CIPHER * aes_ctr_cipher_ptr = &aes_ctr_cipher;
|
if(!aes_256_ctr_cipher) {
|
||||||
return make_ctr_evp(32, &aes_ctr_cipher_ptr, 0);
|
aes_256_ctr_cipher = &aes_ctr_cipher;
|
||||||
|
make_ctr_evp(32, &aes_256_ctr_cipher, 0);
|
||||||
|
}
|
||||||
|
return aes_256_ctr_cipher;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* LIBSSH2_AES_CTR */
|
#endif /* LIBSSH2_AES_CTR && !defined(HAVE_EVP_AES_128_CTR) */
|
||||||
|
|
||||||
#ifndef HAVE_EVP_AES_128_CTR
|
|
||||||
static EVP_CIPHER * aes_128_ctr_cipher = NULL;
|
|
||||||
static EVP_CIPHER * aes_192_ctr_cipher = NULL;
|
|
||||||
static EVP_CIPHER * aes_256_ctr_cipher = NULL;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void _libssh2_openssl_crypto_init(void)
|
void _libssh2_openssl_crypto_init(void)
|
||||||
{
|
{
|
||||||
@@ -649,19 +668,16 @@ void _libssh2_openssl_crypto_init(void)
|
|||||||
ENGINE_register_all_complete();
|
ENGINE_register_all_complete();
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#ifndef HAVE_EVP_AES_128_CTR
|
#if LIBSSH2_AES_CTR && !defined(HAVE_EVP_AES_128_CTR)
|
||||||
if(!aes_128_ctr_cipher)
|
aes_128_ctr_cipher = (EVP_CIPHER *) _libssh2_EVP_aes_128_ctr();
|
||||||
aes_128_ctr_cipher = (EVP_CIPHER *) _libssh2_EVP_aes_128_ctr();
|
aes_192_ctr_cipher = (EVP_CIPHER *) _libssh2_EVP_aes_192_ctr();
|
||||||
if(!aes_192_ctr_cipher)
|
aes_256_ctr_cipher = (EVP_CIPHER *) _libssh2_EVP_aes_256_ctr();
|
||||||
aes_192_ctr_cipher = (EVP_CIPHER *) _libssh2_EVP_aes_192_ctr();
|
|
||||||
if(!aes_256_ctr_cipher)
|
|
||||||
aes_256_ctr_cipher = (EVP_CIPHER *) _libssh2_EVP_aes_256_ctr();
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void _libssh2_openssl_crypto_exit(void)
|
void _libssh2_openssl_crypto_exit(void)
|
||||||
{
|
{
|
||||||
#ifndef HAVE_EVP_AES_128_CTR
|
#if LIBSSH2_AES_CTR && !defined(HAVE_EVP_AES_128_CTR)
|
||||||
#ifdef HAVE_OPAQUE_STRUCTS
|
#ifdef HAVE_OPAQUE_STRUCTS
|
||||||
if(aes_128_ctr_cipher) {
|
if(aes_128_ctr_cipher) {
|
||||||
EVP_CIPHER_meth_free(aes_128_ctr_cipher);
|
EVP_CIPHER_meth_free(aes_128_ctr_cipher);
|
||||||
@@ -1458,75 +1474,53 @@ _libssh2_ecdsa_new_private_frommemory(libssh2_ecdsa_ctx ** ec_ctx,
|
|||||||
#if LIBSSH2_ED25519
|
#if LIBSSH2_ED25519
|
||||||
|
|
||||||
int
|
int
|
||||||
_libssh2_curve25519_new(LIBSSH2_SESSION *session, libssh2_x25519_ctx **out_ctx,
|
_libssh2_curve25519_new(LIBSSH2_SESSION *session,
|
||||||
unsigned char **out_public_key,
|
unsigned char **out_public_key,
|
||||||
unsigned char **out_private_key)
|
unsigned char **out_private_key)
|
||||||
{
|
{
|
||||||
EVP_PKEY *key = NULL;
|
EVP_PKEY *key = NULL;
|
||||||
EVP_PKEY_CTX *pctx = NULL;
|
EVP_PKEY_CTX *pctx = NULL;
|
||||||
PKCS8_PRIV_KEY_INFO *info = NULL;
|
unsigned char *priv = NULL, *pub = NULL;
|
||||||
ASN1_OCTET_STRING *oct = NULL;
|
size_t privLen, pubLen;
|
||||||
X509_PUBKEY *pubkey = NULL;
|
|
||||||
libssh2_ed25519_ctx *ctx = NULL;
|
|
||||||
const unsigned char *pkcs, *priv, *pub;
|
|
||||||
int privLen, pubLen, pkcsLen;
|
|
||||||
int rc = -1;
|
int rc = -1;
|
||||||
|
|
||||||
pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_X25519, NULL);
|
pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_X25519, NULL);
|
||||||
if(pctx == NULL)
|
if(pctx == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
EVP_PKEY_keygen_init(pctx);
|
if(EVP_PKEY_keygen_init(pctx) != 1 ||
|
||||||
EVP_PKEY_keygen(pctx, &key);
|
EVP_PKEY_keygen(pctx, &key) != 1) {
|
||||||
info = EVP_PKEY2PKCS8(key);
|
|
||||||
|
|
||||||
if(info == NULL || !PKCS8_pkey_get0(NULL, &pkcs, &pkcsLen, NULL, info))
|
|
||||||
goto cleanExit;
|
|
||||||
|
|
||||||
oct = d2i_ASN1_OCTET_STRING(NULL, &pkcs, pkcsLen);
|
|
||||||
if(oct == NULL) {
|
|
||||||
goto cleanExit;
|
goto cleanExit;
|
||||||
}
|
}
|
||||||
|
|
||||||
priv = ASN1_STRING_get0_data(oct);
|
|
||||||
privLen = ASN1_STRING_length(oct);
|
|
||||||
|
|
||||||
if(privLen != LIBSSH2_ED25519_KEY_LEN)
|
|
||||||
goto cleanExit;
|
|
||||||
|
|
||||||
pubkey = X509_PUBKEY_new();
|
|
||||||
if(pubkey == NULL || !X509_PUBKEY_set(&pubkey, key))
|
|
||||||
goto cleanExit;
|
|
||||||
|
|
||||||
if(!X509_PUBKEY_get0_param(NULL, &pub, &pubLen, NULL, pubkey))
|
|
||||||
goto cleanExit;
|
|
||||||
|
|
||||||
if(pubLen != LIBSSH2_ED25519_KEY_LEN)
|
|
||||||
goto cleanExit;
|
|
||||||
|
|
||||||
if(out_private_key != NULL) {
|
if(out_private_key != NULL) {
|
||||||
*out_private_key = LIBSSH2_ALLOC(session, LIBSSH2_ED25519_KEY_LEN);
|
privLen = LIBSSH2_ED25519_KEY_LEN;
|
||||||
if(*out_private_key == NULL)
|
priv = LIBSSH2_ALLOC(session, privLen);
|
||||||
|
if(priv == NULL)
|
||||||
goto cleanExit;
|
goto cleanExit;
|
||||||
|
|
||||||
memcpy(*out_private_key, priv, LIBSSH2_ED25519_KEY_LEN);
|
if(EVP_PKEY_get_raw_private_key(key, priv, &privLen) != 1 ||
|
||||||
|
privLen != LIBSSH2_ED25519_KEY_LEN) {
|
||||||
|
goto cleanExit;
|
||||||
|
}
|
||||||
|
|
||||||
|
*out_private_key = priv;
|
||||||
|
priv = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(out_public_key != NULL) {
|
if(out_public_key != NULL) {
|
||||||
*out_public_key = LIBSSH2_ALLOC(session, LIBSSH2_ED25519_KEY_LEN);
|
pubLen = LIBSSH2_ED25519_KEY_LEN;
|
||||||
if(*out_public_key == NULL)
|
pub = LIBSSH2_ALLOC(session, pubLen);
|
||||||
|
if(pub == NULL)
|
||||||
goto cleanExit;
|
goto cleanExit;
|
||||||
|
|
||||||
memcpy(*out_public_key, pub, LIBSSH2_ED25519_KEY_LEN);
|
if(EVP_PKEY_get_raw_public_key(key, pub, &pubLen) != 1 ||
|
||||||
}
|
pubLen != LIBSSH2_ED25519_KEY_LEN) {
|
||||||
|
|
||||||
if(out_ctx != NULL) {
|
|
||||||
ctx = EVP_PKEY_new_raw_private_key(EVP_PKEY_X25519, NULL, priv,
|
|
||||||
LIBSSH2_ED25519_KEY_LEN);
|
|
||||||
if(!ctx)
|
|
||||||
goto cleanExit;
|
goto cleanExit;
|
||||||
|
}
|
||||||
|
|
||||||
*out_ctx = ctx;
|
*out_public_key = pub;
|
||||||
|
pub = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* success */
|
/* success */
|
||||||
@@ -1534,16 +1528,14 @@ _libssh2_curve25519_new(LIBSSH2_SESSION *session, libssh2_x25519_ctx **out_ctx,
|
|||||||
|
|
||||||
cleanExit:
|
cleanExit:
|
||||||
|
|
||||||
if(info)
|
|
||||||
PKCS8_PRIV_KEY_INFO_free(info);
|
|
||||||
if(pctx)
|
if(pctx)
|
||||||
EVP_PKEY_CTX_free(pctx);
|
EVP_PKEY_CTX_free(pctx);
|
||||||
if(oct)
|
|
||||||
ASN1_OCTET_STRING_free(oct);
|
|
||||||
if(pubkey)
|
|
||||||
X509_PUBKEY_free(pubkey);
|
|
||||||
if(key)
|
if(key)
|
||||||
EVP_PKEY_free(key);
|
EVP_PKEY_free(key);
|
||||||
|
if(priv)
|
||||||
|
LIBSSH2_FREE(session, priv);
|
||||||
|
if(pub)
|
||||||
|
LIBSSH2_FREE(session, pub);
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
@@ -1698,6 +1690,8 @@ gen_publickey_from_ed25519_openssh_priv_data(LIBSSH2_SESSION *session,
|
|||||||
|
|
||||||
method_buf = LIBSSH2_ALLOC(session, 11); /* ssh-ed25519. */
|
method_buf = LIBSSH2_ALLOC(session, 11); /* ssh-ed25519. */
|
||||||
if(method_buf == NULL) {
|
if(method_buf == NULL) {
|
||||||
|
_libssh2_error(session, LIBSSH2_ERROR_ALLOC,
|
||||||
|
"Unable to allocate memory for ED25519 key");
|
||||||
goto clean_exit;
|
goto clean_exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1706,6 +1700,8 @@ gen_publickey_from_ed25519_openssh_priv_data(LIBSSH2_SESSION *session,
|
|||||||
key_len = LIBSSH2_ED25519_KEY_LEN + 19;
|
key_len = LIBSSH2_ED25519_KEY_LEN + 19;
|
||||||
key = LIBSSH2_CALLOC(session, key_len);
|
key = LIBSSH2_CALLOC(session, key_len);
|
||||||
if(key == NULL) {
|
if(key == NULL) {
|
||||||
|
_libssh2_error(session, LIBSSH2_ERROR_ALLOC,
|
||||||
|
"Unable to allocate memory for ED25519 key");
|
||||||
goto clean_exit;
|
goto clean_exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2229,6 +2225,19 @@ _libssh2_sha512(const unsigned char *message, unsigned long len,
|
|||||||
int
|
int
|
||||||
_libssh2_md5_init(libssh2_md5_ctx *ctx)
|
_libssh2_md5_init(libssh2_md5_ctx *ctx)
|
||||||
{
|
{
|
||||||
|
/* MD5 digest is not supported in OpenSSL FIPS mode
|
||||||
|
* Trying to init it will result in a latent OpenSSL error:
|
||||||
|
* "digital envelope routines:FIPS_DIGESTINIT:disabled for fips"
|
||||||
|
* So, just return 0 in FIPS mode
|
||||||
|
*/
|
||||||
|
#if OPENSSL_VERSION_NUMBER >= 0x000907000L && \
|
||||||
|
defined(OPENSSL_VERSION_MAJOR) && \
|
||||||
|
OPENSSL_VERSION_MAJOR < 3 && \
|
||||||
|
!defined(LIBRESSL_VERSION_NUMBER)
|
||||||
|
if(FIPS_mode() != 0)
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_OPAQUE_STRUCTS
|
#ifdef HAVE_OPAQUE_STRUCTS
|
||||||
*ctx = EVP_MD_CTX_new();
|
*ctx = EVP_MD_CTX_new();
|
||||||
|
|
||||||
@@ -2419,6 +2428,7 @@ gen_publickey_from_ecdsa_openssh_priv_data(LIBSSH2_SESSION *session,
|
|||||||
|
|
||||||
if((rc = _libssh2_ecdsa_curve_name_with_octal_new(&ec_key, point_buf,
|
if((rc = _libssh2_ecdsa_curve_name_with_octal_new(&ec_key, point_buf,
|
||||||
pointlen, curve_type)) != 0) {
|
pointlen, curve_type)) != 0) {
|
||||||
|
rc = -1;
|
||||||
_libssh2_error(session, LIBSSH2_ERROR_PROTO,
|
_libssh2_error(session, LIBSSH2_ERROR_PROTO,
|
||||||
"ECDSA could not create key");
|
"ECDSA could not create key");
|
||||||
goto fail;
|
goto fail;
|
||||||
@@ -2427,6 +2437,8 @@ gen_publickey_from_ecdsa_openssh_priv_data(LIBSSH2_SESSION *session,
|
|||||||
bn_exponent = BN_new();
|
bn_exponent = BN_new();
|
||||||
if(bn_exponent == NULL) {
|
if(bn_exponent == NULL) {
|
||||||
rc = -1;
|
rc = -1;
|
||||||
|
_libssh2_error(session, LIBSSH2_ERROR_ALLOC,
|
||||||
|
"Unable to allocate memory for private key data");
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2453,15 +2465,10 @@ gen_publickey_from_ecdsa_openssh_priv_data(LIBSSH2_SESSION *session,
|
|||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
|
|
||||||
if(ec_key != NULL)
|
if(ec_key != NULL)
|
||||||
EC_KEY_free(ec_key);
|
EC_KEY_free(ec_key);
|
||||||
|
|
||||||
return _libssh2_error(session,
|
return rc;
|
||||||
LIBSSH2_ERROR_ALLOC,
|
|
||||||
"Unable to allocate memory for private key data");
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@@ -3054,17 +3061,13 @@ _libssh2_pub_priv_openssh_keyfilememory(LIBSSH2_SESSION *session,
|
|||||||
if(key_ctx != NULL)
|
if(key_ctx != NULL)
|
||||||
*key_ctx = NULL;
|
*key_ctx = NULL;
|
||||||
|
|
||||||
if(session == NULL) {
|
if(session == NULL)
|
||||||
_libssh2_error(session, LIBSSH2_ERROR_PROTO,
|
return _libssh2_error(session, LIBSSH2_ERROR_PROTO,
|
||||||
"Session is required");
|
"Session is required");
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(key_type != NULL && (strlen(key_type) > 11 || strlen(key_type) < 7)) {
|
if(key_type != NULL && (strlen(key_type) > 11 || strlen(key_type) < 7))
|
||||||
_libssh2_error(session, LIBSSH2_ERROR_PROTO,
|
return _libssh2_error(session, LIBSSH2_ERROR_PROTO,
|
||||||
"type is invalid");
|
"type is invalid");
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
_libssh2_init_if_needed();
|
_libssh2_init_if_needed();
|
||||||
|
|
||||||
@@ -3072,20 +3075,18 @@ _libssh2_pub_priv_openssh_keyfilememory(LIBSSH2_SESSION *session,
|
|||||||
privatekeydata,
|
privatekeydata,
|
||||||
privatekeydata_len, &decrypted);
|
privatekeydata_len, &decrypted);
|
||||||
|
|
||||||
if(rc) {
|
if(rc)
|
||||||
return rc;
|
return rc;
|
||||||
}
|
|
||||||
|
|
||||||
/* We have a new key file, now try and parse it using supported types */
|
/* We have a new key file, now try and parse it using supported types */
|
||||||
rc = _libssh2_get_string(decrypted, &buf, NULL);
|
rc = _libssh2_get_string(decrypted, &buf, NULL);
|
||||||
|
|
||||||
if(rc != 0 || buf == NULL) {
|
if(rc != 0 || buf == NULL)
|
||||||
_libssh2_error(session, LIBSSH2_ERROR_PROTO,
|
return _libssh2_error(session, LIBSSH2_ERROR_PROTO,
|
||||||
"Public key type in decrypted key data not found");
|
"Public key type in decrypted "
|
||||||
return -1;
|
"key data not found");
|
||||||
}
|
|
||||||
|
|
||||||
rc = -1;
|
rc = LIBSSH2_ERROR_FILE;
|
||||||
|
|
||||||
#if LIBSSH2_ED25519
|
#if LIBSSH2_ED25519
|
||||||
if(strcmp("ssh-ed25519", (const char *)buf) == 0) {
|
if(strcmp("ssh-ed25519", (const char *)buf) == 0) {
|
||||||
@@ -3139,6 +3140,11 @@ _libssh2_pub_priv_openssh_keyfilememory(LIBSSH2_SESSION *session,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if(rc == LIBSSH2_ERROR_FILE)
|
||||||
|
rc = _libssh2_error(session, LIBSSH2_ERROR_FILE,
|
||||||
|
"Unable to extract public key from private key file: "
|
||||||
|
"invalid/unrecognized private key file format");
|
||||||
|
|
||||||
if(decrypted)
|
if(decrypted)
|
||||||
_libssh2_string_buf_free(session, decrypted);
|
_libssh2_string_buf_free(session, decrypted);
|
||||||
|
|
||||||
@@ -3178,10 +3184,10 @@ _libssh2_pub_priv_keyfilememory(LIBSSH2_SESSION *session,
|
|||||||
"Computing public key from private key.");
|
"Computing public key from private key.");
|
||||||
|
|
||||||
bp = BIO_new_mem_buf((char *)privatekeydata, privatekeydata_len);
|
bp = BIO_new_mem_buf((char *)privatekeydata, privatekeydata_len);
|
||||||
if(!bp) {
|
if(!bp)
|
||||||
return -1;
|
return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
|
||||||
}
|
"Unable to allocate memory when"
|
||||||
|
"computing public key");
|
||||||
BIO_reset(bp);
|
BIO_reset(bp);
|
||||||
pk = PEM_read_bio_PrivateKey(bp, NULL, NULL, (void *)passphrase);
|
pk = PEM_read_bio_PrivateKey(bp, NULL, NULL, (void *)passphrase);
|
||||||
BIO_free(bp);
|
BIO_free(bp);
|
||||||
@@ -3196,15 +3202,8 @@ _libssh2_pub_priv_keyfilememory(LIBSSH2_SESSION *session,
|
|||||||
privatekeydata,
|
privatekeydata,
|
||||||
privatekeydata_len,
|
privatekeydata_len,
|
||||||
(unsigned const char *)passphrase);
|
(unsigned const char *)passphrase);
|
||||||
if(st != 0) {
|
if(st != 0)
|
||||||
return _libssh2_error(session,
|
return st;
|
||||||
LIBSSH2_ERROR_FILE,
|
|
||||||
"Unable to extract public key "
|
|
||||||
"from private key file: "
|
|
||||||
"Wrong passphrase or invalid/unrecognized "
|
|
||||||
"private key file format");
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,3 +1,5 @@
|
|||||||
|
#ifndef __LIBSSH2_OPENSSL_H
|
||||||
|
#define __LIBSSH2_OPENSSL_H
|
||||||
/* Copyright (C) 2009, 2010 Simon Josefsson
|
/* Copyright (C) 2009, 2010 Simon Josefsson
|
||||||
* Copyright (C) 2006, 2007 The Written Word, Inc. All rights reserved.
|
* Copyright (C) 2006, 2007 The Written Word, Inc. All rights reserved.
|
||||||
*
|
*
|
||||||
@@ -135,7 +137,7 @@
|
|||||||
|
|
||||||
#define EC_MAX_POINT_LEN ((528 * 2 / 8) + 1)
|
#define EC_MAX_POINT_LEN ((528 * 2 / 8) + 1)
|
||||||
|
|
||||||
#define _libssh2_random(buf, len) RAND_bytes ((buf), (len))
|
#define _libssh2_random(buf, len) (RAND_bytes((buf), (len)) == 1 ? 0 : -1)
|
||||||
|
|
||||||
#define libssh2_prepare_iovec(vec, len) /* Empty. */
|
#define libssh2_prepare_iovec(vec, len) /* Empty. */
|
||||||
|
|
||||||
@@ -323,10 +325,8 @@ libssh2_curve_type;
|
|||||||
|
|
||||||
#if LIBSSH2_ED25519
|
#if LIBSSH2_ED25519
|
||||||
#define libssh2_ed25519_ctx EVP_PKEY
|
#define libssh2_ed25519_ctx EVP_PKEY
|
||||||
#define libssh2_x25519_ctx EVP_PKEY
|
|
||||||
|
|
||||||
#define _libssh2_ed25519_free(ctx) EVP_PKEY_free(ctx)
|
#define _libssh2_ed25519_free(ctx) EVP_PKEY_free(ctx)
|
||||||
#define _libssh2_x25519_free(ctx) EVP_PKEY_free(ctx)
|
|
||||||
#endif /* ED25519 */
|
#endif /* ED25519 */
|
||||||
|
|
||||||
#define _libssh2_cipher_type(name) const EVP_CIPHER *(*name)(void)
|
#define _libssh2_cipher_type(name) const EVP_CIPHER *(*name)(void)
|
||||||
@@ -392,3 +392,5 @@ extern void _libssh2_dh_dtor(_libssh2_dh_ctx *dhctx);
|
|||||||
const EVP_CIPHER *_libssh2_EVP_aes_128_ctr(void);
|
const EVP_CIPHER *_libssh2_EVP_aes_128_ctr(void);
|
||||||
const EVP_CIPHER *_libssh2_EVP_aes_192_ctr(void);
|
const EVP_CIPHER *_libssh2_EVP_aes_192_ctr(void);
|
||||||
const EVP_CIPHER *_libssh2_EVP_aes_256_ctr(void);
|
const EVP_CIPHER *_libssh2_EVP_aes_256_ctr(void);
|
||||||
|
|
||||||
|
#endif /* __LIBSSH2_OPENSSL_H */
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2015-2016 Patrick Monnerat, D+H <patrick.monnerat@dh.com>
|
* Copyright (C) 2015-2016 Patrick Monnerat, D+H <patrick.monnerat@dh.com>
|
||||||
|
* Copyright (C) 2020 Patrick Monnerat <patrick@monnerat.net>.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms,
|
* Redistribution and use in source and binary forms,
|
||||||
@@ -883,11 +884,14 @@ _libssh2_bn_from_bn(_libssh2_bn *to, _libssh2_bn *from)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
int
|
||||||
_libssh2_random(unsigned char *buf, int len)
|
_libssh2_random(unsigned char *buf, int len)
|
||||||
{
|
{
|
||||||
Qc3GenPRNs(buf, len,
|
Qc3GenPRNs(buf, len,
|
||||||
Qc3PRN_TYPE_NORMAL, Qc3PRN_NO_PARITY, (char *) &ecnull);
|
Qc3PRN_TYPE_NORMAL, Qc3PRN_NO_PARITY, (char *) &ecnull);
|
||||||
|
/* FIXME: any error is silently discarded! But Qc3GenPRNs could fail,
|
||||||
|
including if "The system seed digest is not ready" dixit IBM doc. */
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -965,7 +969,7 @@ libssh2_os400qc3_hash_init(Qc3_Format_ALGD0100_T *x, unsigned int algorithm)
|
|||||||
|
|
||||||
void
|
void
|
||||||
libssh2_os400qc3_hash_update(Qc3_Format_ALGD0100_T *ctx,
|
libssh2_os400qc3_hash_update(Qc3_Format_ALGD0100_T *ctx,
|
||||||
unsigned char *data, int len)
|
const unsigned char *data, int len)
|
||||||
{
|
{
|
||||||
char dummy[64];
|
char dummy[64];
|
||||||
|
|
||||||
@@ -995,7 +999,7 @@ libssh2_os400qc3_hash(const unsigned char *message, unsigned long len,
|
|||||||
if(!libssh2_os400qc3_hash_init(&ctx, algo))
|
if(!libssh2_os400qc3_hash_init(&ctx, algo))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
libssh2_os400qc3_hash_update(&ctx, (unsigned char *) message, len);
|
libssh2_os400qc3_hash_update(&ctx, message, len);
|
||||||
libssh2_os400qc3_hash_final(&ctx, out);
|
libssh2_os400qc3_hash_final(&ctx, out);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -1390,8 +1394,7 @@ pbkdf1(LIBSSH2_SESSION *session, char **dk, const unsigned char *passphrase,
|
|||||||
|
|
||||||
/* Initial hash. */
|
/* Initial hash. */
|
||||||
libssh2_os400qc3_hash_init(&hctx, pkcs5->hash);
|
libssh2_os400qc3_hash_init(&hctx, pkcs5->hash);
|
||||||
libssh2_os400qc3_hash_update(&hctx, (unsigned char *) passphrase,
|
libssh2_os400qc3_hash_update(&hctx, passphrase, strlen(passphrase));
|
||||||
strlen(passphrase));
|
|
||||||
hctx.Final_Op_Flag = Qc3_Final;
|
hctx.Final_Op_Flag = Qc3_Final;
|
||||||
Qc3CalculateHash((char *) pkcs5->salt, &len, Qc3_Data, (char *) &hctx,
|
Qc3CalculateHash((char *) pkcs5->salt, &len, Qc3_Data, (char *) &hctx,
|
||||||
Qc3_Alg_Token, anycsp, NULL, *dk, (char *) &ecnull);
|
Qc3_Alg_Token, anycsp, NULL, *dk, (char *) &ecnull);
|
||||||
|
@@ -1,5 +1,8 @@
|
|||||||
|
#ifndef __LIBSSH2_OS400QC3_H
|
||||||
|
#define __LIBSSH2_OS400QC3_H
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2015-2016 Patrick Monnerat, D+H <patrick.monnerat@dh.com>
|
* Copyright (C) 2015-2016 Patrick Monnerat, D+H <patrick.monnerat@dh.com>
|
||||||
|
* Copyright (C) 2020 Patrick Monnerat <patrick@monnerat.net>.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms,
|
* Redistribution and use in source and binary forms,
|
||||||
@@ -36,9 +39,6 @@
|
|||||||
* OF SUCH DAMAGE.
|
* OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef LIBSSH2_OS400QC3_H
|
|
||||||
#define LIBSSH2_OS400QC3_H
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
@@ -176,12 +176,21 @@
|
|||||||
|
|
||||||
#define LIBSSH2_RSA 1
|
#define LIBSSH2_RSA 1
|
||||||
#define LIBSSH2_DSA 0
|
#define LIBSSH2_DSA 0
|
||||||
|
#define LIBSSH2_ECDSA 0
|
||||||
|
#define LIBSSH2_ED25519 0
|
||||||
|
|
||||||
#define MD5_DIGEST_LENGTH 16
|
#define MD5_DIGEST_LENGTH 16
|
||||||
#define SHA_DIGEST_LENGTH 20
|
#define SHA_DIGEST_LENGTH 20
|
||||||
#define SHA256_DIGEST_LENGTH 32
|
#define SHA256_DIGEST_LENGTH 32
|
||||||
|
#define SHA384_DIGEST_LENGTH 48
|
||||||
#define SHA512_DIGEST_LENGTH 64
|
#define SHA512_DIGEST_LENGTH 64
|
||||||
|
|
||||||
|
#define EC_MAX_POINT_LEN ((528 * 2 / 8) + 1)
|
||||||
|
|
||||||
|
#if LIBSSH2_ECDSA
|
||||||
|
#else
|
||||||
|
#define _libssh2_ec_key void
|
||||||
|
#endif
|
||||||
|
|
||||||
/*******************************************************************
|
/*******************************************************************
|
||||||
*
|
*
|
||||||
@@ -225,6 +234,8 @@ typedef struct { /* Diffie-Hellman context. */
|
|||||||
|
|
||||||
#define libssh2_sha1_ctx Qc3_Format_ALGD0100_T
|
#define libssh2_sha1_ctx Qc3_Format_ALGD0100_T
|
||||||
#define libssh2_sha256_ctx Qc3_Format_ALGD0100_T
|
#define libssh2_sha256_ctx Qc3_Format_ALGD0100_T
|
||||||
|
#define libssh2_sha384_ctx Qc3_Format_ALGD0100_T
|
||||||
|
#define libssh2_sha512_ctx Qc3_Format_ALGD0100_T
|
||||||
#define libssh2_md5_ctx Qc3_Format_ALGD0100_T
|
#define libssh2_md5_ctx Qc3_Format_ALGD0100_T
|
||||||
#define libssh2_hmac_ctx _libssh2_os400qc3_crypto_ctx
|
#define libssh2_hmac_ctx _libssh2_os400qc3_crypto_ctx
|
||||||
#define _libssh2_cipher_ctx _libssh2_os400qc3_crypto_ctx
|
#define _libssh2_cipher_ctx _libssh2_os400qc3_crypto_ctx
|
||||||
@@ -239,9 +250,25 @@ typedef struct { /* Diffie-Hellman context. */
|
|||||||
libssh2_os400qc3_hash_update(&(ctx), data, len)
|
libssh2_os400qc3_hash_update(&(ctx), data, len)
|
||||||
#define libssh2_sha256_final(ctx, out) \
|
#define libssh2_sha256_final(ctx, out) \
|
||||||
libssh2_os400qc3_hash_final(&(ctx), out)
|
libssh2_os400qc3_hash_final(&(ctx), out)
|
||||||
#define libssh2_sha256(message, len, out) \
|
#define libssh2_sha256(message, len, out) \
|
||||||
libssh2_os400qc3_hash(message, len, out, \
|
libssh2_os400qc3_hash(message, len, out, \
|
||||||
Qc3_SHA256)
|
Qc3_SHA256)
|
||||||
|
#define libssh2_sha384_init(x) libssh2_os400qc3_hash_init(x, Qc3_SHA384)
|
||||||
|
#define libssh2_sha384_update(ctx, data, len) \
|
||||||
|
libssh2_os400qc3_hash_update(&(ctx), data, len)
|
||||||
|
#define libssh2_sha384_final(ctx, out) \
|
||||||
|
libssh2_os400qc3_hash_final(&(ctx), out)
|
||||||
|
#define libssh2_sha384(message, len, out) \
|
||||||
|
libssh2_os400qc3_hash(message, len, out, \
|
||||||
|
Qc3_SHA384)
|
||||||
|
#define libssh2_sha512_init(x) libssh2_os400qc3_hash_init(x, Qc3_SHA512)
|
||||||
|
#define libssh2_sha512_update(ctx, data, len) \
|
||||||
|
libssh2_os400qc3_hash_update(&(ctx), data, len)
|
||||||
|
#define libssh2_sha512_final(ctx, out) \
|
||||||
|
libssh2_os400qc3_hash_final(&(ctx), out)
|
||||||
|
#define libssh2_sha512(message, len, out) \
|
||||||
|
libssh2_os400qc3_hash(message, len, out, \
|
||||||
|
Qc3_SHA512)
|
||||||
#define libssh2_md5_init(x) libssh2_os400qc3_hash_init(x, Qc3_MD5)
|
#define libssh2_md5_init(x) libssh2_os400qc3_hash_init(x, Qc3_MD5)
|
||||||
#define libssh2_md5_update(ctx, data, len) \
|
#define libssh2_md5_update(ctx, data, len) \
|
||||||
libssh2_os400qc3_hash_update(&(ctx), data, len)
|
libssh2_os400qc3_hash_update(&(ctx), data, len)
|
||||||
@@ -333,12 +360,13 @@ extern int _libssh2_bn_from_bin(_libssh2_bn *bn, int len,
|
|||||||
const unsigned char *v);
|
const unsigned char *v);
|
||||||
extern int _libssh2_bn_set_word(_libssh2_bn *bn, unsigned long val);
|
extern int _libssh2_bn_set_word(_libssh2_bn *bn, unsigned long val);
|
||||||
extern int _libssh2_bn_to_bin(_libssh2_bn *bn, unsigned char *val);
|
extern int _libssh2_bn_to_bin(_libssh2_bn *bn, unsigned char *val);
|
||||||
extern void _libssh2_random(unsigned char *buf, int len);
|
extern int _libssh2_random(unsigned char *buf, int len);
|
||||||
extern void _libssh2_os400qc3_crypto_dtor(_libssh2_os400qc3_crypto_ctx *x);
|
extern void _libssh2_os400qc3_crypto_dtor(_libssh2_os400qc3_crypto_ctx *x);
|
||||||
extern int libssh2_os400qc3_hash_init(Qc3_Format_ALGD0100_T *x,
|
extern int libssh2_os400qc3_hash_init(Qc3_Format_ALGD0100_T *x,
|
||||||
unsigned int algo);
|
unsigned int algo);
|
||||||
extern void libssh2_os400qc3_hash_update(Qc3_Format_ALGD0100_T *ctx,
|
extern void libssh2_os400qc3_hash_update(Qc3_Format_ALGD0100_T *ctx,
|
||||||
unsigned char *data, int len);
|
const unsigned char *data,
|
||||||
|
int len);
|
||||||
extern void libssh2_os400qc3_hash_final(Qc3_Format_ALGD0100_T *ctx,
|
extern void libssh2_os400qc3_hash_final(Qc3_Format_ALGD0100_T *ctx,
|
||||||
unsigned char *out);
|
unsigned char *out);
|
||||||
extern int libssh2_os400qc3_hash(const unsigned char *message,
|
extern int libssh2_os400qc3_hash(const unsigned char *message,
|
||||||
@@ -368,6 +396,6 @@ extern int _libssh2_os400qc3_dh_secret(_libssh2_dh_ctx *dhctx,
|
|||||||
_libssh2_bn *f, _libssh2_bn *p);
|
_libssh2_bn *f, _libssh2_bn *p);
|
||||||
extern void _libssh2_os400qc3_dh_dtor(_libssh2_dh_ctx *dhctx);
|
extern void _libssh2_os400qc3_dh_dtor(_libssh2_dh_ctx *dhctx);
|
||||||
|
|
||||||
#endif
|
#endif /* __LIBSSH2_OS400QC3_H */
|
||||||
|
|
||||||
/* vim: set expandtab ts=4 sw=4: */
|
/* vim: set expandtab ts=4 sw=4: */
|
||||||
|
@@ -1323,9 +1323,11 @@ _libssh2_packet_requirev(LIBSSH2_SESSION *session,
|
|||||||
|
|
||||||
if(strchr((char *) packet_types, ret)) {
|
if(strchr((char *) packet_types, ret)) {
|
||||||
/* Be lazy, let packet_ask pull it out of the brigade */
|
/* Be lazy, let packet_ask pull it out of the brigade */
|
||||||
return _libssh2_packet_askv(session, packet_types, data,
|
int ret = _libssh2_packet_askv(session, packet_types, data,
|
||||||
data_len, match_ofs, match_buf,
|
data_len, match_ofs, match_buf,
|
||||||
match_len);
|
match_len);
|
||||||
|
state->start = 0;
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
#ifndef LIBSSH2_PACKET_H
|
#ifndef __LIBSSH2_PACKET_H
|
||||||
#define LIBSSH2_PACKET_H
|
#define __LIBSSH2_PACKET_H
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2010 by Daniel Stenberg
|
* Copyright (C) 2010 by Daniel Stenberg
|
||||||
* Author: Daniel Stenberg <daniel@haxx.se>
|
* Author: Daniel Stenberg <daniel@haxx.se>
|
||||||
@@ -73,4 +73,4 @@ int _libssh2_packet_write(LIBSSH2_SESSION * session, unsigned char *data,
|
|||||||
int _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
|
int _libssh2_packet_add(LIBSSH2_SESSION * session, unsigned char *data,
|
||||||
size_t datalen, int macstate);
|
size_t datalen, int macstate);
|
||||||
|
|
||||||
#endif /* LIBSSH2_PACKET_H */
|
#endif /* __LIBSSH2_PACKET_H */
|
||||||
|
31
src/pem.c
31
src/pem.c
@@ -176,6 +176,8 @@ _libssh2_pem_parse(LIBSSH2_SESSION * session,
|
|||||||
linelen = strlen(line);
|
linelen = strlen(line);
|
||||||
tmp = LIBSSH2_REALLOC(session, b64data, b64datalen + linelen);
|
tmp = LIBSSH2_REALLOC(session, b64data, b64datalen + linelen);
|
||||||
if(!tmp) {
|
if(!tmp) {
|
||||||
|
_libssh2_error(session, LIBSSH2_ERROR_ALLOC,
|
||||||
|
"Unable to allocate memory for PEM parsing");
|
||||||
ret = -1;
|
ret = -1;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@@ -319,6 +321,8 @@ _libssh2_pem_parse_memory(LIBSSH2_SESSION * session,
|
|||||||
linelen = strlen(line);
|
linelen = strlen(line);
|
||||||
tmp = LIBSSH2_REALLOC(session, b64data, b64datalen + linelen);
|
tmp = LIBSSH2_REALLOC(session, b64data, b64datalen + linelen);
|
||||||
if(!tmp) {
|
if(!tmp) {
|
||||||
|
_libssh2_error(session, LIBSSH2_ERROR_ALLOC,
|
||||||
|
"Unable to allocate memory for PEM parsing");
|
||||||
ret = -1;
|
ret = -1;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@@ -690,6 +694,8 @@ _libssh2_openssh_pem_parse(LIBSSH2_SESSION * session,
|
|||||||
linelen = strlen(line);
|
linelen = strlen(line);
|
||||||
tmp = LIBSSH2_REALLOC(session, b64data, b64datalen + linelen);
|
tmp = LIBSSH2_REALLOC(session, b64data, b64datalen + linelen);
|
||||||
if(!tmp) {
|
if(!tmp) {
|
||||||
|
_libssh2_error(session, LIBSSH2_ERROR_ALLOC,
|
||||||
|
"Unable to allocate memory for PEM parsing");
|
||||||
ret = -1;
|
ret = -1;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@@ -738,17 +744,17 @@ _libssh2_openssh_pem_parse_memory(LIBSSH2_SESSION * session,
|
|||||||
size_t off = 0;
|
size_t off = 0;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if(filedata == NULL || filedata_len <= 0) {
|
if(filedata == NULL || filedata_len <= 0)
|
||||||
return -1;
|
return _libssh2_error(session, LIBSSH2_ERROR_PROTO,
|
||||||
}
|
"Error parsing PEM: filedata missing");
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
|
||||||
*line = '\0';
|
*line = '\0';
|
||||||
|
|
||||||
if(off >= filedata_len) {
|
if(off >= filedata_len)
|
||||||
return -1;
|
return _libssh2_error(session, LIBSSH2_ERROR_PROTO,
|
||||||
}
|
"Error parsing PEM: offset out of bounds");
|
||||||
|
|
||||||
if(readline_memory(line, LINE_SIZE, filedata, filedata_len, &off)) {
|
if(readline_memory(line, LINE_SIZE, filedata, filedata_len, &off)) {
|
||||||
return -1;
|
return -1;
|
||||||
@@ -766,7 +772,9 @@ _libssh2_openssh_pem_parse_memory(LIBSSH2_SESSION * session,
|
|||||||
linelen = strlen(line);
|
linelen = strlen(line);
|
||||||
tmp = LIBSSH2_REALLOC(session, b64data, b64datalen + linelen);
|
tmp = LIBSSH2_REALLOC(session, b64data, b64datalen + linelen);
|
||||||
if(!tmp) {
|
if(!tmp) {
|
||||||
ret = -1;
|
ret = _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
|
||||||
|
"Unable to allocate memory for "
|
||||||
|
"PEM parsing");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
memcpy(tmp + b64datalen, line, linelen);
|
memcpy(tmp + b64datalen, line, linelen);
|
||||||
@@ -777,7 +785,8 @@ _libssh2_openssh_pem_parse_memory(LIBSSH2_SESSION * session,
|
|||||||
*line = '\0';
|
*line = '\0';
|
||||||
|
|
||||||
if(off >= filedata_len) {
|
if(off >= filedata_len) {
|
||||||
ret = -1;
|
ret = _libssh2_error(session, LIBSSH2_ERROR_PROTO,
|
||||||
|
"Error parsing PEM: offset out of bounds");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -787,9 +796,9 @@ _libssh2_openssh_pem_parse_memory(LIBSSH2_SESSION * session,
|
|||||||
}
|
}
|
||||||
} while(strcmp(line, OPENSSH_HEADER_END) != 0);
|
} while(strcmp(line, OPENSSH_HEADER_END) != 0);
|
||||||
|
|
||||||
if(!b64data) {
|
if(!b64data)
|
||||||
return -1;
|
return _libssh2_error(session, LIBSSH2_ERROR_PROTO,
|
||||||
}
|
"Error parsing PEM: base 64 data missing");
|
||||||
|
|
||||||
ret = _libssh2_openssh_pem_parse_data(session, passphrase, b64data,
|
ret = _libssh2_openssh_pem_parse_data(session, passphrase, b64data,
|
||||||
b64datalen, decrypted_buf);
|
b64datalen, decrypted_buf);
|
||||||
|
@@ -65,13 +65,13 @@
|
|||||||
current argument word, add the apostrophe in quotation marks "",
|
current argument word, add the apostrophe in quotation marks "",
|
||||||
and open a new argument word instead (_ indicate the input
|
and open a new argument word instead (_ indicate the input
|
||||||
string characters):
|
string characters):
|
||||||
_____ _ _
|
_____ _ _
|
||||||
'doesn' "'" 't'
|
'doesn' "'" 't'
|
||||||
|
|
||||||
Sequences of apostrophes are combined in one pair of quotation marks:
|
Sequences of apostrophes are combined in one pair of quotation marks:
|
||||||
a'''b
|
a'''b
|
||||||
becomes
|
becomes
|
||||||
_ ___ _
|
_ ___ _
|
||||||
'a'"'''"'b'
|
'a'"'''"'b'
|
||||||
|
|
||||||
o If the string contains an exclamation mark (!), the C-Shell
|
o If the string contains an exclamation mark (!), the C-Shell
|
||||||
@@ -84,7 +84,7 @@
|
|||||||
a!b
|
a!b
|
||||||
|
|
||||||
become
|
become
|
||||||
_ _ _
|
_ _ _
|
||||||
'a'\!'b'
|
'a'\!'b'
|
||||||
|
|
||||||
The result buffer must be large enough for the expanded result. A
|
The result buffer must be large enough for the expanded result. A
|
||||||
|
@@ -219,7 +219,7 @@ banner_send(LIBSSH2_SESSION * session)
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
memcpy(banner_dup, banner, 255);
|
memcpy(banner_dup, banner, 255);
|
||||||
banner[255] = '\0';
|
banner_dup[255] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
_libssh2_debug(session, LIBSSH2_TRACE_TRANS, "Sending Banner: %s",
|
_libssh2_debug(session, LIBSSH2_TRACE_TRANS, "Sending Banner: %s",
|
||||||
@@ -589,7 +589,7 @@ int _libssh2_wait_socket(LIBSSH2_SESSION *session, time_t start_time)
|
|||||||
session->err_code = LIBSSH2_ERROR_NONE;
|
session->err_code = LIBSSH2_ERROR_NONE;
|
||||||
|
|
||||||
rc = libssh2_keepalive_send(session, &seconds_to_next);
|
rc = libssh2_keepalive_send(session, &seconds_to_next);
|
||||||
if(rc < 0)
|
if(rc)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
ms_to_next = seconds_to_next * 1000;
|
ms_to_next = seconds_to_next * 1000;
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
#ifndef LIBSSH2_SESSION_H
|
#ifndef __LIBSSH2_SESSION_H
|
||||||
#define LIBSSH2_SESSION_H
|
#define __LIBSSH2_SESSION_H
|
||||||
/* Copyright (c) 2004-2007 Sara Golemon <sarag@libssh2.org>
|
/* Copyright (c) 2004-2007 Sara Golemon <sarag@libssh2.org>
|
||||||
* Copyright (c) 2009-2010 by Daniel Stenberg
|
* Copyright (c) 2009-2010 by Daniel Stenberg
|
||||||
* Copyright (c) 2010 Simon Josefsson <simon@josefsson.org>
|
* Copyright (c) 2010 Simon Josefsson <simon@josefsson.org>
|
||||||
@@ -90,4 +90,4 @@ int _libssh2_wait_socket(LIBSSH2_SESSION *session, time_t entry_time);
|
|||||||
/* this is the lib-internal set blocking function */
|
/* this is the lib-internal set blocking function */
|
||||||
int _libssh2_session_set_blocking(LIBSSH2_SESSION * session, int blocking);
|
int _libssh2_session_set_blocking(LIBSSH2_SESSION * session, int blocking);
|
||||||
|
|
||||||
#endif /* LIBSSH2_SESSION_H */
|
#endif /* __LIBSSH2_SESSION_H */
|
||||||
|
52
src/sftp.c
52
src/sftp.c
@@ -765,7 +765,7 @@ LIBSSH2_CHANNEL_CLOSE_FUNC(libssh2_sftp_dtor)
|
|||||||
static LIBSSH2_SFTP *sftp_init(LIBSSH2_SESSION *session)
|
static LIBSSH2_SFTP *sftp_init(LIBSSH2_SESSION *session)
|
||||||
{
|
{
|
||||||
unsigned char *data;
|
unsigned char *data;
|
||||||
size_t data_len;
|
size_t data_len = 0;
|
||||||
ssize_t rc;
|
ssize_t rc;
|
||||||
LIBSSH2_SFTP *sftp_handle;
|
LIBSSH2_SFTP *sftp_handle;
|
||||||
struct string_buf buf;
|
struct string_buf buf;
|
||||||
@@ -1561,7 +1561,7 @@ static ssize_t sftp_read(LIBSSH2_SFTP_HANDLE * handle, char *buffer,
|
|||||||
|
|
||||||
while(chunk) {
|
while(chunk) {
|
||||||
unsigned char *data;
|
unsigned char *data;
|
||||||
size_t data_len;
|
size_t data_len = 0;
|
||||||
uint32_t rc32;
|
uint32_t rc32;
|
||||||
static const unsigned char read_responses[2] = {
|
static const unsigned char read_responses[2] = {
|
||||||
SSH_FXP_DATA, SSH_FXP_STATUS
|
SSH_FXP_DATA, SSH_FXP_STATUS
|
||||||
@@ -1751,7 +1751,7 @@ static ssize_t sftp_readdir(LIBSSH2_SFTP_HANDLE *handle, char *buffer,
|
|||||||
LIBSSH2_SFTP *sftp = handle->sftp;
|
LIBSSH2_SFTP *sftp = handle->sftp;
|
||||||
LIBSSH2_CHANNEL *channel = sftp->channel;
|
LIBSSH2_CHANNEL *channel = sftp->channel;
|
||||||
LIBSSH2_SESSION *session = channel->session;
|
LIBSSH2_SESSION *session = channel->session;
|
||||||
size_t data_len;
|
size_t data_len = 0;
|
||||||
uint32_t num_names;
|
uint32_t num_names;
|
||||||
/* 13 = packet_len(4) + packet_type(1) + request_id(4) + handle_len(4) */
|
/* 13 = packet_len(4) + packet_type(1) + request_id(4) + handle_len(4) */
|
||||||
uint32_t packet_len = handle->handle_len + 13;
|
uint32_t packet_len = handle->handle_len + 13;
|
||||||
@@ -2017,10 +2017,10 @@ static ssize_t sftp_write(LIBSSH2_SFTP_HANDLE *handle, const char *buffer,
|
|||||||
LIBSSH2_SFTP *sftp = handle->sftp;
|
LIBSSH2_SFTP *sftp = handle->sftp;
|
||||||
LIBSSH2_CHANNEL *channel = sftp->channel;
|
LIBSSH2_CHANNEL *channel = sftp->channel;
|
||||||
LIBSSH2_SESSION *session = channel->session;
|
LIBSSH2_SESSION *session = channel->session;
|
||||||
size_t data_len;
|
size_t data_len = 0;
|
||||||
uint32_t retcode;
|
uint32_t retcode;
|
||||||
uint32_t packet_len;
|
uint32_t packet_len;
|
||||||
unsigned char *s, *data;
|
unsigned char *s, *data = NULL;
|
||||||
ssize_t rc;
|
ssize_t rc;
|
||||||
struct sftp_pipeline_chunk *chunk;
|
struct sftp_pipeline_chunk *chunk;
|
||||||
struct sftp_pipeline_chunk *next;
|
struct sftp_pipeline_chunk *next;
|
||||||
@@ -2245,8 +2245,8 @@ static int sftp_fsync(LIBSSH2_SFTP_HANDLE *handle)
|
|||||||
/* 34 = packet_len(4) + packet_type(1) + request_id(4) +
|
/* 34 = packet_len(4) + packet_type(1) + request_id(4) +
|
||||||
string_len(4) + strlen("fsync@openssh.com")(17) + handle_len(4) */
|
string_len(4) + strlen("fsync@openssh.com")(17) + handle_len(4) */
|
||||||
uint32_t packet_len = handle->handle_len + 34;
|
uint32_t packet_len = handle->handle_len + 34;
|
||||||
size_t data_len;
|
size_t data_len = 0;
|
||||||
unsigned char *packet, *s, *data;
|
unsigned char *packet, *s, *data = NULL;
|
||||||
ssize_t rc;
|
ssize_t rc;
|
||||||
uint32_t retcode;
|
uint32_t retcode;
|
||||||
|
|
||||||
@@ -2350,11 +2350,11 @@ static int sftp_fstat(LIBSSH2_SFTP_HANDLE *handle,
|
|||||||
LIBSSH2_SFTP *sftp = handle->sftp;
|
LIBSSH2_SFTP *sftp = handle->sftp;
|
||||||
LIBSSH2_CHANNEL *channel = sftp->channel;
|
LIBSSH2_CHANNEL *channel = sftp->channel;
|
||||||
LIBSSH2_SESSION *session = channel->session;
|
LIBSSH2_SESSION *session = channel->session;
|
||||||
size_t data_len;
|
size_t data_len = 0;
|
||||||
/* 13 = packet_len(4) + packet_type(1) + request_id(4) + handle_len(4) */
|
/* 13 = packet_len(4) + packet_type(1) + request_id(4) + handle_len(4) */
|
||||||
uint32_t packet_len =
|
uint32_t packet_len =
|
||||||
handle->handle_len + 13 + (setstat ? sftp_attrsize(attrs->flags) : 0);
|
handle->handle_len + 13 + (setstat ? sftp_attrsize(attrs->flags) : 0);
|
||||||
unsigned char *s, *data;
|
unsigned char *s, *data = NULL;
|
||||||
static const unsigned char fstat_responses[2] =
|
static const unsigned char fstat_responses[2] =
|
||||||
{ SSH_FXP_ATTRS, SSH_FXP_STATUS };
|
{ SSH_FXP_ATTRS, SSH_FXP_STATUS };
|
||||||
ssize_t rc;
|
ssize_t rc;
|
||||||
@@ -2575,7 +2575,7 @@ sftp_close_handle(LIBSSH2_SFTP_HANDLE *handle)
|
|||||||
LIBSSH2_SFTP *sftp = handle->sftp;
|
LIBSSH2_SFTP *sftp = handle->sftp;
|
||||||
LIBSSH2_CHANNEL *channel = sftp->channel;
|
LIBSSH2_CHANNEL *channel = sftp->channel;
|
||||||
LIBSSH2_SESSION *session = channel->session;
|
LIBSSH2_SESSION *session = channel->session;
|
||||||
size_t data_len;
|
size_t data_len = 0;
|
||||||
/* 13 = packet_len(4) + packet_type(1) + request_id(4) + handle_len(4) */
|
/* 13 = packet_len(4) + packet_type(1) + request_id(4) + handle_len(4) */
|
||||||
uint32_t packet_len = handle->handle_len + 13;
|
uint32_t packet_len = handle->handle_len + 13;
|
||||||
unsigned char *s, *data = NULL;
|
unsigned char *s, *data = NULL;
|
||||||
@@ -2705,11 +2705,11 @@ static int sftp_unlink(LIBSSH2_SFTP *sftp, const char *filename,
|
|||||||
{
|
{
|
||||||
LIBSSH2_CHANNEL *channel = sftp->channel;
|
LIBSSH2_CHANNEL *channel = sftp->channel;
|
||||||
LIBSSH2_SESSION *session = channel->session;
|
LIBSSH2_SESSION *session = channel->session;
|
||||||
size_t data_len;
|
size_t data_len = 0;
|
||||||
int retcode;
|
int retcode;
|
||||||
/* 13 = packet_len(4) + packet_type(1) + request_id(4) + filename_len(4) */
|
/* 13 = packet_len(4) + packet_type(1) + request_id(4) + filename_len(4) */
|
||||||
uint32_t packet_len = filename_len + 13;
|
uint32_t packet_len = filename_len + 13;
|
||||||
unsigned char *s, *data;
|
unsigned char *s, *data = NULL;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
if(sftp->unlink_state == libssh2_NB_state_idle) {
|
if(sftp->unlink_state == libssh2_NB_state_idle) {
|
||||||
@@ -2809,14 +2809,14 @@ static int sftp_rename(LIBSSH2_SFTP *sftp, const char *source_filename,
|
|||||||
{
|
{
|
||||||
LIBSSH2_CHANNEL *channel = sftp->channel;
|
LIBSSH2_CHANNEL *channel = sftp->channel;
|
||||||
LIBSSH2_SESSION *session = channel->session;
|
LIBSSH2_SESSION *session = channel->session;
|
||||||
size_t data_len;
|
size_t data_len = 0;
|
||||||
int retcode;
|
int retcode;
|
||||||
uint32_t packet_len =
|
uint32_t packet_len =
|
||||||
source_filename_len + dest_filename_len + 17 + (sftp->version >=
|
source_filename_len + dest_filename_len + 17 + (sftp->version >=
|
||||||
5 ? 4 : 0);
|
5 ? 4 : 0);
|
||||||
/* packet_len(4) + packet_type(1) + request_id(4) +
|
/* packet_len(4) + packet_type(1) + request_id(4) +
|
||||||
source_filename_len(4) + dest_filename_len(4) + flags(4){SFTP5+) */
|
source_filename_len(4) + dest_filename_len(4) + flags(4){SFTP5+) */
|
||||||
unsigned char *data;
|
unsigned char *data = NULL;
|
||||||
ssize_t rc;
|
ssize_t rc;
|
||||||
|
|
||||||
if(sftp->version < 2) {
|
if(sftp->version < 2) {
|
||||||
@@ -2949,12 +2949,12 @@ static int sftp_fstatvfs(LIBSSH2_SFTP_HANDLE *handle, LIBSSH2_SFTP_STATVFS *st)
|
|||||||
LIBSSH2_SFTP *sftp = handle->sftp;
|
LIBSSH2_SFTP *sftp = handle->sftp;
|
||||||
LIBSSH2_CHANNEL *channel = sftp->channel;
|
LIBSSH2_CHANNEL *channel = sftp->channel;
|
||||||
LIBSSH2_SESSION *session = channel->session;
|
LIBSSH2_SESSION *session = channel->session;
|
||||||
size_t data_len;
|
size_t data_len = 0;
|
||||||
/* 17 = packet_len(4) + packet_type(1) + request_id(4) + ext_len(4)
|
/* 17 = packet_len(4) + packet_type(1) + request_id(4) + ext_len(4)
|
||||||
+ handle_len (4) */
|
+ handle_len (4) */
|
||||||
/* 20 = strlen ("fstatvfs@openssh.com") */
|
/* 20 = strlen ("fstatvfs@openssh.com") */
|
||||||
uint32_t packet_len = handle->handle_len + 20 + 17;
|
uint32_t packet_len = handle->handle_len + 20 + 17;
|
||||||
unsigned char *packet, *s, *data;
|
unsigned char *packet, *s, *data = NULL;
|
||||||
ssize_t rc;
|
ssize_t rc;
|
||||||
unsigned int flag;
|
unsigned int flag;
|
||||||
static const unsigned char responses[2] =
|
static const unsigned char responses[2] =
|
||||||
@@ -3085,12 +3085,12 @@ static int sftp_statvfs(LIBSSH2_SFTP *sftp, const char *path,
|
|||||||
{
|
{
|
||||||
LIBSSH2_CHANNEL *channel = sftp->channel;
|
LIBSSH2_CHANNEL *channel = sftp->channel;
|
||||||
LIBSSH2_SESSION *session = channel->session;
|
LIBSSH2_SESSION *session = channel->session;
|
||||||
size_t data_len;
|
size_t data_len = 0;
|
||||||
/* 17 = packet_len(4) + packet_type(1) + request_id(4) + ext_len(4)
|
/* 17 = packet_len(4) + packet_type(1) + request_id(4) + ext_len(4)
|
||||||
+ path_len (4) */
|
+ path_len (4) */
|
||||||
/* 19 = strlen ("statvfs@openssh.com") */
|
/* 19 = strlen ("statvfs@openssh.com") */
|
||||||
uint32_t packet_len = path_len + 19 + 17;
|
uint32_t packet_len = path_len + 19 + 17;
|
||||||
unsigned char *packet, *s, *data;
|
unsigned char *packet, *s, *data = NULL;
|
||||||
ssize_t rc;
|
ssize_t rc;
|
||||||
unsigned int flag;
|
unsigned int flag;
|
||||||
static const unsigned char responses[2] =
|
static const unsigned char responses[2] =
|
||||||
@@ -3225,10 +3225,10 @@ static int sftp_mkdir(LIBSSH2_SFTP *sftp, const char *path,
|
|||||||
LIBSSH2_SFTP_ATTRIBUTES attrs = {
|
LIBSSH2_SFTP_ATTRIBUTES attrs = {
|
||||||
0, 0, 0, 0, 0, 0, 0
|
0, 0, 0, 0, 0, 0, 0
|
||||||
};
|
};
|
||||||
size_t data_len;
|
size_t data_len = 0;
|
||||||
int retcode;
|
int retcode;
|
||||||
ssize_t packet_len;
|
ssize_t packet_len;
|
||||||
unsigned char *packet, *s, *data;
|
unsigned char *packet, *s, *data = NULL;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
if(mode != LIBSSH2_SFTP_DEFAULT_MODE) {
|
if(mode != LIBSSH2_SFTP_DEFAULT_MODE) {
|
||||||
@@ -3340,11 +3340,11 @@ static int sftp_rmdir(LIBSSH2_SFTP *sftp, const char *path,
|
|||||||
{
|
{
|
||||||
LIBSSH2_CHANNEL *channel = sftp->channel;
|
LIBSSH2_CHANNEL *channel = sftp->channel;
|
||||||
LIBSSH2_SESSION *session = channel->session;
|
LIBSSH2_SESSION *session = channel->session;
|
||||||
size_t data_len;
|
size_t data_len = 0;
|
||||||
int retcode;
|
int retcode;
|
||||||
/* 13 = packet_len(4) + packet_type(1) + request_id(4) + path_len(4) */
|
/* 13 = packet_len(4) + packet_type(1) + request_id(4) + path_len(4) */
|
||||||
ssize_t packet_len = path_len + 13;
|
ssize_t packet_len = path_len + 13;
|
||||||
unsigned char *s, *data;
|
unsigned char *s, *data = NULL;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
if(sftp->rmdir_state == libssh2_NB_state_idle) {
|
if(sftp->rmdir_state == libssh2_NB_state_idle) {
|
||||||
@@ -3442,13 +3442,13 @@ static int sftp_stat(LIBSSH2_SFTP *sftp, const char *path,
|
|||||||
{
|
{
|
||||||
LIBSSH2_CHANNEL *channel = sftp->channel;
|
LIBSSH2_CHANNEL *channel = sftp->channel;
|
||||||
LIBSSH2_SESSION *session = channel->session;
|
LIBSSH2_SESSION *session = channel->session;
|
||||||
size_t data_len;
|
size_t data_len = 0;
|
||||||
/* 13 = packet_len(4) + packet_type(1) + request_id(4) + path_len(4) */
|
/* 13 = packet_len(4) + packet_type(1) + request_id(4) + path_len(4) */
|
||||||
ssize_t packet_len =
|
ssize_t packet_len =
|
||||||
path_len + 13 +
|
path_len + 13 +
|
||||||
((stat_type ==
|
((stat_type ==
|
||||||
LIBSSH2_SFTP_SETSTAT) ? sftp_attrsize(attrs->flags) : 0);
|
LIBSSH2_SFTP_SETSTAT) ? sftp_attrsize(attrs->flags) : 0);
|
||||||
unsigned char *s, *data;
|
unsigned char *s, *data = NULL;
|
||||||
static const unsigned char stat_responses[2] =
|
static const unsigned char stat_responses[2] =
|
||||||
{ SSH_FXP_ATTRS, SSH_FXP_STATUS };
|
{ SSH_FXP_ATTRS, SSH_FXP_STATUS };
|
||||||
int rc;
|
int rc;
|
||||||
@@ -3580,12 +3580,12 @@ static int sftp_symlink(LIBSSH2_SFTP *sftp, const char *path,
|
|||||||
{
|
{
|
||||||
LIBSSH2_CHANNEL *channel = sftp->channel;
|
LIBSSH2_CHANNEL *channel = sftp->channel;
|
||||||
LIBSSH2_SESSION *session = channel->session;
|
LIBSSH2_SESSION *session = channel->session;
|
||||||
size_t data_len, link_len;
|
size_t data_len = 0, link_len;
|
||||||
/* 13 = packet_len(4) + packet_type(1) + request_id(4) + path_len(4) */
|
/* 13 = packet_len(4) + packet_type(1) + request_id(4) + path_len(4) */
|
||||||
ssize_t packet_len =
|
ssize_t packet_len =
|
||||||
path_len + 13 +
|
path_len + 13 +
|
||||||
((link_type == LIBSSH2_SFTP_SYMLINK) ? (4 + target_len) : 0);
|
((link_type == LIBSSH2_SFTP_SYMLINK) ? (4 + target_len) : 0);
|
||||||
unsigned char *s, *data;
|
unsigned char *s, *data = NULL;
|
||||||
static const unsigned char link_responses[2] =
|
static const unsigned char link_responses[2] =
|
||||||
{ SSH_FXP_NAME, SSH_FXP_STATUS };
|
{ SSH_FXP_NAME, SSH_FXP_STATUS };
|
||||||
int retcode;
|
int retcode;
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
#ifndef _LIBSSH2_SFTP_H
|
#ifndef __LIBSSH2_SFTP_H
|
||||||
#define _LIBSSH2_SFTP_H
|
#define __LIBSSH2_SFTP_H
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2010 - 2012 by Daniel Stenberg
|
* Copyright (C) 2010 - 2012 by Daniel Stenberg
|
||||||
* Author: Daniel Stenberg <daniel@haxx.se>
|
* Author: Daniel Stenberg <daniel@haxx.se>
|
||||||
@@ -235,4 +235,4 @@ struct _LIBSSH2_SFTP
|
|||||||
uint32_t symlink_request_id;
|
uint32_t symlink_request_id;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif /* __LIBSSH2_SFTP_H */
|
||||||
|
@@ -323,7 +323,7 @@ int _libssh2_transport_read(LIBSSH2_SESSION * session)
|
|||||||
|
|
||||||
do {
|
do {
|
||||||
if(session->socket_state == LIBSSH2_SOCKET_DISCONNECTED) {
|
if(session->socket_state == LIBSSH2_SOCKET_DISCONNECTED) {
|
||||||
return LIBSSH2_ERROR_NONE;
|
return LIBSSH2_ERROR_SOCKET_DISCONNECT;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(session->state & LIBSSH2_STATE_NEWKEYS) {
|
if(session->state & LIBSSH2_STATE_NEWKEYS) {
|
||||||
@@ -465,7 +465,7 @@ int _libssh2_transport_read(LIBSSH2_SESSION * session)
|
|||||||
* or less (including length, padding length, payload,
|
* or less (including length, padding length, payload,
|
||||||
* padding, and MAC.)."
|
* padding, and MAC.)."
|
||||||
*/
|
*/
|
||||||
if(total_num > LIBSSH2_PACKET_MAXPAYLOAD) {
|
if(total_num > LIBSSH2_PACKET_MAXPAYLOAD || total_num == 0) {
|
||||||
return LIBSSH2_ERROR_OUT_OF_BOUNDARY;
|
return LIBSSH2_ERROR_OUT_OF_BOUNDARY;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -488,6 +488,8 @@ int _libssh2_transport_read(LIBSSH2_SESSION * session)
|
|||||||
p->wptr += blocksize - 5; /* advance write pointer */
|
p->wptr += blocksize - 5; /* advance write pointer */
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
if(p->payload)
|
||||||
|
LIBSSH2_FREE(session, p->payload);
|
||||||
return LIBSSH2_ERROR_OUT_OF_BOUNDARY;
|
return LIBSSH2_ERROR_OUT_OF_BOUNDARY;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -570,6 +572,8 @@ int _libssh2_transport_read(LIBSSH2_SESSION * session)
|
|||||||
memcpy(p->wptr, &p->buf[p->readidx], numbytes);
|
memcpy(p->wptr, &p->buf[p->readidx], numbytes);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
if(p->payload)
|
||||||
|
LIBSSH2_FREE(session, p->payload);
|
||||||
return LIBSSH2_ERROR_OUT_OF_BOUNDARY;
|
return LIBSSH2_ERROR_OUT_OF_BOUNDARY;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -765,7 +769,7 @@ int _libssh2_transport_send(LIBSSH2_SESSION *session,
|
|||||||
((session->state & LIBSSH2_STATE_AUTHENTICATED) ||
|
((session->state & LIBSSH2_STATE_AUTHENTICATED) ||
|
||||||
session->local.comp->use_in_auth);
|
session->local.comp->use_in_auth);
|
||||||
|
|
||||||
if(encrypted && compressed) {
|
if(encrypted && compressed && session->local.comp_abstract) {
|
||||||
/* the idea here is that these function must fail if the output gets
|
/* the idea here is that these function must fail if the output gets
|
||||||
larger than what fits in the assigned buffer so thus they don't
|
larger than what fits in the assigned buffer so thus they don't
|
||||||
check the input size as we don't know how much it compresses */
|
check the input size as we don't know how much it compresses */
|
||||||
@@ -858,7 +862,10 @@ int _libssh2_transport_send(LIBSSH2_SESSION *session,
|
|||||||
p->outbuf[4] = (unsigned char)padding_length;
|
p->outbuf[4] = (unsigned char)padding_length;
|
||||||
|
|
||||||
/* fill the padding area with random junk */
|
/* fill the padding area with random junk */
|
||||||
_libssh2_random(p->outbuf + 5 + data_len, padding_length);
|
if(_libssh2_random(p->outbuf + 5 + data_len, padding_length)) {
|
||||||
|
return _libssh2_error(session, LIBSSH2_ERROR_RANDGEN,
|
||||||
|
"Unable to get random bytes for packet padding");
|
||||||
|
}
|
||||||
|
|
||||||
if(encrypted) {
|
if(encrypted) {
|
||||||
size_t i;
|
size_t i;
|
||||||
|
@@ -1,6 +1,5 @@
|
|||||||
#ifndef __LIBSSH2_TRANSPORT_H
|
#ifndef __LIBSSH2_TRANSPORT_H
|
||||||
#define __LIBSSH2_TRANSPORT_H
|
#define __LIBSSH2_TRANSPORT_H
|
||||||
|
|
||||||
/* Copyright (C) 2007 The Written Word, Inc. All rights reserved.
|
/* Copyright (C) 2007 The Written Word, Inc. All rights reserved.
|
||||||
* Copyright (C) 2009-2010 by Daniel Stenberg
|
* Copyright (C) 2009-2010 by Daniel Stenberg
|
||||||
* Author: Daniel Stenberg <daniel@haxx.se>
|
* Author: Daniel Stenberg <daniel@haxx.se>
|
||||||
|
@@ -897,11 +897,6 @@ userauth_hostbased_fromfile(LIBSSH2_SESSION *session,
|
|||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
#if !LIBSSH2_RSA
|
|
||||||
return _libssh2_error(session, LIBSSH2_ERROR_METHOD_NOT_SUPPORTED,
|
|
||||||
"RSA is not supported by crypto backend");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if(session->userauth_host_state == libssh2_NB_state_idle) {
|
if(session->userauth_host_state == libssh2_NB_state_idle) {
|
||||||
const LIBSSH2_HOSTKEY_METHOD *privkeyobj;
|
const LIBSSH2_HOSTKEY_METHOD *privkeyobj;
|
||||||
unsigned char *pubkeydata = NULL;
|
unsigned char *pubkeydata = NULL;
|
||||||
@@ -1144,7 +1139,21 @@ libssh2_userauth_hostbased_fromfile_ex(LIBSSH2_SESSION *session,
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int plain_method_len(const char *method, size_t method_len)
|
||||||
|
{
|
||||||
|
if(!strncmp("ecdsa-sha2-nistp256-cert-v01@openssh.com",
|
||||||
|
method,
|
||||||
|
method_len) ||
|
||||||
|
!strncmp("ecdsa-sha2-nistp384-cert-v01@openssh.com",
|
||||||
|
method,
|
||||||
|
method_len) ||
|
||||||
|
!strncmp("ecdsa-sha2-nistp521-cert-v01@openssh.com",
|
||||||
|
method,
|
||||||
|
method_len)) {
|
||||||
|
return 19;
|
||||||
|
}
|
||||||
|
return method_len;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
_libssh2_userauth_publickey(LIBSSH2_SESSION *session,
|
_libssh2_userauth_publickey(LIBSSH2_SESSION *session,
|
||||||
@@ -1409,6 +1418,10 @@ _libssh2_userauth_publickey(LIBSSH2_SESSION *session,
|
|||||||
s = session->userauth_pblc_packet + session->userauth_pblc_packet_len;
|
s = session->userauth_pblc_packet + session->userauth_pblc_packet_len;
|
||||||
session->userauth_pblc_b = NULL;
|
session->userauth_pblc_b = NULL;
|
||||||
|
|
||||||
|
session->userauth_pblc_method_len =
|
||||||
|
plain_method_len((const char *)session->userauth_pblc_method,
|
||||||
|
session->userauth_pblc_method_len);
|
||||||
|
|
||||||
_libssh2_store_u32(&s,
|
_libssh2_store_u32(&s,
|
||||||
4 + session->userauth_pblc_method_len + 4 +
|
4 + session->userauth_pblc_method_len + 4 +
|
||||||
sig_len);
|
sig_len);
|
||||||
@@ -1507,11 +1520,6 @@ userauth_publickey_frommemory(LIBSSH2_SESSION *session,
|
|||||||
void *abstract = &privkey_file;
|
void *abstract = &privkey_file;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
#if !LIBSSH2_RSA
|
|
||||||
return _libssh2_error(session, LIBSSH2_ERROR_METHOD_NOT_SUPPORTED,
|
|
||||||
"RSA is not supported by crypto backend");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
privkey_file.filename = privatekeydata;
|
privkey_file.filename = privatekeydata;
|
||||||
privkey_file.passphrase = passphrase;
|
privkey_file.passphrase = passphrase;
|
||||||
|
|
||||||
@@ -1526,15 +1534,14 @@ userauth_publickey_frommemory(LIBSSH2_SESSION *session,
|
|||||||
}
|
}
|
||||||
else if(privatekeydata_len && privatekeydata) {
|
else if(privatekeydata_len && privatekeydata) {
|
||||||
/* Compute public key from private key. */
|
/* Compute public key from private key. */
|
||||||
if(_libssh2_pub_priv_keyfilememory(session,
|
rc = _libssh2_pub_priv_keyfilememory(session,
|
||||||
&session->userauth_pblc_method,
|
&session->userauth_pblc_method,
|
||||||
&session->userauth_pblc_method_len,
|
&session->userauth_pblc_method_len,
|
||||||
&pubkeydata, &pubkeydata_len,
|
&pubkeydata, &pubkeydata_len,
|
||||||
privatekeydata, privatekeydata_len,
|
privatekeydata, privatekeydata_len,
|
||||||
passphrase))
|
passphrase);
|
||||||
return _libssh2_error(session, LIBSSH2_ERROR_FILE,
|
if(rc)
|
||||||
"Unable to extract public key "
|
return rc;
|
||||||
"from private key.");
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return _libssh2_error(session, LIBSSH2_ERROR_FILE,
|
return _libssh2_error(session, LIBSSH2_ERROR_FILE,
|
||||||
@@ -1569,11 +1576,6 @@ userauth_publickey_fromfile(LIBSSH2_SESSION *session,
|
|||||||
void *abstract = &privkey_file;
|
void *abstract = &privkey_file;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
#if !LIBSSH2_RSA
|
|
||||||
return _libssh2_error(session, LIBSSH2_ERROR_METHOD_NOT_SUPPORTED,
|
|
||||||
"RSA is not supported by crypto backend");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
privkey_file.filename = privatekey;
|
privkey_file.filename = privatekey;
|
||||||
privkey_file.passphrase = passphrase;
|
privkey_file.passphrase = passphrase;
|
||||||
|
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
#ifndef LIBSSH2_USERAUTH_H
|
#ifndef __LIBSSH2_USERAUTH_H
|
||||||
#define LIBSSH2_USERAUTH_H
|
#define __LIBSSH2_USERAUTH_H
|
||||||
/* Copyright (c) 2004-2007, Sara Golemon <sarag@libssh2.org>
|
/* Copyright (c) 2004-2007, Sara Golemon <sarag@libssh2.org>
|
||||||
* Copyright (c) 2009-2010 by Daniel Stenberg
|
* Copyright (c) 2009-2010 by Daniel Stenberg
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
@@ -48,4 +48,4 @@ _libssh2_userauth_publickey(LIBSSH2_SESSION *session,
|
|||||||
((*sign_callback)),
|
((*sign_callback)),
|
||||||
void *abstract);
|
void *abstract);
|
||||||
|
|
||||||
#endif /* LIBSSH2_USERAUTH_H */
|
#endif /* __LIBSSH2_USERAUTH_H */
|
||||||
|
596
src/wincng.c
Executable file → Normal file
596
src/wincng.c
Executable file → Normal file
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2013-2015 Marc Hoersken <info@marc-hoersken.de>
|
* Copyright (C) 2013-2020 Marc Hoersken <info@marc-hoersken.de>
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms,
|
* Redistribution and use in source and binary forms,
|
||||||
@@ -58,6 +58,7 @@
|
|||||||
|
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <bcrypt.h>
|
#include <bcrypt.h>
|
||||||
|
#include <ntstatus.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include "misc.h"
|
#include "misc.h"
|
||||||
|
|
||||||
@@ -98,6 +99,10 @@
|
|||||||
#define BCRYPT_SHA256_ALGORITHM L"SHA256"
|
#define BCRYPT_SHA256_ALGORITHM L"SHA256"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef BCRYPT_SHA384_ALGORITHM
|
||||||
|
#define BCRYPT_SHA384_ALGORITHM L"SHA384"
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef BCRYPT_SHA512_ALGORITHM
|
#ifndef BCRYPT_SHA512_ALGORITHM
|
||||||
#define BCRYPT_SHA512_ALGORITHM L"SHA512"
|
#define BCRYPT_SHA512_ALGORITHM L"SHA512"
|
||||||
#endif
|
#endif
|
||||||
@@ -122,6 +127,15 @@
|
|||||||
#define BCRYPT_3DES_ALGORITHM L"3DES"
|
#define BCRYPT_3DES_ALGORITHM L"3DES"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef BCRYPT_DH_ALGORITHM
|
||||||
|
#define BCRYPT_DH_ALGORITHM L"DH"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* BCRYPT_KDF_RAW_SECRET is available from Windows 8.1 and onwards */
|
||||||
|
#ifndef BCRYPT_KDF_RAW_SECRET
|
||||||
|
#define BCRYPT_KDF_RAW_SECRET L"TRUNCATE"
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef BCRYPT_ALG_HANDLE_HMAC_FLAG
|
#ifndef BCRYPT_ALG_HANDLE_HMAC_FLAG
|
||||||
#define BCRYPT_ALG_HANDLE_HMAC_FLAG 0x00000008
|
#define BCRYPT_ALG_HANDLE_HMAC_FLAG 0x00000008
|
||||||
#endif
|
#endif
|
||||||
@@ -208,40 +222,88 @@
|
|||||||
* Windows CNG backend: Generic functions
|
* Windows CNG backend: Generic functions
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
struct _libssh2_wincng_ctx _libssh2_wincng;
|
||||||
|
|
||||||
void
|
void
|
||||||
_libssh2_wincng_init(void)
|
_libssh2_wincng_init(void)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
(void)BCryptOpenAlgorithmProvider(&_libssh2_wincng.hAlgRNG,
|
memset(&_libssh2_wincng, 0, sizeof(_libssh2_wincng));
|
||||||
|
|
||||||
|
ret = BCryptOpenAlgorithmProvider(&_libssh2_wincng.hAlgRNG,
|
||||||
BCRYPT_RNG_ALGORITHM, NULL, 0);
|
BCRYPT_RNG_ALGORITHM, NULL, 0);
|
||||||
|
if(!BCRYPT_SUCCESS(ret)) {
|
||||||
|
_libssh2_wincng.hAlgRNG = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
(void)BCryptOpenAlgorithmProvider(&_libssh2_wincng.hAlgHashMD5,
|
ret = BCryptOpenAlgorithmProvider(&_libssh2_wincng.hAlgHashMD5,
|
||||||
BCRYPT_MD5_ALGORITHM, NULL, 0);
|
BCRYPT_MD5_ALGORITHM, NULL, 0);
|
||||||
(void)BCryptOpenAlgorithmProvider(&_libssh2_wincng.hAlgHashSHA1,
|
if(!BCRYPT_SUCCESS(ret)) {
|
||||||
|
_libssh2_wincng.hAlgHashMD5 = NULL;
|
||||||
|
}
|
||||||
|
ret = BCryptOpenAlgorithmProvider(&_libssh2_wincng.hAlgHashSHA1,
|
||||||
BCRYPT_SHA1_ALGORITHM, NULL, 0);
|
BCRYPT_SHA1_ALGORITHM, NULL, 0);
|
||||||
(void)BCryptOpenAlgorithmProvider(&_libssh2_wincng.hAlgHashSHA256,
|
if(!BCRYPT_SUCCESS(ret)) {
|
||||||
|
_libssh2_wincng.hAlgHashSHA1 = NULL;
|
||||||
|
}
|
||||||
|
ret = BCryptOpenAlgorithmProvider(&_libssh2_wincng.hAlgHashSHA256,
|
||||||
BCRYPT_SHA256_ALGORITHM, NULL, 0);
|
BCRYPT_SHA256_ALGORITHM, NULL, 0);
|
||||||
(void)BCryptOpenAlgorithmProvider(&_libssh2_wincng.hAlgHashSHA512,
|
if(!BCRYPT_SUCCESS(ret)) {
|
||||||
|
_libssh2_wincng.hAlgHashSHA256 = NULL;
|
||||||
|
}
|
||||||
|
ret = BCryptOpenAlgorithmProvider(&_libssh2_wincng.hAlgHashSHA384,
|
||||||
|
BCRYPT_SHA384_ALGORITHM, NULL, 0);
|
||||||
|
if(!BCRYPT_SUCCESS(ret)) {
|
||||||
|
_libssh2_wincng.hAlgHashSHA384 = NULL;
|
||||||
|
}
|
||||||
|
ret = BCryptOpenAlgorithmProvider(&_libssh2_wincng.hAlgHashSHA512,
|
||||||
BCRYPT_SHA512_ALGORITHM, NULL, 0);
|
BCRYPT_SHA512_ALGORITHM, NULL, 0);
|
||||||
|
if(!BCRYPT_SUCCESS(ret)) {
|
||||||
|
_libssh2_wincng.hAlgHashSHA512 = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
(void)BCryptOpenAlgorithmProvider(&_libssh2_wincng.hAlgHmacMD5,
|
ret = BCryptOpenAlgorithmProvider(&_libssh2_wincng.hAlgHmacMD5,
|
||||||
BCRYPT_MD5_ALGORITHM, NULL,
|
BCRYPT_MD5_ALGORITHM, NULL,
|
||||||
BCRYPT_ALG_HANDLE_HMAC_FLAG);
|
BCRYPT_ALG_HANDLE_HMAC_FLAG);
|
||||||
(void)BCryptOpenAlgorithmProvider(&_libssh2_wincng.hAlgHmacSHA1,
|
if(!BCRYPT_SUCCESS(ret)) {
|
||||||
|
_libssh2_wincng.hAlgHmacMD5 = NULL;
|
||||||
|
}
|
||||||
|
ret = BCryptOpenAlgorithmProvider(&_libssh2_wincng.hAlgHmacSHA1,
|
||||||
BCRYPT_SHA1_ALGORITHM, NULL,
|
BCRYPT_SHA1_ALGORITHM, NULL,
|
||||||
BCRYPT_ALG_HANDLE_HMAC_FLAG);
|
BCRYPT_ALG_HANDLE_HMAC_FLAG);
|
||||||
(void)BCryptOpenAlgorithmProvider(&_libssh2_wincng.hAlgHmacSHA256,
|
if(!BCRYPT_SUCCESS(ret)) {
|
||||||
|
_libssh2_wincng.hAlgHmacSHA1 = NULL;
|
||||||
|
}
|
||||||
|
ret = BCryptOpenAlgorithmProvider(&_libssh2_wincng.hAlgHmacSHA256,
|
||||||
BCRYPT_SHA256_ALGORITHM, NULL,
|
BCRYPT_SHA256_ALGORITHM, NULL,
|
||||||
BCRYPT_ALG_HANDLE_HMAC_FLAG);
|
BCRYPT_ALG_HANDLE_HMAC_FLAG);
|
||||||
(void)BCryptOpenAlgorithmProvider(&_libssh2_wincng.hAlgHmacSHA512,
|
if(!BCRYPT_SUCCESS(ret)) {
|
||||||
|
_libssh2_wincng.hAlgHmacSHA256 = NULL;
|
||||||
|
}
|
||||||
|
ret = BCryptOpenAlgorithmProvider(&_libssh2_wincng.hAlgHmacSHA384,
|
||||||
|
BCRYPT_SHA384_ALGORITHM, NULL,
|
||||||
|
BCRYPT_ALG_HANDLE_HMAC_FLAG);
|
||||||
|
if(!BCRYPT_SUCCESS(ret)) {
|
||||||
|
_libssh2_wincng.hAlgHmacSHA384 = NULL;
|
||||||
|
}
|
||||||
|
ret = BCryptOpenAlgorithmProvider(&_libssh2_wincng.hAlgHmacSHA512,
|
||||||
BCRYPT_SHA512_ALGORITHM, NULL,
|
BCRYPT_SHA512_ALGORITHM, NULL,
|
||||||
BCRYPT_ALG_HANDLE_HMAC_FLAG);
|
BCRYPT_ALG_HANDLE_HMAC_FLAG);
|
||||||
|
if(!BCRYPT_SUCCESS(ret)) {
|
||||||
|
_libssh2_wincng.hAlgHmacSHA512 = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
(void)BCryptOpenAlgorithmProvider(&_libssh2_wincng.hAlgRSA,
|
ret = BCryptOpenAlgorithmProvider(&_libssh2_wincng.hAlgRSA,
|
||||||
BCRYPT_RSA_ALGORITHM, NULL, 0);
|
BCRYPT_RSA_ALGORITHM, NULL, 0);
|
||||||
(void)BCryptOpenAlgorithmProvider(&_libssh2_wincng.hAlgDSA,
|
if(!BCRYPT_SUCCESS(ret)) {
|
||||||
|
_libssh2_wincng.hAlgRSA = NULL;
|
||||||
|
}
|
||||||
|
ret = BCryptOpenAlgorithmProvider(&_libssh2_wincng.hAlgDSA,
|
||||||
BCRYPT_DSA_ALGORITHM, NULL, 0);
|
BCRYPT_DSA_ALGORITHM, NULL, 0);
|
||||||
|
if(!BCRYPT_SUCCESS(ret)) {
|
||||||
|
_libssh2_wincng.hAlgDSA = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
ret = BCryptOpenAlgorithmProvider(&_libssh2_wincng.hAlgAES_CBC,
|
ret = BCryptOpenAlgorithmProvider(&_libssh2_wincng.hAlgAES_CBC,
|
||||||
BCRYPT_AES_ALGORITHM, NULL, 0);
|
BCRYPT_AES_ALGORITHM, NULL, 0);
|
||||||
@@ -251,7 +313,10 @@ _libssh2_wincng_init(void)
|
|||||||
(PBYTE)BCRYPT_CHAIN_MODE_CBC,
|
(PBYTE)BCRYPT_CHAIN_MODE_CBC,
|
||||||
sizeof(BCRYPT_CHAIN_MODE_CBC), 0);
|
sizeof(BCRYPT_CHAIN_MODE_CBC), 0);
|
||||||
if(!BCRYPT_SUCCESS(ret)) {
|
if(!BCRYPT_SUCCESS(ret)) {
|
||||||
(void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgAES_CBC, 0);
|
ret = BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgAES_CBC, 0);
|
||||||
|
if(BCRYPT_SUCCESS(ret)) {
|
||||||
|
_libssh2_wincng.hAlgAES_CBC = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -263,7 +328,10 @@ _libssh2_wincng_init(void)
|
|||||||
(PBYTE)BCRYPT_CHAIN_MODE_ECB,
|
(PBYTE)BCRYPT_CHAIN_MODE_ECB,
|
||||||
sizeof(BCRYPT_CHAIN_MODE_ECB), 0);
|
sizeof(BCRYPT_CHAIN_MODE_ECB), 0);
|
||||||
if(!BCRYPT_SUCCESS(ret)) {
|
if(!BCRYPT_SUCCESS(ret)) {
|
||||||
(void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgAES_ECB, 0);
|
ret = BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgAES_ECB, 0);
|
||||||
|
if(BCRYPT_SUCCESS(ret)) {
|
||||||
|
_libssh2_wincng.hAlgAES_ECB = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -275,7 +343,10 @@ _libssh2_wincng_init(void)
|
|||||||
(PBYTE)BCRYPT_CHAIN_MODE_NA,
|
(PBYTE)BCRYPT_CHAIN_MODE_NA,
|
||||||
sizeof(BCRYPT_CHAIN_MODE_NA), 0);
|
sizeof(BCRYPT_CHAIN_MODE_NA), 0);
|
||||||
if(!BCRYPT_SUCCESS(ret)) {
|
if(!BCRYPT_SUCCESS(ret)) {
|
||||||
(void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgRC4_NA, 0);
|
ret = BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgRC4_NA, 0);
|
||||||
|
if(BCRYPT_SUCCESS(ret)) {
|
||||||
|
_libssh2_wincng.hAlgRC4_NA = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -287,29 +358,58 @@ _libssh2_wincng_init(void)
|
|||||||
(PBYTE)BCRYPT_CHAIN_MODE_CBC,
|
(PBYTE)BCRYPT_CHAIN_MODE_CBC,
|
||||||
sizeof(BCRYPT_CHAIN_MODE_CBC), 0);
|
sizeof(BCRYPT_CHAIN_MODE_CBC), 0);
|
||||||
if(!BCRYPT_SUCCESS(ret)) {
|
if(!BCRYPT_SUCCESS(ret)) {
|
||||||
(void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlg3DES_CBC,
|
ret = BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlg3DES_CBC,
|
||||||
0);
|
0);
|
||||||
|
if(BCRYPT_SUCCESS(ret)) {
|
||||||
|
_libssh2_wincng.hAlg3DES_CBC = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ret = BCryptOpenAlgorithmProvider(&_libssh2_wincng.hAlgDH,
|
||||||
|
BCRYPT_DH_ALGORITHM, NULL, 0);
|
||||||
|
if(!BCRYPT_SUCCESS(ret)) {
|
||||||
|
_libssh2_wincng.hAlgDH = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
_libssh2_wincng_free(void)
|
_libssh2_wincng_free(void)
|
||||||
{
|
{
|
||||||
(void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgRNG, 0);
|
if(_libssh2_wincng.hAlgRNG)
|
||||||
(void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgHashMD5, 0);
|
(void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgRNG, 0);
|
||||||
(void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgHashSHA1, 0);
|
if(_libssh2_wincng.hAlgHashMD5)
|
||||||
(void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgHashSHA256, 0);
|
(void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgHashMD5, 0);
|
||||||
(void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgHashSHA512, 0);
|
if(_libssh2_wincng.hAlgHashSHA1)
|
||||||
(void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgHmacMD5, 0);
|
(void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgHashSHA1, 0);
|
||||||
(void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgHmacSHA1, 0);
|
if(_libssh2_wincng.hAlgHashSHA256)
|
||||||
(void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgHmacSHA256, 0);
|
(void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgHashSHA256, 0);
|
||||||
(void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgHmacSHA512, 0);
|
if(_libssh2_wincng.hAlgHashSHA384)
|
||||||
(void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgRSA, 0);
|
(void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgHashSHA384, 0);
|
||||||
(void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgDSA, 0);
|
if(_libssh2_wincng.hAlgHashSHA512)
|
||||||
(void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgAES_CBC, 0);
|
(void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgHashSHA512, 0);
|
||||||
(void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgRC4_NA, 0);
|
if(_libssh2_wincng.hAlgHmacMD5)
|
||||||
(void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlg3DES_CBC, 0);
|
(void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgHmacMD5, 0);
|
||||||
|
if(_libssh2_wincng.hAlgHmacSHA1)
|
||||||
|
(void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgHmacSHA1, 0);
|
||||||
|
if(_libssh2_wincng.hAlgHmacSHA256)
|
||||||
|
(void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgHmacSHA256, 0);
|
||||||
|
if(_libssh2_wincng.hAlgHmacSHA384)
|
||||||
|
(void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgHmacSHA384, 0);
|
||||||
|
if(_libssh2_wincng.hAlgHmacSHA512)
|
||||||
|
(void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgHmacSHA512, 0);
|
||||||
|
if(_libssh2_wincng.hAlgRSA)
|
||||||
|
(void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgRSA, 0);
|
||||||
|
if(_libssh2_wincng.hAlgDSA)
|
||||||
|
(void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgDSA, 0);
|
||||||
|
if(_libssh2_wincng.hAlgAES_CBC)
|
||||||
|
(void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgAES_CBC, 0);
|
||||||
|
if(_libssh2_wincng.hAlgRC4_NA)
|
||||||
|
(void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgRC4_NA, 0);
|
||||||
|
if(_libssh2_wincng.hAlg3DES_CBC)
|
||||||
|
(void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlg3DES_CBC, 0);
|
||||||
|
if(_libssh2_wincng.hAlgDH)
|
||||||
|
(void)BCryptCloseAlgorithmProvider(_libssh2_wincng.hAlgDH, 0);
|
||||||
|
|
||||||
memset(&_libssh2_wincng, 0, sizeof(_libssh2_wincng));
|
memset(&_libssh2_wincng, 0, sizeof(_libssh2_wincng));
|
||||||
}
|
}
|
||||||
@@ -342,6 +442,24 @@ _libssh2_wincng_safe_free(void *buf, int len)
|
|||||||
free(buf);
|
free(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Copy a big endian set of bits from src to dest.
|
||||||
|
* if the size of src is smaller than dest then pad the "left" (MSB)
|
||||||
|
* end with zeroes and copy the bits into the "right" (LSB) end. */
|
||||||
|
static void
|
||||||
|
memcpy_with_be_padding(unsigned char *dest, unsigned long dest_len,
|
||||||
|
unsigned char *src, unsigned long src_len)
|
||||||
|
{
|
||||||
|
if(dest_len > src_len) {
|
||||||
|
memset(dest, 0, dest_len - src_len);
|
||||||
|
}
|
||||||
|
memcpy((dest + dest_len) - src_len, src, src_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
round_down(int number, int multiple)
|
||||||
|
{
|
||||||
|
return (number / multiple) * multiple;
|
||||||
|
}
|
||||||
|
|
||||||
/*******************************************************************/
|
/*******************************************************************/
|
||||||
/*
|
/*
|
||||||
@@ -546,7 +664,7 @@ _libssh2_wincng_key_sha1_verify(_libssh2_wincng_key_ctx *ctx,
|
|||||||
static int
|
static int
|
||||||
_libssh2_wincng_load_pem(LIBSSH2_SESSION *session,
|
_libssh2_wincng_load_pem(LIBSSH2_SESSION *session,
|
||||||
const char *filename,
|
const char *filename,
|
||||||
const char *passphrase,
|
const unsigned char *passphrase,
|
||||||
const char *headerbegin,
|
const char *headerbegin,
|
||||||
const char *headerend,
|
const char *headerend,
|
||||||
unsigned char **data,
|
unsigned char **data,
|
||||||
@@ -572,7 +690,7 @@ _libssh2_wincng_load_pem(LIBSSH2_SESSION *session,
|
|||||||
static int
|
static int
|
||||||
_libssh2_wincng_load_private(LIBSSH2_SESSION *session,
|
_libssh2_wincng_load_private(LIBSSH2_SESSION *session,
|
||||||
const char *filename,
|
const char *filename,
|
||||||
const char *passphrase,
|
const unsigned char *passphrase,
|
||||||
unsigned char **ppbEncoded,
|
unsigned char **ppbEncoded,
|
||||||
unsigned long *pcbEncoded,
|
unsigned long *pcbEncoded,
|
||||||
int tryLoadRSA, int tryLoadDSA)
|
int tryLoadRSA, int tryLoadDSA)
|
||||||
@@ -605,7 +723,7 @@ static int
|
|||||||
_libssh2_wincng_load_private_memory(LIBSSH2_SESSION *session,
|
_libssh2_wincng_load_private_memory(LIBSSH2_SESSION *session,
|
||||||
const char *privatekeydata,
|
const char *privatekeydata,
|
||||||
size_t privatekeydata_len,
|
size_t privatekeydata_len,
|
||||||
const char *passphrase,
|
const unsigned char *passphrase,
|
||||||
unsigned char **ppbEncoded,
|
unsigned char **ppbEncoded,
|
||||||
unsigned long *pcbEncoded,
|
unsigned long *pcbEncoded,
|
||||||
int tryLoadRSA, int tryLoadDSA)
|
int tryLoadRSA, int tryLoadDSA)
|
||||||
@@ -1030,8 +1148,7 @@ _libssh2_wincng_rsa_new_private(libssh2_rsa_ctx **rsa,
|
|||||||
|
|
||||||
(void)session;
|
(void)session;
|
||||||
|
|
||||||
ret = _libssh2_wincng_load_private(session, filename,
|
ret = _libssh2_wincng_load_private(session, filename, passphrase,
|
||||||
(const char *)passphrase,
|
|
||||||
&pbEncoded, &cbEncoded, 1, 0);
|
&pbEncoded, &cbEncoded, 1, 0);
|
||||||
if(ret) {
|
if(ret) {
|
||||||
return -1;
|
return -1;
|
||||||
@@ -1055,7 +1172,7 @@ _libssh2_wincng_rsa_new_private_frommemory(libssh2_rsa_ctx **rsa,
|
|||||||
LIBSSH2_SESSION *session,
|
LIBSSH2_SESSION *session,
|
||||||
const char *filedata,
|
const char *filedata,
|
||||||
size_t filedata_len,
|
size_t filedata_len,
|
||||||
unsigned const char *passphrase)
|
const unsigned char *passphrase)
|
||||||
{
|
{
|
||||||
#ifdef HAVE_LIBCRYPT32
|
#ifdef HAVE_LIBCRYPT32
|
||||||
unsigned char *pbEncoded;
|
unsigned char *pbEncoded;
|
||||||
@@ -1065,7 +1182,7 @@ _libssh2_wincng_rsa_new_private_frommemory(libssh2_rsa_ctx **rsa,
|
|||||||
(void)session;
|
(void)session;
|
||||||
|
|
||||||
ret = _libssh2_wincng_load_private_memory(session, filedata, filedata_len,
|
ret = _libssh2_wincng_load_private_memory(session, filedata, filedata_len,
|
||||||
(const char *)passphrase,
|
passphrase,
|
||||||
&pbEncoded, &cbEncoded, 1, 0);
|
&pbEncoded, &cbEncoded, 1, 0);
|
||||||
if(ret) {
|
if(ret) {
|
||||||
return -1;
|
return -1;
|
||||||
@@ -1329,8 +1446,7 @@ _libssh2_wincng_dsa_new_private(libssh2_dsa_ctx **dsa,
|
|||||||
unsigned long cbEncoded;
|
unsigned long cbEncoded;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = _libssh2_wincng_load_private(session, filename,
|
ret = _libssh2_wincng_load_private(session, filename, passphrase,
|
||||||
(const char *)passphrase,
|
|
||||||
&pbEncoded, &cbEncoded, 0, 1);
|
&pbEncoded, &cbEncoded, 0, 1);
|
||||||
if(ret) {
|
if(ret) {
|
||||||
return -1;
|
return -1;
|
||||||
@@ -1354,7 +1470,7 @@ _libssh2_wincng_dsa_new_private_frommemory(libssh2_dsa_ctx **dsa,
|
|||||||
LIBSSH2_SESSION *session,
|
LIBSSH2_SESSION *session,
|
||||||
const char *filedata,
|
const char *filedata,
|
||||||
size_t filedata_len,
|
size_t filedata_len,
|
||||||
unsigned const char *passphrase)
|
const unsigned char *passphrase)
|
||||||
{
|
{
|
||||||
#ifdef HAVE_LIBCRYPT32
|
#ifdef HAVE_LIBCRYPT32
|
||||||
unsigned char *pbEncoded;
|
unsigned char *pbEncoded;
|
||||||
@@ -1362,7 +1478,7 @@ _libssh2_wincng_dsa_new_private_frommemory(libssh2_dsa_ctx **dsa,
|
|||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = _libssh2_wincng_load_private_memory(session, filedata, filedata_len,
|
ret = _libssh2_wincng_load_private_memory(session, filedata, filedata_len,
|
||||||
(const char *)passphrase,
|
passphrase,
|
||||||
&pbEncoded, &cbEncoded, 0, 1);
|
&pbEncoded, &cbEncoded, 0, 1);
|
||||||
if(ret) {
|
if(ret) {
|
||||||
return -1;
|
return -1;
|
||||||
@@ -1610,7 +1726,8 @@ _libssh2_wincng_pub_priv_keyfile(LIBSSH2_SESSION *session,
|
|||||||
unsigned long cbEncoded;
|
unsigned long cbEncoded;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = _libssh2_wincng_load_private(session, privatekey, passphrase,
|
ret = _libssh2_wincng_load_private(session, privatekey,
|
||||||
|
(const unsigned char *)passphrase,
|
||||||
&pbEncoded, &cbEncoded, 1, 1);
|
&pbEncoded, &cbEncoded, 1, 1);
|
||||||
if(ret) {
|
if(ret) {
|
||||||
return -1;
|
return -1;
|
||||||
@@ -1649,7 +1766,9 @@ _libssh2_wincng_pub_priv_keyfilememory(LIBSSH2_SESSION *session,
|
|||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = _libssh2_wincng_load_private_memory(session, privatekeydata,
|
ret = _libssh2_wincng_load_private_memory(session, privatekeydata,
|
||||||
privatekeydata_len, passphrase,
|
privatekeydata_len,
|
||||||
|
(const unsigned char *)
|
||||||
|
passphrase,
|
||||||
&pbEncoded, &cbEncoded, 1, 1);
|
&pbEncoded, &cbEncoded, 1, 1);
|
||||||
if(ret) {
|
if(ret) {
|
||||||
return -1;
|
return -1;
|
||||||
@@ -1914,7 +2033,8 @@ _libssh2_wincng_bignum_rand(_libssh2_bn *rnd, int bits, int top, int bottom)
|
|||||||
if(!rnd)
|
if(!rnd)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
length = (unsigned long)(ceil((float)bits / 8) * sizeof(unsigned char));
|
length = (unsigned long) (ceil(((double)bits) / 8.0) *
|
||||||
|
sizeof(unsigned char));
|
||||||
if(_libssh2_wincng_bignum_resize(rnd, length))
|
if(_libssh2_wincng_bignum_resize(rnd, length))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
@@ -1925,15 +2045,17 @@ _libssh2_wincng_bignum_rand(_libssh2_bn *rnd, int bits, int top, int bottom)
|
|||||||
|
|
||||||
/* calculate significant bits in most significant byte */
|
/* calculate significant bits in most significant byte */
|
||||||
bits %= 8;
|
bits %= 8;
|
||||||
|
if(bits == 0)
|
||||||
|
bits = 8;
|
||||||
|
|
||||||
/* fill most significant byte with zero padding */
|
/* fill most significant byte with zero padding */
|
||||||
bignum[0] &= (1 << (8 - bits)) - 1;
|
bignum[0] &= ((1 << bits) - 1);
|
||||||
|
|
||||||
/* set some special last bits in most significant byte */
|
/* set most significant bits in most significant byte */
|
||||||
if(top == 0)
|
if(top == 0)
|
||||||
bignum[0] |= (1 << (7 - bits));
|
bignum[0] |= (1 << (bits - 1));
|
||||||
else if(top == 1)
|
else if(top == 1)
|
||||||
bignum[0] |= (3 << (6 - bits));
|
bignum[0] |= (3 << (bits - 2));
|
||||||
|
|
||||||
/* make odd by setting first bit in least significant byte */
|
/* make odd by setting first bit in least significant byte */
|
||||||
if(bottom)
|
if(bottom)
|
||||||
@@ -1978,11 +2100,10 @@ _libssh2_wincng_bignum_mod_exp(_libssh2_bn *r,
|
|||||||
offset += p->length;
|
offset += p->length;
|
||||||
|
|
||||||
memcpy(key + offset, m->bignum, m->length);
|
memcpy(key + offset, m->bignum, m->length);
|
||||||
|
offset = 0;
|
||||||
|
|
||||||
ret = BCryptImportKeyPair(_libssh2_wincng.hAlgRSA, NULL,
|
ret = BCryptImportKeyPair(_libssh2_wincng.hAlgRSA, NULL,
|
||||||
BCRYPT_RSAPUBLIC_BLOB, &hKey, key, keylen,
|
BCRYPT_RSAPUBLIC_BLOB, &hKey, key, keylen, 0);
|
||||||
BCRYPT_NO_KEY_VALIDATION);
|
|
||||||
|
|
||||||
if(BCRYPT_SUCCESS(ret)) {
|
if(BCRYPT_SUCCESS(ret)) {
|
||||||
ret = BCryptEncrypt(hKey, a->bignum, a->length, NULL, NULL, 0,
|
ret = BCryptEncrypt(hKey, a->bignum, a->length, NULL, NULL, 0,
|
||||||
NULL, 0, &length, BCRYPT_PAD_NONE);
|
NULL, 0, &length, BCRYPT_PAD_NONE);
|
||||||
@@ -1991,9 +2112,8 @@ _libssh2_wincng_bignum_mod_exp(_libssh2_bn *r,
|
|||||||
length = max(a->length, length);
|
length = max(a->length, length);
|
||||||
bignum = malloc(length);
|
bignum = malloc(length);
|
||||||
if(bignum) {
|
if(bignum) {
|
||||||
offset = length - a->length;
|
memcpy_with_be_padding(bignum, length,
|
||||||
memset(bignum, 0, offset);
|
a->bignum, a->length);
|
||||||
memcpy(bignum + offset, a->bignum, a->length);
|
|
||||||
|
|
||||||
ret = BCryptEncrypt(hKey, bignum, length, NULL, NULL, 0,
|
ret = BCryptEncrypt(hKey, bignum, length, NULL, NULL, 0,
|
||||||
r->bignum, r->length, &offset,
|
r->bignum, r->length, &offset,
|
||||||
@@ -2032,8 +2152,9 @@ _libssh2_wincng_bignum_set_word(_libssh2_bn *bn, unsigned long word)
|
|||||||
number = word;
|
number = word;
|
||||||
while(number >>= 1)
|
while(number >>= 1)
|
||||||
bits++;
|
bits++;
|
||||||
|
bits++;
|
||||||
|
|
||||||
length = (unsigned long) (ceil(((double)(bits + 1)) / 8.0) *
|
length = (unsigned long) (ceil(((double)bits) / 8.0) *
|
||||||
sizeof(unsigned char));
|
sizeof(unsigned char));
|
||||||
if(_libssh2_wincng_bignum_resize(bn, length))
|
if(_libssh2_wincng_bignum_resize(bn, length))
|
||||||
return -1;
|
return -1;
|
||||||
@@ -2050,21 +2171,18 @@ _libssh2_wincng_bignum_bits(const _libssh2_bn *bn)
|
|||||||
unsigned char number;
|
unsigned char number;
|
||||||
unsigned long offset, length, bits;
|
unsigned long offset, length, bits;
|
||||||
|
|
||||||
if(!bn)
|
if(!bn || !bn->bignum || !bn->length)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
length = bn->length - 1;
|
|
||||||
|
|
||||||
offset = 0;
|
offset = 0;
|
||||||
while(!(*(bn->bignum + offset)) && (offset < length))
|
length = bn->length - 1;
|
||||||
|
while(!bn->bignum[offset] && offset < length)
|
||||||
offset++;
|
offset++;
|
||||||
|
|
||||||
bits = (length - offset) * 8;
|
bits = (length - offset) * 8;
|
||||||
number = bn->bignum[offset];
|
number = bn->bignum[offset];
|
||||||
|
|
||||||
while(number >>= 1)
|
while(number >>= 1)
|
||||||
bits++;
|
bits++;
|
||||||
|
|
||||||
bits++;
|
bits++;
|
||||||
|
|
||||||
return bits;
|
return bits;
|
||||||
@@ -2127,6 +2245,7 @@ _libssh2_wincng_bignum_free(_libssh2_bn *bn)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************/
|
||||||
/*
|
/*
|
||||||
* Windows CNG backend: Diffie-Hellman support.
|
* Windows CNG backend: Diffie-Hellman support.
|
||||||
*/
|
*/
|
||||||
@@ -2134,35 +2253,342 @@ _libssh2_wincng_bignum_free(_libssh2_bn *bn)
|
|||||||
void
|
void
|
||||||
_libssh2_dh_init(_libssh2_dh_ctx *dhctx)
|
_libssh2_dh_init(_libssh2_dh_ctx *dhctx)
|
||||||
{
|
{
|
||||||
*dhctx = _libssh2_wincng_bignum_init(); /* Random from client */
|
/* Random from client */
|
||||||
}
|
dhctx->bn = NULL;
|
||||||
|
dhctx->dh_handle = NULL;
|
||||||
int
|
dhctx->dh_params = NULL;
|
||||||
_libssh2_dh_key_pair(_libssh2_dh_ctx *dhctx, _libssh2_bn *public,
|
|
||||||
_libssh2_bn *g, _libssh2_bn *p, int group_order)
|
|
||||||
{
|
|
||||||
/* Generate x and e */
|
|
||||||
if(_libssh2_wincng_bignum_rand(*dhctx, group_order * 8 - 1, 0, -1))
|
|
||||||
return -1;
|
|
||||||
if(_libssh2_wincng_bignum_mod_exp(public, g, *dhctx, p))
|
|
||||||
return -1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
_libssh2_dh_secret(_libssh2_dh_ctx *dhctx, _libssh2_bn *secret,
|
|
||||||
_libssh2_bn *f, _libssh2_bn *p)
|
|
||||||
{
|
|
||||||
/* Compute the shared secret */
|
|
||||||
_libssh2_wincng_bignum_mod_exp(secret, f, *dhctx, p);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
_libssh2_dh_dtor(_libssh2_dh_ctx *dhctx)
|
_libssh2_dh_dtor(_libssh2_dh_ctx *dhctx)
|
||||||
{
|
{
|
||||||
_libssh2_wincng_bignum_free(*dhctx);
|
if(dhctx->dh_handle) {
|
||||||
*dhctx = NULL;
|
BCryptDestroyKey(dhctx->dh_handle);
|
||||||
|
dhctx->dh_handle = NULL;
|
||||||
|
}
|
||||||
|
if(dhctx->dh_params) {
|
||||||
|
/* Since public dh_params are shared in clear text,
|
||||||
|
* we don't need to securely zero them out here */
|
||||||
|
free(dhctx->dh_params);
|
||||||
|
dhctx->dh_params = NULL;
|
||||||
|
}
|
||||||
|
if(dhctx->bn) {
|
||||||
|
_libssh2_wincng_bignum_free(dhctx->bn);
|
||||||
|
dhctx->bn = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Generates a Diffie-Hellman key pair using base `g', prime `p' and the given
|
||||||
|
* `group_order'. Can use the given big number context `bnctx' if needed. The
|
||||||
|
* private key is stored as opaque in the Diffie-Hellman context `*dhctx' and
|
||||||
|
* the public key is returned in `public'. 0 is returned upon success, else
|
||||||
|
* -1. */
|
||||||
|
int
|
||||||
|
_libssh2_dh_key_pair(_libssh2_dh_ctx *dhctx, _libssh2_bn *public,
|
||||||
|
_libssh2_bn *g, _libssh2_bn *p, int group_order)
|
||||||
|
{
|
||||||
|
const int hasAlgDHwithKDF = _libssh2_wincng.hasAlgDHwithKDF;
|
||||||
|
while(_libssh2_wincng.hAlgDH && hasAlgDHwithKDF != -1) {
|
||||||
|
BCRYPT_DH_PARAMETER_HEADER *dh_params = NULL;
|
||||||
|
unsigned long dh_params_len;
|
||||||
|
unsigned char *blob = NULL;
|
||||||
|
int status;
|
||||||
|
/* Note that the DH provider requires that keys be multiples of 64 bits
|
||||||
|
* in length. At the time of writing a practical observed group_order
|
||||||
|
* value is 257, so we need to round down to 8 bytes of length (64/8)
|
||||||
|
* in order for kex to succeed */
|
||||||
|
DWORD key_length_bytes = max(round_down(group_order, 8),
|
||||||
|
max(g->length, p->length));
|
||||||
|
BCRYPT_DH_KEY_BLOB *dh_key_blob;
|
||||||
|
LPCWSTR key_type;
|
||||||
|
|
||||||
|
/* Prepare a key pair; pass the in the bit length of the key,
|
||||||
|
* but the key is not ready for consumption until it is finalized. */
|
||||||
|
status = BCryptGenerateKeyPair(_libssh2_wincng.hAlgDH,
|
||||||
|
&dhctx->dh_handle,
|
||||||
|
key_length_bytes * 8, 0);
|
||||||
|
if(!BCRYPT_SUCCESS(status)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
dh_params_len = sizeof(*dh_params) + 2 * key_length_bytes;
|
||||||
|
blob = malloc(dh_params_len);
|
||||||
|
if(!blob) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Populate DH parameters blob; after the header follows the `p`
|
||||||
|
* value and the `g` value. */
|
||||||
|
dh_params = (BCRYPT_DH_PARAMETER_HEADER*)blob;
|
||||||
|
dh_params->cbLength = dh_params_len;
|
||||||
|
dh_params->dwMagic = BCRYPT_DH_PARAMETERS_MAGIC;
|
||||||
|
dh_params->cbKeyLength = key_length_bytes;
|
||||||
|
memcpy_with_be_padding(blob + sizeof(*dh_params), key_length_bytes,
|
||||||
|
p->bignum, p->length);
|
||||||
|
memcpy_with_be_padding(blob + sizeof(*dh_params) + key_length_bytes,
|
||||||
|
key_length_bytes, g->bignum, g->length);
|
||||||
|
|
||||||
|
status = BCryptSetProperty(dhctx->dh_handle, BCRYPT_DH_PARAMETERS,
|
||||||
|
blob, dh_params_len, 0);
|
||||||
|
if(hasAlgDHwithKDF == -1) {
|
||||||
|
/* We know that the raw KDF is not supported, so discard this. */
|
||||||
|
free(blob);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* Pass ownership to dhctx; these parameters will be freed when
|
||||||
|
* the context is destroyed. We need to keep the parameters more
|
||||||
|
* easily available so that we have access to the `g` value when
|
||||||
|
* _libssh2_dh_secret is called later. */
|
||||||
|
dhctx->dh_params = dh_params;
|
||||||
|
}
|
||||||
|
dh_params = NULL;
|
||||||
|
blob = NULL;
|
||||||
|
|
||||||
|
if(!BCRYPT_SUCCESS(status)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = BCryptFinalizeKeyPair(dhctx->dh_handle, 0);
|
||||||
|
if(!BCRYPT_SUCCESS(status)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
key_length_bytes = 0;
|
||||||
|
if(hasAlgDHwithKDF == 1) {
|
||||||
|
/* Now we need to extract the public portion of the key so that we
|
||||||
|
* set it in the `public` bignum to satisfy our caller.
|
||||||
|
* First measure up the size of the required buffer. */
|
||||||
|
key_type = BCRYPT_DH_PUBLIC_BLOB;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* We also need to extract the private portion of the key to
|
||||||
|
* set it in the `*dhctx' bignum if the raw KDF is not supported.
|
||||||
|
* First measure up the size of the required buffer. */
|
||||||
|
key_type = BCRYPT_DH_PRIVATE_BLOB;
|
||||||
|
}
|
||||||
|
status = BCryptExportKey(dhctx->dh_handle, NULL, key_type,
|
||||||
|
NULL, 0, &key_length_bytes, 0);
|
||||||
|
if(!BCRYPT_SUCCESS(status)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
blob = malloc(key_length_bytes);
|
||||||
|
if(!blob) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = BCryptExportKey(dhctx->dh_handle, NULL, key_type,
|
||||||
|
blob, key_length_bytes,
|
||||||
|
&key_length_bytes, 0);
|
||||||
|
if(!BCRYPT_SUCCESS(status)) {
|
||||||
|
if(hasAlgDHwithKDF == 1) {
|
||||||
|
/* We have no private data, because raw KDF is supported */
|
||||||
|
free(blob);
|
||||||
|
}
|
||||||
|
else { /* we may have potentially private data, use secure free */
|
||||||
|
_libssh2_wincng_safe_free(blob, key_length_bytes);
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(hasAlgDHwithKDF == -1) {
|
||||||
|
/* We know that the raw KDF is not supported, so discard this */
|
||||||
|
BCryptDestroyKey(dhctx->dh_handle);
|
||||||
|
dhctx->dh_handle = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* BCRYPT_DH_PUBLIC_BLOB corresponds to a BCRYPT_DH_KEY_BLOB header
|
||||||
|
* followed by the Modulus, Generator and Public data. Those components
|
||||||
|
* each have equal size, specified by dh_key_blob->cbKey. */
|
||||||
|
dh_key_blob = (BCRYPT_DH_KEY_BLOB*)blob;
|
||||||
|
if(_libssh2_wincng_bignum_resize(public, dh_key_blob->cbKey)) {
|
||||||
|
if(hasAlgDHwithKDF == 1) {
|
||||||
|
/* We have no private data, because raw KDF is supported */
|
||||||
|
free(blob);
|
||||||
|
}
|
||||||
|
else { /* we may have potentially private data, use secure free */
|
||||||
|
_libssh2_wincng_safe_free(blob, key_length_bytes);
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Copy the public key data into the public bignum data buffer */
|
||||||
|
memcpy(public->bignum,
|
||||||
|
blob + sizeof(*dh_key_blob) + 2 * dh_key_blob->cbKey,
|
||||||
|
dh_key_blob->cbKey);
|
||||||
|
|
||||||
|
if(dh_key_blob->dwMagic == BCRYPT_DH_PRIVATE_MAGIC) {
|
||||||
|
/* BCRYPT_DH_PRIVATE_BLOB additionally contains the Private data */
|
||||||
|
dhctx->bn = _libssh2_wincng_bignum_init();
|
||||||
|
if(!dhctx->bn) {
|
||||||
|
_libssh2_wincng_safe_free(blob, key_length_bytes);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if(_libssh2_wincng_bignum_resize(dhctx->bn, dh_key_blob->cbKey)) {
|
||||||
|
_libssh2_wincng_safe_free(blob, key_length_bytes);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Copy the private key data into the dhctx bignum data buffer */
|
||||||
|
memcpy(dhctx->bn->bignum,
|
||||||
|
blob + sizeof(*dh_key_blob) + 3 * dh_key_blob->cbKey,
|
||||||
|
dh_key_blob->cbKey);
|
||||||
|
|
||||||
|
/* Make sure the private key is an odd number, because only
|
||||||
|
* odd primes can be used with the RSA-based fallback while
|
||||||
|
* DH itself does not seem to care about it being odd or not. */
|
||||||
|
if(!(dhctx->bn->bignum[dhctx->bn->length-1] % 2)) {
|
||||||
|
_libssh2_wincng_safe_free(blob, key_length_bytes);
|
||||||
|
/* discard everything first, then try again */
|
||||||
|
_libssh2_dh_dtor(dhctx);
|
||||||
|
_libssh2_dh_init(dhctx);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Generate x and e */
|
||||||
|
dhctx->bn = _libssh2_wincng_bignum_init();
|
||||||
|
if(!dhctx->bn)
|
||||||
|
return -1;
|
||||||
|
if(_libssh2_wincng_bignum_rand(dhctx->bn, group_order * 8 - 1, 0, -1))
|
||||||
|
return -1;
|
||||||
|
if(_libssh2_wincng_bignum_mod_exp(public, g, dhctx->bn, p))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Computes the Diffie-Hellman secret from the previously created context
|
||||||
|
* `*dhctx', the public key `f' from the other party and the same prime `p'
|
||||||
|
* used at context creation. The result is stored in `secret'. 0 is returned
|
||||||
|
* upon success, else -1. */
|
||||||
|
int
|
||||||
|
_libssh2_dh_secret(_libssh2_dh_ctx *dhctx, _libssh2_bn *secret,
|
||||||
|
_libssh2_bn *f, _libssh2_bn *p)
|
||||||
|
{
|
||||||
|
if(_libssh2_wincng.hAlgDH && _libssh2_wincng.hasAlgDHwithKDF != -1 &&
|
||||||
|
dhctx->dh_handle && dhctx->dh_params && f) {
|
||||||
|
BCRYPT_KEY_HANDLE peer_public = NULL;
|
||||||
|
BCRYPT_SECRET_HANDLE agreement = NULL;
|
||||||
|
ULONG secret_len_bytes = 0;
|
||||||
|
unsigned char *blob;
|
||||||
|
int status;
|
||||||
|
unsigned char *start, *end;
|
||||||
|
BCRYPT_DH_KEY_BLOB *public_blob = NULL;
|
||||||
|
DWORD key_length_bytes = max(f->length, dhctx->dh_params->cbKeyLength);
|
||||||
|
DWORD public_blob_len = sizeof(*public_blob) + 3 * key_length_bytes;
|
||||||
|
|
||||||
|
{
|
||||||
|
/* Populate a BCRYPT_DH_KEY_BLOB; after the header follows the
|
||||||
|
* Modulus, Generator and Public data. Those components must have
|
||||||
|
* equal size in this representation. */
|
||||||
|
unsigned char *dest;
|
||||||
|
unsigned char *src;
|
||||||
|
|
||||||
|
blob = malloc(public_blob_len);
|
||||||
|
if(!blob) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
public_blob = (BCRYPT_DH_KEY_BLOB*)blob;
|
||||||
|
public_blob->dwMagic = BCRYPT_DH_PUBLIC_MAGIC;
|
||||||
|
public_blob->cbKey = key_length_bytes;
|
||||||
|
|
||||||
|
dest = (unsigned char *)(public_blob + 1);
|
||||||
|
src = (unsigned char *)(dhctx->dh_params + 1);
|
||||||
|
|
||||||
|
/* Modulus (the p-value from the first call) */
|
||||||
|
memcpy_with_be_padding(dest, key_length_bytes, src,
|
||||||
|
dhctx->dh_params->cbKeyLength);
|
||||||
|
/* Generator (the g-value from the first call) */
|
||||||
|
memcpy_with_be_padding(dest + key_length_bytes, key_length_bytes,
|
||||||
|
src + dhctx->dh_params->cbKeyLength,
|
||||||
|
dhctx->dh_params->cbKeyLength);
|
||||||
|
/* Public from the peer */
|
||||||
|
memcpy_with_be_padding(dest + 2*key_length_bytes, key_length_bytes,
|
||||||
|
f->bignum, f->length);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Import the peer public key information */
|
||||||
|
status = BCryptImportKeyPair(_libssh2_wincng.hAlgDH, NULL,
|
||||||
|
BCRYPT_DH_PUBLIC_BLOB, &peer_public, blob,
|
||||||
|
public_blob_len, 0);
|
||||||
|
if(!BCRYPT_SUCCESS(status)) {
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set up a handle that we can use to establish the shared secret
|
||||||
|
* between ourselves (our saved dh_handle) and the peer. */
|
||||||
|
status = BCryptSecretAgreement(dhctx->dh_handle, peer_public,
|
||||||
|
&agreement, 0);
|
||||||
|
if(!BCRYPT_SUCCESS(status)) {
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Compute the size of the buffer that is needed to hold the derived
|
||||||
|
* shared secret. */
|
||||||
|
status = BCryptDeriveKey(agreement, BCRYPT_KDF_RAW_SECRET, NULL, NULL,
|
||||||
|
0, &secret_len_bytes, 0);
|
||||||
|
if(!BCRYPT_SUCCESS(status)) {
|
||||||
|
if(status == STATUS_NOT_SUPPORTED) {
|
||||||
|
_libssh2_wincng.hasAlgDHwithKDF = -1;
|
||||||
|
}
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Expand the secret bignum to be ready to receive the derived secret
|
||||||
|
* */
|
||||||
|
if(_libssh2_wincng_bignum_resize(secret, secret_len_bytes)) {
|
||||||
|
status = STATUS_NO_MEMORY;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* And populate the secret bignum */
|
||||||
|
status = BCryptDeriveKey(agreement, BCRYPT_KDF_RAW_SECRET, NULL,
|
||||||
|
secret->bignum, secret_len_bytes,
|
||||||
|
&secret_len_bytes, 0);
|
||||||
|
if(!BCRYPT_SUCCESS(status)) {
|
||||||
|
if(status == STATUS_NOT_SUPPORTED) {
|
||||||
|
_libssh2_wincng.hasAlgDHwithKDF = -1;
|
||||||
|
}
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Counter to all the other data in the BCrypt APIs, the raw secret is
|
||||||
|
* returned to us in host byte order, so we need to swap it to big
|
||||||
|
* endian order. */
|
||||||
|
start = secret->bignum;
|
||||||
|
end = secret->bignum + secret->length - 1;
|
||||||
|
while(start < end) {
|
||||||
|
unsigned char tmp = *end;
|
||||||
|
*end = *start;
|
||||||
|
*start = tmp;
|
||||||
|
start++;
|
||||||
|
end--;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = 0;
|
||||||
|
_libssh2_wincng.hasAlgDHwithKDF = 1;
|
||||||
|
|
||||||
|
out:
|
||||||
|
if(peer_public) {
|
||||||
|
BCryptDestroyKey(peer_public);
|
||||||
|
}
|
||||||
|
if(agreement) {
|
||||||
|
BCryptDestroySecret(agreement);
|
||||||
|
}
|
||||||
|
if(status == STATUS_NOT_SUPPORTED &&
|
||||||
|
_libssh2_wincng.hasAlgDHwithKDF == -1) {
|
||||||
|
goto fb; /* fallback to RSA-based implementation */
|
||||||
|
}
|
||||||
|
return BCRYPT_SUCCESS(status) ? 0 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fb:
|
||||||
|
/* Compute the shared secret */
|
||||||
|
return _libssh2_wincng_bignum_mod_exp(secret, f, dhctx->bn, p);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* LIBSSH2_WINCNG */
|
#endif /* LIBSSH2_WINCNG */
|
||||||
|
38
src/wincng.h
Executable file → Normal file
38
src/wincng.h
Executable file → Normal file
@@ -1,5 +1,7 @@
|
|||||||
|
#ifndef __LIBSSH2_WINCNG_H
|
||||||
|
#define __LIBSSH2_WINCNG_H
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2013-2015 Marc Hoersken <info@marc-hoersken.de>
|
* Copyright (C) 2013-2020 Marc Hoersken <info@marc-hoersken.de>
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms,
|
* Redistribution and use in source and binary forms,
|
||||||
@@ -47,7 +49,6 @@
|
|||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <bcrypt.h>
|
#include <bcrypt.h>
|
||||||
|
|
||||||
|
|
||||||
#define LIBSSH2_MD5 1
|
#define LIBSSH2_MD5 1
|
||||||
|
|
||||||
#define LIBSSH2_HMAC_RIPEMD 0
|
#define LIBSSH2_HMAC_RIPEMD 0
|
||||||
@@ -69,6 +70,7 @@
|
|||||||
#define MD5_DIGEST_LENGTH 16
|
#define MD5_DIGEST_LENGTH 16
|
||||||
#define SHA_DIGEST_LENGTH 20
|
#define SHA_DIGEST_LENGTH 20
|
||||||
#define SHA256_DIGEST_LENGTH 32
|
#define SHA256_DIGEST_LENGTH 32
|
||||||
|
#define SHA384_DIGEST_LENGTH 48
|
||||||
#define SHA512_DIGEST_LENGTH 64
|
#define SHA512_DIGEST_LENGTH 64
|
||||||
|
|
||||||
#define EC_MAX_POINT_LEN ((528 * 2 / 8) + 1)
|
#define EC_MAX_POINT_LEN ((528 * 2 / 8) + 1)
|
||||||
@@ -88,10 +90,12 @@ struct _libssh2_wincng_ctx {
|
|||||||
BCRYPT_ALG_HANDLE hAlgHashMD5;
|
BCRYPT_ALG_HANDLE hAlgHashMD5;
|
||||||
BCRYPT_ALG_HANDLE hAlgHashSHA1;
|
BCRYPT_ALG_HANDLE hAlgHashSHA1;
|
||||||
BCRYPT_ALG_HANDLE hAlgHashSHA256;
|
BCRYPT_ALG_HANDLE hAlgHashSHA256;
|
||||||
|
BCRYPT_ALG_HANDLE hAlgHashSHA384;
|
||||||
BCRYPT_ALG_HANDLE hAlgHashSHA512;
|
BCRYPT_ALG_HANDLE hAlgHashSHA512;
|
||||||
BCRYPT_ALG_HANDLE hAlgHmacMD5;
|
BCRYPT_ALG_HANDLE hAlgHmacMD5;
|
||||||
BCRYPT_ALG_HANDLE hAlgHmacSHA1;
|
BCRYPT_ALG_HANDLE hAlgHmacSHA1;
|
||||||
BCRYPT_ALG_HANDLE hAlgHmacSHA256;
|
BCRYPT_ALG_HANDLE hAlgHmacSHA256;
|
||||||
|
BCRYPT_ALG_HANDLE hAlgHmacSHA384;
|
||||||
BCRYPT_ALG_HANDLE hAlgHmacSHA512;
|
BCRYPT_ALG_HANDLE hAlgHmacSHA512;
|
||||||
BCRYPT_ALG_HANDLE hAlgRSA;
|
BCRYPT_ALG_HANDLE hAlgRSA;
|
||||||
BCRYPT_ALG_HANDLE hAlgDSA;
|
BCRYPT_ALG_HANDLE hAlgDSA;
|
||||||
@@ -99,9 +103,11 @@ struct _libssh2_wincng_ctx {
|
|||||||
BCRYPT_ALG_HANDLE hAlgAES_ECB;
|
BCRYPT_ALG_HANDLE hAlgAES_ECB;
|
||||||
BCRYPT_ALG_HANDLE hAlgRC4_NA;
|
BCRYPT_ALG_HANDLE hAlgRC4_NA;
|
||||||
BCRYPT_ALG_HANDLE hAlg3DES_CBC;
|
BCRYPT_ALG_HANDLE hAlg3DES_CBC;
|
||||||
|
BCRYPT_ALG_HANDLE hAlgDH;
|
||||||
|
volatile int hasAlgDHwithKDF; /* -1=no, 0=maybe, 1=yes */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _libssh2_wincng_ctx _libssh2_wincng;
|
extern struct _libssh2_wincng_ctx _libssh2_wincng;
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************/
|
/*******************************************************************/
|
||||||
@@ -162,7 +168,17 @@ typedef struct __libssh2_wincng_hash_ctx {
|
|||||||
#define libssh2_sha256(data, datalen, hash) \
|
#define libssh2_sha256(data, datalen, hash) \
|
||||||
_libssh2_wincng_hash(data, datalen, _libssh2_wincng.hAlgHashSHA256, \
|
_libssh2_wincng_hash(data, datalen, _libssh2_wincng.hAlgHashSHA256, \
|
||||||
hash, SHA256_DIGEST_LENGTH)
|
hash, SHA256_DIGEST_LENGTH)
|
||||||
|
#define libssh2_sha384_ctx _libssh2_wincng_hash_ctx
|
||||||
|
#define libssh2_sha384_init(ctx) \
|
||||||
|
(_libssh2_wincng_hash_init(ctx, _libssh2_wincng.hAlgHashSHA384, \
|
||||||
|
SHA384_DIGEST_LENGTH, NULL, 0) == 0)
|
||||||
|
#define libssh2_sha384_update(ctx, data, datalen) \
|
||||||
|
_libssh2_wincng_hash_update(&ctx, (unsigned char *) data, datalen)
|
||||||
|
#define libssh2_sha384_final(ctx, hash) \
|
||||||
|
_libssh2_wincng_hash_final(&ctx, hash)
|
||||||
|
#define libssh2_sha384(data, datalen, hash) \
|
||||||
|
_libssh2_wincng_hash(data, datalen, _libssh2_wincng.hAlgHashSHA384, \
|
||||||
|
hash, SHA384_DIGEST_LENGTH)
|
||||||
#define libssh2_sha512_ctx _libssh2_wincng_hash_ctx
|
#define libssh2_sha512_ctx _libssh2_wincng_hash_ctx
|
||||||
#define libssh2_sha512_init(ctx) \
|
#define libssh2_sha512_init(ctx) \
|
||||||
(_libssh2_wincng_hash_init(ctx, _libssh2_wincng.hAlgHashSHA512, \
|
(_libssh2_wincng_hash_init(ctx, _libssh2_wincng.hAlgHashSHA512, \
|
||||||
@@ -385,7 +401,17 @@ _libssh2_bn *_libssh2_wincng_bignum_init(void);
|
|||||||
* Windows CNG backend: Diffie-Hellman support
|
* Windows CNG backend: Diffie-Hellman support
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define _libssh2_dh_ctx struct _libssh2_wincng_bignum *
|
typedef struct {
|
||||||
|
/* holds our private and public key components */
|
||||||
|
BCRYPT_KEY_HANDLE dh_handle;
|
||||||
|
/* records the parsed out modulus and generator
|
||||||
|
* parameters that are shared with the peer */
|
||||||
|
BCRYPT_DH_PARAMETER_HEADER *dh_params;
|
||||||
|
/* records the parsed out private key component for
|
||||||
|
* fallback if the DH API raw KDF is not supported */
|
||||||
|
struct _libssh2_wincng_bignum *bn;
|
||||||
|
} _libssh2_dh_ctx;
|
||||||
|
|
||||||
#define libssh2_dh_init(dhctx) _libssh2_dh_init(dhctx)
|
#define libssh2_dh_init(dhctx) _libssh2_dh_init(dhctx)
|
||||||
#define libssh2_dh_key_pair(dhctx, public, g, p, group_order, bnctx) \
|
#define libssh2_dh_key_pair(dhctx, public, g, p, group_order, bnctx) \
|
||||||
_libssh2_dh_key_pair(dhctx, public, g, p, group_order)
|
_libssh2_dh_key_pair(dhctx, public, g, p, group_order)
|
||||||
@@ -569,3 +595,5 @@ _libssh2_dh_secret(_libssh2_dh_ctx *dhctx, _libssh2_bn *secret,
|
|||||||
_libssh2_bn *f, _libssh2_bn *p);
|
_libssh2_bn *f, _libssh2_bn *p);
|
||||||
extern void
|
extern void
|
||||||
_libssh2_dh_dtor(_libssh2_dh_ctx *dhctx);
|
_libssh2_dh_dtor(_libssh2_dh_ctx *dhctx);
|
||||||
|
|
||||||
|
#endif /* __LIBSSH2_WINCNG_H */
|
||||||
|
@@ -130,7 +130,9 @@ if(CRYPTO_BACKEND STREQUAL "OpenSSL")
|
|||||||
public_key_auth_succeeds_with_correct_ed25519_key
|
public_key_auth_succeeds_with_correct_ed25519_key
|
||||||
public_key_auth_succeeds_with_correct_encrypted_ed25519_key
|
public_key_auth_succeeds_with_correct_encrypted_ed25519_key
|
||||||
public_key_auth_succeeds_with_correct_ed25519_key_from_mem
|
public_key_auth_succeeds_with_correct_ed25519_key_from_mem
|
||||||
)
|
public_key_auth_succeeds_with_correct_ecdsa_key
|
||||||
|
public_key_auth_succeeds_with_correct_signed_ecdsa_key
|
||||||
|
)
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
@@ -1,3 +1,5 @@
|
|||||||
|
SUBDIRS = ossfuzz
|
||||||
|
|
||||||
AM_CPPFLAGS = -I$(top_srcdir)/src -I$(top_srcdir)/include -I$(top_builddir)/src
|
AM_CPPFLAGS = -I$(top_srcdir)/src -I$(top_srcdir)/include -I$(top_builddir)/src
|
||||||
LDADD = ../src/libssh2.la
|
LDADD = ../src/libssh2.la
|
||||||
|
|
||||||
@@ -16,26 +18,64 @@ check_PROGRAMS = $(ctests)
|
|||||||
TESTS_ENVIRONMENT = SSHD=$(SSHD) EXEEXT=$(EXEEXT)
|
TESTS_ENVIRONMENT = SSHD=$(SSHD) EXEEXT=$(EXEEXT)
|
||||||
TESTS_ENVIRONMENT += srcdir=$(top_srcdir)/tests builddir=$(top_builddir)/tests
|
TESTS_ENVIRONMENT += srcdir=$(top_srcdir)/tests builddir=$(top_builddir)/tests
|
||||||
|
|
||||||
EXTRA_DIST = ssh2.sh mansyntax.sh
|
EXTRA_DIST = \
|
||||||
EXTRA_DIST += etc/host etc/host.pub etc/user etc/user.pub
|
CMakeLists.txt \
|
||||||
EXTRA_DIST += CMakeLists.txt libssh2_config_cmake.h.in sshd_fixture.sh.in
|
etc/host \
|
||||||
EXTRA_DIST += key_dsa key_dsa.pub key_dsa_wrong key_dsa_wrong.pub key_rsa key_rsa.pub
|
etc/host.pub \
|
||||||
EXTRA_DIST += openssh_server/authorized_keys openssh_server/Dockerfile openssh_server/ssh_host_rsa_key
|
etc/user \
|
||||||
EXTRA_DIST += openssh_fixture.c openssh_fixture.h runner.c session_fixture.c session_fixture.h
|
etc/user.pub \
|
||||||
EXTRA_DIST += test_hostkey.c test_hostkey_hash.c
|
key_dsa \
|
||||||
EXTRA_DIST += test_keyboard_interactive_auth_fails_with_wrong_response.c
|
key_dsa.pub \
|
||||||
EXTRA_DIST += test_keyboard_interactive_auth_succeeds_with_correct_response.c
|
key_dsa_wrong \
|
||||||
EXTRA_DIST += test_password_auth_fails_with_wrong_password.c
|
key_dsa_wrong.pub \
|
||||||
EXTRA_DIST += test_password_auth_fails_with_wrong_username.c
|
key_ecdsa \
|
||||||
EXTRA_DIST += test_password_auth_succeeds_with_correct_credentials.c
|
key_ecdsa.pub \
|
||||||
EXTRA_DIST += test_public_key_auth_fails_with_wrong_key.c
|
signed_key_ecdsa \
|
||||||
EXTRA_DIST += test_public_key_auth_succeeds_with_correct_dsa_key.c
|
signed_key_ecdsa.pub \
|
||||||
EXTRA_DIST += test_public_key_auth_succeeds_with_correct_rsa_key.c
|
signed_key_ecdsa-cert.pub \
|
||||||
EXTRA_DIST += test_public_key_auth_succeeds_with_correct_encrypted_rsa_key.c
|
key_ed25519 \
|
||||||
if OPENSSL
|
key_ed25519.pub \
|
||||||
# TODO: need to add a test for specific openssl version some how
|
key_ed25519_encrypted \
|
||||||
# EXTRA_DIST += test_public_key_auth_succeeds_with_correct_ed25519_key.c
|
key_ed25519_encrypted.pub \
|
||||||
# EXTRA_DIST += test_public_key_auth_succeeds_with_correct_encrypted_ed25519_key.c
|
key_rsa \
|
||||||
# EXTRA_DIST += test_public_key_auth_succeeds_with_correct_ed25519_key_from_mem.c
|
key_rsa.pub \
|
||||||
EXTRA_DIST += test_public_key_auth_succeeds_with_correct_rsa_openssh_key.c
|
key_rsa_encrypted \
|
||||||
endif
|
key_rsa_encrypted.pub \
|
||||||
|
key_rsa_openssh \
|
||||||
|
key_rsa_openssh.pub \
|
||||||
|
libssh2_config_cmake.h.in \
|
||||||
|
mansyntax.sh \
|
||||||
|
openssh_fixture.c \
|
||||||
|
openssh_fixture.h \
|
||||||
|
openssh_server/Dockerfile \
|
||||||
|
openssh_server/authorized_keys \
|
||||||
|
openssh_server/ca_ecdsa \
|
||||||
|
openssh_server/ca_ecdsa.pub \
|
||||||
|
openssh_server/ssh_host_ecdsa_key \
|
||||||
|
openssh_server/ssh_host_ed25519_key \
|
||||||
|
openssh_server/ssh_host_rsa_key \
|
||||||
|
runner.c \
|
||||||
|
session_fixture.c \
|
||||||
|
session_fixture.h \
|
||||||
|
simple.c \
|
||||||
|
ssh2.c \
|
||||||
|
ssh2.sh \
|
||||||
|
sshd_fixture.sh.in \
|
||||||
|
test_agent_forward_succeeds.c \
|
||||||
|
test_hostkey.c \
|
||||||
|
test_hostkey_hash.c \
|
||||||
|
test_keyboard_interactive_auth_fails_with_wrong_response.c \
|
||||||
|
test_keyboard_interactive_auth_succeeds_with_correct_response.c \
|
||||||
|
test_password_auth_fails_with_wrong_password.c \
|
||||||
|
test_password_auth_fails_with_wrong_username.c \
|
||||||
|
test_password_auth_succeeds_with_correct_credentials.c \
|
||||||
|
test_public_key_auth_fails_with_wrong_key.c \
|
||||||
|
test_public_key_auth_succeeds_with_correct_dsa_key.c \
|
||||||
|
test_public_key_auth_succeeds_with_correct_ed25519_key.c \
|
||||||
|
test_public_key_auth_succeeds_with_correct_ed25519_key_from_mem.c \
|
||||||
|
test_public_key_auth_succeeds_with_correct_ecdsa_key.c \
|
||||||
|
test_public_key_auth_succeeds_with_correct_signed_ecdsa_key.c \
|
||||||
|
test_public_key_auth_succeeds_with_correct_encrypted_ed25519_key.c \
|
||||||
|
test_public_key_auth_succeeds_with_correct_encrypted_rsa_key.c \
|
||||||
|
test_public_key_auth_succeeds_with_correct_rsa_key.c \
|
||||||
|
test_public_key_auth_succeeds_with_correct_rsa_openssh_key.c
|
||||||
|
10
tests/key_ecdsa
Normal file
10
tests/key_ecdsa
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
-----BEGIN OPENSSH PRIVATE KEY-----
|
||||||
|
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAiAAAABNlY2RzYS
|
||||||
|
1zaGEyLW5pc3RwMzg0AAAACG5pc3RwMzg0AAAAYQTosiScH/oRSazpIpPSEFcY4YVZyNby
|
||||||
|
peARi49N3qy78OE118KGc5T8eifd+n1PSb7z8PnfDwOL4jBHxW5nWx0RCocIt7tb2a349J
|
||||||
|
gfEl8PegHGcF/DwC+eesIKJvv0MfkAAADIKLgw6yi4MOsAAAATZWNkc2Etc2hhMi1uaXN0
|
||||||
|
cDM4NAAAAAhuaXN0cDM4NAAAAGEE6LIknB/6EUms6SKT0hBXGOGFWcjW8qXgEYuPTd6su/
|
||||||
|
DhNdfChnOU/Hon3fp9T0m+8/D53w8Di+IwR8VuZ1sdEQqHCLe7W9mt+PSYHxJfD3oBxnBf
|
||||||
|
w8AvnnrCCib79DH5AAAAMGYdHu+u2/L8zC/0S9bao9y6vKiLSuTEfZpCIsyE5jWj/vrS0n
|
||||||
|
r1lzv9kKj+5A86aQAAAAA=
|
||||||
|
-----END OPENSSH PRIVATE KEY-----
|
1
tests/key_ecdsa.pub
Normal file
1
tests/key_ecdsa.pub
Normal file
@@ -0,0 +1 @@
|
|||||||
|
ecdsa-sha2-nistp384 AAAAE2VjZHNhLXNoYTItbmlzdHAzODQAAAAIbmlzdHAzODQAAABhBOiyJJwf+hFJrOkik9IQVxjhhVnI1vKl4BGLj03erLvw4TXXwoZzlPx6J936fU9JvvPw+d8PA4viMEfFbmdbHREKhwi3u1vZrfj0mB8SXw96AcZwX8PAL556wgom+/Qx+Q==
|
@@ -62,10 +62,12 @@
|
|||||||
static int run_command_varg(char **output, const char *command, va_list args)
|
static int run_command_varg(char **output, const char *command, va_list args)
|
||||||
{
|
{
|
||||||
FILE *pipe;
|
FILE *pipe;
|
||||||
|
char redirect_stderr[] = "%s 2>&1";
|
||||||
char command_buf[BUFSIZ];
|
char command_buf[BUFSIZ];
|
||||||
char buf[BUFSIZ];
|
char buf[BUFSIZ];
|
||||||
char *p;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
size_t buf_len;
|
||||||
|
|
||||||
if(output) {
|
if(output) {
|
||||||
*output = NULL;
|
*output = NULL;
|
||||||
}
|
}
|
||||||
@@ -78,26 +80,33 @@ static int run_command_varg(char **output, const char *command, va_list args)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Rewrite the command to redirect stderr to stdout to we can output it */
|
/* Rewrite the command to redirect stderr to stdout to we can output it */
|
||||||
if(strlen(command_buf) + 6 >= sizeof(command_buf)) {
|
if(strlen(command_buf) + strlen(redirect_stderr) >= sizeof(buf)) {
|
||||||
fprintf(stderr, "Unable to rewrite command (%s)\n", command);
|
fprintf(stderr, "Unable to rewrite command (%s)\n", command);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
strncat(command_buf, " 2>&1", 6);
|
ret = snprintf(buf, sizeof(buf), redirect_stderr, command_buf);
|
||||||
|
if(ret < 0 || ret >= BUFSIZ) {
|
||||||
|
fprintf(stderr, "Unable to rewrite command (%s)\n", command);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
fprintf(stdout, "Command: %s\n", command);
|
fprintf(stdout, "Command: %s\n", command);
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
pipe = _popen(command_buf, "r");
|
pipe = _popen(buf, "r");
|
||||||
#else
|
#else
|
||||||
pipe = popen(command_buf, "r");
|
pipe = popen(buf, "r");
|
||||||
#endif
|
#endif
|
||||||
if(!pipe) {
|
if(!pipe) {
|
||||||
fprintf(stderr, "Unable to execute command '%s'\n", command);
|
fprintf(stderr, "Unable to execute command '%s'\n", command);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
p = buf;
|
buf[0] = 0;
|
||||||
while(fgets(p, sizeof(buf) - (p - buf), pipe) != NULL)
|
buf_len = 0;
|
||||||
;
|
while(buf_len < (sizeof(buf) - 1) &&
|
||||||
|
fgets(&buf[buf_len], sizeof(buf) - buf_len, pipe) != NULL) {
|
||||||
|
buf_len = strlen(buf);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
ret = _pclose(pipe);
|
ret = _pclose(pipe);
|
||||||
@@ -112,9 +121,9 @@ static int run_command_varg(char **output, const char *command, va_list args)
|
|||||||
if(output) {
|
if(output) {
|
||||||
/* command output may contain a trailing newline, so we trim
|
/* command output may contain a trailing newline, so we trim
|
||||||
* whitespace here */
|
* whitespace here */
|
||||||
size_t end = strlen(buf) - 1;
|
size_t end = strlen(buf);
|
||||||
while(end > 0 && isspace(buf[end])) {
|
while(end > 0 && isspace(buf[end - 1])) {
|
||||||
buf[end] = '\0';
|
buf[end - 1] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
*output = strdup(buf);
|
*output = strdup(buf);
|
||||||
@@ -134,16 +143,32 @@ static int run_command(char **output, const char *command, ...)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int build_openssh_server_docker_image()
|
static int build_openssh_server_docker_image(void)
|
||||||
{
|
{
|
||||||
return run_command(NULL, "docker build -t libssh2/openssh_server openssh_server");
|
return run_command(NULL, "docker build --quiet "
|
||||||
|
"-t libssh2/openssh_server "
|
||||||
|
"openssh_server");
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *openssh_server_port(void)
|
||||||
|
{
|
||||||
|
return getenv("OPENSSH_SERVER_PORT");
|
||||||
}
|
}
|
||||||
|
|
||||||
static int start_openssh_server(char **container_id_out)
|
static int start_openssh_server(char **container_id_out)
|
||||||
{
|
{
|
||||||
return run_command(container_id_out,
|
const char *container_host_port = openssh_server_port();
|
||||||
"docker run --detach -P libssh2/openssh_server"
|
if(container_host_port != NULL) {
|
||||||
);
|
return run_command(container_id_out,
|
||||||
|
"docker run --rm -d -p %s:22 "
|
||||||
|
"libssh2/openssh_server",
|
||||||
|
container_host_port);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return run_command(container_id_out,
|
||||||
|
"docker run --rm -d -p 22 "
|
||||||
|
"libssh2/openssh_server");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int stop_openssh_server(char *container_id)
|
static int stop_openssh_server(char *container_id)
|
||||||
@@ -151,11 +176,48 @@ static int stop_openssh_server(char *container_id)
|
|||||||
return run_command(NULL, "docker stop %s", container_id);
|
return run_command(NULL, "docker stop %s", container_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *docker_machine_name()
|
static const char *docker_machine_name(void)
|
||||||
{
|
{
|
||||||
return getenv("DOCKER_MACHINE_NAME");
|
return getenv("DOCKER_MACHINE_NAME");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int is_running_inside_a_container()
|
||||||
|
{
|
||||||
|
#ifdef WIN32
|
||||||
|
return 0;
|
||||||
|
#else
|
||||||
|
const char *cgroup_filename = "/proc/self/cgroup";
|
||||||
|
FILE *f = NULL;
|
||||||
|
char *line = NULL;
|
||||||
|
size_t len = 0;
|
||||||
|
ssize_t read = 0;
|
||||||
|
int found = 0;
|
||||||
|
f = fopen(cgroup_filename, "r");
|
||||||
|
if(f == NULL) {
|
||||||
|
/* Don't go further, we are not in a container */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
while((read = getline(&line, &len, f)) != -1) {
|
||||||
|
if(strstr(line, "docker") != NULL) {
|
||||||
|
found = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fclose(f);
|
||||||
|
free(line);
|
||||||
|
return found;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static void portable_sleep(unsigned int seconds)
|
||||||
|
{
|
||||||
|
#ifdef WIN32
|
||||||
|
Sleep(seconds);
|
||||||
|
#else
|
||||||
|
sleep(seconds);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
static int ip_address_from_container(char *container_id, char **ip_address_out)
|
static int ip_address_from_container(char *container_id, char **ip_address_out)
|
||||||
{
|
{
|
||||||
const char *active_docker_machine = docker_machine_name();
|
const char *active_docker_machine = docker_machine_name();
|
||||||
@@ -167,9 +229,12 @@ static int ip_address_from_container(char *container_id, char **ip_address_out)
|
|||||||
int attempt_no = 0;
|
int attempt_no = 0;
|
||||||
int wait_time = 500;
|
int wait_time = 500;
|
||||||
for(;;) {
|
for(;;) {
|
||||||
return run_command(ip_address_out, "docker-machine ip %s", active_docker_machine);
|
int ret = run_command(ip_address_out, "docker-machine ip %s",
|
||||||
|
active_docker_machine);
|
||||||
if(attempt_no > 5) {
|
if(ret == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else if(attempt_no > 5) {
|
||||||
fprintf(
|
fprintf(
|
||||||
stderr,
|
stderr,
|
||||||
"Unable to get IP from docker-machine after %d attempts\n",
|
"Unable to get IP from docker-machine after %d attempts\n",
|
||||||
@@ -177,35 +242,44 @@ static int ip_address_from_container(char *container_id, char **ip_address_out)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
#ifdef WIN32
|
portable_sleep(wait_time);
|
||||||
#pragma warning(push)
|
|
||||||
#pragma warning(disable : 4996)
|
|
||||||
_sleep(wait_time);
|
|
||||||
#pragma warning(pop)
|
|
||||||
#else
|
|
||||||
sleep(wait_time);
|
|
||||||
#endif
|
|
||||||
++attempt_no;
|
++attempt_no;
|
||||||
wait_time *= 2;
|
wait_time *= 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return run_command(ip_address_out,
|
if(is_running_inside_a_container()) {
|
||||||
"docker inspect --format "
|
return run_command(ip_address_out,
|
||||||
"\"{{ index (index (index .NetworkSettings.Ports "
|
"docker inspect --format "
|
||||||
"\\\"22/tcp\\\") 0) \\\"HostIp\\\" }}\" %s",
|
"\"{{ .NetworkSettings.IPAddress }}\""
|
||||||
container_id);
|
" %s",
|
||||||
|
container_id);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return run_command(ip_address_out,
|
||||||
|
"docker inspect --format "
|
||||||
|
"\"{{ index (index (index "
|
||||||
|
".NetworkSettings.Ports "
|
||||||
|
"\\\"22/tcp\\\") 0) \\\"HostIp\\\" }}\" %s",
|
||||||
|
container_id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int port_from_container(char *container_id, char **port_out)
|
static int port_from_container(char *container_id, char **port_out)
|
||||||
{
|
{
|
||||||
return run_command(port_out,
|
if(is_running_inside_a_container()) {
|
||||||
"docker inspect --format "
|
*port_out = strdup("22");
|
||||||
"\"{{ index (index (index .NetworkSettings.Ports "
|
return 0;
|
||||||
"\\\"22/tcp\\\") 0) \\\"HostPort\\\" }}\" %s",
|
}
|
||||||
container_id);
|
else {
|
||||||
|
return run_command(port_out,
|
||||||
|
"docker inspect --format "
|
||||||
|
"\"{{ index (index (index .NetworkSettings.Ports "
|
||||||
|
"\\\"22/tcp\\\") 0) \\\"HostPort\\\" }}\" %s",
|
||||||
|
container_id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int open_socket_to_container(char *container_id)
|
static int open_socket_to_container(char *container_id)
|
||||||
@@ -215,20 +289,31 @@ static int open_socket_to_container(char *container_id)
|
|||||||
unsigned long hostaddr;
|
unsigned long hostaddr;
|
||||||
int sock;
|
int sock;
|
||||||
struct sockaddr_in sin;
|
struct sockaddr_in sin;
|
||||||
|
int counter = 0;
|
||||||
|
|
||||||
int ret = ip_address_from_container(container_id, &ip_address);
|
int ret = ip_address_from_container(container_id, &ip_address);
|
||||||
if(ret != 0) {
|
if(ret != 0) {
|
||||||
fprintf(stderr, "Failed to get IP address for container %s\n", container_id);
|
fprintf(stderr, "Failed to get IP address for container %s\n",
|
||||||
|
container_id);
|
||||||
ret = -1;
|
ret = -1;
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = port_from_container(container_id, &port_string);
|
ret = port_from_container(container_id, &port_string);
|
||||||
if(ret != 0) {
|
if(ret != 0) {
|
||||||
fprintf(stderr, "Failed to get port for container %s\n", container_id);
|
fprintf(stderr, "Failed to get port for container %s\n",
|
||||||
|
container_id);
|
||||||
ret = -1;
|
ret = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 0.0.0.0 is returned by Docker for Windows, because the container
|
||||||
|
is reachable from anywhere. But we cannot connect to 0.0.0.0,
|
||||||
|
instead we assume localhost and try to connect to 127.0.0.1. */
|
||||||
|
if(ip_address && strcmp(ip_address, "0.0.0.0") == 0) {
|
||||||
|
free(ip_address);
|
||||||
|
ip_address = strdup("127.0.0.1");
|
||||||
|
}
|
||||||
|
|
||||||
hostaddr = inet_addr(ip_address);
|
hostaddr = inet_addr(ip_address);
|
||||||
if(hostaddr == (unsigned long)(-1)) {
|
if(hostaddr == (unsigned long)(-1)) {
|
||||||
fprintf(stderr, "Failed to convert %s host address\n", ip_address);
|
fprintf(stderr, "Failed to convert %s host address\n", ip_address);
|
||||||
@@ -247,15 +332,26 @@ static int open_socket_to_container(char *container_id)
|
|||||||
sin.sin_port = htons((short)strtol(port_string, NULL, 0));
|
sin.sin_port = htons((short)strtol(port_string, NULL, 0));
|
||||||
sin.sin_addr.s_addr = hostaddr;
|
sin.sin_addr.s_addr = hostaddr;
|
||||||
|
|
||||||
if(connect(sock, (struct sockaddr *)(&sin),
|
for(counter = 0; counter < 3; ++counter) {
|
||||||
sizeof(struct sockaddr_in)) != 0) {
|
if(connect(sock, (struct sockaddr *)(&sin),
|
||||||
fprintf(stderr, "Failed to connect to %s:%s\n", ip_address, port_string);
|
sizeof(struct sockaddr_in)) != 0) {
|
||||||
ret = -1;
|
ret = -1;
|
||||||
|
fprintf(stderr,
|
||||||
|
"Connection to %s:%s attempt #%d failed: retrying...\n",
|
||||||
|
ip_address, port_string, counter);
|
||||||
|
portable_sleep(1 + 2*counter);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ret = sock;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(ret == -1) {
|
||||||
|
fprintf(stderr, "Failed to connect to %s:%s\n",
|
||||||
|
ip_address, port_string);
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = sock;
|
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
free(ip_address);
|
free(ip_address);
|
||||||
free(port_string);
|
free(port_string);
|
||||||
|
@@ -58,10 +58,19 @@ COPY ssh_host_ed25519_key /tmp/etc/ssh/ssh_host_ed25519_key
|
|||||||
RUN mv /tmp/etc/ssh/ssh_host_ed25519_key /etc/ssh/ssh_host_ed25519_key
|
RUN mv /tmp/etc/ssh/ssh_host_ed25519_key /etc/ssh/ssh_host_ed25519_key
|
||||||
RUN chmod 600 /etc/ssh/ssh_host_ed25519_key
|
RUN chmod 600 /etc/ssh/ssh_host_ed25519_key
|
||||||
|
|
||||||
|
COPY ca_ecdsa.pub /tmp/etc/ssh/ca_ecdsa.pub
|
||||||
|
RUN mv /tmp/etc/ssh/ca_ecdsa.pub /etc/ssh/ca_ecdsa.pub
|
||||||
|
RUN chmod 600 /etc/ssh/ca_ecdsa.pub
|
||||||
|
|
||||||
|
COPY ca_ecdsa /tmp/etc/ssh/ca_ecdsa
|
||||||
|
RUN mv /tmp/etc/ssh/ca_ecdsa /etc/ssh/ca_ecdsa
|
||||||
|
RUN chmod 600 /etc/ssh/ca_ecdsa
|
||||||
|
|
||||||
RUN adduser --disabled-password --gecos 'Test user for libssh2 integration tests' libssh2
|
RUN adduser --disabled-password --gecos 'Test user for libssh2 integration tests' libssh2
|
||||||
RUN echo 'libssh2:my test password' | chpasswd
|
RUN echo 'libssh2:my test password' | chpasswd
|
||||||
|
|
||||||
RUN sed -i 's/ChallengeResponseAuthentication no/ChallengeResponseAuthentication yes/' /etc/ssh/sshd_config
|
RUN sed -i 's/ChallengeResponseAuthentication no/ChallengeResponseAuthentication yes/' /etc/ssh/sshd_config
|
||||||
|
RUN echo "TrustedUserCAKeys /etc/ssh/ca_ecdsa.pub" >> /etc/ssh/sshd_config
|
||||||
|
|
||||||
# SSH login fix. Otherwise user is kicked off after login
|
# SSH login fix. Otherwise user is kicked off after login
|
||||||
RUN sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/sshd
|
RUN sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/sshd
|
||||||
|
@@ -4,3 +4,4 @@ ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC92YlGoc4PJy6DzX916JJZhxkvmkWBLGJdWOL7R9B6
|
|||||||
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDTe1lN2L/yet0Ma1JzXkQf3t1f+pauALec2FsGZy87KRJW1AOxcTTiePjlFwP1yfSK1lWXQ+uf0b61gkKqqR52FDky24HJWuYlfXlEQMn2d/PNDNVDDbO4TXKyNxxUHFJ6qYMNd4kWjOH+6rmYoWKsWV+3mDRbHagbVPEYL8wep8OTqKOqruVLVPzZyYZkBtn4XOFi6UE8WKiSVdK1Am1O5UxvlD95t32eYch6wQ9azgMqja6spe/L5UJgP83QZFknVC3wPZWkjqomVFql0FpaQclENwyY/OZMxr0cT/f7bCL6s4A/1XpbsGmC0xak4/THHbOn+0LdIej2nGV8JFoR
|
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDTe1lN2L/yet0Ma1JzXkQf3t1f+pauALec2FsGZy87KRJW1AOxcTTiePjlFwP1yfSK1lWXQ+uf0b61gkKqqR52FDky24HJWuYlfXlEQMn2d/PNDNVDDbO4TXKyNxxUHFJ6qYMNd4kWjOH+6rmYoWKsWV+3mDRbHagbVPEYL8wep8OTqKOqruVLVPzZyYZkBtn4XOFi6UE8WKiSVdK1Am1O5UxvlD95t32eYch6wQ9azgMqja6spe/L5UJgP83QZFknVC3wPZWkjqomVFql0FpaQclENwyY/OZMxr0cT/f7bCL6s4A/1XpbsGmC0xak4/THHbOn+0LdIej2nGV8JFoR
|
||||||
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIxtdyg2ZRXE70UwyPVUH3UyfDBV8GX5cPF636P6hjom
|
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIxtdyg2ZRXE70UwyPVUH3UyfDBV8GX5cPF636P6hjom
|
||||||
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICHxEyUTOVHXvdMFARedFQ+H9DW/n8Zy3daKKRqnTDMq
|
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICHxEyUTOVHXvdMFARedFQ+H9DW/n8Zy3daKKRqnTDMq
|
||||||
|
ecdsa-sha2-nistp384 AAAAE2VjZHNhLXNoYTItbmlzdHAzODQAAAAIbmlzdHAzODQAAABhBOiyJJwf+hFJrOkik9IQVxjhhVnI1vKl4BGLj03erLvw4TXXwoZzlPx6J936fU9JvvPw+d8PA4viMEfFbmdbHREKhwi3u1vZrfj0mB8SXw96AcZwX8PAL556wgom+/Qx+Q==
|
||||||
|
12
tests/openssh_server/ca_ecdsa
Normal file
12
tests/openssh_server/ca_ecdsa
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
-----BEGIN OPENSSH PRIVATE KEY-----
|
||||||
|
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAArAAAABNlY2RzYS
|
||||||
|
1zaGEyLW5pc3RwNTIxAAAACG5pc3RwNTIxAAAAhQQAfv15s+G2xg56J+audKAM4G9qOTFr
|
||||||
|
bZRo0CTwvkb/oHrf9/2RSWqYsx/0m5mYCZVlecnZqwRHAOolXbc/Yb4cGjsALUj3UDirsn
|
||||||
|
YR7Ve+SwnunkpvW/H3a98sA3sS+HCpd5RbpfWClSBOI9JEAlPtS1CrEQ7EmO7hmlFOH2cL
|
||||||
|
0qfHCyYAAAEA763VSe+t1UkAAAATZWNkc2Etc2hhMi1uaXN0cDUyMQAAAAhuaXN0cDUyMQ
|
||||||
|
AAAIUEAH79ebPhtsYOeifmrnSgDOBvajkxa22UaNAk8L5G/6B63/f9kUlqmLMf9JuZmAmV
|
||||||
|
ZXnJ2asERwDqJV23P2G+HBo7AC1I91A4q7J2Ee1XvksJ7p5Kb1vx92vfLAN7EvhwqXeUW6
|
||||||
|
X1gpUgTiPSRAJT7UtQqxEOxJju4ZpRTh9nC9KnxwsmAAAAQgD8VJwi9RHYN13CAfhvdmjW
|
||||||
|
xVjH55J5jDjPlENU2Z+cnm01SQ+9mPFEY4wDSvfiovD1VstNJX/P97WbHw+e5XL+HwAAAA
|
||||||
|
JDQQ==
|
||||||
|
-----END OPENSSH PRIVATE KEY-----
|
1
tests/openssh_server/ca_ecdsa.pub
Normal file
1
tests/openssh_server/ca_ecdsa.pub
Normal file
@@ -0,0 +1 @@
|
|||||||
|
ecdsa-sha2-nistp521 AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAAAIbmlzdHA1MjEAAACFBAB+/Xmz4bbGDnon5q50oAzgb2o5MWttlGjQJPC+Rv+get/3/ZFJapizH/SbmZgJlWV5ydmrBEcA6iVdtz9hvhwaOwAtSPdQOKuydhHtV75LCe6eSm9b8fdr3ywDexL4cKl3lFul9YKVIE4j0kQCU+1LUKsRDsSY7uGaUU4fZwvSp8cLJg== CA
|
2
tests/ossfuzz/.gitignore
vendored
Normal file
2
tests/ossfuzz/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
*.a
|
||||||
|
ssh2_client_fuzzer
|
32
tests/ossfuzz/Makefile.am
Normal file
32
tests/ossfuzz/Makefile.am
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
AM_CPPFLAGS = -I$(top_builddir)/include
|
||||||
|
LDADD = $(top_builddir)/src/libssh2.la
|
||||||
|
|
||||||
|
if USE_OSSFUZZ_FLAG
|
||||||
|
FUZZ_FLAG = $(LIB_FUZZING_ENGINE)
|
||||||
|
else
|
||||||
|
if USE_OSSFUZZ_STATIC
|
||||||
|
LDADD += $(LIB_FUZZING_ENGINE)
|
||||||
|
FUZZ_FLAG =
|
||||||
|
else
|
||||||
|
LDADD += libstandaloneengine.a
|
||||||
|
FUZZ_FLAG =
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
noinst_PROGRAMS =
|
||||||
|
noinst_LIBRARIES =
|
||||||
|
|
||||||
|
if USE_OSSFUZZERS
|
||||||
|
noinst_PROGRAMS += \
|
||||||
|
ssh2_client_fuzzer
|
||||||
|
|
||||||
|
noinst_LIBRARIES += \
|
||||||
|
libstandaloneengine.a
|
||||||
|
endif
|
||||||
|
|
||||||
|
ssh2_client_fuzzer_SOURCES = ssh2_client_fuzzer.cc testinput.h
|
||||||
|
ssh2_client_fuzzer_CXXFLAGS = $(AM_CXXFLAGS) $(FUZZ_FLAG)
|
||||||
|
ssh2_client_fuzzer_LDFLAGS = $(AM_LDFLAGS) -static
|
||||||
|
|
||||||
|
libstandaloneengine_a_SOURCES = standaloneengine.cc
|
||||||
|
libstandaloneengine_a_CXXFLAGS = $(AM_CXXFLAGS)
|
30
tests/ossfuzz/ossfuzz.sh
Executable file
30
tests/ossfuzz/ossfuzz.sh
Executable file
@@ -0,0 +1,30 @@
|
|||||||
|
#!/bin/bash -eu
|
||||||
|
|
||||||
|
# This script is called by the oss-fuzz main project when compiling the fuzz
|
||||||
|
# targets. This script is regression tested by ci/ossfuzz.sh.
|
||||||
|
|
||||||
|
# Save off the current folder as the build root.
|
||||||
|
export BUILD_ROOT=$PWD
|
||||||
|
|
||||||
|
echo "CC: $CC"
|
||||||
|
echo "CXX: $CXX"
|
||||||
|
echo "LIB_FUZZING_ENGINE: $LIB_FUZZING_ENGINE"
|
||||||
|
echo "CFLAGS: $CFLAGS"
|
||||||
|
echo "CXXFLAGS: $CXXFLAGS"
|
||||||
|
echo "OUT: $OUT"
|
||||||
|
|
||||||
|
export MAKEFLAGS+="-j$(nproc)"
|
||||||
|
|
||||||
|
# Install dependencies
|
||||||
|
apt-get -y install automake libtool libssl-dev zlib1g-dev
|
||||||
|
|
||||||
|
# Compile the fuzzer.
|
||||||
|
./buildconf
|
||||||
|
./configure --disable-shared \
|
||||||
|
--enable-ossfuzzers \
|
||||||
|
--disable-examples-build \
|
||||||
|
--enable-debug
|
||||||
|
make V=1
|
||||||
|
|
||||||
|
# Copy the fuzzer to the output directory.
|
||||||
|
cp -v tests/ossfuzz/ssh2_client_fuzzer $OUT/
|
90
tests/ossfuzz/ssh2_client_fuzzer.cc
Normal file
90
tests/ossfuzz/ssh2_client_fuzzer.cc
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
#include <assert.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <libssh2.h>
|
||||||
|
#include "testinput.h"
|
||||||
|
|
||||||
|
#define FUZZ_ASSERT(COND) \
|
||||||
|
if(!(COND)) \
|
||||||
|
{ \
|
||||||
|
fprintf(stderr, "Assertion failed: " #COND "\n%s", \
|
||||||
|
strerror(errno)); \
|
||||||
|
assert((COND)); \
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
|
||||||
|
{
|
||||||
|
int socket_fds[2] = {-1, -1};
|
||||||
|
ssize_t written;
|
||||||
|
int rc;
|
||||||
|
LIBSSH2_SESSION *session = NULL;
|
||||||
|
int handshake_completed = 0;
|
||||||
|
|
||||||
|
rc = libssh2_init(0);
|
||||||
|
|
||||||
|
if(rc != 0) {
|
||||||
|
fprintf(stderr, "libssh2 initialization failed (%d)\n", rc);
|
||||||
|
goto EXIT_LABEL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a socket pair so data can be sent in.
|
||||||
|
rc = socketpair(AF_UNIX, SOCK_STREAM, 0, socket_fds);
|
||||||
|
FUZZ_ASSERT(rc == 0);
|
||||||
|
|
||||||
|
written = send(socket_fds[1], data, size, 0);
|
||||||
|
|
||||||
|
if (written != size)
|
||||||
|
{
|
||||||
|
// Handle whatever error case we're in.
|
||||||
|
fprintf(stderr, "send() of %zu bytes returned %zu (%d)\n",
|
||||||
|
size,
|
||||||
|
written,
|
||||||
|
errno);
|
||||||
|
goto EXIT_LABEL;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = shutdown(socket_fds[1], SHUT_WR);
|
||||||
|
if (rc != 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "socket shutdown failed (%d)\n", rc);
|
||||||
|
goto EXIT_LABEL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a session and start the handshake using the fuzz data passed in.
|
||||||
|
session = libssh2_session_init();
|
||||||
|
if(session) {
|
||||||
|
libssh2_session_set_blocking(session, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(libssh2_session_handshake(session, socket_fds[0])) {
|
||||||
|
goto EXIT_LABEL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we get here the handshake actually completed.
|
||||||
|
handshake_completed = 1;
|
||||||
|
|
||||||
|
EXIT_LABEL:
|
||||||
|
|
||||||
|
if (session != NULL)
|
||||||
|
{
|
||||||
|
if (handshake_completed)
|
||||||
|
{
|
||||||
|
libssh2_session_disconnect(session,
|
||||||
|
"Normal Shutdown, Thank you for playing");
|
||||||
|
}
|
||||||
|
|
||||||
|
libssh2_session_free(session);
|
||||||
|
}
|
||||||
|
|
||||||
|
libssh2_exit();
|
||||||
|
|
||||||
|
close(socket_fds[0]);
|
||||||
|
close(socket_fds[1]);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
74
tests/ossfuzz/standaloneengine.cc
Normal file
74
tests/ossfuzz/standaloneengine.cc
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "testinput.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Main procedure for standalone fuzzing engine.
|
||||||
|
*
|
||||||
|
* Reads filenames from the argument array. For each filename, read the file
|
||||||
|
* into memory and then call the fuzzing interface with the data.
|
||||||
|
*/
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
int ii;
|
||||||
|
for(ii = 1; ii < argc; ii++)
|
||||||
|
{
|
||||||
|
FILE *infile;
|
||||||
|
printf("[%s] ", argv[ii]);
|
||||||
|
|
||||||
|
/* Try and open the file. */
|
||||||
|
infile = fopen(argv[ii], "rb");
|
||||||
|
if(infile)
|
||||||
|
{
|
||||||
|
uint8_t *buffer = NULL;
|
||||||
|
size_t buffer_len;
|
||||||
|
|
||||||
|
printf("Opened.. ");
|
||||||
|
|
||||||
|
/* Get the length of the file. */
|
||||||
|
fseek(infile, 0L, SEEK_END);
|
||||||
|
buffer_len = ftell(infile);
|
||||||
|
|
||||||
|
/* Reset the file indicator to the beginning of the file. */
|
||||||
|
fseek(infile, 0L, SEEK_SET);
|
||||||
|
|
||||||
|
/* Allocate a buffer for the file contents. */
|
||||||
|
buffer = (uint8_t *)calloc(buffer_len, sizeof(uint8_t));
|
||||||
|
if(buffer)
|
||||||
|
{
|
||||||
|
/* Read all the text from the file into the buffer. */
|
||||||
|
fread(buffer, sizeof(uint8_t), buffer_len, infile);
|
||||||
|
printf("Read %zu bytes, fuzzing.. ", buffer_len);
|
||||||
|
|
||||||
|
/* Call the fuzzer with the data. */
|
||||||
|
LLVMFuzzerTestOneInput(buffer, buffer_len);
|
||||||
|
|
||||||
|
printf("complete !!");
|
||||||
|
|
||||||
|
/* Free the buffer as it's no longer needed. */
|
||||||
|
free(buffer);
|
||||||
|
buffer = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fprintf(stderr,
|
||||||
|
"[%s] Failed to allocate %zu bytes \n",
|
||||||
|
argv[ii],
|
||||||
|
buffer_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Close the file as it's no longer needed. */
|
||||||
|
fclose(infile);
|
||||||
|
infile = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Failed to open the file. Maybe wrong name or wrong permissions? */
|
||||||
|
fprintf(stderr, "[%s] Open failed. \n", argv[ii]);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
}
|
3
tests/ossfuzz/testinput.h
Normal file
3
tests/ossfuzz/testinput.h
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
#include <inttypes.h>
|
||||||
|
|
||||||
|
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
|
10
tests/signed_key_ecdsa
Normal file
10
tests/signed_key_ecdsa
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
-----BEGIN OPENSSH PRIVATE KEY-----
|
||||||
|
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAiAAAABNlY2RzYS
|
||||||
|
1zaGEyLW5pc3RwMzg0AAAACG5pc3RwMzg0AAAAYQRv1/fnN1SuIkg222jYnySqIJ88J5M3
|
||||||
|
bB6JGeloKhIvnZdPOSVFuFBjuF7NPrGrsm87QstQFbDiLhIlcDNHIq0VhS5itHNMjtC6Ym
|
||||||
|
RRx7mlQSXPbRRF5MclxvDJCMyAIagAAADQekojnXpKI50AAAATZWNkc2Etc2hhMi1uaXN0
|
||||||
|
cDM4NAAAAAhuaXN0cDM4NAAAAGEEb9f35zdUriJINtto2J8kqiCfPCeTN2weiRnpaCoSL5
|
||||||
|
2XTzklRbhQY7hezT6xq7JvO0LLUBWw4i4SJXAzRyKtFYUuYrRzTI7QumJkUce5pUElz20U
|
||||||
|
ReTHJcbwyQjMgCGoAAAAMQDmng9vaqXjHAhRssuBHeQylRKRwzOYOaToF8f+O0NmpmfLnc
|
||||||
|
/c2wOcXf2f9GBAQdYAAAAAAQIDBAUGBw==
|
||||||
|
-----END OPENSSH PRIVATE KEY-----
|
1
tests/signed_key_ecdsa-cert.pub
Normal file
1
tests/signed_key_ecdsa-cert.pub
Normal file
@@ -0,0 +1 @@
|
|||||||
|
ecdsa-sha2-nistp384-cert-v01@openssh.com AAAAKGVjZHNhLXNoYTItbmlzdHAzODQtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgQCXc1JaqZ4XzkudbzP/pgEUbkioo7pl9aB09h6sg7KYAAAAIbmlzdHAzODQAAABhBG/X9+c3VK4iSDbbaNifJKognzwnkzdsHokZ6WgqEi+dl085JUW4UGO4Xs0+sauybztCy1AVsOIuEiVwM0cirRWFLmK0c0yO0LpiZFHHuaVBJc9tFEXkxyXG8MkIzIAhqAAAAAAAAAABAAAAAQAAAAhpZGVudGl0eQAAAAsAAAAHbGlic3NoMgAAAAAAAAAA//////////8AAAAAAAAAggAAABVwZXJtaXQtWDExLWZvcndhcmRpbmcAAAAAAAAAF3Blcm1pdC1hZ2VudC1mb3J3YXJkaW5nAAAAAAAAABZwZXJtaXQtcG9ydC1mb3J3YXJkaW5nAAAAAAAAAApwZXJtaXQtcHR5AAAAAAAAAA5wZXJtaXQtdXNlci1yYwAAAAAAAAAAAAAArAAAABNlY2RzYS1zaGEyLW5pc3RwNTIxAAAACG5pc3RwNTIxAAAAhQQAfv15s+G2xg56J+audKAM4G9qOTFrbZRo0CTwvkb/oHrf9/2RSWqYsx/0m5mYCZVlecnZqwRHAOolXbc/Yb4cGjsALUj3UDirsnYR7Ve+SwnunkpvW/H3a98sA3sS+HCpd5RbpfWClSBOI9JEAlPtS1CrEQ7EmO7hmlFOH2cL0qfHCyYAAACnAAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAACMAAAAQgGxnhh8z8LNk5pMw0D9InyEtVRm8OJi23XEhqj/ieT/BsLZXbu65UAcMjrUn6DPdERxF9Dwe9pdIAWOLLjLHYEFBQAAAEIAlxz+XjUKa9Q2vpH0y8IgJMm0H1hTBUM1DQEoL8No1BVtgtIO20mac2fE3I35JxNDmmXoW+FuzmJnyrY9rxY+YXM= ./signed_key_ecdsa.pub
|
1
tests/signed_key_ecdsa.pub
Normal file
1
tests/signed_key_ecdsa.pub
Normal file
@@ -0,0 +1 @@
|
|||||||
|
ecdsa-sha2-nistp384 AAAAE2VjZHNhLXNoYTItbmlzdHAzODQAAAAIbmlzdHAzODQAAABhBG/X9+c3VK4iSDbbaNifJKognzwnkzdsHokZ6WgqEi+dl085JUW4UGO4Xs0+sauybztCy1AVsOIuEiVwM0cirRWFLmK0c0yO0LpiZFHHuaVBJc9tFEXkxyXG8MkIzIAhqA==
|
12
tests/ssh2.c
12
tests/ssh2.c
@@ -84,7 +84,8 @@ int main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Create a session instance and start it up
|
/* Create a session instance and start it up
|
||||||
* This will trade welcome banners, exchange keys, and setup crypto, compression, and MAC layers
|
* This will trade welcome banners, exchange keys,
|
||||||
|
* and setup crypto, compression, and MAC layers
|
||||||
*/
|
*/
|
||||||
session = libssh2_session_init();
|
session = libssh2_session_init();
|
||||||
if(libssh2_session_startup(session, sock)) {
|
if(libssh2_session_startup(session, sock)) {
|
||||||
@@ -93,8 +94,10 @@ int main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* At this point we haven't authenticated,
|
/* At this point we haven't authenticated,
|
||||||
* The first thing to do is check the hostkey's fingerprint against our known hosts
|
* The first thing to do is check the hostkey's
|
||||||
* Your app may have it hard coded, may go to a file, may present it to the user, that's your call
|
* fingerprint against our known hosts
|
||||||
|
* Your app may have it hard coded, may go to a file,
|
||||||
|
* may present it to the user, that's your call
|
||||||
*/
|
*/
|
||||||
fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_SHA1);
|
fingerprint = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_SHA1);
|
||||||
printf("Fingerprint: ");
|
printf("Fingerprint: ");
|
||||||
@@ -118,7 +121,8 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
if(auth_pw & 4) {
|
if(auth_pw & 4) {
|
||||||
/* Authenticate by public key */
|
/* Authenticate by public key */
|
||||||
if(libssh2_userauth_publickey_fromfile(session, username, pubkeyfile, privkeyfile, password)) {
|
if(libssh2_userauth_publickey_fromfile(session, username, pubkeyfile,
|
||||||
|
privkeyfile, password)) {
|
||||||
printf("\tAuthentication by public key failed!\n");
|
printf("\tAuthentication by public key failed!\n");
|
||||||
goto shutdown;
|
goto shutdown;
|
||||||
}
|
}
|
||||||
|
@@ -4,9 +4,9 @@
|
|||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
const char *USERNAME = "libssh2"; /* configured in Dockerfile */
|
const char *USERNAME = "libssh2"; /* set in Dockerfile */
|
||||||
const char *KEY_FILE_PRIVATE = "key_rsa";
|
const char *KEY_FILE_PRIVATE = "key_rsa";
|
||||||
const char *KEY_FILE_PUBLIC = "key_rsa.pub"; /* configured in Dockerfile */
|
const char *KEY_FILE_PUBLIC = "key_rsa.pub"; /* set in Dockerfile */
|
||||||
|
|
||||||
int test(LIBSSH2_SESSION *session)
|
int test(LIBSSH2_SESSION *session)
|
||||||
{
|
{
|
||||||
@@ -15,12 +15,12 @@ int test(LIBSSH2_SESSION *session)
|
|||||||
|
|
||||||
const char *userauth_list =
|
const char *userauth_list =
|
||||||
libssh2_userauth_list(session, USERNAME, strlen(USERNAME));
|
libssh2_userauth_list(session, USERNAME, strlen(USERNAME));
|
||||||
if (userauth_list == NULL) {
|
if(userauth_list == NULL) {
|
||||||
print_last_session_error("libssh2_userauth_list");
|
print_last_session_error("libssh2_userauth_list");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strstr(userauth_list, "publickey") == NULL) {
|
if(strstr(userauth_list, "publickey") == NULL) {
|
||||||
fprintf(stderr, "'publickey' was expected in userauth list: %s\n",
|
fprintf(stderr, "'publickey' was expected in userauth list: %s\n",
|
||||||
userauth_list);
|
userauth_list);
|
||||||
return 1;
|
return 1;
|
||||||
@@ -29,21 +29,21 @@ int test(LIBSSH2_SESSION *session)
|
|||||||
rc = libssh2_userauth_publickey_fromfile_ex(
|
rc = libssh2_userauth_publickey_fromfile_ex(
|
||||||
session, USERNAME, strlen(USERNAME), KEY_FILE_PUBLIC, KEY_FILE_PRIVATE,
|
session, USERNAME, strlen(USERNAME), KEY_FILE_PUBLIC, KEY_FILE_PRIVATE,
|
||||||
NULL);
|
NULL);
|
||||||
if (rc != 0) {
|
if(rc != 0) {
|
||||||
print_last_session_error("libssh2_userauth_publickey_fromfile_ex");
|
print_last_session_error("libssh2_userauth_publickey_fromfile_ex");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
channel = libssh2_channel_open_session(session);
|
channel = libssh2_channel_open_session(session);
|
||||||
/* if (channel == NULL) { */
|
/* if(channel == NULL) { */
|
||||||
/* printf("Error opening channel\n"); */
|
/* printf("Error opening channel\n"); */
|
||||||
/* return 1; */
|
/* return 1; */
|
||||||
/* } */
|
/* } */
|
||||||
|
|
||||||
rc = libssh2_channel_request_auth_agent(channel);
|
rc = libssh2_channel_request_auth_agent(channel);
|
||||||
if (rc != 0) {
|
if(rc != 0) {
|
||||||
fprintf(stderr, "Auth agent request for agent forwarding failed, error code %d\n",
|
fprintf(stderr, "Auth agent request for agent forwarding failed, "
|
||||||
rc);
|
"error code %d\n", rc);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -32,11 +32,13 @@ int test(LIBSSH2_SESSION *session)
|
|||||||
|
|
||||||
if(type == LIBSSH2_HOSTKEY_TYPE_ECDSA_256) {
|
if(type == LIBSSH2_HOSTKEY_TYPE_ECDSA_256) {
|
||||||
rc = libssh2_base64_decode(session, &expected_hostkey, &expected_len,
|
rc = libssh2_base64_decode(session, &expected_hostkey, &expected_len,
|
||||||
EXPECTED_ECDSA_HOSTKEY, strlen(EXPECTED_ECDSA_HOSTKEY));
|
EXPECTED_ECDSA_HOSTKEY,
|
||||||
|
strlen(EXPECTED_ECDSA_HOSTKEY));
|
||||||
}
|
}
|
||||||
else if(type == LIBSSH2_HOSTKEY_TYPE_RSA) {
|
else if(type == LIBSSH2_HOSTKEY_TYPE_RSA) {
|
||||||
rc = libssh2_base64_decode(session, &expected_hostkey, &expected_len,
|
rc = libssh2_base64_decode(session, &expected_hostkey, &expected_len,
|
||||||
EXPECTED_RSA_HOSTKEY, strlen(EXPECTED_RSA_HOSTKEY));
|
EXPECTED_RSA_HOSTKEY,
|
||||||
|
strlen(EXPECTED_RSA_HOSTKEY));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
fprintf(stderr, "Unexpected type of hostkey: %i\n", type);
|
fprintf(stderr, "Unexpected type of hostkey: %i\n", type);
|
||||||
@@ -49,7 +51,7 @@ int test(LIBSSH2_SESSION *session)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(len != expected_len) {
|
if(len != expected_len) {
|
||||||
fprintf(stderr, "Hostkey does not have the expected length %ld != %d\n",
|
fprintf(stderr, "Hostkey does not have the expected length %ld!=%d\n",
|
||||||
(unsigned long)len, expected_len);
|
(unsigned long)len, expected_len);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@@ -17,19 +17,23 @@ static const char *EXPECTED_ECDSA_HOSTKEY =
|
|||||||
"AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBC+/syyeKJD9dC2ZH"
|
"AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBC+/syyeKJD9dC2ZH"
|
||||||
"9Q7iJGReR4YM3rUCMsSynkyXojdfSClGCMY7JvWlt30ESjYvxoTfSRGx6WvaqYK/vPoYQ4=";
|
"9Q7iJGReR4YM3rUCMsSynkyXojdfSClGCMY7JvWlt30ESjYvxoTfSRGx6WvaqYK/vPoYQ4=";
|
||||||
|
|
||||||
static const char *EXPECTED_RSA_MD5_HASH_DIGEST = "0C0ED1A5BB10275F76924CE187CE5C5E";
|
static const char *EXPECTED_RSA_MD5_HASH_DIGEST =
|
||||||
|
"0C0ED1A5BB10275F76924CE187CE5C5E";
|
||||||
|
|
||||||
static const char *EXPECTED_RSA_SHA1_HASH_DIGEST =
|
static const char *EXPECTED_RSA_SHA1_HASH_DIGEST =
|
||||||
"F3CD59E2913F4422B80F7B0A82B2B89EAE449387";
|
"F3CD59E2913F4422B80F7B0A82B2B89EAE449387";
|
||||||
|
|
||||||
static const char *EXPECTED_RSA_SHA256_HASH_DIGEST = "92E3DA49DF3C7F99A828F505ED8239397A5D1F62914459760F878F7510F563A3";
|
static const char *EXPECTED_RSA_SHA256_HASH_DIGEST =
|
||||||
|
"92E3DA49DF3C7F99A828F505ED8239397A5D1F62914459760F878F7510F563A3";
|
||||||
|
|
||||||
static const char *EXPECTED_ECDSA_MD5_HASH_DIGEST = "0402E4D897580BBC911379CBD88BCD3D";
|
static const char *EXPECTED_ECDSA_MD5_HASH_DIGEST =
|
||||||
|
"0402E4D897580BBC911379CBD88BCD3D";
|
||||||
|
|
||||||
static const char *EXPECTED_ECDSA_SHA1_HASH_DIGEST =
|
static const char *EXPECTED_ECDSA_SHA1_HASH_DIGEST =
|
||||||
"12FDAD1E3B31B10BABB00F2A8D1B9A62C326BD2F";
|
"12FDAD1E3B31B10BABB00F2A8D1B9A62C326BD2F";
|
||||||
|
|
||||||
static const char *EXPECTED_ECDSA_SHA256_HASH_DIGEST = "56FCD975B166C3F0342D0036E44C311A86C0EAE40713B53FC776369BAE7F5264";
|
static const char *EXPECTED_ECDSA_SHA256_HASH_DIGEST =
|
||||||
|
"56FCD975B166C3F0342D0036E44C311A86C0EAE40713B53FC776369BAE7F5264";
|
||||||
|
|
||||||
static const int MD5_HASH_SIZE = 16;
|
static const int MD5_HASH_SIZE = 16;
|
||||||
static const int SHA1_HASH_SIZE = 20;
|
static const int SHA1_HASH_SIZE = 20;
|
||||||
@@ -51,6 +55,7 @@ int test(LIBSSH2_SESSION *session)
|
|||||||
{
|
{
|
||||||
char buf[BUFSIZ];
|
char buf[BUFSIZ];
|
||||||
|
|
||||||
|
const char *hostkey;
|
||||||
const char *md5_hash;
|
const char *md5_hash;
|
||||||
const char *sha1_hash;
|
const char *sha1_hash;
|
||||||
const char *sha256_hash;
|
const char *sha256_hash;
|
||||||
@@ -61,7 +66,7 @@ int test(LIBSSH2_SESSION *session)
|
|||||||
(void)EXPECTED_RSA_HOSTKEY;
|
(void)EXPECTED_RSA_HOSTKEY;
|
||||||
(void)EXPECTED_ECDSA_HOSTKEY;
|
(void)EXPECTED_ECDSA_HOSTKEY;
|
||||||
|
|
||||||
const char *hostkey = libssh2_session_hostkey(session, &len, &type);
|
hostkey = libssh2_session_hostkey(session, &len, &type);
|
||||||
if(hostkey == NULL) {
|
if(hostkey == NULL) {
|
||||||
print_last_session_error("libssh2_session_hostkey");
|
print_last_session_error("libssh2_session_hostkey");
|
||||||
return 1;
|
return 1;
|
||||||
@@ -79,8 +84,9 @@ int test(LIBSSH2_SESSION *session)
|
|||||||
calculate_digest(md5_hash, MD5_HASH_SIZE, buf, BUFSIZ);
|
calculate_digest(md5_hash, MD5_HASH_SIZE, buf, BUFSIZ);
|
||||||
|
|
||||||
if(strcmp(buf, EXPECTED_ECDSA_MD5_HASH_DIGEST) != 0) {
|
if(strcmp(buf, EXPECTED_ECDSA_MD5_HASH_DIGEST) != 0) {
|
||||||
fprintf(stderr, "ECDSA MD5 hash not as expected - digest %s != %s\n", buf,
|
fprintf(stderr,
|
||||||
EXPECTED_ECDSA_MD5_HASH_DIGEST);
|
"ECDSA MD5 hash not as expected - digest %s != %s\n",
|
||||||
|
buf, EXPECTED_ECDSA_MD5_HASH_DIGEST);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -94,12 +100,14 @@ int test(LIBSSH2_SESSION *session)
|
|||||||
calculate_digest(sha1_hash, SHA1_HASH_SIZE, buf, BUFSIZ);
|
calculate_digest(sha1_hash, SHA1_HASH_SIZE, buf, BUFSIZ);
|
||||||
|
|
||||||
if(strcmp(buf, EXPECTED_ECDSA_SHA1_HASH_DIGEST) != 0) {
|
if(strcmp(buf, EXPECTED_ECDSA_SHA1_HASH_DIGEST) != 0) {
|
||||||
fprintf(stderr, "ECDSA SHA1 hash not as expected - digest %s != %s\n", buf,
|
fprintf(stderr,
|
||||||
EXPECTED_ECDSA_SHA1_HASH_DIGEST);
|
"ECDSA SHA1 hash not as expected - digest %s != %s\n",
|
||||||
|
buf, EXPECTED_ECDSA_SHA1_HASH_DIGEST);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
sha256_hash = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_SHA256);
|
sha256_hash = libssh2_hostkey_hash(session,
|
||||||
|
LIBSSH2_HOSTKEY_HASH_SHA256);
|
||||||
if(sha256_hash == NULL) {
|
if(sha256_hash == NULL) {
|
||||||
print_last_session_error(
|
print_last_session_error(
|
||||||
"libssh2_hostkey_hash(LIBSSH2_HOSTKEY_HASH_SHA256)");
|
"libssh2_hostkey_hash(LIBSSH2_HOSTKEY_HASH_SHA256)");
|
||||||
@@ -109,8 +117,9 @@ int test(LIBSSH2_SESSION *session)
|
|||||||
calculate_digest(sha256_hash, SHA256_HASH_SIZE, buf, BUFSIZ);
|
calculate_digest(sha256_hash, SHA256_HASH_SIZE, buf, BUFSIZ);
|
||||||
|
|
||||||
if(strcmp(buf, EXPECTED_ECDSA_SHA256_HASH_DIGEST) != 0) {
|
if(strcmp(buf, EXPECTED_ECDSA_SHA256_HASH_DIGEST) != 0) {
|
||||||
fprintf(stderr, "ECDSA SHA256 hash not as expected - digest %s != %s\n", buf,
|
fprintf(stderr,
|
||||||
EXPECTED_ECDSA_SHA256_HASH_DIGEST);
|
"ECDSA SHA256 hash not as expected - digest %s != %s\n",
|
||||||
|
buf, EXPECTED_ECDSA_SHA256_HASH_DIGEST);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -127,8 +136,9 @@ int test(LIBSSH2_SESSION *session)
|
|||||||
calculate_digest(md5_hash, MD5_HASH_SIZE, buf, BUFSIZ);
|
calculate_digest(md5_hash, MD5_HASH_SIZE, buf, BUFSIZ);
|
||||||
|
|
||||||
if(strcmp(buf, EXPECTED_RSA_MD5_HASH_DIGEST) != 0) {
|
if(strcmp(buf, EXPECTED_RSA_MD5_HASH_DIGEST) != 0) {
|
||||||
fprintf(stderr, "MD5 hash not as expected - digest %s != %s\n", buf,
|
fprintf(stderr,
|
||||||
EXPECTED_RSA_MD5_HASH_DIGEST);
|
"MD5 hash not as expected - digest %s != %s\n",
|
||||||
|
buf, EXPECTED_RSA_MD5_HASH_DIGEST);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -142,12 +152,14 @@ int test(LIBSSH2_SESSION *session)
|
|||||||
calculate_digest(sha1_hash, SHA1_HASH_SIZE, buf, BUFSIZ);
|
calculate_digest(sha1_hash, SHA1_HASH_SIZE, buf, BUFSIZ);
|
||||||
|
|
||||||
if(strcmp(buf, EXPECTED_RSA_SHA1_HASH_DIGEST) != 0) {
|
if(strcmp(buf, EXPECTED_RSA_SHA1_HASH_DIGEST) != 0) {
|
||||||
fprintf(stderr, "SHA1 hash not as expected - digest %s != %s\n", buf,
|
fprintf(stderr,
|
||||||
EXPECTED_RSA_SHA1_HASH_DIGEST);
|
"SHA1 hash not as expected - digest %s != %s\n",
|
||||||
|
buf, EXPECTED_RSA_SHA1_HASH_DIGEST);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
sha256_hash = libssh2_hostkey_hash(session, LIBSSH2_HOSTKEY_HASH_SHA256);
|
sha256_hash = libssh2_hostkey_hash(session,
|
||||||
|
LIBSSH2_HOSTKEY_HASH_SHA256);
|
||||||
if(sha256_hash == NULL) {
|
if(sha256_hash == NULL) {
|
||||||
print_last_session_error(
|
print_last_session_error(
|
||||||
"libssh2_hostkey_hash(LIBSSH2_HOSTKEY_HASH_SHA256)");
|
"libssh2_hostkey_hash(LIBSSH2_HOSTKEY_HASH_SHA256)");
|
||||||
@@ -157,8 +169,9 @@ int test(LIBSSH2_SESSION *session)
|
|||||||
calculate_digest(sha256_hash, SHA256_HASH_SIZE, buf, BUFSIZ);
|
calculate_digest(sha256_hash, SHA256_HASH_SIZE, buf, BUFSIZ);
|
||||||
|
|
||||||
if(strcmp(buf, EXPECTED_RSA_SHA256_HASH_DIGEST) != 0) {
|
if(strcmp(buf, EXPECTED_RSA_SHA256_HASH_DIGEST) != 0) {
|
||||||
fprintf(stderr, "SHA256 hash not as expected - digest %s != %s\n", buf,
|
fprintf(stderr,
|
||||||
EXPECTED_RSA_SHA256_HASH_DIGEST);
|
"SHA256 hash not as expected - digest %s != %s\n",
|
||||||
|
buf, EXPECTED_RSA_SHA256_HASH_DIGEST);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -4,11 +4,11 @@
|
|||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
static const char *USERNAME = "libssh2"; /* configured in Dockerfile */
|
static const char *USERNAME = "libssh2"; /* set in Dockerfile */
|
||||||
static const char *WRONG_PASSWORD = "i'm not the password";
|
static const char *WRONG_PASSWORD = "i'm not the password";
|
||||||
|
|
||||||
static void kbd_callback(const char *name, int name_len,
|
static void kbd_callback(const char *name, int name_len,
|
||||||
const char *instruction, int instruction_len,
|
const char *instruct, int instruct_len,
|
||||||
int num_prompts,
|
int num_prompts,
|
||||||
const LIBSSH2_USERAUTH_KBDINT_PROMPT *prompts,
|
const LIBSSH2_USERAUTH_KBDINT_PROMPT *prompts,
|
||||||
LIBSSH2_USERAUTH_KBDINT_RESPONSE *responses,
|
LIBSSH2_USERAUTH_KBDINT_RESPONSE *responses,
|
||||||
@@ -17,7 +17,7 @@ static void kbd_callback(const char *name, int name_len,
|
|||||||
int i;
|
int i;
|
||||||
(void)abstract;
|
(void)abstract;
|
||||||
fprintf(stdout, "Kb-int name: %.*s\n", name_len, name);
|
fprintf(stdout, "Kb-int name: %.*s\n", name_len, name);
|
||||||
fprintf(stdout, "Kb-int instruction: %.*s\n", instruction_len, instruction);
|
fprintf(stdout, "Kb-int instruction: %.*s\n", instruct_len, instruct);
|
||||||
for(i = 0; i < num_prompts; ++i) {
|
for(i = 0; i < num_prompts; ++i) {
|
||||||
fprintf(stdout, "Kb-int prompt %d: %.*s\n", i, prompts[i].length,
|
fprintf(stdout, "Kb-int prompt %d: %.*s\n", i, prompts[i].length,
|
||||||
prompts[i].text);
|
prompts[i].text);
|
||||||
|
@@ -4,11 +4,12 @@
|
|||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
static const char *USERNAME = "libssh2"; /* configured in Dockerfile */
|
/* configured in Dockerfile */
|
||||||
static const char *PASSWORD = "my test password"; /* configured in Dockerfile */
|
static const char *USERNAME = "libssh2";
|
||||||
|
static const char *PASSWORD = "my test password";
|
||||||
|
|
||||||
static void kbd_callback(const char *name, int name_len,
|
static void kbd_callback(const char *name, int name_len,
|
||||||
const char *instruction, int instruction_len,
|
const char *instruct, int instruct_len,
|
||||||
int num_prompts,
|
int num_prompts,
|
||||||
const LIBSSH2_USERAUTH_KBDINT_PROMPT *prompts,
|
const LIBSSH2_USERAUTH_KBDINT_PROMPT *prompts,
|
||||||
LIBSSH2_USERAUTH_KBDINT_RESPONSE *responses,
|
LIBSSH2_USERAUTH_KBDINT_RESPONSE *responses,
|
||||||
@@ -18,7 +19,7 @@ static void kbd_callback(const char *name, int name_len,
|
|||||||
(void)abstract;
|
(void)abstract;
|
||||||
|
|
||||||
fprintf(stdout, "Kb-int name: %.*s\n", name_len, name);
|
fprintf(stdout, "Kb-int name: %.*s\n", name_len, name);
|
||||||
fprintf(stdout, "Kb-int instruction: %.*s\n", instruction_len, instruction);
|
fprintf(stdout, "Kb-int instruction: %.*s\n", instruct_len, instruct);
|
||||||
for(i = 0; i < num_prompts; ++i) {
|
for(i = 0; i < num_prompts; ++i) {
|
||||||
fprintf(stdout, "Kb-int prompt %d: %.*s\n", i, prompts[i].length,
|
fprintf(stdout, "Kb-int prompt %d: %.*s\n", i, prompts[i].length,
|
||||||
prompts[i].text);
|
prompts[i].text);
|
||||||
|
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
static const char *USERNAME = "libssh2"; /* configured in Dockerfile */
|
static const char *USERNAME = "libssh2"; /* set in Dockerfile */
|
||||||
static const char *WRONG_PASSWORD = "i'm not the password";
|
static const char *WRONG_PASSWORD = "i'm not the password";
|
||||||
|
|
||||||
int test(LIBSSH2_SESSION *session)
|
int test(LIBSSH2_SESSION *session)
|
||||||
|
@@ -4,7 +4,8 @@
|
|||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
static const char *PASSWORD = "my test password"; /* configured in Dockerfile */
|
/* configured in Dockerfile */
|
||||||
|
static const char *PASSWORD = "my test password";
|
||||||
static const char *WRONG_USERNAME = "i dont exist";
|
static const char *WRONG_USERNAME = "i dont exist";
|
||||||
|
|
||||||
int test(LIBSSH2_SESSION *session)
|
int test(LIBSSH2_SESSION *session)
|
||||||
|
@@ -4,8 +4,9 @@
|
|||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
static const char *USERNAME = "libssh2"; /* configured in Dockerfile */
|
/* configured in Dockerfile */
|
||||||
static const char *PASSWORD = "my test password"; /* configured in Dockerfile */
|
static const char *USERNAME = "libssh2";
|
||||||
|
static const char *PASSWORD = "my test password";
|
||||||
|
|
||||||
int test(LIBSSH2_SESSION *session)
|
int test(LIBSSH2_SESSION *session)
|
||||||
{
|
{
|
||||||
|
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
static const char *USERNAME = "libssh2"; /* configured in Dockerfile */
|
static const char *USERNAME = "libssh2"; /* set in Dockerfile */
|
||||||
static const char *KEY_FILE_PRIVATE = "key_dsa_wrong";
|
static const char *KEY_FILE_PRIVATE = "key_dsa_wrong";
|
||||||
static const char *KEY_FILE_PUBLIC = "key_dsa_wrong.pub";
|
static const char *KEY_FILE_PUBLIC = "key_dsa_wrong.pub";
|
||||||
|
|
||||||
|
@@ -4,9 +4,10 @@
|
|||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
static const char *USERNAME = "libssh2"; /* configured in Dockerfile */
|
/* configured in Dockerfile */
|
||||||
|
static const char *USERNAME = "libssh2";
|
||||||
static const char *KEY_FILE_PRIVATE = "key_dsa";
|
static const char *KEY_FILE_PRIVATE = "key_dsa";
|
||||||
static const char *KEY_FILE_PUBLIC = "key_dsa.pub"; /* configured in Dockerfile */
|
static const char *KEY_FILE_PUBLIC = "key_dsa.pub";
|
||||||
|
|
||||||
int test(LIBSSH2_SESSION *session)
|
int test(LIBSSH2_SESSION *session)
|
||||||
{
|
{
|
||||||
|
38
tests/test_public_key_auth_succeeds_with_correct_ecdsa_key.c
Normal file
38
tests/test_public_key_auth_succeeds_with_correct_ecdsa_key.c
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
#include "session_fixture.h"
|
||||||
|
|
||||||
|
#include <libssh2.h>
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
/* configured in Dockerfile */
|
||||||
|
static const char *USERNAME = "libssh2";
|
||||||
|
static const char *KEY_FILE_PRIVATE = "key_ecdsa";
|
||||||
|
static const char *KEY_FILE_PUBLIC = "key_ecdsa.pub";
|
||||||
|
|
||||||
|
int test(LIBSSH2_SESSION *session)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
const char *userauth_list = NULL;
|
||||||
|
|
||||||
|
userauth_list = libssh2_userauth_list(session, USERNAME, strlen(USERNAME));
|
||||||
|
if(userauth_list == NULL) {
|
||||||
|
print_last_session_error("libssh2_userauth_list");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(strstr(userauth_list, "publickey") == NULL) {
|
||||||
|
fprintf(stderr, "'publickey' was expected in userauth list: %s\n",
|
||||||
|
userauth_list);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = libssh2_userauth_publickey_fromfile_ex(
|
||||||
|
session, USERNAME, strlen(USERNAME), KEY_FILE_PUBLIC, KEY_FILE_PRIVATE,
|
||||||
|
NULL);
|
||||||
|
if(rc != 0) {
|
||||||
|
print_last_session_error("libssh2_userauth_publickey_fromfile_ex");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
@@ -4,9 +4,10 @@
|
|||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
static const char *USERNAME = "libssh2"; /* configured in Dockerfile */
|
/* configured in Dockerfile */
|
||||||
|
static const char *USERNAME = "libssh2";
|
||||||
static const char *KEY_FILE_PRIVATE = "key_ed25519";
|
static const char *KEY_FILE_PRIVATE = "key_ed25519";
|
||||||
static const char *KEY_FILE_PUBLIC = "key_ed25519.pub"; /* configured in Dockerfile */
|
static const char *KEY_FILE_PUBLIC = "key_ed25519.pub";
|
||||||
|
|
||||||
int test(LIBSSH2_SESSION *session)
|
int test(LIBSSH2_SESSION *session)
|
||||||
{
|
{
|
||||||
|
@@ -5,7 +5,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
static const char *USERNAME = "libssh2"; /* configured in Dockerfile */
|
static const char *USERNAME = "libssh2"; /* set in Dockerfile */
|
||||||
static const char *KEY_FILE_ED25519_PRIVATE = "key_ed25519";
|
static const char *KEY_FILE_ED25519_PRIVATE = "key_ed25519";
|
||||||
|
|
||||||
int read_file(const char *path, char **buf, size_t *len);
|
int read_file(const char *path, char **buf, size_t *len);
|
||||||
@@ -13,7 +13,6 @@ int read_file(const char *path, char **buf, size_t *len);
|
|||||||
int test(LIBSSH2_SESSION *session)
|
int test(LIBSSH2_SESSION *session)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
FILE *fp = NULL;
|
|
||||||
char *buffer = NULL;
|
char *buffer = NULL;
|
||||||
size_t len = 0;
|
size_t len = 0;
|
||||||
const char *userauth_list = NULL;
|
const char *userauth_list = NULL;
|
||||||
@@ -35,8 +34,11 @@ int test(LIBSSH2_SESSION *session)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = libssh2_userauth_publickey_frommemory(session, USERNAME, strlen(USERNAME),
|
rc = libssh2_userauth_publickey_frommemory(session,
|
||||||
NULL, 0, buffer, len, NULL);
|
USERNAME, strlen(USERNAME),
|
||||||
|
NULL, 0,
|
||||||
|
buffer, len,
|
||||||
|
NULL);
|
||||||
|
|
||||||
free(buffer);
|
free(buffer);
|
||||||
|
|
||||||
@@ -50,7 +52,6 @@ int test(LIBSSH2_SESSION *session)
|
|||||||
|
|
||||||
int read_file(const char *path, char **out_buffer, size_t *out_len)
|
int read_file(const char *path, char **out_buffer, size_t *out_len)
|
||||||
{
|
{
|
||||||
int rc;
|
|
||||||
FILE *fp = NULL;
|
FILE *fp = NULL;
|
||||||
char *buffer = NULL;
|
char *buffer = NULL;
|
||||||
size_t len = 0;
|
size_t len = 0;
|
||||||
@@ -66,8 +67,8 @@ int read_file(const char *path, char **out_buffer, size_t *out_len)
|
|||||||
fp = fopen(path, "r");
|
fp = fopen(path, "r");
|
||||||
|
|
||||||
if(!fp) {
|
if(!fp) {
|
||||||
fprintf(stderr, "File could not be read.");
|
fprintf(stderr, "File could not be read.");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
fseek(fp, 0L, SEEK_END);
|
fseek(fp, 0L, SEEK_END);
|
||||||
@@ -76,16 +77,16 @@ int read_file(const char *path, char **out_buffer, size_t *out_len)
|
|||||||
|
|
||||||
buffer = calloc(1, len + 1);
|
buffer = calloc(1, len + 1);
|
||||||
if(!buffer) {
|
if(!buffer) {
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
fprintf(stderr, "Could not alloc memory.");
|
fprintf(stderr, "Could not alloc memory.");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(1 != fread(buffer, len, 1, fp)) {
|
if(1 != fread(buffer, len, 1, fp)) {
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
free(buffer);
|
free(buffer);
|
||||||
fprintf(stderr, "Could not read file into memory.");
|
fprintf(stderr, "Could not read file into memory.");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
|
@@ -4,10 +4,11 @@
|
|||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
static const char *USERNAME = "libssh2"; /* configured in Dockerfile */
|
/* configured in Dockerfile */
|
||||||
|
static const char *USERNAME = "libssh2";
|
||||||
static const char *PASSWORD = "libssh2";
|
static const char *PASSWORD = "libssh2";
|
||||||
static const char *KEY_FILE_PRIVATE = "key_ed25519_encrypted";
|
static const char *KEY_FILE_PRIVATE = "key_ed25519_encrypted";
|
||||||
static const char *KEY_FILE_PUBLIC = "key_ed25519_encrypted.pub"; /* configured in Dockerfile */
|
static const char *KEY_FILE_PUBLIC = "key_ed25519_encrypted.pub";
|
||||||
|
|
||||||
int test(LIBSSH2_SESSION *session)
|
int test(LIBSSH2_SESSION *session)
|
||||||
{
|
{
|
||||||
|
@@ -4,10 +4,11 @@
|
|||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
static const char *USERNAME = "libssh2"; /* configured in Dockerfile */
|
/* configured in Dockerfile */
|
||||||
|
static const char *USERNAME = "libssh2";
|
||||||
static const char *PASSWORD = "libssh2";
|
static const char *PASSWORD = "libssh2";
|
||||||
static const char *KEY_FILE_PRIVATE = "key_rsa_encrypted";
|
static const char *KEY_FILE_PRIVATE = "key_rsa_encrypted";
|
||||||
static const char *KEY_FILE_PUBLIC = "key_rsa_encrypted.pub"; /* configured in Dockerfile */
|
static const char *KEY_FILE_PUBLIC = "key_rsa_encrypted.pub";
|
||||||
|
|
||||||
int test(LIBSSH2_SESSION *session)
|
int test(LIBSSH2_SESSION *session)
|
||||||
{
|
{
|
||||||
|
@@ -4,9 +4,10 @@
|
|||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
static const char *USERNAME = "libssh2"; /* configured in Dockerfile */
|
/* configured in Dockerfile */
|
||||||
|
static const char *USERNAME = "libssh2";
|
||||||
static const char *KEY_FILE_PRIVATE = "key_rsa";
|
static const char *KEY_FILE_PRIVATE = "key_rsa";
|
||||||
static const char *KEY_FILE_PUBLIC = "key_rsa.pub"; /* configured in Dockerfile */
|
static const char *KEY_FILE_PUBLIC = "key_rsa.pub";
|
||||||
|
|
||||||
int test(LIBSSH2_SESSION *session)
|
int test(LIBSSH2_SESSION *session)
|
||||||
{
|
{
|
||||||
|
@@ -4,9 +4,10 @@
|
|||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
static const char *USERNAME = "libssh2"; /* configured in Dockerfile */
|
/* configured in Dockerfile */
|
||||||
|
static const char *USERNAME = "libssh2";
|
||||||
static const char *KEY_FILE_PRIVATE = "key_rsa_openssh";
|
static const char *KEY_FILE_PRIVATE = "key_rsa_openssh";
|
||||||
static const char *KEY_FILE_PUBLIC = "key_rsa_openssh.pub"; /* configured in Dockerfile */
|
static const char *KEY_FILE_PUBLIC = "key_rsa_openssh.pub";
|
||||||
|
|
||||||
int test(LIBSSH2_SESSION *session)
|
int test(LIBSSH2_SESSION *session)
|
||||||
{
|
{
|
||||||
|
@@ -0,0 +1,38 @@
|
|||||||
|
#include "session_fixture.h"
|
||||||
|
|
||||||
|
#include <libssh2.h>
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
/* configured in Dockerfile */
|
||||||
|
static const char *USERNAME = "libssh2";
|
||||||
|
static const char *KEY_FILE_PRIVATE = "signed_key_ecdsa";
|
||||||
|
static const char *KEY_FILE_PUBLIC = "signed_key_ecdsa-cert.pub";
|
||||||
|
|
||||||
|
int test(LIBSSH2_SESSION *session)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
const char *userauth_list = NULL;
|
||||||
|
|
||||||
|
userauth_list = libssh2_userauth_list(session, USERNAME, strlen(USERNAME));
|
||||||
|
if(userauth_list == NULL) {
|
||||||
|
print_last_session_error("libssh2_userauth_list");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(strstr(userauth_list, "publickey") == NULL) {
|
||||||
|
fprintf(stderr, "'publickey' was expected in userauth list: %s\n",
|
||||||
|
userauth_list);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = libssh2_userauth_publickey_fromfile_ex(
|
||||||
|
session, USERNAME, strlen(USERNAME), KEY_FILE_PUBLIC, KEY_FILE_PRIVATE,
|
||||||
|
NULL);
|
||||||
|
if(rc != 0) {
|
||||||
|
print_last_session_error("libssh2_userauth_publickey_fromfile_ex");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
@@ -29,7 +29,7 @@ $ man2help -a [-.docs]AUTHORS.; libssh2.hlp -b 2
|
|||||||
$ man2help -a [-.docs]BINDINGS.; libssh2.hlp -b 2
|
$ man2help -a [-.docs]BINDINGS.; libssh2.hlp -b 2
|
||||||
$ man2help -a [-.docs]HACKING.; libssh2.hlp -b 2
|
$ man2help -a [-.docs]HACKING.; libssh2.hlp -b 2
|
||||||
$ if f$search("[]HACKING_CRYPTO.") .nes. "" then delete []HACKING_CRYPTO.;*
|
$ if f$search("[]HACKING_CRYPTO.") .nes. "" then delete []HACKING_CRYPTO.;*
|
||||||
$ copy [-.docs]HACKING.CRYPTO; []HACKING_CRYPTO.
|
$ copy [-.docs]HACKING-CRYPTO; []HACKING_CRYPTO.
|
||||||
$ man2help -a []HACKING_CRYPTO.; libssh2.hlp -b 2
|
$ man2help -a []HACKING_CRYPTO.; libssh2.hlp -b 2
|
||||||
$ man2help -a [-.docs]TODO.; libssh2.hlp -b 2
|
$ man2help -a [-.docs]TODO.; libssh2.hlp -b 2
|
||||||
$!
|
$!
|
||||||
|
Reference in New Issue
Block a user