Compare commits

..

1 Commits

Author SHA1 Message Date
Andreas Schneider
2721cbc8ee ChangeLog: Set release date for 0.7.0 2015-05-11 10:42:08 +02:00
430 changed files with 23665 additions and 91558 deletions

View File

@@ -1,4 +0,0 @@
{
"phabricator.uri" : "https://bugs.libssh.org/",
"history.immutable": true
}

13
.clang_complete Normal file
View File

@@ -0,0 +1,13 @@
-DWITH_SERVER=1
-DWITH_GSSAPI=1
-DWITH_ZLIB=1
-DWITH_SFTP=1
-DWITH_SSH1=1
-DWITH_PCAP=1
-DHAVE_ECDH=1
-DHAVE_ECC=1
-Iinclude/libssh
-Iinclude
-Ibuild
-Itests
-Isrc

View File

@@ -1,18 +0,0 @@
root = true
[*]
charset = utf-8
max_line_length = 80
end_of_line = lf
trim_trailing_whitespace = true
insert_final_newline = true
[*.{c,h}]
indent_style = space
indent_size = 4
tab_width = 4
[{CMakeLists.txt,*.cmake}]
indent_style = space
indent_size = 4
tab_width = 4

7
.gitignore vendored
View File

@@ -3,10 +3,7 @@
.* .*
*.swp *.swp
*~$ *~$
obj
cscope.* cscope.*
compile_commands.json
/.cache
/.clangd
tags tags
/build build
/obj*

View File

@@ -1,528 +0,0 @@
---
variables:
BUILD_IMAGES_PROJECT: libssh/build-images
CENTOS7_BUILD: buildenv-centos7
CENTOS9_BUILD: buildenv-c9s
COVERITY_BUILD: buildenv-coverity
FEDORA_BUILD: buildenv-fedora
MINGW_BUILD: buildenv-mingw
TUMBLEWEED_BUILD: buildenv-tumbleweed
UBUNTU_BUILD: buildenv-ubuntu
ALPINE_BUILD: buildenv-alpine
stages:
- build
- test
- analysis
.build:
stage: build
variables:
CMAKE_DEFAULT_OPTIONS: "-DCMAKE_BUILD_TYPE=RelWithDebInfo -DPICKY_DEVELOPER=ON"
CMAKE_BUILD_OPTIONS: "-DWITH_BLOWFISH_CIPHER=ON -DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON -DWITH_DEBUG_CRYPTO=ON -DWITH_DEBUG_PACKET=ON -DWITH_DEBUG_CALLTRACE=ON -DWITH_DSA=ON"
CMAKE_TEST_OPTIONS: "-DUNIT_TESTING=ON -DCLIENT_TESTING=ON -DSERVER_TESTING=ON -DWITH_BENCHMARKS=ON"
CMAKE_OPTIONS: $CMAKE_DEFAULT_OPTIONS $CMAKE_BUILD_OPTIONS $CMAKE_TEST_OPTIONS
before_script: &build
- uname -a
- cat /etc/os-release
- mount
- df -h
- cat /proc/swaps
- free -h
- mkdir -p obj && cd obj
script:
- cmake $CMAKE_OPTIONS $CMAKE_ADDITIONAL_OPTIONS .. &&
make -j$(nproc) &&
make -j$(nproc) install
# Do not use after_script as it does not make the targets fail
tags:
- shared
except:
- tags
artifacts:
expire_in: 1 week
when: on_failure
paths:
- obj/
.tests:
extends: .build
stage: test
# This is needed to prevent passing artifacts from previous stages
dependencies: []
script:
- cmake $CMAKE_OPTIONS $CMAKE_ADDITIONAL_OPTIONS .. &&
make -j$(nproc) &&
ctest --output-on-failure
# Do not use after_script as it does not make the targets fail
.fedora:
extends: .tests
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD
variables:
CMAKE_ADDITIONAL_OPTIONS: -DWITH_PKCS11_URI=ON
.tumbleweed:
extends: .tests
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$TUMBLEWEED_BUILD
###############################################################################
# CentOS builds #
###############################################################################
# pkd tests fail on CentOS7 docker images, so we don't use -DSERVER_TESTING=ON
centos7/openssl_1.0.x/x86_64:
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$CENTOS7_BUILD
extends: .tests
script:
- cmake3 $CMAKE_OPTIONS .. &&
make -j$(nproc) &&
ctest --output-on-failure
centos9s/openssl_3.0.x/x86_64:
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$CENTOS9_BUILD
extends: .tests
script:
- export OPENSSL_ENABLE_SHA1_SIGNATURES=1
- cmake3 $CMAKE_OPTIONS .. &&
make -j$(nproc) &&
ctest --output-on-failure
###############################################################################
# Fedora builds #
###############################################################################
fedora/build:
extends: .build
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD
fedora/docs:
extends: .build
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD
script:
- cmake .. && make docs
fedora/ninja:
extends: .fedora
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD
script:
- cmake -G Ninja $CMAKE_OPTIONS ../ && ninja && ninja test
fedora/openssl_3.0.x/x86_64:
extends: .fedora
fedora/openssl_3.0.x/x86_64/fips:
extends: .fedora
before_script:
- echo "# userspace fips" > /etc/system-fips
# We do not need the kernel part, but in case we ever do:
# mkdir -p /var/tmp/userspace-fips
# echo 1 > /var/tmp/userspace-fips/fips_enabled
# mount --bind /var/tmp/userspace-fips/fips_enabled \
# /proc/sys/crypto/fips_enabled
- update-crypto-policies --show
- update-crypto-policies --set FIPS
- update-crypto-policies --show
- mkdir -p obj && cd obj && cmake
-DCMAKE_BUILD_TYPE=RelWithDebInfo
-DPICKY_DEVELOPER=ON
-DWITH_BLOWFISH_CIPHER=ON
-DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON
-DWITH_DEBUG_CRYPTO=ON -DWITH_DEBUG_PACKET=ON -DWITH_DEBUG_CALLTRACE=ON
-DWITH_DSA=ON
-DUNIT_TESTING=ON -DCLIENT_TESTING=ON -DSERVER_TESTING=ON ..
script:
- cmake $CMAKE_OPTIONS .. &&
make -j$(nproc) &&
OPENSSL_FORCE_FIPS_MODE=1 ctest --output-on-failure
fedora/openssl_3.0.x/x86_64/minimal:
extends: .fedora
variables:
script:
- cmake $CMAKE_DEFAULT_OPTIONS
-DWITH_SFTP=OFF
-DWITH_SERVER=OFF
-DWITH_ZLIB=OFF
-DWITH_PCAP=OFF
-DWITH_DSA=OFF
-DUNIT_TESTING=ON
-DCLIENT_TESTING=ON
-DWITH_GEX=OFF .. &&
make -j$(nproc)
# Address sanitizer doesn't mix well with LD_PRELOAD used in the testsuite
# so, this is only enabled for unit tests right now.
# TODO: add -DCLIENT_TESTING=ON -DSERVER_TESTING=ON
fedora/address-sanitizer:
extends: .fedora
stage: analysis
script:
- cmake
-DCMAKE_BUILD_TYPE=AddressSanitizer
-DCMAKE_C_COMPILER=clang
-DCMAKE_CXX_COMPILER=clang++
-DPICKY_DEVELOPER=ON
$CMAKE_BUILD_OPTIONS
-DUNIT_TESTING=ON
-DFUZZ_TESTING=ON .. &&
make -j$(nproc) &&
ctest --output-on-failure
# This is disabled as it report OpenSSL issues
# It also has the same issues with cwrap as AddressSanitizer
.fedora/memory-sanitizer:
extends: .fedora
stage: analysis
script:
- cmake
-DCMAKE_BUILD_TYPE=MemorySanitizer
-DCMAKE_C_COMPILER=clang
-DCMAKE_CXX_COMPILER=clang++
-DPICKY_DEVELOPER=ON
$CMAKE_BUILD_OPTIONS
-DUNIT_TESTING=ON
-DFUZZ_TESTING=ON .. &&
make -j$(nproc) &&
ctest --output-on-failure
fedora/undefined-sanitizer:
extends: .fedora
stage: analysis
script:
- cmake
-DCMAKE_BUILD_TYPE=UndefinedSanitizer
-DCMAKE_C_COMPILER=clang
-DCMAKE_CXX_COMPILER=clang++
-DPICKY_DEVELOPER=ON
$CMAKE_BUILD_OPTIONS
-DUNIT_TESTING=ON
-DFUZZ_TESTING=ON .. &&
make -j$(nproc) &&
ctest --output-on-failure
fedora/libgcrypt/x86_64:
extends: .fedora
variables:
CMAKE_ADDITIONAL_OPTIONS: "-DWITH_GCRYPT=ON -DWITH_DEBUG_CRYPTO=ON"
fedora/mbedtls/x86_64:
extends: .fedora
variables:
CMAKE_ADDITIONAL_OPTIONS: "-DWITH_MBEDTLS=ON -DWITH_DEBUG_CRYPTO=ON -DWITH_DSA=OFF"
# Unit testing only, no client and pkd testing, because cwrap is not available
# for MinGW
fedora/mingw64:
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$MINGW_BUILD
extends: .tests
script:
- export WINEPATH=/usr/x86_64-w64-mingw32/sys-root/mingw/bin
- export WINEDEBUG=-all
- mingw64-cmake $CMAKE_DEFAULT_OPTIONS
-DWITH_SFTP=ON
-DWITH_SERVER=ON
-DWITH_ZLIB=ON
-DWITH_PCAP=ON
-DUNIT_TESTING=ON .. &&
make -j$(nproc) &&
ctest --output-on-failure
# Unit testing only, no client and pkd testing, because cwrap is not available
# for MinGW
fedora/mingw32:
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$MINGW_BUILD
extends: .tests
script:
- export WINEPATH=/usr/i686-w64-mingw32/sys-root/mingw/bin
- export WINEDEBUG=-all
- mingw32-cmake $CMAKE_DEFAULT_OPTIONS
-DWITH_SFTP=ON
-DWITH_SERVER=ON
-DWITH_ZLIB=ON
-DWITH_PCAP=ON
-DUNIT_TESTING=ON .. &&
make -j$(nproc) &&
ctest --output-on-failure
###############################################################################
# Fedora csbuild #
###############################################################################
.csbuild:
stage: analysis
variables:
GIT_DEPTH: "100"
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD
before_script:
- |
if [[ -z "$CI_COMMIT_BEFORE_SHA" ]]; then
export CI_COMMIT_BEFORE_SHA=$(git rev-parse "${CI_COMMIT_SHA}~20")
fi
# Check if the commit exists in this branch
# This is not the case for a force push
git branch --contains $CI_COMMIT_BEFORE_SHA 2>/dev/null || export CI_COMMIT_BEFORE_SHA=$(git rev-parse "${CI_COMMIT_SHA}~20")
export CI_COMMIT_RANGE="$CI_COMMIT_BEFORE_SHA..$CI_COMMIT_SHA"
tags:
- shared
except:
- tags
artifacts:
expire_in: 1 week
when: on_failure
paths:
- obj-csbuild/
fedora/csbuild/openssl_3.0.x:
extends: .csbuild
script:
- csbuild
--build-dir=obj-csbuild
--build-cmd "rm -rf CMakeFiles CMakeCache.txt && cmake -DCMAKE_BUILD_TYPE=Debug -DPICKY_DEVELOPER=ON -DUNIT_TESTING=ON -DCLIENT_TESTING=ON -DSERVER_TESTING=ON -DFUZZ_TESTING=ON -DWITH_DSA=ON @SRCDIR@ && make clean && make -j$(nproc)"
--git-commit-range $CI_COMMIT_RANGE
--color
--print-current --print-fixed
fedora/csbuild/libgcrypt:
extends: .csbuild
script:
- csbuild
--build-dir=obj-csbuild
--build-cmd "rm -rf CMakeFiles CMakeCache.txt && cmake -DCMAKE_BUILD_TYPE=Debug -DPICKY_DEVELOPER=ON -DUNIT_TESTING=ON -DCLIENT_TESTING=ON -DSERVER_TESTING=ON -DFUZZ_TESTING=ON -DWITH_GCRYPT=ON -DWITH_DSA=ON @SRCDIR@ && make clean && make -j$(nproc)"
--git-commit-range $CI_COMMIT_RANGE
--color
--print-current --print-fixed
fedora/csbuild/mbedtls:
extends: .csbuild
script:
- csbuild
--build-dir=obj-csbuild
--build-cmd "rm -rf CMakeFiles CMakeCache.txt && cmake -DCMAKE_BUILD_TYPE=Debug -DPICKY_DEVELOPER=ON -DUNIT_TESTING=ON -DCLIENT_TESTING=ON -DSERVER_TESTING=ON -DFUZZ_TESTING=ON -DWITH_MBEDTLS=ON @SRCDIR@ && make clean && make -j$(nproc)"
--git-commit-range $CI_COMMIT_RANGE
--color
--print-current --print-fixed
###############################################################################
# Ubuntu builds #
###############################################################################
ubuntu/openssl_1.1.x/x86_64:
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$UBUNTU_BUILD
extends: .tests
###############################################################################
# Alpine builds #
###############################################################################
alpine/musl:
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$ALPINE_BUILD
extends: .tests
script:
- cmake $CMAKE_DEFAULT_OPTIONS
-DWITH_SFTP=ON
-DWITH_SERVER=ON
-DWITH_ZLIB=ON
-DWITH_PCAP=ON
-DUNIT_TESTING=ON .. &&
make -j$(nproc) &&
ctest --output-on-failure
###############################################################################
# Tumbleweed builds #
###############################################################################
tumbleweed/openssl_1.1.x/x86_64/gcc:
extends: .tumbleweed
variables:
CMAKE_ADDITIONAL_OPTIONS: "-DKRB5_CONFIG=/usr/lib/mit/bin/krb5-config"
tumbleweed/openssl_1.1.x/x86/gcc:
extends: .tumbleweed
script:
- cmake
-DCMAKE_TOOLCHAIN_FILE=../cmake/Toolchain-cross-m32.cmake
$CMAKE_DEFAULT_OPTIONS
-DWITH_SFTP=ON
-DWITH_SERVER=ON
-DWITH_ZLIB=ON
-DWITH_PCAP=ON
-DWITH_DSA=ON
-DUNIT_TESTING=ON ..
tumbleweed/openssl_1.1.x/x86_64/gcc7:
extends: .tumbleweed
variables:
CMAKE_ADDITIONAL_OPTIONS: "-DCMAKE_C_COMPILER=gcc-7 -DCMAKE_CXX_COMPILER=g++-7 -DKRB5_CONFIG=/usr/lib/mit/bin/krb5-config"
tumbleweed/openssl_1.1.x/x86/gcc7:
extends: .tumbleweed
script:
- cmake
-DCMAKE_TOOLCHAIN_FILE=../cmake/Toolchain-cross-m32.cmake
-DCMAKE_C_COMPILER=gcc-7 -DCMAKE_CXX_COMPILER=g++-7
$CMAKE_DEFAULT_OPTIONS
-DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON
-DWITH_DSA=ON
-DUNIT_TESTING=ON .. &&
make -j$(nproc) &&
ctest --output-on-failure
tumbleweed/openssl_1.1.x/x86_64/clang:
extends: .tumbleweed
variables:
CMAKE_ADDITIONAL_OPTIONS: "-DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DKRB5_CONFIG=/usr/lib/mit/bin/krb5-config"
tumbleweed/static-analysis:
extends: .tests
stage: analysis
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$TUMBLEWEED_BUILD
script:
- export CCC_CC=clang
- export CCC_CXX=clang++
- scan-build cmake
-DCMAKE_BUILD_TYPE=Debug
-DCMAKE_C_COMPILER=clang
-DCMAKE_CXX_COMPILER=clang++
-DPICKY_DEVELOPER=ON
$CMAKE_BUILD_OPTIONS
$CMAKE_TEST_OPTIONS .. &&
scan-build --status-bugs -o scan make -j$(nproc)
artifacts:
expire_in: 1 week
when: on_failure
paths:
- obj/scan
###############################################################################
# FreeBSD builds #
###############################################################################
# That is a specific runner that we cannot enable universally.
# We restrict it to builds under the $BUILD_IMAGES_PROJECT project.
freebsd/x86_64:
image:
extends: .tests
before_script:
- mkdir -p obj && cd obj && cmake
-DCMAKE_BUILD_TYPE=RelWithDebInfo
-DPICKY_DEVELOPER=ON
-DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON
-DUNIT_TESTING=ON ..
script:
- cmake $CMAKE_DEFAULT_OPTIONS
-DWITH_SFTP=ON
-DWITH_SERVER=ON
-DWITH_ZLIB=ON
-DWITH_PCAP=ON
-DUNIT_TESTING=ON .. &&
make &&
ctest --output-on-failure
tags:
- private
- freebsd
only:
- branches@libssh/libssh-mirror
- branches@cryptomilk/libssh-mirror
- branches@jjelen/libssh-mirror
- branches@marco.fortina/libssh-mirror
###############################################################################
# Visual Studio builds #
###############################################################################
.vs:
stage: test
cache:
key: vcpkg.${CI_JOB_NAME}
paths:
- .vcpkg
variables:
ErrorActionPreference: STOP
script:
- cmake --build .
- ctest --output-on-failure
tags:
- windows
- shared-windows
except:
- tags
artifacts:
expire_in: 1 week
when: on_failure
paths:
- obj/
before_script:
- choco install --no-progress -y cmake
- $env:Path += ';C:\Program Files\CMake\bin'
- If (!(test-path .vcpkg\archives)) { mkdir -p .vcpkg\archives }
- $env:VCPKG_DEFAULT_BINARY_CACHE="$PWD\.vcpkg\archives"
- echo $env:VCPKG_DEFAULT_BINARY_CACHE
- $env:VCPKG_DEFAULT_TRIPLET="$TRIPLET-windows"
- vcpkg install cmocka
- vcpkg install openssl
- vcpkg install zlib
- vcpkg integrate install
- mkdir -p obj; if ($?) {cd obj}; if (! $?) {exit 1}
- cmake
-A $PLATFORM
-DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake
-DPICKY_DEVELOPER=ON
-DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON
-DUNIT_TESTING=ON ..
visualstudio/x86_64:
extends: .vs
variables:
PLATFORM: "x64"
TRIPLET: "x64"
visualstudio/x86:
extends: .vs
variables:
PLATFORM: "win32"
TRIPLET: "x86"
###############################################################################
# Coverity #
###############################################################################
#
# git push -o ci.variable="COVERITY_SCAN_TOKEN=XXXXXX" \
# -o ci.variable="COVERITY_SCAN_PROJECT_NAME=XXXXXX" \
# -o ci.variable="COVERITY_SCAN_EMAIL=XXXXXX" \
# -f gitlab
coverity:
stage: analysis
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$COVERITY_BUILD
script:
- mkdir obj && cd obj
- wget https://scan.coverity.com/download/linux64 --post-data "token=$COVERITY_SCAN_TOKEN&project=$COVERITY_SCAN_PROJECT_NAME" -O /tmp/coverity_tool.tgz
- tar xf /tmp/coverity_tool.tgz
- cmake -DCMAKE_BUILD_TYPE=Debug $CMAKE_BUILD_OPTIONS $CMAKE_TEST_OPTIONS ..
- cov-analysis-linux64-*/bin/cov-build --dir cov-int make -j$(nproc)
- tar czf cov-int.tar.gz cov-int
- curl
--form token=$COVERITY_SCAN_TOKEN
--form email=$COVERITY_SCAN_EMAIL
--form file=@cov-int.tar.gz
--form version="`git describe --tags`"
--form description="CI build"
https://scan.coverity.com/builds?project=$COVERITY_SCAN_PROJECT_NAME
tags:
- shared
only:
refs:
- master
- schedules
variables:
- $COVERITY_SCAN_TOKEN != null
- $COVERITY_SCAN_PROJECT_NAME != null
- $COVERITY_SCAN_EMAIL != null
artifacts:
expire_in: 1 week
when: on_failure
paths:
- obj/cov-int/*.txt

View File

@@ -1,20 +1,17 @@
cmake_minimum_required(VERSION 3.3.0) project(libssh C)
cmake_policy(SET CMP0048 NEW)
# Specify search path for CMake modules to be loaded by include() # Required cmake version
# and find_package() cmake_minimum_required(VERSION 2.8.5)
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules")
# Add defaults for cmake # global needed variables
# Those need to be set before the project() call.
include(DefineCMakeDefaults)
include(DefineCompilerFlags)
project(libssh VERSION 0.10.4 LANGUAGES C)
# global needed variable
set(APPLICATION_NAME ${PROJECT_NAME}) set(APPLICATION_NAME ${PROJECT_NAME})
set(APPLICATION_VERSION_MAJOR "0")
set(APPLICATION_VERSION_MINOR "7")
set(APPLICATION_VERSION_PATCH "0")
set(APPLICATION_VERSION "${APPLICATION_VERSION_MAJOR}.${APPLICATION_VERSION_MINOR}.${APPLICATION_VERSION_PATCH}")
# SOVERSION scheme: CURRENT.AGE.REVISION # SOVERSION scheme: CURRENT.AGE.REVISION
# If there was an incompatible interface change: # If there was an incompatible interface change:
# Increment CURRENT. Set AGE and REVISION to 0 # Increment CURRENT. Set AGE and REVISION to 0
@@ -22,26 +19,26 @@ set(APPLICATION_NAME ${PROJECT_NAME})
# Increment AGE. Set REVISION to 0 # Increment AGE. Set REVISION to 0
# If the source code was changed, but there were no interface changes: # If the source code was changed, but there were no interface changes:
# Increment REVISION. # Increment REVISION.
set(LIBRARY_VERSION "4.9.4") set(LIBRARY_VERSION "4.4.0")
set(LIBRARY_SOVERSION "4") set(LIBRARY_SOVERSION "4")
# where to look first for cmake modules, before ${CMAKE_ROOT}/Modules/ is checked # where to look first for cmake modules, before ${CMAKE_ROOT}/Modules/ is checked
set(CMAKE_MODULE_PATH
${CMAKE_SOURCE_DIR}/cmake/Modules
)
# add definitions # add definitions
include(DefineCMakeDefaults)
include(DefinePlatformDefaults) include(DefinePlatformDefaults)
include(DefineCompilerFlags)
include(DefineInstallationPaths)
include(DefineOptions.cmake) include(DefineOptions.cmake)
include(CPackConfig.cmake) include(CPackConfig.cmake)
include(GNUInstallDirs)
include(CompilerChecks.cmake)
# disallow in-source build # disallow in-source build
include(MacroEnsureOutOfSourceBuild) include(MacroEnsureOutOfSourceBuild)
macro_ensure_out_of_source_build("${PROJECT_NAME} requires an out of source build. Please create a separate build directory and run 'cmake /path/to/${PROJECT_NAME} [options]' there.") macro_ensure_out_of_source_build("${PROJECT_NAME} requires an out of source build. Please create a separate build directory and run 'cmake /path/to/${PROJECT_NAME} [options]' there.")
# Copy library files to a lib sub-directory
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib")
# search for libraries # search for libraries
if (WITH_ZLIB) if (WITH_ZLIB)
find_package(ZLIB REQUIRED) find_package(ZLIB REQUIRED)
@@ -52,50 +49,24 @@ if (WITH_GCRYPT)
if (NOT GCRYPT_FOUND) if (NOT GCRYPT_FOUND)
message(FATAL_ERROR "Could not find GCrypt") message(FATAL_ERROR "Could not find GCrypt")
endif (NOT GCRYPT_FOUND) endif (NOT GCRYPT_FOUND)
elseif(WITH_MBEDTLS)
find_package(MbedTLS REQUIRED)
if (NOT MBEDTLS_FOUND)
message(FATAL_ERROR "Could not find mbedTLS")
endif (NOT MBEDTLS_FOUND)
else (WITH_GCRYPT) else (WITH_GCRYPT)
find_package(OpenSSL 1.0.1) find_package(OpenSSL)
if (OPENSSL_FOUND) if (NOT OPENSSL_FOUND)
# On CMake < 3.16, OPENSSL_CRYPTO_LIBRARIES is usually a synonym for OPENSSL_CRYPTO_LIBRARY, but is not defined
# when building on Windows outside of Cygwin. We provide the synonym here, if FindOpenSSL didn't define it already.
if (NOT DEFINED OPENSSL_CRYPTO_LIBRARIES)
set(OPENSSL_CRYPTO_LIBRARIES ${OPENSSL_CRYPTO_LIBRARY})
endif (NOT DEFINED OPENSSL_CRYPTO_LIBRARIES)
else (OPENSSL_FOUND)
find_package(GCrypt) find_package(GCrypt)
if (NOT GCRYPT_FOUND) if (NOT GCRYPT_FOUND)
find_package(MbedTLS) message(FATAL_ERROR "Could not find OpenSSL or GCrypt")
if (NOT MBEDTLS_FOUND)
message(FATAL_ERROR "Could not find OpenSSL, GCrypt or mbedTLS")
endif (NOT MBEDTLS_FOUND)
endif (NOT GCRYPT_FOUND) endif (NOT GCRYPT_FOUND)
endif (OPENSSL_FOUND) endif (NOT OPENSSL_FOUND)
endif(WITH_GCRYPT) endif(WITH_GCRYPT)
if (UNIT_TESTING)
find_package(CMocka REQUIRED)
endif ()
# Find out if we have threading available # Find out if we have threading available
set(CMAKE_THREAD_PREFER_PTHREADS ON) set(CMAKE_THREAD_PREFER_PTHREADS ON)
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads) find_package(Threads)
if (WITH_GSSAPI) if (WITH_GSSAPI)
find_package(GSSAPI) find_package(GSSAPI)
endif (WITH_GSSAPI) endif (WITH_GSSAPI)
if (WITH_PKCS11_URI)
find_package(softhsm)
if (NOT SOFTHSM_FOUND)
message(SEND_ERROR "Could not find softhsm module!")
endif (NOT SOFTHSM_FOUND)
endif (WITH_PKCS11_URI)
if (WITH_NACL) if (WITH_NACL)
find_package(NaCl) find_package(NaCl)
if (NOT NACL_FOUND) if (NOT NACL_FOUND)
@@ -103,17 +74,6 @@ if (WITH_NACL)
endif (NOT NACL_FOUND) endif (NOT NACL_FOUND)
endif (WITH_NACL) endif (WITH_NACL)
if (BSD OR SOLARIS OR OSX OR CYGWIN)
find_package(Argp)
endif (BSD OR SOLARIS OR OSX OR CYGWIN)
# Disable symbol versioning in non UNIX platforms
if (UNIX)
find_package(ABIMap 0.3.1)
else (UNIX)
set(WITH_SYMBOL_VERSIONING OFF)
endif (UNIX)
# config.h checks # config.h checks
include(ConfigureChecks.cmake) include(ConfigureChecks.cmake)
configure_file(config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config.h) configure_file(config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config.h)
@@ -124,141 +84,68 @@ add_subdirectory(include)
add_subdirectory(src) add_subdirectory(src)
# pkg-config file # pkg-config file
if (UNIX OR MINGW)
configure_file(libssh.pc.cmake ${CMAKE_CURRENT_BINARY_DIR}/libssh.pc) configure_file(libssh.pc.cmake ${CMAKE_CURRENT_BINARY_DIR}/libssh.pc)
configure_file(libssh_threads.pc.cmake ${CMAKE_CURRENT_BINARY_DIR}/libssh_threads.pc)
install( install(
FILES FILES
${CMAKE_CURRENT_BINARY_DIR}/libssh.pc ${CMAKE_CURRENT_BINARY_DIR}/libssh.pc
${CMAKE_CURRENT_BINARY_DIR}/libssh_threads.pc
DESTINATION DESTINATION
${CMAKE_INSTALL_LIBDIR}/pkgconfig ${LIB_INSTALL_DIR}/pkgconfig
COMPONENT COMPONENT
pkgconfig pkgconfig
) )
endif (UNIX OR MINGW)
# CMake config files
include(CMakePackageConfigHelpers)
# cmake config files
set(LIBSSH_LIBRARY_NAME ${CMAKE_SHARED_LIBRARY_PREFIX}ssh${CMAKE_SHARED_LIBRARY_SUFFIX}) set(LIBSSH_LIBRARY_NAME ${CMAKE_SHARED_LIBRARY_PREFIX}ssh${CMAKE_SHARED_LIBRARY_SUFFIX})
set(LIBSSH_THREADS_LIBRARY_NAME ${CMAKE_SHARED_LIBRARY_PREFIX}ssh${CMAKE_SHARED_LIBRARY_SUFFIX})
# libssh-config-version.cmake configure_file(${PROJECT_NAME}-config.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config.cmake @ONLY)
write_basic_package_version_file(libssh-config-version.cmake configure_file(${PROJECT_NAME}-config-version.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config-version.cmake @ONLY)
VERSION ${PROJECT_VERSION}
COMPATIBILITY SameMajorVersion)
install( install(
FILES FILES
${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config.cmake
${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config-version.cmake ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config-version.cmake
DESTINATION DESTINATION
${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME} ${CMAKE_INSTALL_DIR}/${PROJECT_NAME}
COMPONENT COMPONENT
devel) devel
)
# in tree build settings
configure_file(libssh-build-tree-settings.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/libssh-build-tree-settings.cmake @ONLY)
if (WITH_EXAMPLES) if (WITH_EXAMPLES)
add_subdirectory(examples) add_subdirectory(examples)
endif (WITH_EXAMPLES) endif (WITH_EXAMPLES)
if (UNIT_TESTING) if (WITH_TESTING)
include(AddCMockaTest) find_package(CMocka REQUIRED)
add_subdirectory(tests) include(AddCMockaTest)
endif (UNIT_TESTING) add_subdirectory(tests)
endif (WITH_TESTING)
### SOURCE PACKAGE
if (WITH_SYMBOL_VERSIONING AND ABIMAP_FOUND)
# Get the current ABI version from source
get_filename_component(current_abi_path
"${CMAKE_SOURCE_DIR}/src/ABI/current"
ABSOLUTE)
# Check if the ABI version should be updated
file(READ ${current_abi_path} CURRENT_ABI_CONTENT)
string(STRIP "${CURRENT_ABI_CONTENT}" CURRENT_ABI_VERSION)
if (LIBRARY_VERSION VERSION_GREATER CURRENT_ABI_VERSION)
set(UPDATE_ABI TRUE)
endif ()
if (UPDATE_ABI)
message(STATUS "Library version bumped to ${LIBRARY_VERSION}: Updating ABI")
# Get the list of header files
get_file_list(${PROJECT_NAME}_header_list
DIRECTORIES "${CMAKE_SOURCE_DIR}/include/libssh"
FILES_PATTERNS "*.h")
# Extract the symbols marked as "LIBSSH_API" from the header files
extract_symbols(${PROJECT_NAME}.symbols
HEADERS_LIST ${PROJECT_NAME}_header_list
FILTER_PATTERN "LIBSSH_API"
COPY_TO "${CMAKE_SOURCE_DIR}/src/ABI/${PROJECT_NAME}-${LIBRARY_VERSION}.symbols")
if (WITH_ABI_BREAK)
set(ALLOW_ABI_BREAK "BREAK_ABI")
endif()
# Target we can depend on in 'make dist'
set(_SYMBOL_TARGET "${PROJECT_NAME}.map")
# Set the path to the current map file
set(MAP_PATH "${CMAKE_SOURCE_DIR}/src/${_SYMBOL_TARGET}")
# Generate the symbol version map file
generate_map_file(${_SYMBOL_TARGET}
SYMBOLS ${PROJECT_NAME}.symbols
RELEASE_NAME_VERSION ${PROJECT_NAME}_${LIBRARY_VERSION}
CURRENT_MAP ${MAP_PATH}
COPY_TO ${MAP_PATH}
FINAL
${ALLOW_ABI_BREAK})
# Write the current version to the source
file(WRITE ${current_abi_path} ${LIBRARY_VERSION})
endif(UPDATE_ABI)
endif (WITH_SYMBOL_VERSIONING AND ABIMAP_FOUND)
add_custom_target(dist COMMAND ${CMAKE_MAKE_PROGRAM} package_source DEPENDS ${_SYMBOL_TARGET} VERBATIM)
# Link compile database for clangd
execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink
"${CMAKE_BINARY_DIR}/compile_commands.json"
"${CMAKE_SOURCE_DIR}/compile_commands.json")
message(STATUS "********************************************") message(STATUS "********************************************")
message(STATUS "********** ${PROJECT_NAME} build options : **********") message(STATUS "********** ${PROJECT_NAME} build options : **********")
message(STATUS "zlib support: ${WITH_ZLIB}") message(STATUS "zlib support: ${WITH_ZLIB}")
message(STATUS "libgcrypt support: ${WITH_GCRYPT}") message(STATUS "libgcrypt support: ${WITH_GCRYPT}")
message(STATUS "libmbedTLS support: ${WITH_MBEDTLS}")
message(STATUS "libnacl support: ${WITH_NACL}") message(STATUS "libnacl support: ${WITH_NACL}")
message(STATUS "SSH-1 support: ${WITH_SSH1}")
message(STATUS "SFTP support: ${WITH_SFTP}") message(STATUS "SFTP support: ${WITH_SFTP}")
message(STATUS "Server support : ${WITH_SERVER}") message(STATUS "Server support : ${WITH_SERVER}")
message(STATUS "GSSAPI support : ${WITH_GSSAPI}") message(STATUS "GSSAPI support : ${WITH_GSSAPI}")
message(STATUS "GEX support : ${WITH_GEX}")
message(STATUS "Support insecure none cipher and MAC : ${WITH_INSECURE_NONE}")
message(STATUS "Pcap debugging support : ${WITH_PCAP}") message(STATUS "Pcap debugging support : ${WITH_PCAP}")
message(STATUS "Build shared library: ${BUILD_SHARED_LIBS}") message(STATUS "With static library: ${WITH_STATIC_LIB}")
message(STATUS "Unit testing: ${UNIT_TESTING}") message(STATUS "Unit testing: ${WITH_TESTING}")
message(STATUS "Client code testing: ${CLIENT_TESTING}") message(STATUS "Client code Unit testing: ${WITH_CLIENT_TESTING}")
message(STATUS "Blowfish cipher support: ${WITH_BLOWFISH_CIPHER}")
message(STATUS "PKCS #11 URI support: ${WITH_PKCS11_URI}")
message(STATUS "DSA support: ${WITH_DSA}")
set(_SERVER_TESTING OFF)
if (WITH_SERVER)
set(_SERVER_TESTING ${SERVER_TESTING})
endif()
message(STATUS "Server code testing: ${_SERVER_TESTING}")
if (WITH_INTERNAL_DOC) if (WITH_INTERNAL_DOC)
message(STATUS "Internal documentation generation") message(STATUS "Internal documentation generation")
else (WITH_INTERNAL_DOC) else (WITH_INTERNAL_DOC)
message(STATUS "Public API documentation generation") message(STATUS "Public API documentation generation")
endif (WITH_INTERNAL_DOC) endif (WITH_INTERNAL_DOC)
message(STATUS "Benchmarks: ${WITH_BENCHMARKS}") message(STATUS "Benchmarks: ${WITH_BENCHMARKS}")
message(STATUS "Symbol versioning: ${WITH_SYMBOL_VERSIONING}")
message(STATUS "Allow ABI break: ${WITH_ABI_BREAK}")
message(STATUS "Release is final: ${WITH_FINAL}")
message(STATUS "Global client config: ${GLOBAL_CLIENT_CONFIG}")
if (WITH_SERVER)
message(STATUS "Global bind config: ${GLOBAL_BIND_CONFIG}")
endif()
message(STATUS "********************************************") message(STATUS "********************************************")

13
COPYING
View File

@@ -455,15 +455,6 @@ FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES. DAMAGES.
Linking with OpenSSL Linking with OpenSSL
17. In addition, as a special exception, we give permission to link the code of its release of libssh with the OpenSSL project's "OpenSSL" library (or with modified versions of it that use the same license as the "OpenSSL" library), and distribute the linked executables. You must obey the GNU Lesser General Public License in all respects for all of the code used other than "OpenSSL". If you modify this file, you may extend this exception to your version of the file, but you are not obligated to do so. If you do not wish to do so, delete this exception statement from your version.
17. In addition, as a special exception, we give permission to link the code
of its release of libssh with the OpenSSL project's "OpenSSL" library (or with
modified versions of it that use the same license as the "OpenSSL" library),
and distribute the linked executables. You must obey the GNU Lesser General
Public License in all respects for all of the code used other than "OpenSSL".
If you modify this file, you may extend this exception to your version of the
file, but you are not obligated to do so. If you do not wish to do so, delete
this exception statement from your version.
END OF TERMS AND CONDITIONS END OF TERMS AND CONDITIONS

View File

@@ -1,19 +1,27 @@
### GENERAL SETTINGS # For help take a look at:
set(CPACK_PACKAGE_NAME ${PROJECT_NAME}) # http://www.cmake.org/Wiki/CMake:CPackConfiguration
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "The SSH Library")
set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/README") ### general settings
set(CPACK_PACKAGE_NAME ${APPLICATION_NAME})
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "The SSH library")
set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_SOURCE_DIR}/README")
set(CPACK_PACKAGE_VENDOR "The SSH Library Development Team") set(CPACK_PACKAGE_VENDOR "The SSH Library Development Team")
set(CPACK_PACKAGE_INSTALL_DIRECTORY ${CPACK_PACKAGE_NAME}) set(CPACK_PACKAGE_INSTALL_DIRECTORY ${CPACK_PACKAGE_NAME})
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/COPYING") set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/COPYING")
set(CPACK_PACKAGE_VERSION ${PROJECT_VERSION})
# SOURCE GENERATOR ### versions
set(CPACK_SOURCE_GENERATOR "TXZ") set(CPACK_PACKAGE_VERSION_MAJOR ${APPLICATION_VERSION_MAJOR})
set(CPACK_SOURCE_IGNORE_FILES "~$;[.]swp$;/[.]git/;/[.]clangd/;/[.]cache/;.gitignore;/build*;/obj*;tags;cscope.*;compile_commands.json;.*\.patch") set(CPACK_PACKAGE_VERSION_MINOR ${APPLICATION_VERSION_MINOR})
set(CPACK_PACKAGE_VERSION_PATCH ${APPLICATION_VERSION_PATCH})
set(CPACK_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}")
### source generator
set(CPACK_SOURCE_GENERATOR "TGZ")
set(CPACK_SOURCE_IGNORE_FILES "~$;[.]swp$;/[.]svn/;/[.]git/;.gitignore;/build/;/obj/;tags;cscope.*")
set(CPACK_SOURCE_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}") set(CPACK_SOURCE_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}")
### NSIS INSTALLER
if (WIN32) if (WIN32)
set(CPACK_GENERATOR "ZIP") set(CPACK_GENERATOR "ZIP")
@@ -23,7 +31,7 @@ if (WIN32)
set(CPACK_GENERATOR "${CPACK_GENERATOR};NSIS") set(CPACK_GENERATOR "${CPACK_GENERATOR};NSIS")
set(CPACK_NSIS_DISPLAY_NAME "The SSH Library") set(CPACK_NSIS_DISPLAY_NAME "The SSH Library")
set(CPACK_NSIS_COMPRESSOR "/SOLID zlib") set(CPACK_NSIS_COMPRESSOR "/SOLID zlib")
set(CPACK_NSIS_MENU_LINKS "https://www.libssh.org/" "libssh homepage") set(CPACK_NSIS_MENU_LINKS "http://www.libssh.org/" "libssh homepage")
endif (NSIS_MAKE) endif (NSIS_MAKE)
endif (WIN32) endif (WIN32)
@@ -38,6 +46,7 @@ set(CPACK_COMPONENT_LIBRARIES_DESCRIPTION
set(CPACK_COMPONENT_HEADERS_DESCRIPTION set(CPACK_COMPONENT_HEADERS_DESCRIPTION
"C/C++ header files for use with libssh") "C/C++ header files for use with libssh")
set(CPACK_COMPONENT_HEADERS_DEPENDS libraries) set(CPACK_COMPONENT_HEADERS_DEPENDS libraries)
#set(CPACK_COMPONENT_APPLICATIONS_GROUP "Runtime")
set(CPACK_COMPONENT_LIBRARIES_GROUP "Development") set(CPACK_COMPONENT_LIBRARIES_GROUP "Development")
set(CPACK_COMPONENT_HEADERS_GROUP "Development") set(CPACK_COMPONENT_HEADERS_GROUP "Development")

View File

@@ -1,177 +1,5 @@
CHANGELOG ChangeLog
========= ==========
version 0.10.4 (released 2022-09-07)
* Fixed issues with KDF on big endian
version 0.10.3 (released 2022-09-05)
* Fixed possible infinite loop in known hosts checking
version 0.10.2 (released 2022-09-02)
* Fixed tilde expansion when handling include directives
* Fixed building the shared torture library
* Made rekey test more robust (fixes running on i586 build systems e.g koji)
version 0.10.1 (released 2022-08-30)
* Fixed proxycommand support
* Fixed musl libc support
version 0.10.0 (released 2022-08-26)
* Added support for OpenSSL 3.0
* Added support for mbedTLS 3
* Added support for Smart Cards (through openssl pkcs11 engine)
* Added support for chacha20-poly1305@openssh.com with libgcrypt
* Added support ed25519 keys in PEM files
* Added support for sk-ecdsa and sk-ed25519 (server side)
* Added support for limiting RSA key sizes and not accepting small one by
default
* Added support for ssh-agent on Windows
* Added ssh_userauth_publickey_auto_get_current_identity() API
* Added ssh_vlog() API
* Added ssh_send_issue_banner() API
* Added ssh_session_set_disconnect_message() API
* Added new configuration options:
+ IdentityAgent
+ ModuliFile
* Provided X11 client example
* Disabled DSA support at build time by default (will be removed in the next
release)
* Deprecated the SCP API!
* Deprecated old pubkey, privatekey API
* Avoided some needless large stack buffers to minimize memory footprint
* Removed support for OpenSSL < 1.0.1
* Fixed parsing username@host in login name
* Free global init mutex in the destructor on Windows
* Fixed PEM parsing in mbedtls to support both legacy and new PKCS8 formats
version 0.9.6 (released 2021-08-26)
* CVE-2021-3634: Fix possible heap-buffer overflow when rekeying with
different key exchange mechanism
* Fix several memory leaks on error paths
* Reset pending_call_state on disconnect
* Fix handshake bug with AEAD ciphers and no HMAC overlap
* Use OPENSSL_CRYPTO_LIBRARIES in CMake
* Ignore request success and failure message if they are not expected
* Support more identity files in configuration
* Avoid setting compiler flags directly in CMake
* Support build directories with special characters
* Include stdlib.h to avoid crash in Windows
* Fix sftp_new_channel constructs an invalid object
* Fix Ninja multiple rules error
* Several tests fixes
version 0.9.5 (released 2020-09-10)
* CVE-2020-16135: Avoid null pointer dereference in sftpserver (T232)
* Improve handling of library initialization (T222)
* Fix parsing of subsecond times in SFTP (T219)
* Make the documentation reproducible
* Remove deprecated API usage in OpenSSL
* Fix regression of ssh_channel_poll_timeout() returning SSH_AGAIN
* Define version in one place (T226)
* Prevent invalid free when using different C runtimes than OpenSSL (T229)
* Compatibility improvements to testsuite
version 0.9.4 (released 2020-04-09)
* Fixed CVE-2020-1730 - Possible DoS in client and server when handling
AES-CTR keys with OpenSSL
* Added diffie-hellman-group14-sha256
* Fixed serveral possible memory leaks
version 0.9.3 (released 2019-12-10)
* Fixed CVE-2019-14889 - SCP: Unsanitized location leads to command execution
* SSH-01-003 Client: Missing NULL check leads to crash in erroneous state
* SSH-01-006 General: Various unchecked Null-derefs cause DOS
* SSH-01-007 PKI Gcrypt: Potential UAF/double free with RSA pubkeys
* SSH-01-010 SSH: Deprecated hash function in fingerprinting
* SSH-01-013 Conf-Parsing: Recursive wildcards in hostnames lead to DOS
* SSH-01-014 Conf-Parsing: Integer underflow leads to OOB array access
* SSH-01-001 State Machine: Initial machine states should be set explicitly
* SSH-01-002 Kex: Differently bound macros used to iterate same array
* SSH-01-005 Code-Quality: Integer sign confusion during assignments
* SSH-01-008 SCP: Protocol Injection via unescaped File Names
* SSH-01-009 SSH: Update documentation which RFCs are implemented
* SSH-01-012 PKI: Information leak via uninitialized stack buffer
version 0.9.2 (released 2019-11-07)
* Fixed libssh-config.cmake
* Fixed issues with rsa algorithm negotiation (T191)
* Fixed detection of OpenSSL ed25519 support (T197)
version 0.9.1 (released 2019-10-25)
* Added support for Ed25519 via OpenSSL
* Added support for X25519 via OpenSSL
* Added support for localuser in Match keyword
* Fixed Match keyword to be case sensitive
* Fixed compilation with LibreSSL
* Fixed error report of channel open (T75)
* Fixed sftp documentation (T137)
* Fixed known_hosts parsing (T156)
* Fixed build issue with MinGW (T157)
* Fixed build with gcc 9 (T164)
* Fixed deprecation issues (T165)
* Fixed known_hosts directory creation (T166)
version 0.9.0 (released 2019-02-xx)
* Added support for AES-GCM
* Added improved rekeying support
* Added performance improvements
* Disabled blowfish support by default
* Fixed several ssh config parsing issues
* Added support for DH Group Exchange KEX
* Added support for Encrypt-then-MAC mode
* Added support for parsing server side configuration file
* Added support for ECDSA/Ed25519 certificates
* Added FIPS 140-2 compatibility
* Improved known_hosts parsing
* Improved documentation
* Improved OpenSSL API usage for KEX, DH, and signatures
version 0.8.0 (released 2018-08-10)
* Removed support for deprecated SSHv1 protocol
* Added new connector API for clients
* Added new known_hosts parsing API
* Added support for OpenSSL 1.1
* Added support for chacha20-poly1305 cipher
* Added crypto backend for mbedtls crypto library
* Added ECDSA support with gcrypt backend
* Added advanced client and server testing using cwrap.org
* Added support for curve25519-sha256 alias
* Added support for global known_hosts file
* Added support for symbol versioning
* Improved ssh_config parsing
* Improved threading support
version 0.7.5 (released 2017-04-13)
* Fixed a memory allocation issue with buffers
* Fixed PKI on Windows
* Fixed some SSHv1 functions
* Fixed config hostname expansion
version 0.7.4 (released 2017-02-03)
* Added id_ed25519 to the default identity list
* Fixed sftp EOF packet handling
* Fixed ssh_send_banner() to confirm with RFC 4253
* Fixed some memory leaks
version 0.7.3 (released 2016-01-23)
* Fixed CVE-2016-0739
* Fixed ssh-agent on big endian
* Fixed some documentation issues
version 0.7.2 (released 2015-09-15)
* Fixed OpenSSL detection on Windows
* Fixed return status for ssh_userauth_agent()
* Fixed KEX to prefer hmac-sha2-256
* Fixed sftp packet handling
* Fixed return values of ssh_key_is_(public|private)
* Fixed bug in global success reply
version 0.7.1 (released 2015-06-30)
* Fixed SSH_AUTH_PARTIAL auth with auto public key
* Fixed memory leak in session options
* Fixed allocation of ed25519 public keys
* Fixed channel exit-status and exit-signal
* Reintroduce ssh_forward_listen()
version 0.7.0 (released 2015-05-11) version 0.7.0 (released 2015-05-11)
* Added support for ed25519 keys * Added support for ed25519 keys
@@ -460,6 +288,14 @@ version 0.3.2 (released 2009-08-05)
* Fixed compilation on Solaris. * Fixed compilation on Solaris.
* Fixed SSHv1 compilation. * Fixed SSHv1 compilation.
version 0.3.1 (released 2009-07-14)
* Added return code SSH_SERVER_FILE_NOT_FOUND.
* Fixed compilation of SSHv1.
* Fixed several memory leaks.
* Fixed possible infinite loops.
* Fixed a possible crash bug.
* Fixed build warnings.
* Fixed cmake on BSD.
version 0.3.1 (released 2009-07-14) version 0.3.1 (released 2009-07-14)
* Added return code SSH_SERVER_FILE_NOT_FOUND. * Added return code SSH_SERVER_FILE_NOT_FOUND.
* Fixed compilation of SSHv1. * Fixed compilation of SSHv1.
@@ -509,7 +345,7 @@ version 0.2 (released 2007-11-29)
version 0.11-dev version 0.11-dev
* Server implementation development. * Server implementation development.
* Small bug corrected when connecting to sun ssh servers. * Small bug corrected when connecting to sun ssh servers.
* Channel weirdness corrected (writing huge data packets) * Channel wierdness corrected (writing huge data packets)
* Channel_read_nonblocking added * Channel_read_nonblocking added
* Channel bug where stderr wasn't correctly read fixed. * Channel bug where stderr wasn't correctly read fixed.
* Added sftp_file_set_nonblocking(), which is nonblocking SFTP IO * Added sftp_file_set_nonblocking(), which is nonblocking SFTP IO

View File

@@ -1,124 +0,0 @@
include(AddCCompilerFlag)
include(CheckCCompilerFlagSSP)
if (UNIX)
#
# Check for -Werror turned on if possible
#
# This will prevent that compiler flags are detected incorrectly.
#
check_c_compiler_flag("-Werror" REQUIRED_FLAGS_WERROR)
if (REQUIRED_FLAGS_WERROR)
set(CMAKE_REQUIRED_FLAGS "-Werror")
if (PICKY_DEVELOPER)
list(APPEND SUPPORTED_COMPILER_FLAGS "-Werror")
endif()
endif()
add_c_compiler_flag("-std=gnu99" SUPPORTED_COMPILER_FLAGS)
add_c_compiler_flag("-Wpedantic" SUPPORTED_COMPILER_FLAGS)
add_c_compiler_flag("-Wall" SUPPORTED_COMPILER_FLAGS)
add_c_compiler_flag("-Wshadow" SUPPORTED_COMPILER_FLAGS)
add_c_compiler_flag("-Wmissing-prototypes" SUPPORTED_COMPILER_FLAGS)
add_c_compiler_flag("-Wcast-align" SUPPORTED_COMPILER_FLAGS)
#add_c_compiler_flag("-Wcast-qual" SUPPORTED_COMPILER_FLAGS)
add_c_compiler_flag("-Werror=address" SUPPORTED_COMPILER_FLAGS)
add_c_compiler_flag("-Wstrict-prototypes" SUPPORTED_COMPILER_FLAGS)
add_c_compiler_flag("-Werror=strict-prototypes" SUPPORTED_COMPILER_FLAGS)
add_c_compiler_flag("-Wwrite-strings" SUPPORTED_COMPILER_FLAGS)
add_c_compiler_flag("-Werror=write-strings" SUPPORTED_COMPILER_FLAGS)
add_c_compiler_flag("-Werror-implicit-function-declaration" SUPPORTED_COMPILER_FLAGS)
add_c_compiler_flag("-Wpointer-arith" SUPPORTED_COMPILER_FLAGS)
add_c_compiler_flag("-Werror=pointer-arith" SUPPORTED_COMPILER_FLAGS)
add_c_compiler_flag("-Wdeclaration-after-statement" SUPPORTED_COMPILER_FLAGS)
add_c_compiler_flag("-Werror=declaration-after-statement" SUPPORTED_COMPILER_FLAGS)
add_c_compiler_flag("-Wreturn-type" SUPPORTED_COMPILER_FLAGS)
add_c_compiler_flag("-Werror=return-type" SUPPORTED_COMPILER_FLAGS)
add_c_compiler_flag("-Wuninitialized" SUPPORTED_COMPILER_FLAGS)
add_c_compiler_flag("-Werror=uninitialized" SUPPORTED_COMPILER_FLAGS)
add_c_compiler_flag("-Wimplicit-fallthrough" SUPPORTED_COMPILER_FLAGS)
add_c_compiler_flag("-Werror=strict-overflow" SUPPORTED_COMPILER_FLAGS)
add_c_compiler_flag("-Wstrict-overflow=2" SUPPORTED_COMPILER_FLAGS)
add_c_compiler_flag("-Wno-format-zero-length" SUPPORTED_COMPILER_FLAGS)
add_c_compiler_flag("-Wmissing-field-initializers" SUPPORTED_COMPILER_FLAGS)
add_c_compiler_flag("-Wsign-compare" SUPPORTED_COMPILER_FLAGS)
check_c_compiler_flag("-Wformat" REQUIRED_FLAGS_WFORMAT)
if (REQUIRED_FLAGS_WFORMAT)
list(APPEND SUPPORTED_COMPILER_FLAGS "-Wformat")
set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -Wformat")
endif()
add_c_compiler_flag("-Wformat-security" SUPPORTED_COMPILER_FLAGS)
add_c_compiler_flag("-Werror=format-security" SUPPORTED_COMPILER_FLAGS)
# Allow zero for a variadic macro argument
string(TOLOWER "${CMAKE_C_COMPILER_ID}" _C_COMPILER_ID)
if ("${_C_COMPILER_ID}" STREQUAL "clang")
add_c_compiler_flag("-Wno-gnu-zero-variadic-macro-arguments" SUPPORTED_COMPILER_FLAGS)
endif()
add_c_compiler_flag("-fno-common" SUPPORTED_COMPILER_FLAGS)
if (CMAKE_BUILD_TYPE)
string(TOLOWER "${CMAKE_BUILD_TYPE}" CMAKE_BUILD_TYPE_LOWER)
if (CMAKE_BUILD_TYPE_LOWER MATCHES (release|relwithdebinfo|minsizerel))
add_c_compiler_flag("-Wp,-D_FORTIFY_SOURCE=2" SUPPORTED_COMPILER_FLAGS)
endif()
endif()
check_c_compiler_flag_ssp("-fstack-protector-strong" WITH_STACK_PROTECTOR_STRONG)
if (WITH_STACK_PROTECTOR_STRONG)
list(APPEND SUPPORTED_COMPILER_FLAGS "-fstack-protector-strong")
# This is needed as Solaris has a seperate libssp
if (SOLARIS)
list(APPEND SUPPORTED_LINKER_FLAGS "-fstack-protector-strong")
endif()
else (WITH_STACK_PROTECTOR_STRONG)
check_c_compiler_flag_ssp("-fstack-protector" WITH_STACK_PROTECTOR)
if (WITH_STACK_PROTECTOR)
list(APPEND SUPPORTED_COMPILER_FLAGS "-fstack-protector")
# This is needed as Solaris has a seperate libssp
if (SOLARIS)
list(APPEND SUPPORTED_LINKER_FLAGS "-fstack-protector")
endif()
endif()
endif (WITH_STACK_PROTECTOR_STRONG)
if (NOT WINDOWS AND NOT CYGWIN)
check_c_compiler_flag_ssp("-fstack-clash-protection" WITH_STACK_CLASH_PROTECTION)
if (WITH_STACK_CLASH_PROTECTION)
list(APPEND SUPPORTED_COMPILER_FLAGS "-fstack-clash-protection")
endif()
endif()
if (PICKY_DEVELOPER)
add_c_compiler_flag("-Wno-error=deprecated-declarations" SUPPORTED_COMPILER_FLAGS)
add_c_compiler_flag("-Wno-error=tautological-compare" SUPPORTED_COMPILER_FLAGS)
endif()
add_c_compiler_flag("-Wno-deprecated-declarations" DEPRECATION_COMPILER_FLAGS)
# Unset CMAKE_REQUIRED_FLAGS
unset(CMAKE_REQUIRED_FLAGS)
endif()
if (MSVC)
add_c_compiler_flag("/D _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES=1" SUPPORTED_COMPILER_FLAGS)
add_c_compiler_flag("/D _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT=1" SUPPORTED_COMPILER_FLAGS)
add_c_compiler_flag("/D _CRT_NONSTDC_NO_WARNINGS=1" SUPPORTED_COMPILER_FLAGS)
add_c_compiler_flag("/D _CRT_SECURE_NO_WARNINGS=1" SUPPORTED_COMPILER_FLAGS)
endif()
# This removes this annoying warning
# "warning: 'BN_CTX_free' is deprecated: first deprecated in OS X 10.7 [-Wdeprecated-declarations]"
if (OSX)
add_c_compiler_flag("-Wno-deprecated-declarations" SUPPORTED_COMPILER_FLAGS)
endif()
set(DEFAULT_C_COMPILE_FLAGS ${SUPPORTED_COMPILER_FLAGS} CACHE INTERNAL "Default C Compiler Flags" FORCE)
set(DEFAULT_LINK_FLAGS ${SUPPORTED_LINKER_FLAGS} CACHE INTERNAL "Default C Linker Flags" FORCE)
if (DEPRECATION_COMPILER_FLAGS)
set(DEFAULT_C_NO_DEPRECATION_FLAGS ${DEPRECATION_COMPILER_FLAGS} CACHE INTERNAL "Default no deprecation flags" FORCE)
endif()

View File

@@ -1,15 +1,17 @@
include(CheckIncludeFile) include(CheckIncludeFile)
include(CheckIncludeFiles)
include(CheckSymbolExists) include(CheckSymbolExists)
include(CheckFunctionExists) include(CheckFunctionExists)
include(CheckLibraryExists) include(CheckLibraryExists)
include(CheckTypeSize) include(CheckTypeSize)
include(CheckStructHasMember) include(CheckCXXSourceCompiles)
include(TestBigEndian) include(TestBigEndian)
set(PACKAGE ${PROJECT_NAME}) set(PACKAGE ${APPLICATION_NAME})
set(VERSION ${PROJECT_VERSION}) set(VERSION ${APPLICATION_VERSION})
set(SYSCONFDIR ${CMAKE_INSTALL_SYSCONFDIR}) set(DATADIR ${DATA_INSTALL_DIR})
set(LIBDIR ${LIB_INSTALL_DIR})
set(PLUGINDIR "${PLUGIN_INSTALL_DIR}-${LIBRARY_SOVERSION}")
set(SYSCONFDIR ${SYSCONF_INSTALL_DIR})
set(BINARYDIR ${CMAKE_BINARY_DIR}) set(BINARYDIR ${CMAKE_BINARY_DIR})
set(SOURCEDIR ${CMAKE_SOURCE_DIR}) set(SOURCEDIR ${CMAKE_SOURCE_DIR})
@@ -39,33 +41,23 @@ if(CMAKE_COMPILER_IS_GNUCC AND NOT MINGW AND NOT OS2)
"void __attribute__((visibility(\"default\"))) test() {} "void __attribute__((visibility(\"default\"))) test() {}
int main(void){ return 0; } int main(void){ return 0; }
" WITH_VISIBILITY_HIDDEN) " WITH_VISIBILITY_HIDDEN)
unset(CMAKE_REQUIRED_FLAGS) set(CMAKE_REQUIRED_FLAGS "")
endif (NOT GNUCC_VERSION EQUAL 34) endif (NOT GNUCC_VERSION EQUAL 34)
endif(CMAKE_COMPILER_IS_GNUCC AND NOT MINGW AND NOT OS2) endif(CMAKE_COMPILER_IS_GNUCC AND NOT MINGW AND NOT OS2)
# HEADER FILES # HEADER FILES
set(CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES} ${ARGP_INCLUDE_DIR})
check_include_file(argp.h HAVE_ARGP_H) check_include_file(argp.h HAVE_ARGP_H)
unset(CMAKE_REQUIRED_INCLUDES)
check_include_file(pty.h HAVE_PTY_H) check_include_file(pty.h HAVE_PTY_H)
check_include_file(utmp.h HAVE_UTMP_H) check_include_file(utmp.h HAVE_UTMP_H)
check_include_file(termios.h HAVE_TERMIOS_H) check_include_file(termios.h HAVE_TERMIOS_H)
check_include_file(unistd.h HAVE_UNISTD_H) check_include_file(unistd.h HAVE_UNISTD_H)
check_include_file(stdint.h HAVE_STDINT_H)
check_include_file(util.h HAVE_UTIL_H) check_include_file(util.h HAVE_UTIL_H)
check_include_file(libutil.h HAVE_LIBUTIL_H) check_include_file(libutil.h HAVE_LIBUTIL_H)
check_include_file(sys/time.h HAVE_SYS_TIME_H) check_include_file(sys/time.h HAVE_SYS_TIME_H)
check_include_file(sys/utime.h HAVE_SYS_UTIME_H)
check_include_file(sys/param.h HAVE_SYS_PARAM_H) check_include_file(sys/param.h HAVE_SYS_PARAM_H)
check_include_file(arpa/inet.h HAVE_ARPA_INET_H) check_include_file(arpa/inet.h HAVE_ARPA_INET_H)
check_include_file(byteswap.h HAVE_BYTESWAP_H)
check_include_file(glob.h HAVE_GLOB_H)
check_include_file(valgrind/valgrind.h HAVE_VALGRIND_VALGRIND_H)
if (WIN32) if (WIN32)
check_include_file(io.h HAVE_IO_H)
check_include_files("winsock2.h;ws2tcpip.h;wspiapi.h" HAVE_WSPIAPI_H) check_include_files("winsock2.h;ws2tcpip.h;wspiapi.h" HAVE_WSPIAPI_H)
if (NOT HAVE_WSPIAPI_H) if (NOT HAVE_WSPIAPI_H)
message(STATUS "WARNING: Without wspiapi.h, this build will only work on Windows XP and newer versions") message(STATUS "WARNING: Without wspiapi.h, this build will only work on Windows XP and newer versions")
@@ -73,89 +65,29 @@ if (WIN32)
check_include_files("winsock2.h;ws2tcpip.h" HAVE_WS2TCPIP_H) check_include_files("winsock2.h;ws2tcpip.h" HAVE_WS2TCPIP_H)
endif (WIN32) endif (WIN32)
if (OPENSSL_FOUND) set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIRS})
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR}) check_include_file(openssl/aes.h HAVE_OPENSSL_AES_H)
check_include_file(openssl/des.h HAVE_OPENSSL_DES_H)
if (NOT HAVE_OPENSSL_DES_H)
message(FATAL_ERROR "Could not detect openssl/des.h")
endif()
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR}) set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIRS})
check_include_file(openssl/aes.h HAVE_OPENSSL_AES_H) check_include_file(openssl/blowfish.h HAVE_OPENSSL_BLOWFISH_H)
if (NOT HAVE_OPENSSL_AES_H)
message(FATAL_ERROR "Could not detect openssl/aes.h")
endif()
if (WITH_BLOWFISH_CIPHER) set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIRS})
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR}) check_include_file(openssl/des.h HAVE_OPENSSL_DES_H)
check_include_file(openssl/blowfish.h HAVE_OPENSSL_BLOWFISH_H)
endif()
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR}) set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIRS})
check_include_file(openssl/ecdh.h HAVE_OPENSSL_ECDH_H) check_include_file(openssl/ecdh.h HAVE_OPENSSL_ECDH_H)
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR}) set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIRS})
check_include_file(openssl/ec.h HAVE_OPENSSL_EC_H) check_include_file(openssl/ec.h HAVE_OPENSSL_EC_H)
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR}) set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIRS})
check_include_file(openssl/ecdsa.h HAVE_OPENSSL_ECDSA_H) check_include_file(openssl/ecdsa.h HAVE_OPENSSL_ECDSA_H)
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARIES})
check_function_exists(EVP_KDF_CTX_new_id HAVE_OPENSSL_EVP_KDF_CTX_NEW_ID)
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARIES})
check_function_exists(EVP_KDF_CTX_new HAVE_OPENSSL_EVP_KDF_CTX_NEW)
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARIES})
check_function_exists(FIPS_mode HAVE_OPENSSL_FIPS_MODE)
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARIES})
check_function_exists(RAND_priv_bytes HAVE_OPENSSL_RAND_PRIV_BYTES)
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARIES})
check_function_exists(EVP_DigestSign HAVE_OPENSSL_EVP_DIGESTSIGN)
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARIES})
check_function_exists(EVP_DigestVerify HAVE_OPENSSL_EVP_DIGESTVERIFY)
check_function_exists(OPENSSL_ia32cap_loc HAVE_OPENSSL_IA32CAP_LOC)
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARIES})
check_symbol_exists(EVP_PKEY_ED25519 "openssl/evp.h" FOUND_OPENSSL_ED25519)
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARIES})
check_function_exists(EVP_chacha20 HAVE_OPENSSL_EVP_CHACHA20)
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARIES})
check_symbol_exists(EVP_PKEY_POLY1305 "openssl/evp.h" HAVE_OPENSSL_EVP_POLY1305)
if (HAVE_OPENSSL_EVP_DIGESTSIGN AND HAVE_OPENSSL_EVP_DIGESTVERIFY AND
FOUND_OPENSSL_ED25519)
set(HAVE_OPENSSL_ED25519 1)
endif()
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARIES})
check_symbol_exists(EVP_PKEY_X25519 "openssl/evp.h" HAVE_OPENSSL_X25519)
unset(CMAKE_REQUIRED_INCLUDES)
unset(CMAKE_REQUIRED_LIBRARIES)
endif()
if (CMAKE_HAVE_PTHREAD_H) if (CMAKE_HAVE_PTHREAD_H)
set(HAVE_PTHREAD_H 1) set(HAVE_PTHREAD_H 1)
endif (CMAKE_HAVE_PTHREAD_H) endif (CMAKE_HAVE_PTHREAD_H)
if (NOT WITH_GCRYPT AND NOT WITH_MBEDTLS) if (NOT WITH_GCRYPT)
if (HAVE_OPENSSL_EC_H AND HAVE_OPENSSL_ECDSA_H) if (HAVE_OPENSSL_EC_H AND HAVE_OPENSSL_ECDSA_H)
set(HAVE_OPENSSL_ECC 1) set(HAVE_OPENSSL_ECC 1)
endif (HAVE_OPENSSL_EC_H AND HAVE_OPENSSL_ECDSA_H) endif (HAVE_OPENSSL_EC_H AND HAVE_OPENSSL_ECDSA_H)
@@ -163,46 +95,22 @@ if (NOT WITH_GCRYPT AND NOT WITH_MBEDTLS)
if (HAVE_OPENSSL_ECC) if (HAVE_OPENSSL_ECC)
set(HAVE_ECC 1) set(HAVE_ECC 1)
endif (HAVE_OPENSSL_ECC) endif (HAVE_OPENSSL_ECC)
endif (NOT WITH_GCRYPT)
if (HAVE_OPENSSL_EVP_KDF_CTX_NEW_ID OR HAVE_OPENSSL_EVP_KDF_CTX_NEW)
set(HAVE_OPENSSL_EVP_KDF_CTX 1)
endif (HAVE_OPENSSL_EVP_KDF_CTX_NEW_ID OR HAVE_OPENSSL_EVP_KDF_CTX_NEW)
endif ()
if (WITH_DSA)
if (NOT WITH_MBEDTLS)
set(HAVE_DSA 1)
endif (NOT WITH_MBEDTLS)
endif()
# FUNCTIONS # FUNCTIONS
check_function_exists(isblank HAVE_ISBLANK) check_function_exists(isblank HAVE_ISBLANK)
check_function_exists(strncpy HAVE_STRNCPY) check_function_exists(strncpy HAVE_STRNCPY)
check_function_exists(strndup HAVE_STRNDUP) check_function_exists(vsnprintf HAVE_VSNPRINTF)
check_function_exists(strtoull HAVE_STRTOULL) check_function_exists(snprintf HAVE_SNPRINTF)
check_function_exists(explicit_bzero HAVE_EXPLICIT_BZERO)
check_function_exists(memset_s HAVE_MEMSET_S)
if (HAVE_GLOB_H)
check_struct_has_member(glob_t gl_flags glob.h HAVE_GLOB_GL_FLAGS_MEMBER)
check_function_exists(glob HAVE_GLOB)
endif (HAVE_GLOB_H)
if (NOT WIN32)
check_function_exists(vsnprintf HAVE_VSNPRINTF)
check_function_exists(snprintf HAVE_SNPRINTF)
endif (NOT WIN32)
if (WIN32) if (WIN32)
check_symbol_exists(vsnprintf "stdio.h" HAVE_VSNPRINTF) check_function_exists(_strtoui64 HAVE__STRTOUI64)
check_symbol_exists(snprintf "stdio.h" HAVE_SNPRINTF)
check_symbol_exists(_vsnprintf_s "stdio.h" HAVE__VSNPRINTF_S) check_function_exists(_vsnprintf_s HAVE__VSNPRINTF_S)
check_symbol_exists(_vsnprintf "stdio.h" HAVE__VSNPRINTF) check_function_exists(_vsnprintf HAVE__VSNPRINTF)
check_symbol_exists(_snprintf "stdio.h" HAVE__SNPRINTF) check_function_exists(_snprintf HAVE__SNPRINTF)
check_symbol_exists(_snprintf_s "stdio.h" HAVE__SNPRINTF_S) check_function_exists(_snprintf_s HAVE__SNPRINTF_S)
if (HAVE_WSPIAPI_H OR HAVE_WS2TCPIP_H) if (HAVE_WSPIAPI_H OR HAVE_WS2TCPIP_H)
check_symbol_exists(ntohll winsock2.h HAVE_NTOHLL) check_symbol_exists(ntohll winsock2.h HAVE_NTOHLL)
@@ -213,14 +121,10 @@ if (WIN32)
check_symbol_exists(poll "winsock2.h;ws2tcpip.h" HAVE_SELECT) check_symbol_exists(poll "winsock2.h;ws2tcpip.h" HAVE_SELECT)
# The getaddrinfo function is defined to the WspiapiGetAddrInfo inline function # The getaddrinfo function is defined to the WspiapiGetAddrInfo inline function
check_symbol_exists(getaddrinfo "winsock2.h;ws2tcpip.h" HAVE_GETADDRINFO) check_symbol_exists(getaddrinfo "winsock2.h;ws2tcpip.h" HAVE_GETADDRINFO)
unset(CMAKE_REQUIRED_LIBRARIES) set(CMAKE_REQUIRED_LIBRARIES)
endif (HAVE_WSPIAPI_H OR HAVE_WS2TCPIP_H) endif (HAVE_WSPIAPI_H OR HAVE_WS2TCPIP_H)
check_function_exists(_strtoui64 HAVE__STRTOUI64)
set(HAVE_SELECT TRUE) set(HAVE_SELECT TRUE)
check_symbol_exists(SecureZeroMemory "windows.h" HAVE_SECURE_ZERO_MEMORY)
else (WIN32) else (WIN32)
check_function_exists(poll HAVE_POLL) check_function_exists(poll HAVE_POLL)
check_function_exists(select HAVE_SELECT) check_function_exists(select HAVE_SELECT)
@@ -237,13 +141,13 @@ if (UNIX)
check_library_exists(socket getaddrinfo "" HAVE_LIBSOCKET) check_library_exists(socket getaddrinfo "" HAVE_LIBSOCKET)
if (HAVE_LIBSOCKET) if (HAVE_LIBSOCKET)
set(HAVE_GETADDRINFO TRUE) set(HAVE_GETADDRINFO TRUE)
set(_REQUIRED_LIBRARIES ${_REQUIRED_LIBRARIES} socket) set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} socket)
endif (HAVE_LIBSOCKET) endif (HAVE_LIBSOCKET)
# libnsl/inet_pton (Solaris) # libnsl/inet_pton (Solaris)
check_library_exists(nsl inet_pton "" HAVE_LIBNSL) check_library_exists(nsl inet_pton "" HAVE_LIBNSL)
if (HAVE_LIBNSL) if (HAVE_LIBNSL)
set(_REQUIRED_LIBRARIES ${_REQUIRED_LIBRARIES} nsl) set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} nsl)
endif (HAVE_LIBNSL) endif (HAVE_LIBNSL)
# librt # librt
@@ -252,15 +156,16 @@ if (UNIX)
check_library_exists(rt clock_gettime "" HAVE_CLOCK_GETTIME) check_library_exists(rt clock_gettime "" HAVE_CLOCK_GETTIME)
if (HAVE_LIBRT OR HAVE_CLOCK_GETTIME) if (HAVE_LIBRT OR HAVE_CLOCK_GETTIME)
set(_REQUIRED_LIBRARIES ${_REQUIRED_LIBRARIES} rt) set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} rt)
endif (HAVE_LIBRT OR HAVE_CLOCK_GETTIME) endif (HAVE_LIBRT OR HAVE_CLOCK_GETTIME)
check_library_exists(util forkpty "" HAVE_LIBUTIL) check_library_exists(util forkpty "" HAVE_LIBUTIL)
check_function_exists(cfmakeraw HAVE_CFMAKERAW) check_function_exists(cfmakeraw HAVE_CFMAKERAW)
check_function_exists(strtoull HAVE_STRTOULL)
check_function_exists(__strtoull HAVE___STRTOULL) check_function_exists(__strtoull HAVE___STRTOULL)
endif (UNIX) endif (UNIX)
set(LIBSSH_REQUIRED_LIBRARIES ${_REQUIRED_LIBRARIES} CACHE INTERNAL "libssh required system libraries") set(LIBSSH_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} CACHE INTERNAL "libssh required system libraries")
# LIBRARIES # LIBRARIES
if (OPENSSL_FOUND) if (OPENSSL_FOUND)
@@ -270,37 +175,15 @@ endif (OPENSSL_FOUND)
if (GCRYPT_FOUND) if (GCRYPT_FOUND)
set(HAVE_LIBGCRYPT 1) set(HAVE_LIBGCRYPT 1)
if (GCRYPT_VERSION VERSION_GREATER "1.4.6") if (GCRYPT_VERSION VERSION_GREATER "1.4.6")
set(HAVE_GCRYPT_ECC 1) #set(HAVE_GCRYPT_ECC 1)
set(HAVE_ECC 1) #set(HAVE_ECC 1)
endif (GCRYPT_VERSION VERSION_GREATER "1.4.6") endif (GCRYPT_VERSION VERSION_GREATER "1.4.6")
if (NOT GCRYPT_VERSION VERSION_LESS "1.7.0")
set(HAVE_GCRYPT_CHACHA_POLY 1)
endif (NOT GCRYPT_VERSION VERSION_LESS "1.7.0")
endif (GCRYPT_FOUND) endif (GCRYPT_FOUND)
if (MBEDTLS_FOUND)
set(HAVE_LIBMBEDCRYPTO 1)
set(HAVE_ECC 1)
set(CMAKE_REQUIRED_INCLUDES "${MBEDTLS_INCLUDE_DIR}/mbedtls")
check_include_file(chacha20.h HAVE_MBEDTLS_CHACHA20_H)
check_include_file(poly1305.h HAVE_MBEDTLS_POLY1305_H)
unset(CMAKE_REQUIRED_INCLUDES)
endif (MBEDTLS_FOUND)
if (CMAKE_USE_PTHREADS_INIT) if (CMAKE_USE_PTHREADS_INIT)
set(HAVE_PTHREAD 1) set(HAVE_PTHREAD 1)
endif (CMAKE_USE_PTHREADS_INIT) endif (CMAKE_USE_PTHREADS_INIT)
if (UNIT_TESTING)
if (CMOCKA_FOUND)
set(CMAKE_REQUIRED_LIBRARIES ${CMOCKA_LIBRARIES})
check_function_exists(cmocka_set_test_filter HAVE_CMOCKA_SET_TEST_FILTER)
unset(CMAKE_REQUIRED_LIBRARIES)
endif ()
endif ()
# OPTIONS # OPTIONS
check_c_source_compiles(" check_c_source_compiles("
__thread int tls; __thread int tls;
@@ -316,104 +199,6 @@ int main(void) {
return 0; return 0;
}" HAVE_MSC_THREAD_LOCAL_STORAGE) }" HAVE_MSC_THREAD_LOCAL_STORAGE)
###########################################################
# For detecting attributes we need to treat warnings as
# errors
if (UNIX OR MINGW)
# Get warnings for attributs
check_c_compiler_flag("-Wattributes" REQUIRED_FLAGS_WERROR)
if (REQUIRED_FLAGS_WERROR)
string(APPEND CMAKE_REQUIRED_FLAGS "-Wattributes ")
endif()
# Turn warnings into errors
check_c_compiler_flag("-Werror" REQUIRED_FLAGS_WERROR)
if (REQUIRED_FLAGS_WERROR)
string(APPEND CMAKE_REQUIRED_FLAGS "-Werror ")
endif()
endif ()
check_c_source_compiles("
void test_constructor_attribute(void) __attribute__ ((constructor));
void test_constructor_attribute(void)
{
return;
}
int main(void) {
return 0;
}" HAVE_CONSTRUCTOR_ATTRIBUTE)
check_c_source_compiles("
void test_destructor_attribute(void) __attribute__ ((destructor));
void test_destructor_attribute(void)
{
return;
}
int main(void) {
return 0;
}" HAVE_DESTRUCTOR_ATTRIBUTE)
check_c_source_compiles("
#define FALL_THROUGH __attribute__((fallthrough))
int main(void) {
int i = 2;
switch (i) {
case 0:
FALL_THROUGH;
case 1:
break;
default:
break;
}
return 0;
}" HAVE_FALLTHROUGH_ATTRIBUTE)
check_c_source_compiles("
#define WEAK __attribute__((weak))
WEAK int sum(int a, int b)
{
return a + b;
}
int main(void)
{
int i = sum(2, 2);
(void)i;
return 0;
}" HAVE_WEAK_ATTRIBUTE)
if (NOT WIN32)
check_c_source_compiles("
#define __unused __attribute__((unused))
static int do_nothing(int i __unused)
{
return 0;
}
int main(void)
{
int i;
i = do_nothing(5);
if (i > 5) {
return 1;
}
return 0;
}" HAVE_UNUSED_ATTRIBUTE)
endif()
check_c_source_compiles(" check_c_source_compiles("
#include <string.h> #include <string.h>
@@ -421,11 +206,23 @@ int main(void)
{ {
char buf[] = \"This is some content\"; char buf[] = \"This is some content\";
memset(buf, '\\\\0', sizeof(buf)); __asm__ volatile(\"\" : : \"g\"(&buf) : \"memory\"); memset(buf, '\\\\0', sizeof(buf)); __asm__ volatile(\"\" : : \"r\"(&buf) : \"memory\");
return 0; return 0;
}" HAVE_GCC_VOLATILE_MEMORY_PROTECTION) }" HAVE_GCC_VOLATILE_MEMORY_PROTECTION)
check_c_source_compiles("
#include <stdio.h>
#define __VA_NARG__(...) (__VA_NARG_(_0, ## __VA_ARGS__, __RSEQ_N()) - 1)
#define __VA_NARG_(...) __VA_ARG_N(__VA_ARGS__)
#define __VA_ARG_N( _1, _2, _3, _4, _5, _6, _7, _8, _9,_10,N,...) N
#define __RSEQ_N() 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
#define myprintf(format, ...) printf((format), __VA_NARG__(__VA_ARGS__), __VA_ARGS__)
int main(void) {
myprintf(\"%d %d %d %d\",1,2,3);
return 0;
}" HAVE_GCC_NARG_MACRO)
check_c_source_compiles(" check_c_source_compiles("
#include <stdio.h> #include <stdio.h>
int main(void) { int main(void) {
@@ -440,43 +237,11 @@ int main(void) {
return 0; return 0;
}" HAVE_COMPILER__FUNCTION__) }" HAVE_COMPILER__FUNCTION__)
# This is only available with OpenBSD's gcc implementation */
if (OPENBSD)
check_c_source_compiles("
#define ARRAY_LEN 16
void test_attr(const unsigned char *k)
__attribute__((__bounded__(__minbytes__, 2, 16)));
int main(void) {
return 0;
}" HAVE_GCC_BOUNDED_ATTRIBUTE)
endif(OPENBSD)
# Stop treating warnings as errors
unset(CMAKE_REQUIRED_FLAGS)
# Check for version script support
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/conftest.map" "VERS_1 {
global: sym;
};
VERS_2 {
global: sym;
} VERS_1;
")
set(CMAKE_REQUIRED_FLAGS "-Wl,--version-script=\"${CMAKE_CURRENT_BINARY_DIR}/conftest.map\"")
check_c_source_compiles("int main(void) { return 0; }" HAVE_LD_VERSION_SCRIPT)
unset(CMAKE_REQUIRED_FLAGS)
file(REMOVE "${CMAKE_CURRENT_BINARY_DIR}/conftest.map")
if (WITH_DEBUG_CRYPTO) if (WITH_DEBUG_CRYPTO)
set(DEBUG_CRYPTO 1) set(DEBUG_CRYPTO 1)
endif (WITH_DEBUG_CRYPTO) endif (WITH_DEBUG_CRYPTO)
if (WITH_DEBUG_PACKET)
set(DEBUG_PACKET 1)
endif (WITH_DEBUG_PACKET)
if (WITH_DEBUG_CALLTRACE) if (WITH_DEBUG_CALLTRACE)
set(DEBUG_CALLTRACE 1) set(DEBUG_CALLTRACE 1)
endif (WITH_DEBUG_CALLTRACE) endif (WITH_DEBUG_CALLTRACE)
@@ -485,28 +250,6 @@ if (WITH_GSSAPI AND NOT GSSAPI_FOUND)
set(WITH_GSSAPI 0) set(WITH_GSSAPI 0)
endif (WITH_GSSAPI AND NOT GSSAPI_FOUND) endif (WITH_GSSAPI AND NOT GSSAPI_FOUND)
if (WITH_PKCS11_URI)
if (WITH_GCRYPT)
message(FATAL_ERROR "PKCS #11 is not supported for gcrypt.")
set(WITH_PKCS11_URI 0)
endif()
if (WITH_MBEDTLS)
message(FATAL_ERROR "PKCS #11 is not supported for mbedcrypto")
set(WITH_PKCS11_URI 0)
endif()
if (HAVE_OPENSSL AND NOT OPENSSL_VERSION VERSION_GREATER_EQUAL "1.1.1")
message(FATAL_ERROR "PKCS #11 requires at least OpenSSL 1.1.1")
set(WITH_PKCS11_URI 0)
endif()
endif()
if (WITH_MBEDTLS)
if (WITH_DSA)
message(FATAL_ERROR "DSA is not supported with mbedTLS crypto")
set(HAVE_DSA 0)
endif()
endif()
# ENDIAN # ENDIAN
if (NOT WIN32) if (NOT WIN32)
test_big_endian(WORDS_BIGENDIAN) test_big_endian(WORDS_BIGENDIAN)

View File

@@ -1,62 +1,33 @@
option(WITH_GSSAPI "Build with GSSAPI support" ON) option(WITH_GSSAPI "Build with GSSAPI support" ON)
option(WITH_ZLIB "Build with ZLIB support" ON) option(WITH_ZLIB "Build with ZLIB support" ON)
option(WITH_SSH1 "Build with SSH1 support" OFF)
option(WITH_SFTP "Build with SFTP support" ON) option(WITH_SFTP "Build with SFTP support" ON)
option(WITH_SERVER "Build with SSH server support" ON) option(WITH_SERVER "Build with SSH server support" ON)
option(WITH_STATIC_LIB "Build with a static library" OFF)
option(WITH_DEBUG_CRYPTO "Build with cryto debug output" OFF) option(WITH_DEBUG_CRYPTO "Build with cryto debug output" OFF)
option(WITH_DEBUG_PACKET "Build with packet debug output" OFF)
option(WITH_DEBUG_CALLTRACE "Build with calltrace debug output" ON) option(WITH_DEBUG_CALLTRACE "Build with calltrace debug output" ON)
option(WITH_DSA "Build with DSA" OFF)
option(WITH_GCRYPT "Compile against libgcrypt" OFF) option(WITH_GCRYPT "Compile against libgcrypt" OFF)
option(WITH_MBEDTLS "Compile against libmbedtls" OFF)
option(WITH_BLOWFISH_CIPHER "Compile with blowfish support" OFF)
option(WITH_PCAP "Compile with Pcap generation support" ON) option(WITH_PCAP "Compile with Pcap generation support" ON)
option(WITH_INTERNAL_DOC "Compile doxygen internal documentation" OFF) option(WITH_INTERNAL_DOC "Compile doxygen internal documentation" OFF)
option(BUILD_SHARED_LIBS "Build shared libraries" ON) option(WITH_TESTING "Build with unit tests" OFF)
option(WITH_PKCS11_URI "Build with PKCS#11 URI support" OFF) option(WITH_CLIENT_TESTING "Build with client tests; requires a running sshd" OFF)
option(UNIT_TESTING "Build with unit tests" OFF)
option(CLIENT_TESTING "Build with client tests; requires openssh" OFF)
option(SERVER_TESTING "Build with server tests; requires openssh and dropbear" OFF)
option(WITH_BENCHMARKS "Build benchmarks tools" OFF) option(WITH_BENCHMARKS "Build benchmarks tools" OFF)
option(WITH_EXAMPLES "Build examples" ON) option(WITH_EXAMPLES "Build examples" ON)
option(WITH_NACL "Build with libnacl (curve25519)" ON) option(WITH_NACL "Build with libnacl (curve25519" ON)
option(WITH_SYMBOL_VERSIONING "Build with symbol versioning" ON)
option(WITH_ABI_BREAK "Allow ABI break" OFF)
option(WITH_GEX "Enable DH Group exchange mechanisms" ON)
option(WITH_INSECURE_NONE "Enable insecure none cipher and MAC algorithms (not suitable for production!)" OFF)
option(FUZZ_TESTING "Build with fuzzer for the server and client (automatically enables none cipher!)" OFF)
option(PICKY_DEVELOPER "Build with picky developer flags" OFF)
if (WITH_ZLIB) if (WITH_ZLIB)
set(WITH_LIBZ ON) set(WITH_LIBZ ON)
else (WITH_ZLIB) else (WITH_ZLIB)
set(WITH_LIBZ OFF) set(WITH_LIBZ OFF)
endif (WITH_ZLIB) endif (WITH_ZLIB)
if (WITH_BENCHMARKS) if(WITH_BENCHMARKS)
set(UNIT_TESTING ON) set(WITH_TESTING ON)
set(CLIENT_TESTING ON) endif(WITH_BENCHMARKS)
endif()
if (UNIT_TESTING OR CLIENT_TESTING OR SERVER_TESTING) if (WITH_TESTING)
set(BUILD_STATIC_LIB ON) set(WITH_STATIC_LIB ON)
endif() endif (WITH_TESTING)
if (WITH_NACL) if (WITH_NACL)
set(WITH_NACL ON) set(WITH_NACL ON)
endif (WITH_NACL) endif (WITH_NACL)
if (WITH_ABI_BREAK)
set(WITH_SYMBOL_VERSIONING ON)
endif (WITH_ABI_BREAK)
if (NOT GLOBAL_BIND_CONFIG)
set(GLOBAL_BIND_CONFIG "/etc/ssh/libssh_server_config")
endif (NOT GLOBAL_BIND_CONFIG)
if (NOT GLOBAL_CLIENT_CONFIG)
set(GLOBAL_CLIENT_CONFIG "/etc/ssh/ssh_config")
endif (NOT GLOBAL_CLIENT_CONFIG)
if (FUZZ_TESTING)
set(WITH_INSECURE_NONE ON)
endif (FUZZ_TESTING)

39
INSTALL
View File

@@ -7,28 +7,23 @@
In order to build libssh, you need to install several components: In order to build libssh, you need to install several components:
- A C compiler - A C compiler
- [CMake](https://www.cmake.org) >= 3.3.0 - [CMake](http://www.cmake.org) >= 2.6.0.
- [openssl](https://www.openssl.org) >= 1.0.1 - [openssl](http://www.openssl.org) >= 0.9.8
or or
- [gcrypt](https://www.gnu.org/directory/Security/libgcrypt.html) >= 1.4 - [gcrypt](http://www.gnu.org/directory/Security/libgcrypt.html) >= 1.4
- [libz](https://www.zlib.net) >= 1.2
optional: optional:
- [cmocka](https://cmocka.org/) >= 1.1.0 - [libz](http://www.zlib.net) >= 1.2
- [socket_wrapper](https://cwrap.org/) >= 1.1.5
- [nss_wrapper](https://cwrap.org/) >= 1.1.2
- [uid_wrapper](https://cwrap.org/) >= 1.2.0
- [pam_wrapper](https://cwrap.org/) >= 1.0.1
Note that these version numbers are version we know works correctly. If you Note that these version numbers are version we know works correctly. If you
build and run libssh successfully with an older version, please let us know. build and run libssh successfully with an older version, please let us know.
For Windows use vcpkg: Windows binaries known to be working:
https://github.com/Microsoft/vcpkg - http://www.slproweb.com/products/Win32OpenSSL.html
- http://zlib.net/ -> zlib compiled DLL
which you can use to install openssl and zlib. libssh itself is also part of We installed them in C:\Program Files
vcpkg!
## Building ## Building
First, you need to configure the compilation, using CMake. Go inside the First, you need to configure the compilation, using CMake. Go inside the
@@ -36,27 +31,13 @@ First, you need to configure the compilation, using CMake. Go inside the
GNU/Linux, MacOS X, MSYS/MinGW: GNU/Linux, MacOS X, MSYS/MinGW:
cmake -DUNIT_TESTING=ON -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Debug .. cmake -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Debug ..
make make
On Windows you should choose a makefile gernerator with -G or use On Windows you should choose a makefile gernerator with -G or use
cmake-gui.exe .. cmake-gui.exe ..
To enable additional client tests against a local OpenSSH server, add the
compile option -DCLIENT_TESTING=ON. These tests require an OpenSSH
server package and some wrapper libraries (see optional requirements) to
be installed.
If you're interested in server testing, then a OpenSSH client should be
installed on the system and if possible also dropbear. Once that is done
enable server support with -DWITH_SERVER=ON and enable testing of it with
-DSERVER_TESTING=ON.
## Testing build
make test
### CMake standard options ### CMake standard options
Here is a list of the most interesting options provided out of the box by Here is a list of the most interesting options provided out of the box by
CMake. CMake.
@@ -117,4 +98,4 @@ This document is written using [Markdown][] syntax, making it possible to
provide usable information in both plain text and HTML format. Whenever provide usable information in both plain text and HTML format. Whenever
modifying this document please use [Markdown][] syntax. modifying this document please use [Markdown][] syntax.
[markdown]: https://www.daringfireball.net/projects/markdown [markdown]: http://www.daringfireball.net/projects/markdown

127
README
View File

@@ -31,13 +31,132 @@ If you ask yourself how to compile libssh, please read INSTALL before anything.
3* Where ? 3* Where ?
-_-_-_-_-_-_ -_-_-_-_-_-_
https://www.libssh.org http://www.libssh.org
4* Contributing 4* API Changes !
-_-_-_-_-_-_-_-_-_ -_-_-_-_-_-_-_-_-_
Please read the file 'CONTRIBUTING.md' next to this README file. It explains Changes between 0.4 and 0.5
our copyright policy and how you should send patches for upstream inclusion. ---------------------------
We use the ssh_ prefix as namespace for every function now. There is a legacy.h
which could be used to get the old function names.
Changes between 0.3 and 0.4
---------------------------
We changed libssh to be typesafe now:
SSH_SESSION *session -> ssh_session session
SFTP_SESSION *sftp -> sftp_session sftp
CHANNEL *channel -> ssh_channel channel
STRING *string -> ssh_string string
...
The options structure has been removed and there is a new function. This
function can set all available options now. You can find the enum in the
header file and it is documented. Example:
ssh_options_set(session, SSH_OPTIONS_HOST, "localhost");
5* Copyright policy
-_-_-_-_-_-_-_-_-_-_
libssh is a project with distributed copyright ownership, which means we prefer
the copyright on parts of libssh to be held by individuals rather than
corporations if possible. There are historical legal reasons for this, but one
of the best ways to explain it is that its much easier to work with
individuals who have ownership than corporate legal departments if we ever need
to make reasonable compromises with people using and working with libssh.
We track the ownership of every part of libssh via git, our source code control
system, so we know the provenance of every piece of code that is committed to
libssh.
So if possible, if youre doing libssh changes on behalf of a company who
normally owns all the work you do please get them to assign personal copyright
ownership of your changes to you as an individual, that makes things very easy
for us to work with and avoids bringing corporate legal departments into the
picture.
If you cant do this we can still accept patches from you owned by your
employer under a standard employment contract with corporate copyright
ownership. It just requires a simple set-up process first.
We use a process very similar to the way things are done in the Linux Kernel
community, so it should be very easy to get a sign off from your corporate
legal department. The only changes weve made are to accommodate the license we
use, which is LGPLv2 (or later) whereas the Linux kernel uses GPLv2.
The process is called signing.
How to sign your work
----------------------
Once you have permission to contribute to libssh from your employer, simply
email a copy of the following text from your corporate email address to:
contributing@libssh.org
--------------------------------------------------------------------------
libssh Developer's Certificate of Origin. Version 1.0
By making a contribution to this project, I certify that:
(a) The contribution was created in whole or in part by me and I
have the right to submit it under the appropriate
version of the GNU General Public License; or
(b) The contribution is based upon previous work that, to the best of
my knowledge, is covered under an appropriate open source license
and I have the right under that license to submit that work with
modifications, whether created in whole or in part by me, under
the GNU General Public License, in the appropriate version; or
(c) The contribution was provided directly to me by some other
person who certified (a) or (b) and I have not modified it.
(d) I understand and agree that this project and the contribution are
public and that a record of the contribution (including all
metadata and personal information I submit with it, including my
sign-off) is maintained indefinitely and may be redistributed
consistent with the libssh Team's policies and the requirements of
the GNU GPL where they are relevant.
(e) I am granting this work to this project under the terms of the
GNU Lesser General Public License as published by the
Free Software Foundation; either version 2.1 of
the License, or (at the option of the project) any later version.
http://www.gnu.org/licenses/lgpl-2.1.html
--------------------------------------------------------------------------
We will maintain a copy of that email as a record that you have the rights to
contribute code to libssh under the required licenses whilst working for the
company where the email came from.
Then when sending in a patch via the normal mechanisms described above, add a
line that states:
Signed-off-by: Random J Developer <random@developer.example.org>
using your real name and the email address you sent the original email you used
to send the libssh Developers Certificate of Origin to us (sorry, no
pseudonyms or anonymous contributions.)
Thats it! Such code can then quite happily contain changes that have copyright
messages such as:
(c) Example Corporation.
and can be merged into the libssh codebase in the same way as patches from any
other individual. You dont need to send in a copy of the libssh Developers
Certificate of Origin for each patch, or inside each patch. Just the sign-off
message is all that is required once weve received the initial email.
Have fun and happy libssh hacking! Have fun and happy libssh hacking!

View File

@@ -1,126 +1,9 @@
# How to contribute a patch to libssh Coding conventions in the libssh tree
======================================
Please checkout the libssh source code using git. ===========
Quick Start
For contributions we prefer Merge Requests on Gitlab: ===========
https://gitlab.com/libssh/libssh-mirror/
This way you get continuous integration which runs the complete libssh
testsuite for you.
For larger code changes, breaking the changes up into a set of simple
patches, each of which does a single thing, are much easier to review.
Patch sets like that will most likely have an easier time being merged
into the libssh code than large single patches that make lots of
changes in one large diff.
Also bugfixes and new features should be covered by tests. We use the cmocka
and cwrap framework for our testing and you can simply run it locally by
calling `make test`.
## Ownership of the contributed code
libssh is a project with distributed copyright ownership, which means
we prefer the copyright on parts of libssh to be held by individuals
rather than corporations if possible. There are historical legal
reasons for this, but one of the best ways to explain it is that it's
much easier to work with individuals who have ownership than corporate
legal departments if we ever need to make reasonable compromises with
people using and working with libssh.
We track the ownership of every part of libssh via https://git.libssh.org,
our source code control system, so we know the provenance of every piece
of code that is committed to libssh.
So if possible, if you're doing libssh changes on behalf of a company
who normally owns all the work you do please get them to assign
personal copyright ownership of your changes to you as an individual,
that makes things very easy for us to work with and avoids bringing
corporate legal departments into the picture.
If you can't do this we can still accept patches from you owned by
your employer under a standard employment contract with corporate
copyright ownership. It just requires a simple set-up process first.
We use a process very similar to the way things are done in the Linux
Kernel community, so it should be very easy to get a sign off from
your corporate legal department. The only changes we've made are to
accommodate the license we use, which is LGPLv2 (or later) whereas the
Linux kernel uses GPLv2.
The process is called signing.
## How to sign your work
Once you have permission to contribute to libssh from your employer, simply
email a copy of the following text from your corporate email address to:
contributing@libssh.org
```
libssh Developer's Certificate of Origin. Version 1.0
By making a contribution to this project, I certify that:
(a) The contribution was created in whole or in part by me and I
have the right to submit it under the appropriate
version of the GNU General Public License; or
(b) The contribution is based upon previous work that, to the best of
my knowledge, is covered under an appropriate open source license
and I have the right under that license to submit that work with
modifications, whether created in whole or in part by me, under
the GNU General Public License, in the appropriate version; or
(c) The contribution was provided directly to me by some other
person who certified (a) or (b) and I have not modified it.
(d) I understand and agree that this project and the contribution are
public and that a record of the contribution (including all
metadata and personal information I submit with it, including my
sign-off) is maintained indefinitely and may be redistributed
consistent with the libssh Team's policies and the requirements of
the GNU GPL where they are relevant.
(e) I am granting this work to this project under the terms of the
GNU Lesser General Public License as published by the
Free Software Foundation; either version 2.1 of
the License, or (at the option of the project) any later version.
https://www.gnu.org/licenses/lgpl-2.1.html
```
We will maintain a copy of that email as a record that you have the
rights to contribute code to libssh under the required licenses whilst
working for the company where the email came from.
Then when sending in a patch via the normal mechanisms described
above, add a line that states:
Signed-off-by: Random J Developer <random@developer.example.org>
using your real name and the email address you sent the original email
you used to send the libssh Developer's Certificate of Origin to us
(sorry, no pseudonyms or anonymous contributions.)
That's it! Such code can then quite happily contain changes that have
copyright messages such as:
(c) Example Corporation.
and can be merged into the libssh codebase in the same way as patches
from any other individual. You don't need to send in a copy of the
libssh Developer's Certificate of Origin for each patch, or inside each
patch. Just the sign-off message is all that is required once we've
received the initial email.
# Coding conventions in the libssh tree
## Quick Start
Coding style guidelines are about reducing the number of unnecessary Coding style guidelines are about reducing the number of unnecessary
reformatting patches and making things easier for developers to work together. reformatting patches and making things easier for developers to work together.
@@ -153,28 +36,31 @@ are the highlights.
have a copy of "The C Programming Language" anyways right? have a copy of "The C Programming Language" anyways right?
## Editor Hints =============
Editor Hints
### Emacs =============
Emacs
------
Add the follow to your $HOME/.emacs file: Add the follow to your $HOME/.emacs file:
(add-hook 'c-mode-hook (add-hook 'c-mode-hook
(lambda () (lambda ()
(c-set-style "linux") (c-set-style "linux")
(c-toggle-auto-state))) (c-toggle-auto-state)))
## Neovim/VIM Vim
----
For the basic vi editor included with all variants of \*nix, add the For the basic vi editor included with all variants of \*nix, add the
following to ~/.config/nvim/init.rc or ~/.vimrc: following to $HOME/.vimrc:
set ts=4 sw=4 et cindent set ts=4 sw=4 et cindent
You can use the Vim gitmodline plugin to store this in the git config: You can use the Vim gitmodline plugin to store this in the git config:
https://git.cryptomilk.org/projects/vim-gitmodeline.git/ http://git.cryptomilk.org/projects/vim-gitmodeline.git/
For Vim, the following settings in $HOME/.vimrc will also deal with For Vim, the following settings in $HOME/.vimrc will also deal with
displaying trailing whitespace: displaying trailing whitespace:
@@ -195,9 +81,12 @@ displaying trailing whitespace:
autocmd BufNewFile,BufRead *.c,*.h exec 'match Todo /\%>' . &textwidth . 'v.\+/' autocmd BufNewFile,BufRead *.c,*.h exec 'match Todo /\%>' . &textwidth . 'v.\+/'
## FAQ & Statement Reference ==========================
FAQ & Statement Reference
==========================
### Comments Comments
---------
Comments should always use the standard C syntax. C++ style comments are not Comments should always use the standard C syntax. C++ style comments are not
currently allowed. currently allowed.
@@ -274,7 +163,8 @@ This is bad:
* This is a multi line comment, * This is a multi line comment,
* with some more words...*/ * with some more words...*/
### Indention & Whitespace & 80 columns Indention & Whitespace & 80 columns
------------------------------------
To avoid confusion, indentations have to be 4 spaces. Do not use tabs!. When To avoid confusion, indentations have to be 4 spaces. Do not use tabs!. When
wrapping parameters for function calls, align the parameter list with the first wrapping parameters for function calls, align the parameter list with the first
@@ -290,7 +180,8 @@ splitting. Never split a line before columns 70 - 79 unless you
have a really good reason. Be smart about formatting. have a really good reason. Be smart about formatting.
### If, switch, & Code blocks If, switch, & Code blocks
--------------------------
Always follow an 'if' keyword with a space but don't include additional Always follow an 'if' keyword with a space but don't include additional
spaces following or preceding the parentheses in the conditional. spaces following or preceding the parentheses in the conditional.
@@ -316,7 +207,7 @@ invoking functions.
Braces for code blocks used by for, if, switch, while, do..while, etc. should Braces for code blocks used by for, if, switch, while, do..while, etc. should
begin on the same line as the statement keyword and end on a line of their own. begin on the same line as the statement keyword and end on a line of their own.
You should always include braces, even if the block only contains one You should always include braces, even if the block only contains one
statement. **NOTE**: Functions are different and the beginning left brace should statement. NOTE: Functions are different and the beginning left brace should
be located in the first column on the next line. be located in the first column on the next line.
If the beginning statement has to be broken across lines due to length, the If the beginning statement has to be broken across lines due to length, the
@@ -363,7 +254,8 @@ Bad examples:
print("I should be in braces.\n"); print("I should be in braces.\n");
### Goto Goto
-----
While many people have been academically taught that "goto"s are fundamentally While many people have been academically taught that "goto"s are fundamentally
evil, they can greatly enhance readability and reduce memory leaks when used as evil, they can greatly enhance readability and reduce memory leaks when used as
@@ -395,34 +287,16 @@ Good Examples:
return rc; return rc;
} }
### Initialize pointers
All pointer variables **MUST** be initialized to `NULL`. History has Typedefs
demonstrated that uninitialized pointer variables have lead to various ---------
bugs and security issues.
Pointers **MUST** be initialized even if the assignment directly follows libssh tries to avoid "typedef struct { .. } x_t;" so we do always try to use
the declaration, like pointer2 in the example below, because the "struct x { .. };". We know there are still such typedefs in the code, but for
instructions sequence may change over time.
Good Example:
char *pointer1 = NULL;
char *pointer2 = NULL;
pointer2 = some_func2();
...
pointer1 = some_func1();
### Typedefs
libssh tries to avoid `typedef struct { .. } x_t;` so we do always try to use
`struct x { .. };`. We know there are still such typedefs in the code, but for
new code, please don't do that anymore. new code, please don't do that anymore.
### Make use of helper variables Make use of helper variables
-----------------------------
Please try to avoid passing function calls as function parameters in new code. Please try to avoid passing function calls as function parameters in new code.
This makes the code much easier to read and it's also easier to use the "step" This makes the code much easier to read and it's also easier to use the "step"
@@ -472,13 +346,9 @@ an iterator style:
But in general, please try to avoid this pattern. But in general, please try to avoid this pattern.
### Control-Flow changing macros Control-Flow changing macros
-----------------------------
Macros like `STATUS_NOT_OK_RETURN` that change control flow (return/goto/etc) Macros like STATUS_NOT_OK_RETURN that change control flow (return/goto/etc)
from within the macro are considered bad, because they look like function calls from within the macro are considered bad, because they look like function calls
that never change control flow. Please do not introduce them. that never change control flow. Please do not introduce them.
Have fun and happy libssh hacking!
The libssh Team

View File

@@ -1,11 +0,0 @@
mbedTLS and libssh in multithreaded applications
==================================================
To use libssh with mbedTLS in a multithreaded application, mbedTLS has to be
built with threading support enabled.
If threading support is not available and multi threading is used, ssh_init
will fail.
More information about building mbedTLS with threading support can be found
in the mbedTLS documentation.

View File

@@ -1,45 +0,0 @@
[![pipeline status](https://gitlab.com/libssh/libssh-mirror/badges/master/pipeline.svg)](https://gitlab.com/libssh/libssh-mirror/commits/master)
[![Fuzzing Status](https://oss-fuzz-build-logs.storage.googleapis.com/badges/libssh.svg)](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:libssh)
```
_ _ _ _
(_) (_) (_) (_)
(_) _ (_) _ _ _ _ _ (_) _
(_) (_) (_)(_) _ (_)(_) (_)(_) (_)(_) _
(_) (_) (_) (_) _ (_) _ (_) (_) (_)
(_) (_) (_)(_)(_) (_)(_) (_)(_) (_) (_).org
The SSH library
```
# Why?
Why not ? :) I've began to work on my own implementation of the ssh protocol
because i didn't like the currently public ones.
Not any allowed you to import and use the functions as a powerful library,
and so i worked on a library-based SSH implementation which was non-existing
in the free and open source software world.
# How/Who?
If you downloaded this file, you must know what it is : a library for
accessing ssh client services through C libraries calls in a simple manner.
Everybody can use this software under the terms of the LGPL - see the COPYING
file
If you ask yourself how to compile libssh, please read INSTALL before anything.
# Where ?
https://www.libssh.org
# Contributing
Please read the file 'CONTRIBUTING.md' next to this README file. It explains
our copyright policy and how you should send patches for upstream inclusion.
Have fun and happy libssh hacking!
The libssh Team

118
SubmittingPatches Normal file
View File

@@ -0,0 +1,118 @@
How to contribute a patch to libssh
====================================
Simple, just make the code change, and email it as either a "diff -u"
change, or as a "git format-patch" change against the original source
code to libssh@libssh.org, or attach it to a bug report at
https://red.libssh.org/
For larger code changes, breaking the changes up into a set of simple
patches, each of which does a single thing, are much easier to review.
Patch sets like that will most likely have an easier time being merged
into the libssh code than large single patches that make lots of
changes in one large diff.
Ownership of the contributed code
==================================
libssh is a project with distributed copyright ownership, which means
we prefer the copyright on parts of libssh to be held by individuals
rather than corporations if possible. There are historical legal
reasons for this, but one of the best ways to explain it is that it's
much easier to work with individuals who have ownership than corporate
legal departments if we ever need to make reasonable compromises with
people using and working with libssh.
We track the ownership of every part of libssh via http://git.libssh.org,
our source code control system, so we know the provenance of every piece
of code that is committed to libssh.
So if possible, if you're doing libssh changes on behalf of a company
who normally owns all the work you do please get them to assign
personal copyright ownership of your changes to you as an individual,
that makes things very easy for us to work with and avoids bringing
corporate legal departments into the picture.
If you can't do this we can still accept patches from you owned by
your employer under a standard employment contract with corporate
copyright ownership. It just requires a simple set-up process first.
We use a process very similar to the way things are done in the Linux
Kernel community, so it should be very easy to get a sign off from
your corporate legal department. The only changes we've made are to
accommodate the license we use, which is LGPLv2 (or later) whereas the
Linux kernel uses GPLv2.
The process is called signing.
How to sign your work
----------------------
Once you have permission to contribute to libssh from your employer, simply
email a copy of the following text from your corporate email address to:
contributing@libssh.org
libssh Developer's Certificate of Origin. Version 1.0
By making a contribution to this project, I certify that:
(a) The contribution was created in whole or in part by me and I
have the right to submit it under the appropriate
version of the GNU General Public License; or
(b) The contribution is based upon previous work that, to the best of
my knowledge, is covered under an appropriate open source license
and I have the right under that license to submit that work with
modifications, whether created in whole or in part by me, under
the GNU General Public License, in the appropriate version; or
(c) The contribution was provided directly to me by some other
person who certified (a) or (b) and I have not modified it.
(d) I understand and agree that this project and the contribution are
public and that a record of the contribution (including all
metadata and personal information I submit with it, including my
sign-off) is maintained indefinitely and may be redistributed
consistent with the libssh Team's policies and the requirements of
the GNU GPL where they are relevant.
(e) I am granting this work to this project under the terms of the
GNU Lesser General Public License as published by the
Free Software Foundation; either version 2.1 of
the License, or (at the option of the project) any later version.
http://www.gnu.org/licenses/lgpl-2.1.html
We will maintain a copy of that email as a record that you have the
rights to contribute code to libssh under the required licenses whilst
working for the company where the email came from.
Then when sending in a patch via the normal mechanisms described
above, add a line that states:
Signed-off-by: Random J Developer <random@developer.example.org>
using your real name and the email address you sent the original email
you used to send the libssh Developer's Certificate of Origin to us
(sorry, no pseudonyms or anonymous contributions.)
That's it! Such code can then quite happily contain changes that have
copyright messages such as:
(c) Example Corporation.
and can be merged into the libssh codebase in the same way as patches
from any other individual. You don't need to send in a copy of the
libssh Developer's Certificate of Origin for each patch, or inside each
patch. Just the sign-off message is all that is required once we've
received the initial email.
Have fun and happy libssh hacking !
The libssh Team

View File

@@ -1,21 +0,0 @@
#
# add_c_compiler_flag("-Werror" SUPPORTED_CFLAGS)
#
# Copyright (c) 2018 Andreas Schneider <asn@cryptomilk.org>
#
# Redistribution and use is allowed according to the terms of the BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
include(CheckCCompilerFlag)
macro(add_c_compiler_flag _COMPILER_FLAG _OUTPUT_VARIABLE)
string(TOUPPER ${_COMPILER_FLAG} _COMPILER_FLAG_NAME)
string(REGEX REPLACE "^-" "" _COMPILER_FLAG_NAME "${_COMPILER_FLAG_NAME}")
string(REGEX REPLACE "(-|=|\ )" "_" _COMPILER_FLAG_NAME "${_COMPILER_FLAG_NAME}")
check_c_compiler_flag("${_COMPILER_FLAG}" WITH_${_COMPILER_FLAG_NAME}_FLAG)
if (WITH_${_COMPILER_FLAG_NAME}_FLAG)
#string(APPEND ${_OUTPUT_VARIABLE} "${_COMPILER_FLAG} ")
list(APPEND ${_OUTPUT_VARIABLE} ${_COMPILER_FLAG})
endif()
endmacro()

View File

@@ -1,120 +1,30 @@
# # - ADD_CHECK_TEST(test_name test_source linklib1 ... linklibN)
# Copyright (c) 2007 Daniel Gollub <dgollub@suse.de> # Copyright (c) 2007 Daniel Gollub <dgollub@suse.de>
# Copyright (c) 2007-2018 Andreas Schneider <asn@cryptomilk.org> # Copyright (c) 2007-2010 Andreas Schneider <asn@cryptomilk.org>
# Copyright (c) 2018 Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
# #
# Redistribution and use is allowed according to the terms of the BSD license. # Redistribution and use is allowed according to the terms of the BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file. # For details see the accompanying COPYING-CMAKE-SCRIPTS file.
#.rst:
# AddCMockaTest
# -------------
#
# This file provides a function to add a test
#
# Functions provided
# ------------------
#
# ::
#
# add_cmocka_test(target_name
# SOURCES src1 src2 ... srcN
# [COMPILE_OPTIONS opt1 opt2 ... optN]
# [LINK_LIBRARIES lib1 lib2 ... libN]
# [LINK_OPTIONS lopt1 lop2 .. loptN]
# )
#
# ``target_name``:
# Required, expects the name of the test which will be used to define a target
#
# ``SOURCES``:
# Required, expects one or more source files names
#
# ``COMPILE_OPTIONS``:
# Optional, expects one or more options to be passed to the compiler
#
# ``LINK_LIBRARIES``:
# Optional, expects one or more libraries to be linked with the test
# executable.
#
# ``LINK_OPTIONS``:
# Optional, expects one or more options to be passed to the linker
#
#
# Example:
#
# .. code-block:: cmake
#
# add_cmocka_test(my_test
# SOURCES my_test.c other_source.c
# COMPILE_OPTIONS -g -Wall
# LINK_LIBRARIES mylib
# LINK_OPTIONS -Wl,--enable-syscall-fixup
# )
#
# Where ``my_test`` is the name of the test, ``my_test.c`` and
# ``other_source.c`` are sources for the binary, ``-g -Wall`` are compiler
# options to be used, ``mylib`` is a target of a library to be linked, and
# ``-Wl,--enable-syscall-fixup`` is an option passed to the linker.
#
enable_testing() enable_testing()
include(CTest) include(CTest)
if (CMAKE_CROSSCOMPILING) if(CMAKE_COMPILER_IS_GNUCC AND NOT MINGW)
if (WIN32) # Profiling
find_program(WINE_EXECUTABLE set(CMAKE_C_FLAGS_PROFILING "-g -O0 -Wall -W -Wshadow -Wunused-variable -Wunused-parameter -Wunused-function -Wunused -Wno-system-headers -Wwrite-strings -fprofile-arcs -ftest-coverage" CACHE STRING "Profiling Compiler Flags")
NAMES wine) set(CMAKE_SHARED_LINKER_FLAGS_PROFILING " -fprofile-arcs -ftest-coverage" CACHE STRING "Profiling Linker Flags")
set(TARGET_SYSTEM_EMULATOR ${WINE_EXECUTABLE}) set(CMAKE_MODULE_LINKER_FLAGS_PROFILING " -fprofile-arcs -ftest-coverage" CACHE STRING "Profiling Linker Flags")
endif() set(CMAKE_EXEC_LINKER_FLAGS_PROFILING " -fprofile-arcs -ftest-coverage" CACHE STRING "Profiling Linker Flags")
endif()
function(ADD_CMOCKA_TEST _TARGET_NAME) # Address Sanitizer
set(CMAKE_C_FLAGS_ADDRESSSANITIZER "-g -O1 -fsanitize=address -fno-omit-frame-pointer" CACHE STRING "Address sanitizer compiler flags")
set(one_value_arguments set(CMAKE_SHARED_LINKER_FLAGS_ADDRESSSANITIZER "-fsanitize=address" CACHE STRING "Address sanitizer shared linker flags")
) set(CMAKE_MODULE_LINKER_FLAGS_ADDRESSSANITIZER "-fsanitize=address" CACHE STRING "Address sanitizer module linker flags")
set(CMAKE_EXEC_LINKER_FLAGS_ADDRESSSANITIZER "-fsanitize=address" CACHE STRING "Address sanitizer executable linker flags")
set(multi_value_arguments endif(CMAKE_COMPILER_IS_GNUCC AND NOT MINGW)
SOURCES
COMPILE_OPTIONS
LINK_LIBRARIES
LINK_OPTIONS
)
cmake_parse_arguments(_add_cmocka_test
""
"${one_value_arguments}"
"${multi_value_arguments}"
${ARGN}
)
if (NOT DEFINED _add_cmocka_test_SOURCES)
message(FATAL_ERROR "No sources provided for target ${_TARGET_NAME}")
endif()
add_executable(${_TARGET_NAME} ${_add_cmocka_test_SOURCES})
if (DEFINED _add_cmocka_test_COMPILE_OPTIONS)
target_compile_options(${_TARGET_NAME}
PRIVATE ${_add_cmocka_test_COMPILE_OPTIONS}
)
endif()
if (DEFINED _add_cmocka_test_LINK_LIBRARIES)
target_link_libraries(${_TARGET_NAME}
PRIVATE ${_add_cmocka_test_LINK_LIBRARIES}
)
endif()
if (DEFINED _add_cmocka_test_LINK_OPTIONS)
set_target_properties(${_TARGET_NAME}
PROPERTIES LINK_FLAGS
${_add_cmocka_test_LINK_OPTIONS}
)
endif()
add_test(${_TARGET_NAME}
${TARGET_SYSTEM_EMULATOR} ${_TARGET_NAME}
)
function (ADD_CMOCKA_TEST _testName _testSource)
add_executable(${_testName} ${_testSource})
target_link_libraries(${_testName} ${ARGN})
add_test(${_testName} ${CMAKE_CURRENT_BINARY_DIR}/${_testName})
endfunction (ADD_CMOCKA_TEST) endfunction (ADD_CMOCKA_TEST)

View File

@@ -15,15 +15,12 @@
# Redistribution and use is allowed according to the terms of the BSD license. # Redistribution and use is allowed according to the terms of the BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file. # For details see the accompanying COPYING-CMAKE-SCRIPTS file.
# Requires cmake 3.10
#include_guard(GLOBAL)
include(CheckCSourceCompiles) include(CheckCSourceCompiles)
macro(CHECK_C_COMPILER_FLAG_SSP _FLAG _RESULT) function(CHECK_C_COMPILER_FLAG_SSP _FLAG _RESULT)
set(SAFE_CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS}") set(SAFE_CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS}")
set(CMAKE_REQUIRED_FLAGS "${_FLAG}") set(CMAKE_REQUIRED_DEFINITIONS "${_FLAG}")
check_c_source_compiles("int main(int argc, char **argv) { char buffer[256]; return buffer[argc]=0;}" ${_RESULT}) check_c_source_compiles("int main(int argc, char **argv) { char buffer[256]; return buffer[argc]=0;}" ${_RESULT})
set(CMAKE_REQUIRED_DEFINITIONS "${SAFE_CMAKE_REQUIRED_DEFINITIONS}")
set(CMAKE_REQUIRED_FLAGS "${SAFE_CMAKE_REQUIRED_FLAGS}") endfunction(CHECK_C_COMPILER_FLAG_SSP)
endmacro(CHECK_C_COMPILER_FLAG_SSP)

View File

@@ -14,8 +14,17 @@ set(CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE ON)
# since cmake 2.4.0 # since cmake 2.4.0
set(CMAKE_COLOR_MAKEFILE ON) set(CMAKE_COLOR_MAKEFILE ON)
# Define the generic version of the libraries here
set(GENERIC_LIB_VERSION "0.1.0")
set(GENERIC_LIB_SOVERSION "0")
# Set the default build type to release with debug info
if (NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE RelWithDebInfo
CACHE STRING
"Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel."
)
endif (NOT CMAKE_BUILD_TYPE)
# Create the compile command database for clang by default # Create the compile command database for clang by default
set(CMAKE_EXPORT_COMPILE_COMMANDS ON) set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
# Always build with -fPIC
set(CMAKE_POSITION_INDEPENDENT_CODE ON)

View File

@@ -1,49 +1,84 @@
# define system dependent compiler flags
include(CheckCCompilerFlag)
include(CheckCCompilerFlagSSP)
if (UNIX AND NOT WIN32) if (UNIX AND NOT WIN32)
# Activate with: -DCMAKE_BUILD_TYPE=Profiling #
set(CMAKE_C_FLAGS_PROFILING "-O0 -g -fprofile-arcs -ftest-coverage" # Define GNUCC compiler flags
CACHE STRING "Flags used by the C compiler during PROFILING builds.") #
set(CMAKE_CXX_FLAGS_PROFILING "-O0 -g -fprofile-arcs -ftest-coverage" if (${CMAKE_C_COMPILER_ID} MATCHES "(GNU|Clang)")
CACHE STRING "Flags used by the CXX compiler during PROFILING builds.")
set(CMAKE_SHARED_LINKER_FLAGS_PROFILING "-fprofile-arcs -ftest-coverage"
CACHE STRING "Flags used by the linker during the creation of shared libraries during PROFILING builds.")
set(CMAKE_MODULE_LINKER_FLAGS_PROFILING "-fprofile-arcs -ftest-coverage"
CACHE STRING "Flags used by the linker during the creation of shared libraries during PROFILING builds.")
set(CMAKE_EXEC_LINKER_FLAGS_PROFILING "-fprofile-arcs -ftest-coverage"
CACHE STRING "Flags used by the linker during PROFILING builds.")
# Activate with: -DCMAKE_BUILD_TYPE=AddressSanitizer # add -Wconversion ?
set(CMAKE_C_FLAGS_ADDRESSSANITIZER "-g -O1 -fsanitize=address -fno-omit-frame-pointer" set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99 -pedantic -pedantic-errors")
CACHE STRING "Flags used by the C compiler during ADDRESSSANITIZER builds.") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wshadow -Wmissing-prototypes -Wdeclaration-after-statement")
set(CMAKE_CXX_FLAGS_ADDRESSSANITIZER "-g -O1 -fsanitize=address -fno-omit-frame-pointer" set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wunused -Wfloat-equal -Wpointer-arith -Wwrite-strings -Wformat-security")
CACHE STRING "Flags used by the CXX compiler during ADDRESSSANITIZER builds.") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wmissing-format-attribute")
set(CMAKE_SHARED_LINKER_FLAGS_ADDRESSSANITIZER "-fsanitize=address"
CACHE STRING "Flags used by the linker during the creation of shared libraries during ADDRESSSANITIZER builds.")
set(CMAKE_MODULE_LINKER_FLAGS_ADDRESSSANITIZER "-fsanitize=address"
CACHE STRING "Flags used by the linker during the creation of shared libraries during ADDRESSSANITIZER builds.")
set(CMAKE_EXEC_LINKER_FLAGS_ADDRESSSANITIZER "-fsanitize=address"
CACHE STRING "Flags used by the linker during ADDRESSSANITIZER builds.")
# Activate with: -DCMAKE_BUILD_TYPE=MemorySanitizer # with -fPIC
set(CMAKE_C_FLAGS_MEMORYSANITIZER "-g -O2 -fsanitize=memory -fsanitize-memory-track-origins=2 -fno-omit-frame-pointer" check_c_compiler_flag("-fPIC" WITH_FPIC)
CACHE STRING "Flags used by the C compiler during MEMORYSANITIZER builds.") if (WITH_FPIC)
set(CMAKE_CXX_FLAGS_MEMORYSANITIZER "-g -O2 -fsanitize=memory -fsanitize-memory-track-origins=2 -fno-omit-frame-pointer" set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC")
CACHE STRING "Flags used by the CXX compiler during MEMORYSANITIZER builds.") endif (WITH_FPIC)
set(CMAKE_SHARED_LINKER_FLAGS_MEMORYSANITIZER "-fsanitize=memory"
CACHE STRING "Flags used by the linker during the creation of shared libraries during MEMORYSANITIZER builds.") check_c_compiler_flag_ssp("-fstack-protector" WITH_STACK_PROTECTOR)
set(CMAKE_MODULE_LINKER_FLAGS_MEMORYSANITIZER "-fsanitize=memory" if (WITH_STACK_PROTECTOR)
CACHE STRING "Flags used by the linker during the creation of shared libraries during MEMORYSANITIZER builds.") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fstack-protector")
set(CMAKE_EXEC_LINKER_FLAGS_MEMORYSANITIZER "-fsanitize=memory" endif (WITH_STACK_PROTECTOR)
CACHE STRING "Flags used by the linker during MEMORYSANITIZER builds.")
if (CMAKE_BUILD_TYPE)
string(TOLOWER "${CMAKE_BUILD_TYPE}" CMAKE_BUILD_TYPE_LOWER)
if (CMAKE_BUILD_TYPE_LOWER MATCHES (release|relwithdebinfo|minsizerel))
check_c_compiler_flag("-Wp,-D_FORTIFY_SOURCE=2" WITH_FORTIFY_SOURCE)
if (WITH_FORTIFY_SOURCE)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wp,-D_FORTIFY_SOURCE=2")
endif (WITH_FORTIFY_SOURCE)
endif()
endif()
endif (${CMAKE_C_COMPILER_ID} MATCHES "(GNU|Clang)")
#
# Check for large filesystem support
#
if (CMAKE_SIZEOF_VOID_P MATCHES "8")
# with large file support
execute_process(
COMMAND
getconf LFS64_CFLAGS
OUTPUT_VARIABLE
_lfs_CFLAGS
ERROR_QUIET
OUTPUT_STRIP_TRAILING_WHITESPACE
)
else (CMAKE_SIZEOF_VOID_P MATCHES "8")
# with large file support
execute_process(
COMMAND
getconf LFS_CFLAGS
OUTPUT_VARIABLE
_lfs_CFLAGS
ERROR_QUIET
OUTPUT_STRIP_TRAILING_WHITESPACE
)
endif (CMAKE_SIZEOF_VOID_P MATCHES "8")
if (_lfs_CFLAGS)
string(REGEX REPLACE "[\r\n]" " " "${_lfs_CFLAGS}" "${${_lfs_CFLAGS}}")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${_lfs_CFLAGS}")
endif (_lfs_CFLAGS)
endif (UNIX AND NOT WIN32)
if (MSVC)
# Use secure functions by defaualt and suppress warnings about
#"deprecated" functions
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /D _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES=1")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /D _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT=1")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /D _CRT_NONSTDC_NO_WARNINGS=1 /D _CRT_SECURE_NO_WARNINGS=1")
endif (MSVC)
# This removes this annoying warning
# "warning: 'BN_CTX_free' is deprecated: first deprecated in OS X 10.7 [-Wdeprecated-declarations]"
if (OSX)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-deprecated-declarations")
endif (OSX)
# Activate with: -DCMAKE_BUILD_TYPE=UndefinedSanitizer
set(CMAKE_C_FLAGS_UNDEFINEDSANITIZER "-g -O1 -fsanitize=undefined -fsanitize=null -fsanitize=alignment -fno-sanitize-recover=undefined,integer"
CACHE STRING "Flags used by the C compiler during UNDEFINEDSANITIZER builds.")
set(CMAKE_CXX_FLAGS_UNDEFINEDSANITIZER "-g -O1 -fsanitize=undefined -fsanitize=null -fsanitize=alignment -fno-sanitize-recover=undefined,integer"
CACHE STRING "Flags used by the CXX compiler during UNDEFINEDSANITIZER builds.")
set(CMAKE_SHARED_LINKER_FLAGS_UNDEFINEDSANITIZER "-fsanitize=undefined"
CACHE STRING "Flags used by the linker during the creation of shared libraries during UNDEFINEDSANITIZER builds.")
set(CMAKE_MODULE_LINKER_FLAGS_UNDEFINEDSANITIZER "-fsanitize=undefined"
CACHE STRING "Flags used by the linker during the creation of shared libraries during UNDEFINEDSANITIZER builds.")
set(CMAKE_EXEC_LINKER_FLAGS_UNDEFINEDSANITIZER "-fsanitize=undefined"
CACHE STRING "Flags used by the linker during UNDEFINEDSANITIZER builds.")
endif()

View File

@@ -0,0 +1,109 @@
if (UNIX OR OS2)
IF (NOT APPLICATION_NAME)
MESSAGE(STATUS "${PROJECT_NAME} is used as APPLICATION_NAME")
SET(APPLICATION_NAME ${PROJECT_NAME})
ENDIF (NOT APPLICATION_NAME)
# Suffix for Linux
SET(LIB_SUFFIX
CACHE STRING "Define suffix of directory name (32/64)"
)
SET(EXEC_INSTALL_PREFIX
"${CMAKE_INSTALL_PREFIX}"
CACHE PATH "Base directory for executables and libraries"
)
SET(SHARE_INSTALL_PREFIX
"${CMAKE_INSTALL_PREFIX}/share"
CACHE PATH "Base directory for files which go to share/"
)
SET(DATA_INSTALL_PREFIX
"${SHARE_INSTALL_PREFIX}/${APPLICATION_NAME}"
CACHE PATH "The parent directory where applications can install their data")
# The following are directories where stuff will be installed to
SET(BIN_INSTALL_DIR
"${EXEC_INSTALL_PREFIX}/bin"
CACHE PATH "The ${APPLICATION_NAME} binary install dir (default prefix/bin)"
)
SET(SBIN_INSTALL_DIR
"${EXEC_INSTALL_PREFIX}/sbin"
CACHE PATH "The ${APPLICATION_NAME} sbin install dir (default prefix/sbin)"
)
SET(LIB_INSTALL_DIR
"${EXEC_INSTALL_PREFIX}/lib${LIB_SUFFIX}"
CACHE PATH "The subdirectory relative to the install prefix where libraries will be installed (default is prefix/lib)"
)
SET(LIBEXEC_INSTALL_DIR
"${EXEC_INSTALL_PREFIX}/libexec"
CACHE PATH "The subdirectory relative to the install prefix where libraries will be installed (default is prefix/libexec)"
)
SET(PLUGIN_INSTALL_DIR
"${LIB_INSTALL_DIR}/${APPLICATION_NAME}"
CACHE PATH "The subdirectory relative to the install prefix where plugins will be installed (default is prefix/lib/${APPLICATION_NAME})"
)
SET(INCLUDE_INSTALL_DIR
"${CMAKE_INSTALL_PREFIX}/include"
CACHE PATH "The subdirectory to the header prefix (default prefix/include)"
)
set(CMAKE_INSTALL_DIR
"${LIB_INSTALL_DIR}/cmake"
CACHE PATH "The subdirectory to install cmake config files")
SET(DATA_INSTALL_DIR
"${DATA_INSTALL_PREFIX}"
CACHE PATH "The parent directory where applications can install their data (default prefix/share/${APPLICATION_NAME})"
)
SET(HTML_INSTALL_DIR
"${DATA_INSTALL_PREFIX}/doc/HTML"
CACHE PATH "The HTML install dir for documentation (default data/doc/html)"
)
SET(ICON_INSTALL_DIR
"${DATA_INSTALL_PREFIX}/icons"
CACHE PATH "The icon install dir (default data/icons/)"
)
SET(SOUND_INSTALL_DIR
"${DATA_INSTALL_PREFIX}/sounds"
CACHE PATH "The install dir for sound files (default data/sounds)"
)
SET(LOCALE_INSTALL_DIR
"${SHARE_INSTALL_PREFIX}/locale"
CACHE PATH "The install dir for translations (default prefix/share/locale)"
)
SET(XDG_APPS_DIR
"${SHARE_INSTALL_PREFIX}/applications/"
CACHE PATH "The XDG apps dir"
)
SET(XDG_DIRECTORY_DIR
"${SHARE_INSTALL_PREFIX}/desktop-directories"
CACHE PATH "The XDG directory"
)
SET(SYSCONF_INSTALL_DIR
"${EXEC_INSTALL_PREFIX}/etc"
CACHE PATH "The ${APPLICATION_NAME} sysconfig install dir (default prefix/etc)"
)
SET(MAN_INSTALL_DIR
"${SHARE_INSTALL_PREFIX}/man"
CACHE PATH "The ${APPLICATION_NAME} man install dir (default prefix/man)"
)
SET(INFO_INSTALL_DIR
"${SHARE_INSTALL_PREFIX}/info"
CACHE PATH "The ${APPLICATION_NAME} info install dir (default prefix/info)"
)
else()
# Same same
set(BIN_INSTALL_DIR "bin" CACHE PATH "-")
set(SBIN_INSTALL_DIR "sbin" CACHE PATH "-")
set(LIB_INSTALL_DIR "lib${LIB_SUFFIX}" CACHE PATH "-")
set(INCLUDE_INSTALL_DIR "include" CACHE PATH "-")
set(CMAKE_INSTALL_DIR "CMake" CACHE PATH "-")
set(PLUGIN_INSTALL_DIR "plugins" CACHE PATH "-")
set(HTML_INSTALL_DIR "doc/HTML" CACHE PATH "-")
set(ICON_INSTALL_DIR "icons" CACHE PATH "-")
set(SOUND_INSTALL_DIR "soudns" CACHE PATH "-")
set(LOCALE_INSTALL_DIR "lang" CACHE PATH "-")
endif ()

View File

@@ -1,92 +0,0 @@
#
# Copyright (c) 2018 Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
#
# Redistribution and use is allowed according to the terms of the New
# BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
#
#.rst:
# ExtractSymbols
# --------------
#
# This is a helper script for FindABImap.cmake.
#
# Extract symbols from header files and output a list to a file.
# This script is run in build time to extract symbols from the provided header
# files. This way, symbols added or removed can be checked and used to update
# the symbol version script.
#
# All symbols followed by the character ``'('`` are extracted. If a
# ``FILTER_PATTERN`` is provided, only the lines containing the given string are
# considered.
#
# Expected defined variables
# --------------------------
#
# ``HEADERS_LIST_FILE``:
# Required, expects a file containing the list of header files to be parsed.
#
# ``OUTPUT_PATH``:
# Required, expects the output file path.
#
# Optionally defined variables
# ----------------------------
#
# ``FILTER_PATTERN``:
# Expects a string. Only lines containing the given string will be considered
# when extracting symbols.
#
if (NOT DEFINED OUTPUT_PATH)
message(SEND_ERROR "OUTPUT_PATH not defined")
endif()
if (NOT DEFINED HEADERS_LIST_FILE)
message(SEND_ERROR "HEADERS not defined")
endif()
file(READ ${HEADERS_LIST_FILE} HEADERS_LIST)
set(symbols)
foreach(header ${HEADERS_LIST})
# Filter only lines containing the FILTER_PATTERN
file(STRINGS ${header} contain_filter
REGEX "^.*${FILTER_PATTERN}.*[(]"
)
# Remove function-like macros
foreach(line ${contain_filter})
if (NOT ${line} MATCHES ".*#[ ]*define")
list(APPEND not_macro ${line})
endif()
endforeach()
set(functions)
# Get only the function names followed by '('
foreach(line ${not_macro})
string(REGEX MATCHALL "[a-zA-Z0-9_]+[ ]*[(]" func ${line})
list(APPEND functions ${func})
endforeach()
set(extracted_symbols)
# Remove '('
foreach(line ${functions})
string(REGEX REPLACE "[(]" "" symbol ${line})
string(STRIP "${symbol}" symbol)
list(APPEND extracted_symbols ${symbol})
endforeach()
list(APPEND symbols ${extracted_symbols})
endforeach()
list(REMOVE_DUPLICATES symbols)
list(SORT symbols)
string(REPLACE ";" "\n" symbols_list "${symbols}")
file(WRITE ${OUTPUT_PATH} "${symbols_list}")

View File

@@ -1,492 +0,0 @@
#
# Copyright (c) 2018 Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
#
# Redistribution and use is allowed according to the terms of the New
# BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
#
#.rst:
# FindABIMap
# ----------
#
# This file provides functions to generate the symbol version script. It uses
# the ``abimap`` tool to generate and update the linker script file. It can be
# installed by calling::
#
# $ pip install abimap
#
# The ``function generate_map_file`` generates a symbol version script
# containing the provided symbols. It defines a custom command which sets
# ``target_name`` as its ``OUTPUT``.
#
# The experimental function ``extract_symbols()`` is provided as a simple
# parser to extract the symbols from C header files. It simply extracts symbols
# followed by an opening '``(``'. It is recommended to use a filter pattern to
# select the lines to be considered. It defines a custom command which sets
# ``target_name`` as its output.
#
# The helper function ``get_files_list()`` is provided to find files given a
# name pattern. It defines a custom command which sets ``target_name`` as its
# output.
#
# Functions provided
# ------------------
#
# ::
#
# generate_map_file(target_name
# RELEASE_NAME_VERSION release_name
# SYMBOLS symbols_target
# [CURRENT_MAP cur_map]
# [FINAL]
# [BREAK_ABI]
# [COPY_TO output]
# )
#
# ``target_name``:
# Required, expects the name of the file to receive the generated symbol
# version script. It should be added as a dependency for the library. Use the
# linker option ``--version-script filename`` to add the version information
# to the symbols when building the library.
#
# ``RELEASE_NAME_VERSION``:
# Required, expects a string containing the name and version information to be
# added to the symbols in the format ``lib_name_1_2_3``.
#
# ``SYMBOLS``:
# Required, expects a target with the property ``LIST_FILE`` containing a path
# to a file containing the list of symbols to be added to the symbol version
# script.
#
# ``CURRENT_MAP``:
# Optional. If given, the new set of symbols will be checked against the
# ones contained in the ``cur_map`` file and updated properly. If an
# incompatible change is detected and ``BREAK_ABI`` is not defined, the build
# will fail.
#
# ``FINAL``:
# Optional. If given, will provide the ``--final`` option to ``abimap`` tool,
# which will mark the modified release in the symbol version script with a
# special comment, preventing later changes. This option should be set when
# creating a library release and the resulting map file should be stored with
# the source code.
#
# ``BREAK_ABI``:
# Optional. If provided, will use ``abimap`` ``--allow-abi-break`` option, which
# accepts incompatible changes to the set of symbols. This is necessary if any
# previously existing symbol were removed.
#
# ``COPY_TO``:
# Optional, expects a string containing the path to where the generated
# map file will be copied.
#
# Example:
#
# .. code-block:: cmake
#
# find_package(ABIMap)
# generate_map_file("lib.map"
# RELEASE_NAME_VERSION "lib_1_0_0"
# SYMBOLS symbols
# )
#
# Where the target ``symbols`` has its property ``LIST_FILE`` set to the path to
# a file containing::
#
# ``symbol1``
# ``symbol2``
#
# This example would result in the symbol version script to be created in
# ``${CMAKE_CURRENT_BINARY_DIR}/lib.map`` containing the provided symbols.
#
# ::
#
# get_files_list(target_name
# DIRECTORIES dir1 [dir2 ...]
# FILES_PATTERNS exp1 [exp2 ...]
# [COPY_TO output]
# )
#
# ``target_name``:
# Required, expects the name of the target to be created. A file named as
# ``${target_name}.list`` will be created in
# ``${CMAKE_CURRENT_BINARY_DIR}`` to receive the list of files found.
#
# ``DIRECTORIES``:
# Required, expects a list of directories paths. Only absolute paths are
# supported.
#
# ``FILES_PATTERN``:
# Required, expects a list of matching expressions to find the files to be
# considered in the directories.
#
# ``COPY_TO``:
# Optional, expects a string containing the path to where the file containing
# the list of files will be copied.
#
# This command searches the directories provided in ``DIRECTORIES`` for files
# matching any of the patterns provided in ``FILES_PATTERNS``. The obtained list
# is written to the path specified by ``output``. A target named ``target_name``
# will be created and its property ``LIST_FILE`` will be set to contain
# ``${CMAKE_CURRENT_BINARY_DIR}/${target_name}.list``
#
# Example:
#
# .. code-block:: cmake
#
# find_package(ABIMap)
# get_files_list(target
# DIRECTORIES "/include/mylib"
# FILES_PATTERNS "*.h"
# COPY_TO "my_list.txt"
# )
#
# Consider that ``/include/mylib`` contains 3 files, ``h1.h``, ``h2.h``, and
# ``h3.hpp``
#
# Will result in a file ``my_list.txt`` containing::
#
# ``h1.h;h2.h``
#
# And the target ``target`` will have its property ``LIST_FILE`` set to contain
# ``${CMAKE_CURRENT_BINARY_DIR}/target.list``
#
# ::
#
# extract_symbols(target_name
# HEADERS_LIST headers_list_target
# [FILTER_PATTERN pattern]
# [COPY_TO output]
# )
#
# ``target_name``:
# Required, expects the name of the target to be created. A file named after
# the string given in ``target_name`` will be created in
# ``${CMAKE_CURRENT_BINARY_DIR}`` to receive the list of symbols.
#
# ``HEADERS_LIST``:
# Required, expects a target with the property ``LIST_FILE`` set, containing a
# file path. Such file must contain a list of files paths.
#
# ``FILTER_PATTERN``:
# Optional, expects a string. Only the lines containing the filter pattern
# will be considered.
#
# ``COPY_TO``:
# Optional, expects a string containing the path to where the file containing
# the found symbols will be copied.
#
# This command extracts the symbols from the files listed in
# ``headers_list`` and write them on the ``output`` file. If ``pattern``
# is provided, then only the lines containing the string given in ``pattern``
# will be considered. It is recommended to provide a ``FILTER_PATTERN`` to mark
# the lines containing exported function declaration, since this function is
# experimental and can return wrong symbols when parsing the header files. A
# target named ``target_name`` will be created with the property ``LIST_FILE``
# set to contain ``${CMAKE_CURRENT_BINARY_DIR}/${target_name}.list``.
#
# Example:
#
# .. code-block:: cmake
#
# find_package(ABIMap)
# extract_symbols("lib.symbols"
# HEADERS_LIST "headers_target"
# FILTER_PATTERN "API_FUNCTION"
# )
#
# Where ``LIST_FILE`` property in ``headers_target`` points to a file
# containing::
#
# header1.h;header2.h
#
# Where ``header1.h`` contains::
#
# API_FUNCTION int exported_func1(int a, int b);
#
# ``header2.h`` contains::
#
# API_FUNCTION int exported_func2(int a);
#
# int private_func2(int b);
#
# Will result in a file ``lib.symbols.list`` in ``${CMAKE_CURRENT_BINARY_DIR}``
# containing::
#
# ``exported_func1``
# ``exported_func2``
#
# Search for python which is required
if (ABIMap_FIND_REQURIED)
find_package(PythonInterp REQUIRED)
else()
find_package(PythonInterp)
endif()
if (PYTHONINTERP_FOUND)
# Search for abimap tool used to generate the map files
find_program(ABIMAP_EXECUTABLE NAMES abimap DOC "path to the abimap executable")
mark_as_advanced(ABIMAP_EXECUTABLE)
if (NOT ABIMAP_EXECUTABLE AND UNIX)
message(STATUS "Could not find `abimap` in PATH."
" It can be found in PyPI as `abimap`"
" (try `pip install abimap`)")
endif ()
if (ABIMAP_EXECUTABLE)
# Get the abimap version
execute_process(COMMAND ${ABIMAP_EXECUTABLE} version
OUTPUT_VARIABLE ABIMAP_VERSION_STRING
OUTPUT_STRIP_TRAILING_WHITESPACE)
# If the version string starts with abimap-, strip it
if ("abimap" STRLESS_EQUAL ${ABIMAP_VERSION_STRING})
string(REGEX REPLACE "abimap-" "" ABIMAP_VERSION_STRING "${ABIMAP_VERSION_STRING}")
endif()
endif()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(ABIMap
REQUIRED_VARS ABIMAP_EXECUTABLE
VERSION_VAR ABIMAP_VERSION_STRING)
endif()
if (ABIMAP_FOUND)
# Define helper scripts
set(_EXTRACT_SYMBOLS_SCRIPT ${CMAKE_CURRENT_LIST_DIR}/ExtractSymbols.cmake)
set(_GENERATE_MAP_SCRIPT ${CMAKE_CURRENT_LIST_DIR}/GenerateMap.cmake)
set(_GET_FILES_LIST_SCRIPT ${CMAKE_CURRENT_LIST_DIR}/GetFilesList.cmake)
function(get_file_list _TARGET_NAME)
set(one_value_arguments
COPY_TO
)
set(multi_value_arguments
DIRECTORIES
FILES_PATTERNS
)
cmake_parse_arguments(_get_files_list
""
"${one_value_arguments}"
"${multi_value_arguments}"
${ARGN}
)
# The DIRS argument is required
if (NOT DEFINED _get_files_list_DIRECTORIES)
message(FATAL_ERROR "No directories paths provided. Provide a list of"
" directories paths containing header files.")
endif()
# The FILES_PATTERNS argument is required
if (NOT DEFINED _get_files_list_FILES_PATTERNS)
message(FATAL_ERROR "No matching expressions provided. Provide a list"
" of matching patterns for the header files.")
endif()
set(_FILES_LIST_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR}/${_TARGET_NAME}.list)
get_filename_component(_get_files_list_OUTPUT_PATH
"${_FILES_LIST_OUTPUT_PATH}"
ABSOLUTE)
add_custom_target(
${_TARGET_NAME}_int ALL
COMMAND ${CMAKE_COMMAND}
-DOUTPUT_PATH=${_get_files_list_OUTPUT_PATH}
-DDIRECTORIES=${_get_files_list_DIRECTORIES}
-DFILES_PATTERNS=${_get_files_list_FILES_PATTERNS}
-P ${_GET_FILES_LIST_SCRIPT}
COMMENT
"Searching for files"
VERBATIM
)
if (DEFINED _get_files_list_COPY_TO)
# Copy the generated file back to the COPY_TO
add_custom_target(${_TARGET_NAME} ALL
COMMAND
${CMAKE_COMMAND} -E copy_if_different
${_FILES_LIST_OUTPUT_PATH} ${_get_files_list_COPY_TO}
DEPENDS ${_TARGET_NAME}_int
COMMENT "Copying ${_TARGET_NAME} to ${_get_files_list_COPY_TO}"
VERBATIM
)
else()
add_custom_target(${_TARGET_NAME} ALL
DEPENDS ${_TARGET_NAME}_int
)
endif()
set_target_properties(${_TARGET_NAME}
PROPERTIES LIST_FILE ${_FILES_LIST_OUTPUT_PATH}
)
endfunction()
function(extract_symbols _TARGET_NAME)
set(one_value_arguments
FILTER_PATTERN
HEADERS_LIST
COPY_TO
)
set(multi_value_arguments
)
cmake_parse_arguments(_extract_symbols
""
"${one_value_arguments}"
"${multi_value_arguments}"
${ARGN}
)
# The HEADERS_LIST_FILE argument is required
if (NOT DEFINED _extract_symbols_HEADERS_LIST)
message(FATAL_ERROR "No target provided in HEADERS_LIST. Provide a"
" target with the property LIST_FILE set as the"
" path to the file containing the list of headers.")
endif()
get_filename_component(_SYMBOLS_OUTPUT_PATH
"${CMAKE_CURRENT_BINARY_DIR}/${_TARGET_NAME}.list"
ABSOLUTE
)
get_target_property(_HEADERS_LIST_FILE
${_extract_symbols_HEADERS_LIST}
LIST_FILE
)
add_custom_target(
${_TARGET_NAME}_int ALL
COMMAND ${CMAKE_COMMAND}
-DOUTPUT_PATH=${_SYMBOLS_OUTPUT_PATH}
-DHEADERS_LIST_FILE=${_HEADERS_LIST_FILE}
-DFILTER_PATTERN=${_extract_symbols_FILTER_PATTERN}
-P ${_EXTRACT_SYMBOLS_SCRIPT}
DEPENDS ${_extract_symbols_HEADERS_LIST}
COMMENT "Extracting symbols from headers"
VERBATIM
)
if (DEFINED _extract_symbols_COPY_TO)
# Copy the generated file back to the COPY_TO
add_custom_target(${_TARGET_NAME} ALL
COMMAND
${CMAKE_COMMAND} -E copy_if_different
${_SYMBOLS_OUTPUT_PATH} ${_extract_symbols_COPY_TO}
DEPENDS ${_TARGET_NAME}_int
COMMENT "Copying ${_TARGET_NAME} to ${_extract_symbols_COPY_TO}"
VERBATIM
)
else()
add_custom_target(${_TARGET_NAME} ALL
DEPENDS ${_TARGET_NAME}_int
)
endif()
set_target_properties(${_TARGET_NAME}
PROPERTIES LIST_FILE ${_SYMBOLS_OUTPUT_PATH}
)
endfunction()
function(generate_map_file _TARGET_NAME)
set(options
FINAL
BREAK_ABI
)
set(one_value_arguments
RELEASE_NAME_VERSION
SYMBOLS
CURRENT_MAP
COPY_TO
)
set(multi_value_arguments
)
cmake_parse_arguments(_generate_map_file
"${options}"
"${one_value_arguments}"
"${multi_value_arguments}"
${ARGN}
)
if (NOT DEFINED _generate_map_file_SYMBOLS)
message(FATAL_ERROR "No target provided in SYMBOLS. Provide a target"
" with the property LIST_FILE set as the path to"
" the file containing the list of symbols.")
endif()
if (NOT DEFINED _generate_map_file_RELEASE_NAME_VERSION)
message(FATAL_ERROR "Release name and version not provided."
" (e.g. libname_1_0_0)")
endif()
get_target_property(_SYMBOLS_FILE
${_generate_map_file_SYMBOLS}
LIST_FILE
)
# Set generated map file path
get_filename_component(_MAP_OUTPUT_PATH
"${CMAKE_CURRENT_BINARY_DIR}/${_TARGET_NAME}"
ABSOLUTE
)
add_custom_target(
${_TARGET_NAME}_int ALL
COMMAND ${CMAKE_COMMAND}
-DABIMAP_EXECUTABLE=${ABIMAP_EXECUTABLE}
-DSYMBOLS=${_SYMBOLS_FILE}
-DCURRENT_MAP=${_generate_map_file_CURRENT_MAP}
-DOUTPUT_PATH=${_MAP_OUTPUT_PATH}
-DFINAL=${_generate_map_file_FINAL}
-DBREAK_ABI=${_generate_map_file_BREAK_ABI}
-DRELEASE_NAME_VERSION=${_generate_map_file_RELEASE_NAME_VERSION}
-P ${_GENERATE_MAP_SCRIPT}
DEPENDS ${_generate_map_file_SYMBOLS}
COMMENT "Generating the map ${_TARGET_NAME}"
VERBATIM
)
# Add a custom command setting the map as OUTPUT to allow it to be added as
# a generated source
add_custom_command(
OUTPUT ${_MAP_OUTPUT_PATH}
DEPENDS ${_TARGET_NAME}_copy
)
if (DEFINED _generate_map_file_COPY_TO)
# Copy the generated map back to the COPY_TO
add_custom_target(${_TARGET_NAME}_copy ALL
COMMAND
${CMAKE_COMMAND} -E copy_if_different ${_MAP_OUTPUT_PATH}
${_generate_map_file_COPY_TO}
DEPENDS ${_TARGET_NAME}_int
COMMENT "Copying ${_MAP_OUTPUT_PATH} to ${_generate_map_file_COPY_TO}"
VERBATIM
)
else()
add_custom_target(${_TARGET_NAME}_copy ALL
DEPENDS ${_TARGET_NAME}_int
)
endif()
endfunction()
endif (ABIMAP_FOUND)

View File

@@ -1,66 +1,60 @@
# - Try to find ARGP # - Try to find Argp
# Once done this will define # Once done this will define
# #
# ARGP_ROOT_DIR - Set this variable to the root installation of ARGP # ARGP_FOUND - system has Argp
# ARGP_INCLUDE_DIRS - the Argp include directory
# ARGP_LIBRARIES - Link these to use Argp
# ARGP_DEFINITIONS - Compiler switches required for using Argp
# #
# Read-Only variables: # Copyright (c) 2010 Andreas Schneider <asn@cryptomilk.org>
# ARGP_FOUND - system has ARGP
# ARGP_INCLUDE_DIR - the ARGP include directory
# ARGP_LIBRARIES - Link these to use ARGP
# ARGP_DEFINITIONS - Compiler switches required for using ARGP
# #
#============================================================================= # Redistribution and use is allowed according to the terms of the New
# Copyright (c) 2011-2016 Andreas Schneider <asn@cryptomilk.org> # BSD license.
# # For details see the accompanying COPYING-CMAKE-SCRIPTS file.
# Distributed under the OSI-approved BSD License (the "License");
# see accompanying file Copyright.txt for details.
#
# This software is distributed WITHOUT ANY WARRANTY; without even the
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the License for more information.
#=============================================================================
# #
set(_ARGP_ROOT_HINTS
)
set(_ARGP_ROOT_PATHS if (ARGP_LIBRARIES AND ARGP_INCLUDE_DIRS)
"$ENV{PROGRAMFILES}/argp" # in cache already
) set(ARGP_FOUND TRUE)
else (ARGP_LIBRARIES AND ARGP_INCLUDE_DIRS)
find_path(ARGP_ROOT_DIR find_path(ARGP_INCLUDE_DIR
NAMES NAMES
include/argp.h argp.h
HINTS
${_ARGP_ROOT_HINTS}
PATHS PATHS
${_ARGP_ROOT_PATHS} /usr/include
) /usr/local/include
mark_as_advanced(ARGP_ROOT_DIR) /opt/local/include
/sw/include
find_path(ARGP_INCLUDE_DIR
NAMES
argp.h
PATHS
${ARGP_ROOT_DIR}/include
)
find_library(ARGP_LIBRARY
NAMES
argp
PATHS
${ARGP_ROOT_DIR}/lib
)
if (ARGP_LIBRARY)
set(ARGP_LIBRARIES
${ARGP_LIBRARIES}
${ARGP_LIBRARY}
) )
endif (ARGP_LIBRARY)
include(FindPackageHandleStandardArgs) find_library(ARGP_LIBRARY
find_package_handle_standard_args(ARGP DEFAULT_MSG ARGP_LIBRARIES ARGP_INCLUDE_DIR) NAMES
argp
PATHS
/usr/lib
/usr/local/lib
/opt/local/lib
/sw/lib
)
set(ARGP_INCLUDE_DIRS
${ARGP_INCLUDE_DIR}
)
if (ARGP_LIBRARY)
set(ARGP_LIBRARIES
${ARGP_LIBRARIES}
${ARGP_LIBRARY}
)
endif (ARGP_LIBRARY)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Argp DEFAULT_MSG ARGP_LIBRARIES ARGP_INCLUDE_DIRS)
# show the ARGP_INCLUDE_DIRS and ARGP_LIBRARIES variables only in the advanced view
mark_as_advanced(ARGP_INCLUDE_DIRS ARGP_LIBRARIES)
endif (ARGP_LIBRARIES AND ARGP_INCLUDE_DIRS)
# show the ARGP_INCLUDE_DIR and ARGP_LIBRARIES variables only in the advanced view
mark_as_advanced(ARGP_INCLUDE_DIR ARGP_LIBRARIES)

View File

@@ -35,8 +35,6 @@ find_path(GCRYPT_INCLUDE_DIR
gcrypt.h gcrypt.h
HINTS HINTS
${_GCRYPT_ROOT_HINTS_AND_PATHS} ${_GCRYPT_ROOT_HINTS_AND_PATHS}
PATH_SUFFIXES
include
) )
find_library(GCRYPT_LIBRARY find_library(GCRYPT_LIBRARY
@@ -46,23 +44,13 @@ find_library(GCRYPT_LIBRARY
libgcrypt-11 libgcrypt-11
HINTS HINTS
${_GCRYPT_ROOT_HINTS_AND_PATHS} ${_GCRYPT_ROOT_HINTS_AND_PATHS}
PATH_SUFFIXES
lib
) )
find_library(GCRYPT_ERROR_LIBRARY set(GCRYPT_LIBRARIES ${GCRYPT_LIBRARY})
NAMES
gpg-error
libgpg-error-0
libgpg-error6-0
HINTS
${_GCRYPT_ROOT_HINTS_AND_PATHS}
)
set(GCRYPT_LIBRARIES ${GCRYPT_LIBRARY} ${GCRYPT_ERROR_LIBRARY})
if (GCRYPT_INCLUDE_DIR) if (GCRYPT_INCLUDE_DIR)
file(STRINGS "${GCRYPT_INCLUDE_DIR}/gcrypt.h" _gcrypt_version_str REGEX "^#define GCRYPT_VERSION \"[0-9]+\\.[0-9]+\\.[0-9]") file(STRINGS "${GCRYPT_INCLUDE_DIR}/gcrypt.h" _gcrypt_version_str REGEX "^#define GCRYPT_VERSION \"[0-9]+.[0-9]+.[0-9]+\"")
string(REGEX REPLACE "^.*GCRYPT_VERSION.*([0-9]+\\.[0-9]+\\.[0-9]+).*" "\\1" GCRYPT_VERSION "${_gcrypt_version_str}") string(REGEX REPLACE "^.*GCRYPT_VERSION.*([0-9]+.[0-9]+.[0-9]+).*" "\\1" GCRYPT_VERSION "${_gcrypt_version_str}")
endif (GCRYPT_INCLUDE_DIR) endif (GCRYPT_INCLUDE_DIR)
include(FindPackageHandleStandardArgs) include(FindPackageHandleStandardArgs)

View File

@@ -54,8 +54,7 @@ if (UNIX)
OUTPUT_VARIABLE OUTPUT_VARIABLE
_GSSAPI_VENDOR_STRING) _GSSAPI_VENDOR_STRING)
if ((_GSSAPI_VENDOR_STRING MATCHES ".*Massachusetts.*") OR (_GSSAPI_VENDOR_STRING if (_GSSAPI_VENDOR_STRING MATCHES ".*Massachusetts.*")
MATCHES ".*MITKerberosShim.*"))
set(GSSAPI_FLAVOR_MIT TRUE) set(GSSAPI_FLAVOR_MIT TRUE)
else() else()
execute_process( execute_process(

View File

@@ -1,104 +0,0 @@
# - Try to find mbedTLS
# Once done this will define
#
# MBEDTLS_FOUND - system has mbedTLS
# MBEDTLS_INCLUDE_DIRS - the mbedTLS include directory
# MBEDTLS_LIBRARIES - Link these to use mbedTLS
# MBEDTLS_DEFINITIONS - Compiler switches required for using mbedTLS
#=============================================================================
# Copyright (c) 2017 Sartura d.o.o.
#
# Author: Juraj Vijtiuk <juraj.vijtiuk@sartura.hr>
#
# Distributed under the OSI-approved BSD License (the "License");
# see accompanying file Copyright.txt for details.
#
# This software is distributed WITHOUT ANY WARRANTY; without even the
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the License for more information.
#=============================================================================
#
set(_MBEDTLS_ROOT_HINTS
$ENV{MBEDTLS_ROOT_DIR}
${MBEDTLS_ROOT_DIR})
set(_MBEDTLS_ROOT_PATHS
"$ENV{PROGRAMFILES}/libmbedtls")
set(_MBEDTLS_ROOT_HINTS_AND_PATHS
HINTS ${_MBEDTLS_ROOT_HINTS}
PATHS ${_MBEDTLS_ROOT_PATHS})
find_path(MBEDTLS_INCLUDE_DIR
NAMES
mbedtls/config.h
HINTS
${_MBEDTLS_ROOT_HINTS_AND_PATHS}
PATH_SUFFIXES
include
)
find_library(MBEDTLS_SSL_LIBRARY
NAMES
mbedtls
HINTS
${_MBEDTLS_ROOT_HINTS_AND_PATHS}
PATH_SUFFIXES
lib
)
find_library(MBEDTLS_CRYPTO_LIBRARY
NAMES
mbedcrypto
HINTS
${_MBEDTLS_ROOT_HINTS_AND_PATHS}
PATH_SUFFIXES
lib
)
find_library(MBEDTLS_X509_LIBRARY
NAMES
mbedx509
HINTS
${_MBEDTLS_ROOT_HINTS_AND_PATHS}
PATH_SUFFIXES
lib
)
set(MBEDTLS_LIBRARIES ${MBEDTLS_SSL_LIBRARY} ${MBEDTLS_CRYPTO_LIBRARY}
${MBEDTLS_X509_LIBRARY})
if (MBEDTLS_INCLUDE_DIR AND EXISTS "${MBEDTLS_INCLUDE_DIR}/mbedtls/version.h")
file(STRINGS "${MBEDTLS_INCLUDE_DIR}/mbedtls/version.h" _mbedtls_version_str REGEX
"^#[\t ]*define[\t ]+MBEDTLS_VERSION_STRING[\t ]+\"[0-9]+.[0-9]+.[0-9]+\"")
string(REGEX REPLACE "^.*MBEDTLS_VERSION_STRING.*([0-9]+.[0-9]+.[0-9]+).*"
"\\1" MBEDTLS_VERSION "${_mbedtls_version_str}")
endif ()
include(FindPackageHandleStandardArgs)
if (MBEDTLS_VERSION)
find_package_handle_standard_args(MbedTLS
REQUIRED_VARS
MBEDTLS_INCLUDE_DIR
MBEDTLS_LIBRARIES
VERSION_VAR
MBEDTLS_VERSION
FAIL_MESSAGE
"Could NOT find mbedTLS, try to set the path to mbedTLS root folder
in the system variable MBEDTLS_ROOT_DIR"
)
else (MBEDTLS_VERSION)
find_package_handle_standard_args(MBedTLS
"Could NOT find mbedTLS, try to set the path to mbedLS root folder in
the system variable MBEDTLS_ROOT_DIR"
MBEDTLS_INCLUDE_DIR
MBEDTLS_LIBRARIES)
endif (MBEDTLS_VERSION)
# show the MBEDTLS_INCLUDE_DIRS and MBEDTLS_LIBRARIES variables only in the advanced view
mark_as_advanced(MBEDTLS_INCLUDE_DIR MBEDTLS_LIBRARIES)

View File

@@ -21,16 +21,17 @@
# #
if (WIN32) if (WIN32)
set(_x86 "(x86)") set(_NSIS_ROOT_HINTS
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\NSIS;Default]")
set(_NSIS_ROOT_PATHS set(_NSIS_ROOT_PATHS
"$ENV{ProgramFiles}/NSIS" $ENV{PROGRAMFILES}/NSIS)
"$ENV{ProgramFiles${_x86}}/NSIS"
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\NSIS;Default]")
find_path(NSIS_ROOT_PATH find_path(NSIS_ROOT_PATH
NAMES NAMES
Include/Library.nsh Include/Library.nsh
HINTS
${_NSIS_ROOT_HINTS}
PATHS PATHS
${_NSIS_ROOT_PATHS} ${_NSIS_ROOT_PATHS}
) )

View File

@@ -1,36 +0,0 @@
# - Try to find softhsm
# Once done this will define
#
# SOFTHSM_FOUND - system has softhsm
# SOFTHSM_LIBRARIES - Link these to use softhsm
#
#=============================================================================
# Copyright (c) 2019 Sahana Prasad <sahana@redhat.com>
#
# Distributed under the OSI-approved BSD License (the "License");
# see accompanying file Copyright.txt for details.
#
# This software is distributed WITHOUT ANY WARRANTY; without even the
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the License for more information.
#=============================================================================
#
find_library(SOFTHSM2_LIBRARY
NAMES
softhsm2
)
if (SOFTHSM2_LIBRARY)
set(SOFTHSM_LIBRARIES
${SOFTHSM_LIBRARIES}
${SOFTHSM2_LIBRARY}
)
endif (SOFTHSM2_LIBRARY)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(softhsm DEFAULT_MSG SOFTHSM_LIBRARIES)
# show the SOFTHSM_INCLUDE_DIR and SOFTHSM_LIBRARIES variables only in the advanced view
mark_as_advanced(SOFTHSM_LIBRARIES)

View File

@@ -1,118 +0,0 @@
#
# Copyright (c) 2018 Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
#
# Redistribution and use is allowed according to the terms of the New
# BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
#
#.rst:
# GenerateMap
# -----------
#
# This is a helper script for FindABImap.cmake.
#
# Generates a symbols version script using the abimap tool.
# This script is run in build time to use the correct command depending on the
# existence of the file provided ``CURRENT_MAP``.
#
# If the file exists, the ``abimap update`` subcommand is used to update the
# existing map. Otherwise, the ``abimap new`` subcommand is used to create a new
# map file.
#
# If the file provided in ``CURRENT_MAP`` exists, it is copied to the
# ``OUTPUT_PATH`` before updating.
# This is required because ``abimap`` do not generate output if no symbols were
# changed when updating an existing file.
#
# Expected defined variables
# --------------------------
#
# ``SYMBOLS``:
# Required file containing the symbols to be used as input. Usually this is
# the ``OUTPUT`` generated by ``extract_symbols()`` function provided in
# FindABImap.cmake
#
# ``RELEASE_NAME_VERSION``:
# Required, expects the library name and version information to be added to
# the symbols in the format ``library_name_1_2_3``
#
# ``CURRENT_MAP``:
# Required, expects the path to the current map file (or the path were it
# should be)
#
# ``OUTPUT_PATH``:
# Required, expects the output file path.
#
# ``ABIMAP_EXECUTABLE``:
# Required, expects the path to the ``abimap`` tool.
#
# Optionally defined variables
# ----------------------------
#
# ``FINAL``:
# If defined, will mark the modified set of symbols in the symbol version
# script as final, preventing later changes using ``abimap``.
#
# ``BREAK_ABI``:
# If defined, the build will not fail if symbols were removed.
# If defined and a symbol is removed, a new release is created containing
# all symbols from all released versions. This makes an incompatible release.
#
if (NOT DEFINED RELEASE_NAME_VERSION)
message(SEND_ERROR "RELEASE_NAME_VERSION not defined")
endif()
if (NOT DEFINED SYMBOLS)
message(SEND_ERROR "SYMBOLS not defined")
endif()
if (NOT DEFINED CURRENT_MAP)
message(SEND_ERROR "CURRENT_MAP not defined")
endif()
if (NOT DEFINED OUTPUT_PATH)
message(SEND_ERROR "OUTPUT_PATH not defined")
endif()
if (NOT ABIMAP_EXECUTABLE)
message(SEND_ERROR "ABIMAP_EXECUTABLE not defined")
endif()
set(ARGS_LIST)
if (FINAL)
list(APPEND ARGS_LIST "--final")
endif()
if (EXISTS ${CURRENT_MAP})
if (BREAK_ABI)
list(APPEND ARGS_LIST "--allow-abi-break")
endif()
execute_process(
COMMAND
${CMAKE_COMMAND} -E copy_if_different ${CURRENT_MAP} ${OUTPUT_PATH}
COMMAND
${ABIMAP_EXECUTABLE} update ${ARGS_LIST}
-r ${RELEASE_NAME_VERSION}
-i ${SYMBOLS}
-o ${OUTPUT_PATH}
${CURRENT_MAP}
RESULT_VARIABLE result
)
else ()
execute_process(
COMMAND
${ABIMAP_EXECUTABLE} new ${ARGS_LIST}
-r ${RELEASE_NAME_VERSION}
-i ${SYMBOLS}
-o ${OUTPUT_PATH}
RESULT_VARIABLE result
)
endif()
if (NOT "${result}" STREQUAL "0")
message(SEND_ERROR "Map generation failed")
endif()

View File

@@ -1,59 +0,0 @@
#
# Copyright (c) 2018 Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
#
# Redistribution and use is allowed according to the terms of the New
# BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
#
#.rst:
# GetFilesList
# ------------
#
# This is a helper script for FindABImap.cmake.
#
# Search in the provided directories for files matching the provided pattern.
# The list of files is then written to the output file.
#
# Expected defined variables
# --------------------------
#
# ``DIRECTORIES``:
# Required, expects a list of directories paths.
#
# ``FILES_PATTERNS``:
# Required, expects a list of patterns to be used to search files
#
# ``OUTPUT_PATH``:
# Required, expects the output file path.
if (NOT DEFINED DIRECTORIES)
message(SEND_ERROR "DIRECTORIES not defined")
endif()
if (NOT DEFINED FILES_PATTERNS)
message(SEND_ERROR "FILES_PATTERNS not defined")
endif()
if (NOT DEFINED OUTPUT_PATH)
message(SEND_ERROR "OUTPUT_PATH not defined")
endif()
string(REPLACE " " ";" DIRECTORIES_LIST "${DIRECTORIES}")
string(REPLACE " " ";" FILES_PATTERNS_LIST "${FILES_PATTERNS}")
# Create the list of expressions for the files
set(glob_expressions)
foreach(dir ${DIRECTORIES_LIST})
foreach(exp ${FILES_PATTERNS_LIST})
list(APPEND glob_expressions
"${dir}/${exp}"
)
endforeach()
endforeach()
# Create the list of files
file(GLOB files ${glob_expressions})
# Write to the output
file(WRITE ${OUTPUT_PATH} "${files}")

View File

@@ -0,0 +1,140 @@
# - Run Doxygen
#
# Adds a doxygen target that runs doxygen to generate the html
# and optionally the LaTeX API documentation.
# The doxygen target is added to the doc target as a dependency.
# i.e.: the API documentation is built with:
# make doc
#
# USAGE: GLOBAL INSTALL
#
# Install it with:
# cmake ./ && sudo make install
# Add the following to the CMakeLists.txt of your project:
# include(UseDoxygen OPTIONAL)
# Optionally copy Doxyfile.in in the directory of CMakeLists.txt and edit it.
#
# USAGE: INCLUDE IN PROJECT
#
# set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR})
# include(UseDoxygen)
# Add the Doxyfile.in and UseDoxygen.cmake files to the projects source directory.
#
#
# CONFIGURATION
#
# To configure Doxygen you can edit Doxyfile.in and set some variables in cmake.
# Variables you may define are:
# DOXYFILE_SOURCE_DIR - Path where the Doxygen input files are.
# Defaults to the current source directory.
# DOXYFILE_EXTRA_SOURCES - Additional source diretories/files for Doxygen to scan.
# The Paths should be in double quotes and separated by space. e.g.:
# "${CMAKE_CURRENT_BINARY_DIR}/foo.c" "${CMAKE_CURRENT_BINARY_DIR}/bar/"
#
# DOXYFILE_OUTPUT_DIR - Path where the Doxygen output is stored.
# Defaults to "${CMAKE_CURRENT_BINARY_DIR}/doc".
#
# DOXYFILE_LATEX - ON/OFF; Set to "ON" if you want the LaTeX documentation
# to be built.
# DOXYFILE_LATEX_DIR - Directory relative to DOXYFILE_OUTPUT_DIR where
# the Doxygen LaTeX output is stored. Defaults to "latex".
#
# DOXYFILE_HTML_DIR - Directory relative to DOXYFILE_OUTPUT_DIR where
# the Doxygen html output is stored. Defaults to "html".
#
#
# Copyright (c) 2009, 2010, 2011 Tobias Rautenkranz <tobias@rautenkranz.ch>
#
# Redistribution and use is allowed according to the terms of the New
# BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
#
macro(usedoxygen_set_default name value type docstring)
if(NOT DEFINED "${name}")
set("${name}" "${value}" CACHE "${type}" "${docstring}")
endif()
endmacro()
find_package(Doxygen)
if(DOXYGEN_FOUND)
find_file(DOXYFILE_IN "Doxyfile.in"
PATHS "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_ROOT}/Modules/"
NO_DEFAULT_PATH
DOC "Path to the doxygen configuration template file")
set(DOXYFILE "${CMAKE_CURRENT_BINARY_DIR}/Doxyfile")
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(DOXYFILE_IN DEFAULT_MSG "DOXYFILE_IN")
endif()
if(DOXYGEN_FOUND AND DOXYFILE_IN_FOUND)
usedoxygen_set_default(DOXYFILE_OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}/doc"
PATH "Doxygen output directory")
usedoxygen_set_default(DOXYFILE_HTML_DIR "html"
STRING "Doxygen HTML output directory")
usedoxygen_set_default(DOXYFILE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}"
PATH "Input files source directory")
usedoxygen_set_default(DOXYFILE_EXTRA_SOURCE_DIRS ""
STRING "Additional source files/directories separated by space")
set(DOXYFILE_SOURCE_DIRS "\"${DOXYFILE_SOURCE_DIR}\" ${DOXYFILE_EXTRA_SOURCES}")
usedoxygen_set_default(DOXYFILE_LATEX YES BOOL "Generate LaTeX API documentation" OFF)
usedoxygen_set_default(DOXYFILE_LATEX_DIR "latex" STRING "LaTex output directory")
mark_as_advanced(DOXYFILE_OUTPUT_DIR DOXYFILE_HTML_DIR DOXYFILE_LATEX_DIR
DOXYFILE_SOURCE_DIR DOXYFILE_EXTRA_SOURCE_DIRS DOXYFILE_IN)
set_property(DIRECTORY
APPEND PROPERTY
ADDITIONAL_MAKE_CLEAN_FILES
"${DOXYFILE_OUTPUT_DIR}/${DOXYFILE_HTML_DIR}")
add_custom_target(doxygen
COMMAND "${DOXYGEN_EXECUTABLE}"
"${DOXYFILE}"
COMMENT "Writing documentation to ${DOXYFILE_OUTPUT_DIR}..."
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}")
set(DOXYFILE_DOT "NO")
if(DOXYGEN_DOT_EXECUTABLE)
set(DOXYFILE_DOT "YES")
endif()
## LaTeX
set(DOXYFILE_PDFLATEX "NO")
set_property(DIRECTORY APPEND PROPERTY
ADDITIONAL_MAKE_CLEAN_FILES
"${DOXYFILE_OUTPUT_DIR}/${DOXYFILE_LATEX_DIR}")
if(DOXYFILE_LATEX STREQUAL "ON")
set(DOXYFILE_GENERATE_LATEX "YES")
find_package(LATEX)
find_program(DOXYFILE_MAKE make)
mark_as_advanced(DOXYFILE_MAKE)
if(LATEX_COMPILER AND MAKEINDEX_COMPILER AND DOXYFILE_MAKE)
if(PDFLATEX_COMPILER)
set(DOXYFILE_PDFLATEX "YES")
endif()
add_custom_command(TARGET doxygen
POST_BUILD
COMMAND "${DOXYFILE_MAKE}"
COMMENT "Running LaTeX for Doxygen documentation in ${DOXYFILE_OUTPUT_DIR}/${DOXYFILE_LATEX_DIR}..."
WORKING_DIRECTORY "${DOXYFILE_OUTPUT_DIR}/${DOXYFILE_LATEX_DIR}")
else()
set(DOXYGEN_LATEX "NO")
endif()
else()
set(DOXYFILE_GENERATE_LATEX "NO")
endif()
configure_file("${DOXYFILE_IN}" "${DOXYFILE}" @ONLY)
add_custom_target(doc)
add_dependencies(doc doxygen)
endif()

View File

@@ -1,23 +0,0 @@
set(CMAKE_C_FLAGS "-m32" CACHE STRING "C compiler flags" FORCE)
set(CMAKE_CXX_FLAGS "-m32" CACHE STRING "C++ compiler flags" FORCE)
set(LIB32 /usr/lib) # Fedora
if(EXISTS /usr/lib32)
set(LIB32 /usr/lib32) # Arch, Solus
endif()
set(CMAKE_SYSTEM_LIBRARY_PATH ${LIB32} CACHE STRING "system library search path" FORCE)
set(CMAKE_LIBRARY_PATH ${LIB32} CACHE STRING "library search path" FORCE)
# this is probably unlikely to be needed, but just in case
set(CMAKE_EXE_LINKER_FLAGS "-m32 -L${LIB32}" CACHE STRING "executable linker flags" FORCE)
set(CMAKE_SHARED_LINKER_FLAGS "-m32 -L${LIB32}" CACHE STRING "shared library linker flags" FORCE)
set(CMAKE_MODULE_LINKER_FLAGS "-m32 -L${LIB32}" CACHE STRING "module linker flags" FORCE)
# on Fedora and Arch and similar, point pkgconfig at 32 bit .pc files. We have
# to include the regular system .pc files as well (at the end), because some
# are not always present in the 32 bit directory
if(EXISTS ${LIB32}/pkgconfig)
set(ENV{PKG_CONFIG_LIBDIR} ${LIB32}/pkgconfig:/usr/share/pkgconfig:/usr/lib/pkgconfig:/usr/lib64/pkgconfig)
endiF()

View File

@@ -1,19 +1,17 @@
/* Name of package */ /* Name of package */
#cmakedefine PACKAGE "${PROJECT_NAME}" #cmakedefine PACKAGE "${APPLICATION_NAME}"
/* Version number of package */ /* Version number of package */
#cmakedefine VERSION "${PROJECT_VERSION}" #cmakedefine VERSION "${APPLICATION_VERSION}"
#cmakedefine LOCALEDIR "${LOCALE_INSTALL_DIR}"
#cmakedefine DATADIR "${DATADIR}"
#cmakedefine LIBDIR "${LIBDIR}"
#cmakedefine PLUGINDIR "${PLUGINDIR}"
#cmakedefine SYSCONFDIR "${SYSCONFDIR}" #cmakedefine SYSCONFDIR "${SYSCONFDIR}"
#cmakedefine BINARYDIR "${BINARYDIR}" #cmakedefine BINARYDIR "${BINARYDIR}"
#cmakedefine SOURCEDIR "${SOURCEDIR}" #cmakedefine SOURCEDIR "${SOURCEDIR}"
/* Global bind configuration file path */
#cmakedefine GLOBAL_BIND_CONFIG "${GLOBAL_BIND_CONFIG}"
/* Global client configuration file path */
#cmakedefine GLOBAL_CLIENT_CONFIG "${GLOBAL_CLIENT_CONFIG}"
/************************** HEADER FILES *************************/ /************************** HEADER FILES *************************/
/* Define to 1 if you have the <argp.h> header file. */ /* Define to 1 if you have the <argp.h> header file. */
@@ -22,12 +20,6 @@
/* Define to 1 if you have the <aprpa/inet.h> header file. */ /* Define to 1 if you have the <aprpa/inet.h> header file. */
#cmakedefine HAVE_ARPA_INET_H 1 #cmakedefine HAVE_ARPA_INET_H 1
/* Define to 1 if you have the <glob.h> header file. */
#cmakedefine HAVE_GLOB_H 1
/* Define to 1 if you have the <valgrind/valgrind.h> header file. */
#cmakedefine HAVE_VALGRIND_VALGRIND_H 1
/* Define to 1 if you have the <pty.h> header file. */ /* Define to 1 if you have the <pty.h> header file. */
#cmakedefine HAVE_PTY_H 1 #cmakedefine HAVE_PTY_H 1
@@ -43,21 +35,12 @@
/* Define to 1 if you have the <sys/time.h> header file. */ /* Define to 1 if you have the <sys/time.h> header file. */
#cmakedefine HAVE_SYS_TIME_H 1 #cmakedefine HAVE_SYS_TIME_H 1
/* Define to 1 if you have the <sys/utime.h> header file. */
#cmakedefine HAVE_SYS_UTIME_H 1
/* Define to 1 if you have the <io.h> header file. */
#cmakedefine HAVE_IO_H 1
/* Define to 1 if you have the <termios.h> header file. */ /* Define to 1 if you have the <termios.h> header file. */
#cmakedefine HAVE_TERMIOS_H 1 #cmakedefine HAVE_TERMIOS_H 1
/* Define to 1 if you have the <unistd.h> header file. */ /* Define to 1 if you have the <unistd.h> header file. */
#cmakedefine HAVE_UNISTD_H 1 #cmakedefine HAVE_UNISTD_H 1
/* Define to 1 if you have the <stdint.h> header file. */
#cmakedefine HAVE_STDINT_H 1
/* Define to 1 if you have the <openssl/aes.h> header file. */ /* Define to 1 if you have the <openssl/aes.h> header file. */
#cmakedefine HAVE_OPENSSL_AES_H 1 #cmakedefine HAVE_OPENSSL_AES_H 1
@@ -91,44 +74,8 @@
/* Define to 1 if you have eliptic curve cryptography */ /* Define to 1 if you have eliptic curve cryptography */
#cmakedefine HAVE_ECC 1 #cmakedefine HAVE_ECC 1
/* Define to 1 if you have DSA */
#cmakedefine HAVE_DSA 1
/* Define to 1 if you have gl_flags as a glob_t sturct member */
#cmakedefine HAVE_GLOB_GL_FLAGS_MEMBER 1
/* Define to 1 if you have OpenSSL with Ed25519 support */
#cmakedefine HAVE_OPENSSL_ED25519 1
/* Define to 1 if you have OpenSSL with X25519 support */
#cmakedefine HAVE_OPENSSL_X25519 1
/* Define to 1 if you have OpenSSL with Poly1305 support */
#cmakedefine HAVE_OPENSSL_EVP_POLY1305 1
/* Define to 1 if you have gcrypt with ChaCha20/Poly1305 support */
#cmakedefine HAVE_GCRYPT_CHACHA_POLY 1
/*************************** FUNCTIONS ***************************/ /*************************** FUNCTIONS ***************************/
/* Define to 1 if you have the `EVP_chacha20' function. */
#cmakedefine HAVE_OPENSSL_EVP_CHACHA20 1
/* Define to 1 if you have the `EVP_KDF_CTX_new_id' or `EVP_KDF_CTX_new` function. */
#cmakedefine HAVE_OPENSSL_EVP_KDF_CTX 1
/* Define to 1 if you have the `FIPS_mode' function. */
#cmakedefine HAVE_OPENSSL_FIPS_MODE 1
/* Define to 1 if you have the `EVP_DigestSign' function. */
#cmakedefine HAVE_OPENSSL_EVP_DIGESTSIGN 1
/* Define to 1 if you have the `EVP_DigestVerify' function. */
#cmakedefine HAVE_OPENSSL_EVP_DIGESTVERIFY 1
/* Define to 1 if you have the `OPENSSL_ia32cap_loc' function. */
#cmakedefine HAVE_OPENSSL_IA32CAP_LOC 1
/* Define to 1 if you have the `snprintf' function. */ /* Define to 1 if you have the `snprintf' function. */
#cmakedefine HAVE_SNPRINTF 1 #cmakedefine HAVE_SNPRINTF 1
@@ -153,9 +100,6 @@
/* Define to 1 if you have the `strncpy' function. */ /* Define to 1 if you have the `strncpy' function. */
#cmakedefine HAVE_STRNCPY 1 #cmakedefine HAVE_STRNCPY 1
/* Define to 1 if you have the `strndup' function. */
#cmakedefine HAVE_STRNDUP 1
/* Define to 1 if you have the `cfmakeraw' function. */ /* Define to 1 if you have the `cfmakeraw' function. */
#cmakedefine HAVE_CFMAKERAW 1 #cmakedefine HAVE_CFMAKERAW 1
@@ -186,21 +130,6 @@
/* Define to 1 if you have the `_strtoui64' function. */ /* Define to 1 if you have the `_strtoui64' function. */
#cmakedefine HAVE__STRTOUI64 1 #cmakedefine HAVE__STRTOUI64 1
/* Define to 1 if you have the `glob' function. */
#cmakedefine HAVE_GLOB 1
/* Define to 1 if you have the `explicit_bzero' function. */
#cmakedefine HAVE_EXPLICIT_BZERO 1
/* Define to 1 if you have the `memset_s' function. */
#cmakedefine HAVE_MEMSET_S 1
/* Define to 1 if you have the `SecureZeroMemory' function. */
#cmakedefine HAVE_SECURE_ZERO_MEMORY 1
/* Define to 1 if you have the `cmocka_set_test_filter' function. */
#cmakedefine HAVE_CMOCKA_SET_TEST_FILTER 1
/*************************** LIBRARIES ***************************/ /*************************** LIBRARIES ***************************/
/* Define to 1 if you have the `crypto' library (-lcrypto). */ /* Define to 1 if you have the `crypto' library (-lcrypto). */
@@ -209,34 +138,20 @@
/* Define to 1 if you have the `gcrypt' library (-lgcrypt). */ /* Define to 1 if you have the `gcrypt' library (-lgcrypt). */
#cmakedefine HAVE_LIBGCRYPT 1 #cmakedefine HAVE_LIBGCRYPT 1
/* Define to 1 if you have the 'mbedTLS' library (-lmbedtls). */
#cmakedefine HAVE_LIBMBEDCRYPTO 1
/* Define to 1 if you have the `pthread' library (-lpthread). */ /* Define to 1 if you have the `pthread' library (-lpthread). */
#cmakedefine HAVE_PTHREAD 1 #cmakedefine HAVE_PTHREAD 1
/* Define to 1 if you have the `cmocka' library (-lcmocka). */
#cmakedefine HAVE_CMOCKA 1
/**************************** OPTIONS ****************************/ /**************************** OPTIONS ****************************/
#cmakedefine HAVE_GCC_THREAD_LOCAL_STORAGE 1 #cmakedefine HAVE_GCC_THREAD_LOCAL_STORAGE 1
#cmakedefine HAVE_MSC_THREAD_LOCAL_STORAGE 1 #cmakedefine HAVE_MSC_THREAD_LOCAL_STORAGE 1
#cmakedefine HAVE_FALLTHROUGH_ATTRIBUTE 1
#cmakedefine HAVE_UNUSED_ATTRIBUTE 1
#cmakedefine HAVE_WEAK_ATTRIBUTE 1
#cmakedefine HAVE_CONSTRUCTOR_ATTRIBUTE 1
#cmakedefine HAVE_DESTRUCTOR_ATTRIBUTE 1
#cmakedefine HAVE_GCC_VOLATILE_MEMORY_PROTECTION 1 #cmakedefine HAVE_GCC_VOLATILE_MEMORY_PROTECTION 1
#cmakedefine HAVE_GCC_NARG_MACRO 1
#cmakedefine HAVE_COMPILER__FUNC__ 1 #cmakedefine HAVE_COMPILER__FUNC__ 1
#cmakedefine HAVE_COMPILER__FUNCTION__ 1 #cmakedefine HAVE_COMPILER__FUNCTION__ 1
#cmakedefine HAVE_GCC_BOUNDED_ATTRIBUTE 1
/* Define to 1 if you want to enable GSSAPI */ /* Define to 1 if you want to enable GSSAPI */
#cmakedefine WITH_GSSAPI 1 #cmakedefine WITH_GSSAPI 1
@@ -246,24 +161,15 @@
/* Define to 1 if you want to enable SFTP */ /* Define to 1 if you want to enable SFTP */
#cmakedefine WITH_SFTP 1 #cmakedefine WITH_SFTP 1
/* Define to 1 if you want to enable SSH1 */
#cmakedefine WITH_SSH1 1
/* Define to 1 if you want to enable server support */ /* Define to 1 if you want to enable server support */
#cmakedefine WITH_SERVER 1 #cmakedefine WITH_SERVER 1
/* Define to 1 if you want to enable DH group exchange algorithms */
#cmakedefine WITH_GEX 1
/* Define to 1 if you want to enable none cipher and MAC */
#cmakedefine WITH_INSECURE_NONE 1
/* Define to 1 if you want to enable blowfish cipher support */
#cmakedefine WITH_BLOWFISH_CIPHER 1
/* Define to 1 if you want to enable debug output for crypto functions */ /* Define to 1 if you want to enable debug output for crypto functions */
#cmakedefine DEBUG_CRYPTO 1 #cmakedefine DEBUG_CRYPTO 1
/* Define to 1 if you want to enable debug output for packet functions */
#cmakedefine DEBUG_PACKET 1
/* Define to 1 if you want to enable pcap output support (experimental) */ /* Define to 1 if you want to enable pcap output support (experimental) */
#cmakedefine WITH_PCAP 1 #cmakedefine WITH_PCAP 1
@@ -273,9 +179,6 @@
/* Define to 1 if you want to enable NaCl support */ /* Define to 1 if you want to enable NaCl support */
#cmakedefine WITH_NACL 1 #cmakedefine WITH_NACL 1
/* Define to 1 if you want to enable PKCS #11 URI support */
#cmakedefine WITH_PKCS11_URI 1
/*************************** ENDIAN *****************************/ /*************************** ENDIAN *****************************/
/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most /* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most

View File

@@ -1,49 +1,5 @@
# #
# Build the documentation # Build the documentation
# #
if (${CMAKE_VERSION} VERSION_GREATER "3.8.99") include(UseDoxygen OPTIONAL)
find_package(Doxygen)
if (DOXYGEN_FOUND)
set(DOXYGEN_PROJECT_NAME ${PROJECT_NAME})
set(DOXYGEN_PROJECT_NUMBER ${PROJECT_VERSION})
set(DOXYGEN_PROJECT_BRIEF "The SSH library")
set(DOXYGEN_TAB_SIZE 4)
set(DOXYGEN_OPTIMIZE_OUTPUT_FOR_C YES)
set(DOXYGEN_MARKDOWN_SUPPORT YES)
set(DOXYGEN_FULL_PATH_NAMES NO)
set(DOXYGEN_PREDEFINED DOXYGEN
WITH_SERVER
WITH_SFTP
PRINTF_ATTRIBUTE(x,y))
set(DOXYGEN_EXCLUDE ${CMAKE_CURRENT_SOURCE_DIR}/that_style)
set(DOXYGEN_HTML_HEADER ${CMAKE_CURRENT_SOURCE_DIR}/that_style/header.html)
set(DOXYGEN_HTML_EXTRA_STYLESHEET ${CMAKE_CURRENT_SOURCE_DIR}/that_style/that_style.css)
set(DOXYGEN_HTML_EXTRA_FILES ${CMAKE_CURRENT_SOURCE_DIR}/that_style/img/nav_edge_left.svg
${CMAKE_CURRENT_SOURCE_DIR}/that_style/img/nav_edge_right.svg
${CMAKE_CURRENT_SOURCE_DIR}/that_style/img/nav_edge_inter.svg
${CMAKE_CURRENT_SOURCE_DIR}/that_style/img/sync_off.png
${CMAKE_CURRENT_SOURCE_DIR}/that_style/img/sync_on.png
${CMAKE_CURRENT_SOURCE_DIR}/that_style/img/splitbar_handle.svg
${CMAKE_CURRENT_SOURCE_DIR}/that_style/img/doc.svg
${CMAKE_CURRENT_SOURCE_DIR}/that_style/img/mag_glass.svg
${CMAKE_CURRENT_SOURCE_DIR}/that_style/img/folderclosed.svg
${CMAKE_CURRENT_SOURCE_DIR}/that_style/img/folderopen.svg
${CMAKE_CURRENT_SOURCE_DIR}/that_style/js/striped_bg.js)
# This updates the Doxyfile if we do changes here
set(_doxyfile_template "${CMAKE_BINARY_DIR}/CMakeDoxyfile.in")
set(_target_doxyfile "${CMAKE_CURRENT_BINARY_DIR}/Doxyfile.docs")
configure_file("${_doxyfile_template}" "${_target_doxyfile}")
doxygen_add_docs(docs
${CMAKE_SOURCE_DIR}/include/libssh
${CMAKE_SOURCE_DIR}/src
${CMAKE_CURRENT_SOURCE_DIR})
endif() # DOXYGEN_FOUND
endif() # CMAKE_VERSION

1917
doc/Doxyfile.in Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,101 +0,0 @@
# Install a FreeBSD CI instance
Install the following packages:
```
pkg install -y bash git gmake cmake cmocka openssl wget pkgconf ccache bash
```
Create gitlab-runner user:
```
pw group add -n gitlab-runner
pw user add -n gitlab-runner -g gitlab-runner -s /usr/local/bin/bash
mkdir /home/gitlab-runner
chown gitlab-runner:gitlab-runner /home/gitlab-runner
```
Get the gitlab-runner binary for freebsd:
```
wget -O /usr/local/bin/gitlab-runner https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-freebsd-amd64
chmod +x /usr/local/bin/gitlab-runner
```
Create a log file and allow access:
```
touch /var/log/gitlab_runner.log && chown gitlab-runner:gitlab-runner /var/log/gitlab_runner.log
```
We need a start script to run it on boot:
```
mkdir -p /usr/local/etc/rc.d
cat > /usr/local/etc/rc.d/gitlab_runner << EOF
#!/usr/local/bin/bash
# PROVIDE: gitlab_runner
# REQUIRE: DAEMON NETWORKING
# BEFORE:
# KEYWORD:
. /etc/rc.subr
name="gitlab_runner"
rcvar="gitlab_runner_enable"
load_rc_config $name
user="gitlab-runner"
user_home="/home/gitlab-runner"
command="/usr/local/bin/gitlab-runner run"
pidfile="/var/run/${name}.pid"
start_cmd="gitlab_runner_start"
stop_cmd="gitlab_runner_stop"
status_cmd="gitlab_runner_status"
gitlab_runner_start()
{
export USER=${user}
export HOME=${user_home}
if checkyesno ${rcvar}; then
cd ${user_home}
/usr/sbin/daemon -u ${user} -p ${pidfile} ${command} > /var/log/gitlab_runner.log 2>&1
fi
}
gitlab_runner_stop()
{
if [ -f ${pidfile} ]; then
kill `cat ${pidfile}`
fi
}
gitlab_runner_status()
{
if [ ! -f ${pidfile} ] || kill -0 `cat ${pidfile}`; then
echo "Service ${name} is not running."
else
echo "${name} appears to be running."
fi
}
run_rc_command $1
EOF
chmod +x /usr/local/etc/rc.d/gitlab_runner
```
Register your gitlab-runner with your gitlab project
```
su gitlab-runner -c 'gitlab-runner register'
```
Start the gitlab runner service:
```
sysrc -f /etc/rc.conf "gitlab_runner_enable=YES"
service gitlab_runner start
```

View File

@@ -33,9 +33,6 @@ The process of authenticating by public key to a server is the following:
used to authenticate the user). used to authenticate the user).
- then, you retrieve the private key for this key and send a message - then, you retrieve the private key for this key and send a message
proving that you know that private key. proving that you know that private key.
- when several identity files are specified, then the order of processing of
these files is from the last-mentioned to the first one
(if specified in the ~/.ssh/config, then starting from the bottom to the top).
The function ssh_userauth_autopubkey() does this using the available keys in The function ssh_userauth_autopubkey() does this using the available keys in
"~/.ssh/". The return values are the following: "~/.ssh/". The return values are the following:
@@ -49,7 +46,7 @@ The ssh_userauth_publickey_auto() function also tries to authenticate using the
SSH agent, if you have one running, or the "none" method otherwise. SSH agent, if you have one running, or the "none" method otherwise.
If you wish to authenticate with public key by your own, follow these steps: If you wish to authenticate with public key by your own, follow these steps:
- Retrieve the public key with ssh_pki_import_pubkey_file(). - Retrieve the public key with ssh_import_pubkey_file().
- Offer the public key to the SSH server using ssh_userauth_try_publickey(). - Offer the public key to the SSH server using ssh_userauth_try_publickey().
If the return value is SSH_AUTH_SUCCESS, the SSH server accepts to If the return value is SSH_AUTH_SUCCESS, the SSH server accepts to
authenticate using the public key and you can go to the next step. authenticate using the public key and you can go to the next step.
@@ -66,7 +63,7 @@ int authenticate_pubkey(ssh_session session)
{ {
int rc; int rc;
rc = ssh_userauth_publickey_auto(session, NULL, NULL); rc = ssh_userauth_publickey_auto(session, NULL);
if (rc == SSH_AUTH_ERROR) if (rc == SSH_AUTH_ERROR)
{ {
@@ -130,7 +127,7 @@ The keyboard-interactive method is, as its name tells, interactive. The
server will issue one or more challenges that the user has to answer, server will issue one or more challenges that the user has to answer,
until the server takes an authentication decision. until the server takes an authentication decision.
ssh_userauth_kbdint() is the the main keyboard-interactive function. ssh_userauth_kbdint() is the the main keyboard-interactive function.
It will return SSH_AUTH_SUCCESS,SSH_AUTH_DENIED, SSH_AUTH_PARTIAL, It will return SSH_AUTH_SUCCESS,SSH_AUTH_DENIED, SSH_AUTH_PARTIAL,
SSH_AUTH_ERROR, or SSH_AUTH_INFO, depending on the result of the request. SSH_AUTH_ERROR, or SSH_AUTH_INFO, depending on the result of the request.
@@ -157,9 +154,9 @@ Here are a few remarks:
- Even the first call can return SSH_AUTH_DENIED or SSH_AUTH_SUCCESS. - Even the first call can return SSH_AUTH_DENIED or SSH_AUTH_SUCCESS.
- The server can send an empty question set (this is the default behavior - The server can send an empty question set (this is the default behavior
on my system) after you have sent the answers to the first questions. on my system) after you have sent the answers to the first questions.
You must still parse the answer, it might contain some You must still parse the answer, it might contain some
message from the server saying hello or such things. Just call message from the server saying hello or such things. Just call
ssh_userauth_kbdint() until needed. ssh_userauth_kbdint() until needed.
- The meaning of "name", "prompt", "instruction" may be a little - The meaning of "name", "prompt", "instruction" may be a little
confusing. An explanation is given in the RFC section that follows. confusing. An explanation is given in the RFC section that follows.
@@ -190,7 +187,7 @@ keyboard-interactive authentication, coming from the RFC itself (rfc4256):
the name and prompts. If the server presents names or prompts longer than 30 the name and prompts. If the server presents names or prompts longer than 30
characters, the client MAY truncate these fields to the length it can characters, the client MAY truncate these fields to the length it can
display. If the client does truncate any fields, there MUST be an obvious display. If the client does truncate any fields, there MUST be an obvious
indication that such truncation has occurred. indication that such truncation has occured.
The instruction field SHOULD NOT be truncated. Clients SHOULD use control The instruction field SHOULD NOT be truncated. Clients SHOULD use control
character filtering as discussed in [SSH-ARCH] to avoid attacks by character filtering as discussed in [SSH-ARCH] to avoid attacks by
@@ -284,7 +281,7 @@ pass, ssh_userauth_none() might answer SSH_AUTH_SUCCESS.
The following example shows how to perform "none" authentication: The following example shows how to perform "none" authentication:
@code @code
int authenticate_none(ssh_session session) int authenticate_kbdint(ssh_session session)
{ {
int rc; int rc;
@@ -308,7 +305,7 @@ int test_several_auth_methods(ssh_session session)
int method, rc; int method, rc;
rc = ssh_userauth_none(session, NULL); rc = ssh_userauth_none(session, NULL);
if (rc == SSH_AUTH_SUCCESS || rc == SSH_AUTH_ERROR) { if (rc != SSH_AUTH_SUCCESS) {
return rc; return rc;
} }

View File

@@ -56,7 +56,7 @@ If an error has been encountered, it returns a negative value:
@code @code
char buffer[256]; char buffer[256];
int nbytes; unsigned int nbytes;
nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0); nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
while (nbytes > 0) while (nbytes > 0)

View File

@@ -112,8 +112,8 @@ This number is calculated using the following procedure:
This conversion follows the network byte order. This step differs from This conversion follows the network byte order. This step differs from
RFC5656. RFC5656.
[RFC5656] https://tools.ietf.org/html/rfc5656 [RFC5656] http://tools.ietf.org/html/rfc5656
[SCHNEIER] https://www.schneier.com/blog/archives/2013/09/the_nsa_is_brea.html#c1675929 [SCHNEIER] https://www.schneier.com/blog/archives/2013/09/the_nsa_is_brea.html#c1675929
[DJB] https://cr.yp.to/talks/2013.05.31/slides-dan+tanja-20130531-4x3.pdf [DJB] http://cr.yp.to/talks/2013.05.31/slides-dan+tanja-20130531-4x3.pdf
[Curve25519] "Curve25519: new Diffie-Hellman speed records." [Curve25519] "Curve25519: new Diffie-Hellman speed records."
https://cr.yp.to/ecdh/curve25519-20060209.pdf http://cr.yp.to/ecdh/curve25519-20060209.pdf

View File

@@ -4,7 +4,7 @@
Port forwarding comes in SSH protocol in two different flavours: Port forwarding comes in SSH protocol in two different flavours:
direct or reverse port forwarding. Direct port forwarding is also direct or reverse port forwarding. Direct port forwarding is also
named local port forwarding, and reverse port forwarding is also called named local port forwardind, and reverse port forwarding is also called
remote port forwarding. SSH also allows X11 tunnels. remote port forwarding. SSH also allows X11 tunnels.
@@ -23,15 +23,15 @@ Mail client application Google Mail
5555 (arbitrary) | 5555 (arbitrary) |
| 143 (IMAP2) | 143 (IMAP2)
V | V |
SSH client =====> SSH server SSH client =====> SSH server
Legend: Legend:
--P-->: port connections through port P --P-->: port connexion through port P
=====>: SSH tunnel =====>: SSH tunnel
@endverbatim @endverbatim
A mail client connects to port 5555 of a client. An encrypted tunnel is A mail client connects to port 5555 of a client. An encrypted tunnel is
established to the server. The server connects to port 143 of Google Mail (the established to the server. The server connects to port 143 of Google Mail (the
end point). Now the local mail client can retrieve mail. end point). Now the local mail client can retreive mail.
@subsection forwarding_reverse Reverse port forwarding @subsection forwarding_reverse Reverse port forwarding
@@ -51,7 +51,7 @@ Example of use of reverse port forwarding:
SSH client <===== SSH server SSH client <===== SSH server
Legend: Legend:
--P-->: port connections through port P --P-->: port connexion through port P
=====>: SSH tunnel =====>: SSH tunnel
@endverbatim @endverbatim
In this example, the SSH client establishes the tunnel, In this example, the SSH client establishes the tunnel,
@@ -101,7 +101,7 @@ used to retrieve google's home page from the remote SSH server.
int direct_forwarding(ssh_session session) int direct_forwarding(ssh_session session)
{ {
ssh_channel forwarding_channel; ssh_channel forwarding_channel;
int rc = SSH_ERROR; int rc;
char *http_get = "GET / HTTP/1.1\nHost: www.google.com\n\n"; char *http_get = "GET / HTTP/1.1\nHost: www.google.com\n\n";
int nbytes, nwritten; int nbytes, nwritten;
@@ -148,9 +148,9 @@ To do reverse port forwarding, call ssh_channel_listen_forward(),
then ssh_channel_accept_forward(). then ssh_channel_accept_forward().
When you call ssh_channel_listen_forward(), you can let the remote server When you call ssh_channel_listen_forward(), you can let the remote server
chose the non-privileged port it should listen to. Otherwise, you can chose chose the non-priviledged port it should listen to. Otherwise, you can chose
your own privileged or non-privileged port. Beware that you should have your own priviledged or non-priviledged port. Beware that you should have
administrative privileges on the remote server to open a privileged port administrative priviledges on the remote server to open a priviledged port
(port number < 1024). (port number < 1024).
Below is an example of a very rough web server waiting for connections on port Below is an example of a very rough web server waiting for connections on port
@@ -165,8 +165,6 @@ int web_server(ssh_session session)
char buffer[256]; char buffer[256];
int nbytes, nwritten; int nbytes, nwritten;
int port = 0; int port = 0;
char *peer_address = NULL;
int peer_port = 0;
char *helloworld = "" char *helloworld = ""
"HTTP/1.1 200 OK\n" "HTTP/1.1 200 OK\n"
"Content-Type: text/html\n" "Content-Type: text/html\n"
@@ -189,8 +187,7 @@ int web_server(ssh_session session)
return rc; return rc;
} }
channel = ssh_channel_open_forward_port(session, 60000, &port, channel = ssh_channel_accept_forward(session, 60000, &port);
&peer_address, &peer_port);
if (channel == NULL) if (channel == NULL)
{ {
fprintf(stderr, "Error waiting for incoming connection: %s\n", fprintf(stderr, "Error waiting for incoming connection: %s\n",
@@ -207,7 +204,6 @@ int web_server(ssh_session session)
ssh_get_error(session)); ssh_get_error(session));
ssh_channel_send_eof(channel); ssh_channel_send_eof(channel);
ssh_channel_free(channel); ssh_channel_free(channel);
ssh_string_free_char(peer_address);
return SSH_ERROR; return SSH_ERROR;
} }
if (strncmp(buffer, "GET /", 5)) continue; if (strncmp(buffer, "GET /", 5)) continue;
@@ -220,15 +216,13 @@ int web_server(ssh_session session)
ssh_get_error(session)); ssh_get_error(session));
ssh_channel_send_eof(channel); ssh_channel_send_eof(channel);
ssh_channel_free(channel); ssh_channel_free(channel);
ssh_string_free_char(peer_address);
return SSH_ERROR; return SSH_ERROR;
} }
printf("Sent answer to %s:%d\n", peer_address, peer_port); printf("Sent answer\n");
} }
ssh_channel_send_eof(channel); ssh_channel_send_eof(channel);
ssh_channel_free(channel); ssh_channel_free(channel);
ssh_string_free_char(peer_address);
return SSH_OK; return SSH_OK;
} }
@endcode @endcode

View File

@@ -31,20 +31,20 @@ A SSH session goes through the following steps:
- Invoke your own subsystem. This is outside the scope of this document, - Invoke your own subsystem. This is outside the scope of this document,
but can be done. but can be done.
- When everything is finished, just close the channels, and then the connection. - When everything is finished, just close the channels, and then the connection.
The sftp and scp subsystems use channels, but libssh hides them to The sftp and scp subsystems use channels, but libssh hides them to
the programmer. If you want to use those subsystems, instead of a channel, the programmer. If you want to use those subsystems, instead of a channel,
you'll usually open a "sftp session" or a "scp session". you'll usually open a "sftp session" or a "scp session".
@subsection setup Creating the session and setting options @subsection setup Creating the session and setting options
The most important object in a SSH connection is the SSH session. In order The most important object in a SSH connection is the SSH session. In order
to allocate a new SSH session, you use ssh_new(). Don't forget to to allocate a new SSH session, you use ssh_new(). Don't forget to
always verify that the allocation succeeded. always verify that the allocation successed.
@code @code
#include <libssh/libssh.h> #include <libssh/libssh.h>
#include <stdlib.h> #include <stdlib.h>
int main() int main()
@@ -69,12 +69,12 @@ The ssh_options_set() function sets the options of the session. The most importa
The complete list of options can be found in the documentation of ssh_options_set(). The complete list of options can be found in the documentation of ssh_options_set().
The only mandatory option is SSH_OPTIONS_HOST. If you don't use SSH_OPTIONS_USER, The only mandatory option is SSH_OPTIONS_HOST. If you don't use SSH_OPTIONS_USER,
the local username of your account will be used. the local username of your account will be used.
Here is a small example of how to use it: Here is a small example of how to use it:
@code @code
#include <libssh/libssh.h> #include <libssh/libssh.h>
#include <stdlib.h> #include <stdlib.h>
int main() int main()
@@ -122,7 +122,7 @@ Here's an example:
@code @code
#include <libssh/libssh.h> #include <libssh/libssh.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
int main() int main()
{ {
@@ -158,7 +158,7 @@ you just connected to is known and safe to use (remember, SSH is about security
authentication). authentication).
There are two ways of doing this: There are two ways of doing this:
- The first way (recommended) is to use the ssh_session_is_known_server() - The first way (recommended) is to use the ssh_is_server_known()
function. This function will look into the known host file function. This function will look into the known host file
(~/.ssh/known_hosts on UNIX), look for the server hostname's pattern, (~/.ssh/known_hosts on UNIX), look for the server hostname's pattern,
and determine whether this host is present or not in the list. and determine whether this host is present or not in the list.
@@ -185,89 +185,74 @@ examples/ directory:
int verify_knownhost(ssh_session session) int verify_knownhost(ssh_session session)
{ {
enum ssh_known_hosts_e state; int state, hlen;
unsigned char *hash = NULL; unsigned char *hash = NULL;
ssh_key srv_pubkey = NULL; char *hexa;
size_t hlen; char buf[10];
char buf[10];
char *hexa;
char *p;
int cmp;
int rc;
rc = ssh_get_server_publickey(session, &srv_pubkey); state = ssh_is_server_known(session);
if (rc < 0) {
hlen = ssh_get_pubkey_hash(session, &hash);
if (hlen < 0)
return -1;
switch (state)
{
case SSH_SERVER_KNOWN_OK:
break; /* ok */
case SSH_SERVER_KNOWN_CHANGED:
fprintf(stderr, "Host key for server changed: it is now:\n");
ssh_print_hexa("Public key hash", hash, hlen);
fprintf(stderr, "For security reasons, connection will be stopped\n");
free(hash);
return -1;
case SSH_SERVER_FOUND_OTHER:
fprintf(stderr, "The host key for this server was not found but an other"
"type of key exists.\n");
fprintf(stderr, "An attacker might change the default server key to"
"confuse your client into thinking the key does not exist\n");
free(hash);
return -1;
case SSH_SERVER_FILE_NOT_FOUND:
fprintf(stderr, "Could not find known host file.\n");
fprintf(stderr, "If you accept the host key here, the file will be"
"automatically created.\n");
/* fallback to SSH_SERVER_NOT_KNOWN behavior */
case SSH_SERVER_NOT_KNOWN:
hexa = ssh_get_hexa(hash, hlen);
fprintf(stderr,"The server is unknown. Do you trust the host key?\n");
fprintf(stderr, "Public key hash: %s\n", hexa);
free(hexa);
if (fgets(buf, sizeof(buf), stdin) == NULL)
{
free(hash);
return -1; return -1;
} }
if (strncasecmp(buf, "yes", 3) != 0)
rc = ssh_get_publickey_hash(srv_pubkey, {
SSH_PUBLICKEY_HASH_SHA1, free(hash);
&hash,
&hlen);
ssh_key_free(srv_pubkey);
if (rc < 0) {
return -1; return -1;
} }
if (ssh_write_knownhost(session) < 0)
{
fprintf(stderr, "Error %s\n", strerror(errno));
free(hash);
return -1;
}
break;
state = ssh_session_is_known_server(session); case SSH_SERVER_ERROR:
switch (state) { fprintf(stderr, "Error %s", ssh_get_error(session));
case SSH_KNOWN_HOSTS_OK: free(hash);
/* OK */ return -1;
}
break; free(hash);
case SSH_KNOWN_HOSTS_CHANGED: return 0;
fprintf(stderr, "Host key for server changed: it is now:\n");
ssh_print_hexa("Public key hash", hash, hlen);
fprintf(stderr, "For security reasons, connection will be stopped\n");
ssh_clean_pubkey_hash(&hash);
return -1;
case SSH_KNOWN_HOSTS_OTHER:
fprintf(stderr, "The host key for this server was not found but an other"
"type of key exists.\n");
fprintf(stderr, "An attacker might change the default server key to"
"confuse your client into thinking the key does not exist\n");
ssh_clean_pubkey_hash(&hash);
return -1;
case SSH_KNOWN_HOSTS_NOT_FOUND:
fprintf(stderr, "Could not find known host file.\n");
fprintf(stderr, "If you accept the host key here, the file will be"
"automatically created.\n");
/* FALL THROUGH to SSH_SERVER_NOT_KNOWN behavior */
case SSH_KNOWN_HOSTS_UNKNOWN:
hexa = ssh_get_hexa(hash, hlen);
fprintf(stderr,"The server is unknown. Do you trust the host key?\n");
fprintf(stderr, "Public key hash: %s\n", hexa);
ssh_string_free_char(hexa);
ssh_clean_pubkey_hash(&hash);
p = fgets(buf, sizeof(buf), stdin);
if (p == NULL) {
return -1;
}
cmp = strncasecmp(buf, "yes", 3);
if (cmp != 0) {
return -1;
}
rc = ssh_session_update_known_hosts(session);
if (rc < 0) {
fprintf(stderr, "Error %s\n", strerror(errno));
return -1;
}
break;
case SSH_KNOWN_HOSTS_ERROR:
fprintf(stderr, "Error %s", ssh_get_error(session));
ssh_clean_pubkey_hash(&hash);
return -1;
}
ssh_clean_pubkey_hash(&hash);
return 0;
} }
@endcode @endcode
@@ -275,19 +260,18 @@ int verify_knownhost(ssh_session session)
@see ssh_disconnect @see ssh_disconnect
@see ssh_get_error @see ssh_get_error
@see ssh_get_error_code @see ssh_get_error_code
@see ssh_get_server_publickey @see ssh_get_pubkey_hash
@see ssh_get_publickey_hash @see ssh_is_server_known
@see ssh_session_is_known_server @see ssh_write_knownhost
@see ssh_session_update_known_hosts
@subsection auth Authenticating the user @subsection auth Authenticating the user
The authentication process is the way a service provider can identify a The authentication process is the way a service provider can identify a
user and verify his/her identity. The authorization process is about enabling user and verify his/her identity. The authorization process is about enabling
the authenticated user the access to resources. In SSH, the two concepts the authenticated user the access to ressources. In SSH, the two concepts
are linked. After authentication, the server can grant the user access to are linked. After authentication, the server can grant the user access to
several resources such as port forwarding, shell, sftp subsystem, and so on. several ressources such as port forwarding, shell, sftp subsystem, and so on.
libssh supports several methods of authentication: libssh supports several methods of authentication:
- "none" method. This method allows to get the available authentications - "none" method. This method allows to get the available authentications
@@ -313,7 +297,7 @@ The example below shows an authentication with password:
@code @code
#include <libssh/libssh.h> #include <libssh/libssh.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
int main() int main()
{ {
@@ -338,7 +322,7 @@ int main()
} }
// Verify the server's identity // Verify the server's identity
// For the source code of verify_knownhost(), check previous example // For the source code of verify_knowhost(), check previous example
if (verify_knownhost(my_ssh_session) < 0) if (verify_knownhost(my_ssh_session) < 0)
{ {
ssh_disconnect(my_ssh_session); ssh_disconnect(my_ssh_session);
@@ -383,7 +367,7 @@ int show_remote_processes(ssh_session session)
ssh_channel channel; ssh_channel channel;
int rc; int rc;
char buffer[256]; char buffer[256];
int nbytes; unsigned int nbytes;
channel = ssh_channel_new(session); channel = ssh_channel_new(session);
if (channel == NULL) if (channel == NULL)
@@ -407,7 +391,7 @@ int show_remote_processes(ssh_session session)
nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0); nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
while (nbytes > 0) while (nbytes > 0)
{ {
if (write(1, buffer, nbytes) != (unsigned int) nbytes) if (write(1, buffer, nbytes) != nbytes)
{ {
ssh_channel_close(channel); ssh_channel_close(channel);
ssh_channel_free(channel); ssh_channel_free(channel);
@@ -415,7 +399,7 @@ int show_remote_processes(ssh_session session)
} }
nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0); nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
} }
if (nbytes < 0) if (nbytes < 0)
{ {
ssh_channel_close(channel); ssh_channel_close(channel);
@@ -431,9 +415,6 @@ int show_remote_processes(ssh_session session)
} }
@endcode @endcode
Each ssh_channel_request_exec() needs to be run on freshly created
and connected (with ssh_channel_open_session()) channel.
@see @ref opening_shell @see @ref opening_shell
@see @ref remote_command @see @ref remote_command
@see @ref sftp_subsystem @see @ref sftp_subsystem
@@ -459,7 +440,7 @@ might be recoverable. SSH_FATAL means the connection has an important
problem and isn't probably recoverable. problem and isn't probably recoverable.
Most of time, the error returned are SSH_FATAL, but some functions Most of time, the error returned are SSH_FATAL, but some functions
(generally the ssh_request_xxx ones) may fail because of server denying request. (generaly the ssh_request_xxx ones) may fail because of server denying request.
In these cases, SSH_REQUEST_DENIED is returned. In these cases, SSH_REQUEST_DENIED is returned.
For thread safety, errors are bound to ssh_session objects. For thread safety, errors are bound to ssh_session objects.

View File

@@ -12,13 +12,13 @@ mean that you should not try to know about and understand these details.
libssh is a Free Software / Open Source project. The libssh library libssh is a Free Software / Open Source project. The libssh library
is distributed under LGPL license. The libssh project has nothing to do with is distributed under LGPL license. The libssh project has nothing to do with
"libssh2", which is a completely different and independent project. "libssh2", which is a completly different and independant project.
libssh can run on top of either libgcrypt or libcrypto, libssh can run on top of either libgcrypt or libcrypto,
two general-purpose cryptographic libraries. two general-purpose cryptographic libraries.
This tutorial concentrates for its main part on the "client" side of libssh. This tutorial concentrates for its main part on the "client" side of libssh.
To learn how to accept incoming SSH connections (how to write a SSH server), To learn how to accept incoming SSH connexions (how to write a SSH server),
you'll have to jump to the end of this document. you'll have to jump to the end of this document.
This tutorial describes libssh version 0.5.0. This version is a little different This tutorial describes libssh version 0.5.0. This version is a little different

View File

@@ -27,7 +27,4 @@ the dllimport attribute.
#include <libssh/libssh.h> #include <libssh/libssh.h>
@endcode @endcode
If you're are statically linking with OpenSSL, read the "Linking your
application" section in the NOTES.[OS] in the OpenSSL source tree!
*/ */

View File

@@ -19,16 +19,16 @@ the interesting functions as you go.
The libssh library provides: The libssh library provides:
- <strong>Key Exchange Methods</strong>: <i>curve25519-sha256, curve25519-sha256@libssh.org, ecdh-sha2-nistp256, ecdh-sha2-nistp384, ecdh-sha2-nistp521</i>, diffie-hellman-group1-sha1, diffie-hellman-group14-sha1 - <strong>Key Exchange Methods</strong>: <i>curve25519-sha256@libssh.org, ecdh-sha2-nistp256</i>, diffie-hellman-group1-sha1, diffie-hellman-group14-sha1
- <strong>Public Key Algorithms</strong>: ssh-ed25519, ecdsa-sha2-nistp256, ecdsa-sha2-nistp384, ecdsa-sha2-nistp521, ssh-rsa, rsa-sha2-512, rsa-sha2-256,ssh-dss - <strong>Hostkey Types</strong>: <i>ecdsa-sha2-nistp256</i>, ssh-dss, ssh-rsa
- <strong>Ciphers</strong>: <i>aes256-ctr, aes192-ctr, aes128-ctr</i>, aes256-cbc (rijndael-cbc@lysator.liu.se), aes192-cbc, aes128-cbc, 3des-cbc, blowfish-cbc - <strong>Ciphers</strong>: <i>aes256-ctr, aes192-ctr, aes128-ctr</i>, aes256-cbc (rijndael-cbc@lysator.liu.se), aes192-cbc, aes128-cbc, 3des-cbc, des-cbc-ssh1, blowfish-cbc, none
- <strong>Compression Schemes</strong>: zlib, <i>zlib@openssh.com</i>, none - <strong>Compression Schemes</strong>: zlib, <i>zlib@openssh.com</i>, none
- <strong>MAC hashes</strong>: hmac-sha1, hmac-sha2-256, hmac-sha2-512, hmac-md5 - <strong>MAC hashes</strong>: hmac-sha1, none
- <strong>Authentication</strong>: none, password, public-key, keyboard-interactive, <i>gssapi-with-mic</i> - <strong>Authentication</strong>: none, password, public-key, hostbased, keyboard-interactive, <i>gssapi-with-mic</i>
- <strong>Channels</strong>: shell, exec (incl. SCP wrapper), direct-tcpip, subsystem, <i>auth-agent-req@openssh.com</i> - <strong>Channels</strong>: shell, exec (incl. SCP wrapper), direct-tcpip, subsystem, <i>auth-agent-req@openssh.com</i>
- <strong>Global Requests</strong>: tcpip-forward, forwarded-tcpip - <strong>Global Requests</strong>: tcpip-forward, forwarded-tcpip
- <strong>Channel Requests</strong>: x11, pty, <i>exit-status, signal, exit-signal, keepalive@openssh.com, auth-agent-req@openssh.com</i> - <strong>Channel Requests</strong>: x11, pty, <i>exit-status, signal, exit-signal, keepalive@openssh.com, auth-agent-req@openssh.com</i>
- <strong>Subsystems</strong>: sftp(version 3), <i>OpenSSH Extensions</i> - <strong>Subsystems</strong>: sftp(version 3), publickey(version 2), <i>OpenSSH Extensions</i>
- <strong>SFTP</strong>: <i>statvfs@openssh.com, fstatvfs@openssh.com</i> - <strong>SFTP</strong>: <i>statvfs@openssh.com, fstatvfs@openssh.com</i>
- <strong>Thread-safe</strong>: Just don't share sessions - <strong>Thread-safe</strong>: Just don't share sessions
- <strong>Non-blocking</strong>: it can be used both blocking and non-blocking - <strong>Non-blocking</strong>: it can be used both blocking and non-blocking
@@ -38,9 +38,9 @@ The libssh library provides:
@section main-additional-features Additional Features @section main-additional-features Additional Features
- Client <b>and</b> server support - Client <b>and</b> server support
- SSHv2 protocol support - SSHv2 and SSHv1 protocol support
- Supports <a href="https://test.libssh.org/" target="_blank">Linux, UNIX, BSD, Solaris, OS/2 and Windows</a> - Supports <a href="http://test.libssh.org/" target="_blank">Linux, UNIX, BSD, Solaris, OS/2 and Windows</a>
- Automated test cases with nightly <a href="https://test.libssh.org/" target="_blank">tests</a> - Automated test cases with nightly <a href="http://test.libssh.org/" target="_blank">tests</a>
- Event model based on poll(2), or a poll(2)-emulation. - Event model based on poll(2), or a poll(2)-emulation.
@section main-copyright Copyright Policy @section main-copyright Copyright Policy
@@ -111,7 +111,7 @@ By making a contribution to this project, I certify that:
Free Software Foundation; either version 2.1 of Free Software Foundation; either version 2.1 of
the License, or (at the option of the project) any later version. the License, or (at the option of the project) any later version.
https://www.gnu.org/licenses/lgpl-2.1.html http://www.gnu.org/licenses/lgpl-2.1.html
@endverbatim @endverbatim
We will maintain a copy of that email as a record that you have the rights to We will maintain a copy of that email as a record that you have the rights to
@@ -151,81 +151,47 @@ The libssh Team
The following RFC documents described SSH-2 protcol as an Internet standard. The following RFC documents described SSH-2 protcol as an Internet standard.
- <a href="https://tools.ietf.org/html/rfc4250" target="_blank">RFC 4250</a>, - <a href="http://tools.ietf.org/html/rfc4250" target="_blank">RFC 4250</a>,
The Secure Shell (SSH) Protocol Assigned Numbers The Secure Shell (SSH) Protocol Assigned Numbers
- <a href="https://tools.ietf.org/html/rfc4251" target="_blank">RFC 4251</a>, - <a href="http://tools.ietf.org/html/rfc4251" target="_blank">RFC 4251</a>,
The Secure Shell (SSH) Protocol Architecture The Secure Shell (SSH) Protocol Architecture
- <a href="https://tools.ietf.org/html/rfc4252" target="_blank">RFC 4252</a>, - <a href="http://tools.ietf.org/html/rfc4252" target="_blank">RFC 4252</a>,
The Secure Shell (SSH) Authentication Protocol The Secure Shell (SSH) Authentication Protocol
- <a href="https://tools.ietf.org/html/rfc4253" target="_blank">RFC 4253</a>, - <a href="http://tools.ietf.org/html/rfc4253" target="_blank">RFC 4253</a>,
The Secure Shell (SSH) Transport Layer Protocol The Secure Shell (SSH) Transport Layer Protocol
- <a href="https://tools.ietf.org/html/rfc4254" target="_blank">RFC 4254</a>, - <a href="http://tools.ietf.org/html/rfc4254" target="_blank">RFC 4254</a>,
The Secure Shell (SSH) Connection Protocol The Secure Shell (SSH) Connection Protocol
- <a href="https://tools.ietf.org/html/rfc4255" target="_blank">RFC 4255</a>, - <a href="http://tools.ietf.org/html/rfc4255" target="_blank">RFC 4255</a>,
Using DNS to Securely Publish Secure Shell (SSH) Key Fingerprints Using DNS to Securely Publish Secure Shell (SSH) Key Fingerprints
(not implemented in libssh) - <a href="http://tools.ietf.org/html/rfc4256" target="_blank">RFC 4256</a>,
- <a href="https://tools.ietf.org/html/rfc4256" target="_blank">RFC 4256</a>,
Generic Message Exchange Authentication for the Secure Shell Protocol (SSH) Generic Message Exchange Authentication for the Secure Shell Protocol (SSH)
- <a href="https://tools.ietf.org/html/rfc4335" target="_blank">RFC 4335</a>, - <a href="http://tools.ietf.org/html/rfc4335" target="_blank">RFC 4335</a>,
The Secure Shell (SSH) Session Channel Break Extension The Secure Shell (SSH) Session Channel Break Extension
- <a href="https://tools.ietf.org/html/rfc4344" target="_blank">RFC 4344</a>, - <a href="http://tools.ietf.org/html/rfc4344" target="_blank">RFC 4344</a>,
The Secure Shell (SSH) Transport Layer Encryption Modes The Secure Shell (SSH) Transport Layer Encryption Modes
- <a href="https://tools.ietf.org/html/rfc4345" target="_blank">RFC 4345</a>, - <a href="http://tools.ietf.org/html/rfc4345" target="_blank">RFC 4345</a>,
Improved Arcfour Modes for the Secure Shell (SSH) Transport Layer Protocol Improved Arcfour Modes for the Secure Shell (SSH) Transport Layer Protocol
It was later modified and expanded by the following RFCs. It was later modified and expanded by the following RFCs.
- <a href="https://tools.ietf.org/html/rfc4419" target="_blank">RFC 4419</a>, - <a href="http://tools.ietf.org/html/rfc4419" target="_blank">RFC 4419</a>,
Diffie-Hellman Group Exchange for the Secure Shell (SSH) Transport Layer Diffie-Hellman Group Exchange for the Secure Shell (SSH) Transport Layer
Protocol Protocol
- <a href="https://tools.ietf.org/html/rfc4432" target="_blank">RFC 4432</a>, - <a href="http://tools.ietf.org/html/rfc4432" target="_blank">RFC 4432</a>,
RSA Key Exchange for the Secure Shell (SSH) Transport Layer Protocol RSA Key Exchange for the Secure Shell (SSH) Transport Layer Protocol
(not implemented in libssh) - <a href="http://tools.ietf.org/html/rfc4462" target="_blank">RFC 4462</a>,
- <a href="https://tools.ietf.org/html/rfc4462" target="_blank">RFC 4462</a>,
Generic Security Service Application Program Interface (GSS-API) Generic Security Service Application Program Interface (GSS-API)
Authentication and Key Exchange for the Secure Shell (SSH) Protocol Authentication and Key Exchange for the Secure Shell (SSH) Protocol
(only the authentication implemented in libssh) - <a href="http://tools.ietf.org/html/rfc4716" target="_blank">RFC 4716</a>,
- <a href="https://tools.ietf.org/html/rfc4716" target="_blank">RFC 4716</a>,
The Secure Shell (SSH) Public Key File Format The Secure Shell (SSH) Public Key File Format
(not implemented in libssh) - <a href="http://tools.ietf.org/html/rfc5647" target="_blank">RFC 5647</a>,
- <a href="https://tools.ietf.org/html/rfc5647" target="_blank">RFC 5647</a>,
AES Galois Counter Mode for the Secure Shell Transport Layer Protocol AES Galois Counter Mode for the Secure Shell Transport Layer Protocol
(the algorithm negotiation implemented according to openssh.com) - <a href="http://tools.ietf.org/html/rfc5656" target="_blank">RFC 5656</a>,
- <a href="https://tools.ietf.org/html/rfc5656" target="_blank">RFC 5656</a>,
Elliptic Curve Algorithm Integration in the Secure Shell Transport Layer Elliptic Curve Algorithm Integration in the Secure Shell Transport Layer
- <a href="https://tools.ietf.org/html/rfc6594" target="_blank">RFC 6594</a>,
Use of the SHA-256 Algorithm with RSA, DSA, and ECDSA in SSHFP Resource Records
(not implemented in libssh)
- <a href="https://tools.ietf.org/html/rfc6668" target="_blank">RFC 6668</a>,
SHA-2 Data Integrity Verification for the Secure Shell (SSH) Transport Layer Protocol
- <a href="https://tools.ietf.org/html/rfc7479" target="_blank">RFC 7479</a>,
Using Ed25519 in SSHFP Resource Records
(not implemented in libssh)
- <a href="https://tools.ietf.org/html/rfc8160" target="_blank">RFC 8160</a>,
IUTF8 Terminal Mode in Secure Shell (SSH)
(not handled in libssh)
- <a href="https://tools.ietf.org/html/rfc8270" target="_blank">RFC 8270</a>,
Increase the Secure Shell Minimum Recommended Diffie-Hellman Modulus Size to 2048 Bits
- <a href="https://tools.ietf.org/html/rfc8308" target="_blank">RFC 8308</a>,
Extension Negotiation in the Secure Shell (SSH) Protocol
(only the "server-sig-algs" extension implemented)
- <a href="https://tools.ietf.org/html/rfc8332" target="_blank">RFC 8332</a>,
Use of RSA Keys with SHA-256 and SHA-512 in the Secure Shell (SSH) Protocol
- <a href="https://tools.ietf.org/html/rfc8709" target="_blank">RFC 8709</a>,
Ed25519 and Ed448 Public Key Algorithms for the Secure Shell (SSH) Protocol
There are also drafts that are being currently developed and followed.
- <a href="https://tools.ietf.org/html/draft-ietf-curdle-ssh-kex-sha2-10" target="_blank">draft-ietf-curdle-ssh-kex-sha2-10</a>
Key Exchange (KEX) Method Updates and Recommendations for Secure Shell (SSH)
- <a href="https://tools.ietf.org/html/draft-miller-ssh-agent-03" target="_blank">draft-miller-ssh-agent-03</a>
SSH Agent Protocol
- <a href="https://tools.ietf.org/html/draft-ietf-curdle-ssh-curves-12" target="_blank">draft-ietf-curdle-ssh-curves-12</a>
Secure Shell (SSH) Key Exchange Method using Curve25519 and Curve448
Interesting cryptography documents: Interesting cryptography documents:
- <a href="https://www.cryptsoft.com/pkcs11doc/" target="_blank">PKCS #11</a>, PKCS #11 reference documents, describing interface with smartcards. - <a href="http://www.cryptsoft.com/pkcs11doc/" target="_blank">PKCS #11</a>, PKCS #11 reference documents, describing interface with smartcards.
@subsection main-rfc-sftp Secure Shell File Transfer Protocol (SFTP) @subsection main-rfc-sftp Secure Shell File Transfer Protocol (SFTP)
@@ -233,22 +199,26 @@ The protocol is not an Internet standard but it is still widely implemented.
OpenSSH and most other implementation implement Version 3 of the protocol. We OpenSSH and most other implementation implement Version 3 of the protocol. We
do the same in libssh. do the same in libssh.
- <a href="https://tools.ietf.org/html/draft-ietf-secsh-filexfer-02" target="_blank"> - <a href="http://tools.ietf.org/html/draft-ietf-secsh-filexfer-02" target="_blank">
draft-ietf-secsh-filexfer-02.txt</a>, draft-ietf-secsh-filexfer-02.txt</a>,
SSH File Transfer Protocol SSH File Transfer Protocol
@subsection main-rfc-extensions Secure Shell Extensions @subsection main-rfc-extensions Secure Shell Extensions
The libssh project has an extension to support Curve25519 which is also supported by
the OpenSSH project.
- <a href="http://git.libssh.org/projects/libssh.git/tree/doc/curve25519-sha256@libssh.org.txt" target="_blank">curve25519-sha256@libssh.org</a>,
Curve25519-SHA256 for ECDH KEX
The OpenSSH project has defined some extensions to the protocol. We support some of The OpenSSH project has defined some extensions to the protocol. We support some of
them like the statvfs calls in SFTP or the ssh-agent. them like the statvfs calls in SFTP or the ssh-agent.
- <a href="https://api.libssh.org/rfc/PROTOCOL" target="_blank"> - <a href="http://api.libssh.org/rfc/PROTOCOL" target="_blank">
OpenSSH's deviations and extensions</a> OpenSSH's deviations and extensions</a>
- <a href="https://api.libssh.org/rfc/PROTOCOL.certkeys" target="_blank"> - <a href="http://api.libssh.org/rfc/PROTOCOL.agent" target="_blank">
OpenSSH's ssh-agent</a>
- <a href="http://api.libssh.org/rfc/PROTOCOL.certkeys" target="_blank">
OpenSSH's pubkey certificate authentication</a> OpenSSH's pubkey certificate authentication</a>
- <a href="https://api.libssh.org/rfc/PROTOCOL.chacha20poly1305" target="_blank">
chacha20-poly1305@openssh.com authenticated encryption mode</a>
- <a href="https://api.libssh.org/rfc/PROTOCOL.key" target="_blank">
OpenSSH private key format (openssh-key-v1)</a>
*/ */

View File

@@ -1,67 +0,0 @@
/**
@page libssh_tutor_pkcs11 Chapter 9: Authentication using PKCS #11 URIs
@section how_to How to use PKCS #11 URIs in libssh?
PKCS #11 is a Cryptographic Token Interface Standard that provides an API
to devices like smart cards that store cryptographic private information.
Such cryptographic devices are referenced as tokens. A mechanism through which
objects stored on the tokens can be uniquely identified is called PKCS #11 URI
(Uniform Resource Identifier) and is defined in RFC 7512
(https://tools.ietf.org/html/rfc7512).
Pre-requisites:
OpenSSL defines an abstract layer called the "engine" to achieve cryptographic
acceleration. The engine_pkcs11 module acts like an interface between the PKCS #11
modules and the OpenSSL engine.
To build and use libssh with PKCS #11 support:
1. Enable the cmake option: $ cmake -DWITH_PKCS11_URI=ON
2. Build with OpenSSL.
3. Install and configure engine_pkcs11 (https://github.com/OpenSC/libp11).
4. Plug in a working smart card or configure softhsm (https://www.opendnssec.org/softhsm).
The functions ssh_pki_import_pubkey_file() and ssh_pki_import_privkey_file() that
import the public and private keys from files respectively are now modified to support
PKCS #11 URIs. These functions automatically detect if the provided filename is a file path
or a PKCS #11 URI (when it begins with "pkcs11:"). If a PKCS #11 URI is detected,
the engine is loaded and initialized. Through the engine, the private/public key
corresponding to the PKCS #11 URI are loaded from the PKCS #11 device.
If you wish to authenticate using public keys on your own, follow the steps mentioned under
"Authentication with public keys" in Chapter 2 - A deeper insight into authentication.
The function pki_uri_import() is used to populate the public/private ssh_key from the
engine with PKCS #11 URIs as the look up.
Here is a minimalistic example of public key authentication using PKCS #11 URIs:
@code
int authenticate_pkcs11_URI(ssh_session session)
{
int rc;
char priv_uri[1042] = "pkcs11:token=my-token;object=my-object;type=private?pin-value=1234";
rc = ssh_options_set(session, SSH_OPTIONS_IDENTITY, priv_uri);
assert_int_equal(rc, SSH_OK)
rc = ssh_userauth_publickey_auto(session, NULL, NULL);
if (rc == SSH_AUTH_ERROR)
{
fprintf(stderr, "Authentication with PKCS #11 URIs failed: %s\n",
ssh_get_error(session));
return SSH_AUTH_ERROR;
}
return rc;
}
@endcode
@subsection Caveats
We recommend the users to provide a specific PKCS #11 URI so that it matches only a single slot in the engine.
If the engine discovers multiple slots that could potentially contain the private keys referenced
by the provided PKCS #11 URI, the engine will not try to authenticate.
*/

View File

@@ -2,7 +2,7 @@
@page libssh_tutor_scp Chapter 6: The SCP subsystem @page libssh_tutor_scp Chapter 6: The SCP subsystem
@section scp_subsystem The SCP subsystem @section scp_subsystem The SCP subsystem
The SCP subsystem has far less functionality than the SFTP subsystem. The SCP subsystem has far less functionnality than the SFTP subsystem.
However, if you only need to copy files from and to the remote system, However, if you only need to copy files from and to the remote system,
it does its job. it does its job.
@@ -158,7 +158,7 @@ Let's say you want to copy the following tree of files to the remote site:
+-- file1 +-- file1
+-- B --+ +-- B --+
| +-- file2 | +-- file2
-- A --+ -- A --+
| +-- file3 | +-- file3
+-- C --+ +-- C --+
+-- file4 +-- file4
@@ -210,7 +210,7 @@ int scp_receive(ssh_session session, ssh_scp scp)
size = ssh_scp_request_get_size(scp); size = ssh_scp_request_get_size(scp);
filename = strdup(ssh_scp_request_get_filename(scp)); filename = strdup(ssh_scp_request_get_filename(scp));
mode = ssh_scp_request_get_permissions(scp); mode = ssh_scp_request_get_permissions(scp);
printf("Receiving file %s, size %d, permissions 0%o\n", printf("Receiving file %s, size %d, permisssions 0%o\n",
filename, size, mode); filename, size, mode);
free(filename); free(filename);

View File

@@ -61,7 +61,7 @@ int sftp_helloworld(ssh_session session)
rc = sftp_init(sftp); rc = sftp_init(sftp);
if (rc != SSH_OK) if (rc != SSH_OK)
{ {
fprintf(stderr, "Error initializing SFTP session: code %d.\n", fprintf(stderr, "Error initializing SFTP session: %s.\n",
sftp_get_error(sftp)); sftp_get_error(sftp));
sftp_free(sftp); sftp_free(sftp);
return rc; return rc;
@@ -100,7 +100,7 @@ Possible errors are:
@subsection sftp_mkdir Creating a directory @subsection sftp_mkdir Creating a directory
The function sftp_mkdir() takes the "SFTP session" we just created as The function sftp_mkdir() tahes the "SFTP session" we juste created as
its first argument. It also needs the name of the file to create, and the its first argument. It also needs the name of the file to create, and the
desired permissions. The permissions are the same as for the usual mkdir() desired permissions. The permissions are the same as for the usual mkdir()
function. To get a comprehensive list of the available permissions, use the function. To get a comprehensive list of the available permissions, use the
@@ -253,7 +253,7 @@ int sftp_read_sync(ssh_session session, sftp_session sftp)
return SSH_ERROR; return SSH_ERROR;
} }
nwritten = write(fd, buffer, nbytes); nwritten = write(fd, buf, nbytes);
if (nwritten != nbytes) { if (nwritten != nbytes) {
fprintf(stderr, "Error writing: %s\n", fprintf(stderr, "Error writing: %s\n",
strerror(errno)); strerror(errno));
@@ -282,7 +282,7 @@ sftp_async_read() waits for the data to come. To open a file in nonblocking mode
call sftp_file_set_nonblocking() right after you opened it. Default is blocking mode. call sftp_file_set_nonblocking() right after you opened it. Default is blocking mode.
The example below reads a very big file in asynchronous, nonblocking, mode. Each The example below reads a very big file in asynchronous, nonblocking, mode. Each
time the data is not ready yet, a counter is incremented. time the data are not ready yet, a counter is incrementer.
@code @code
// Good chunk size // Good chunk size
@@ -358,19 +358,19 @@ int sftp_read_async(ssh_session session, sftp_session sftp)
@subsection sftp_ls Listing the contents of a directory @subsection sftp_ls Listing the contents of a directory
The functions sftp_opendir(), sftp_readdir(), sftp_dir_eof(), The functions sftp_opendir(), sftp_readdir(), sftp_dir_eof(),
and sftp_closedir() enable to list the contents of a directory. and sftp_closedir() enable to list the contents of a directory.
They use a new handle_type, "sftp_dir", which gives access to the They use a new handle_type, "sftp_dir", which gives access to the
directory being read. directory being read.
In addition, sftp_readdir() returns a "sftp_attributes" which is a pointer In addition, sftp_readdir() returns a "sftp_attributes" which is a pointer
to a structure with information about a directory entry: to a structure with informations about a directory entry:
- name: the name of the file or directory - name: the name of the file or directory
- size: its size in bytes - size: its size in bytes
- etc. - etc.
sftp_readdir() might return NULL under two conditions: sftp_readdir() might return NULL under two conditions:
- when the end of the directory has been met - when the end of the directory has been met
- when an error occurred - when an error occured
To tell the difference, call sftp_dir_eof(). To tell the difference, call sftp_dir_eof().

View File

@@ -209,7 +209,7 @@ int interactive_shell_session(ssh_channel channel)
Of course, this is a poor terminal emulator, since the echo from the keys Of course, this is a poor terminal emulator, since the echo from the keys
pressed should not be done locally, but should be done by the remote side. pressed should not be done locally, but should be done by the remote side.
Also, user's input should not be sent once "Enter" key is pressed, but Also, user's input should not be sent once "Enter" key is pressed, but
immediately after each key is pressed. This can be accomplished immediately after each key is pressed. This can be accomplished
by setting the local terminal to "raw" mode with the cfmakeraw(3) function. by setting the local terminal to "raw" mode with the cfmakeraw(3) function.
cfmakeraw() is a standard function under Linux, on other systems you can cfmakeraw() is a standard function under Linux, on other systems you can
@@ -245,13 +245,13 @@ provide a more elegant way to wait for data coming from many sources.
The functions ssh_select() and ssh_channel_select() remind of the standard The functions ssh_select() and ssh_channel_select() remind of the standard
UNIX select(2) function. The idea is to wait for "something" to happen: UNIX select(2) function. The idea is to wait for "something" to happen:
incoming data to be read, outgoing data to block, or an exception to incoming data to be read, outcoming data to block, or an exception to
occur. Both these functions do a "passive wait", i.e. you can safely use occur. Both these functions do a "passive wait", i.e. you can safely use
them repeatedly in a loop, it will not consume exaggerate processor time them repeatedly in a loop, it will not consume exaggerate processor time
and make your computer unresponsive. It is quite common to use these and make your computer unresponsive. It is quite common to use these
functions in your application's main loop. functions in your application's main loop.
The difference between ssh_select() and ssh_channel_select() is that The difference between ssh_select() and ssh_channel_select() is that
ssh_channel_select() is simpler, but allows you only to watch SSH channels. ssh_channel_select() is simpler, but allows you only to watch SSH channels.
ssh_select() is more complete and enables watching regular file descriptors ssh_select() is more complete and enables watching regular file descriptors
as well, in the same function call. as well, in the same function call.
@@ -320,36 +320,18 @@ int interactive_shell_session(ssh_session session, ssh_channel channel)
If your remote application is graphical, you can forward the X11 protocol to If your remote application is graphical, you can forward the X11 protocol to
your local computer. your local computer.
To do that, you first declare a callback to manage channel_open_request_x11_function. To do that, you first declare that you accept X11 connections with
Then you create the forwarding tunnel for the X11 protocol with ssh_channel_request_x11(). ssh_channel_accept_x11(). Then you create the forwarding tunnel for
the X11 protocol with ssh_channel_request_x11().
The following code performs channel initialization and shell session The following code performs channel initialization and shell session
opening, and handles a parallel X11 connection: opening, and handles a parallel X11 connection:
@code @code
#include <libssh/callbacks.h>
ssh_channel x11channel = NULL;
ssh_channel x11_open_request_callback(ssh_session session, const char *shost, int sport, void *userdata)
{
x11channel = ssh_channel_new(session);
return x11channel;
}
int interactive_shell_session(ssh_channel channel) int interactive_shell_session(ssh_channel channel)
{ {
int rc; int rc;
ssh_channel x11channel;
struct ssh_callbacks_struct cb =
{
.channel_open_request_x11_function = x11_open_request_callback,
.userdata = NULL
};
ssh_callbacks_init(&cb);
rc = ssh_set_callbacks(session, &cb);
if (rc != SSH_OK) return rc;
rc = ssh_channel_request_pty(channel); rc = ssh_channel_request_pty(channel);
if (rc != SSH_OK) return rc; if (rc != SSH_OK) return rc;
@@ -368,15 +350,12 @@ int interactive_shell_session(ssh_channel channel)
} }
@endcode @endcode
Don't forget to check the $DISPLAY environment variable on the remote Don't forget to set the $DISPLAY environment variable on the remote
side, or the remote applications won't try using the X11 tunnel: side, or the remote applications won't try using the X11 tunnel:
@code @code
$ echo $DISPLAY $ export DISPLAY=:0
localhost:10.0
$ xclock & $ xclock &
@endcode @endcode
See an implementation example at https://gitlab.com/libssh/libssh-mirror/-/tree/master/examples/ssh_X11_client.c for details.
*/ */

View File

@@ -1,21 +0,0 @@
MIT License
Copyright (c) 2017 Jan-Lukas Wynen
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

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

View File

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

View File

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

Before

Width:  |  Height:  |  Size: 6.5 KiB

View File

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

Before

Width:  |  Height:  |  Size: 3.4 KiB

View File

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

Before

Width:  |  Height:  |  Size: 4.1 KiB

View File

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

Before

Width:  |  Height:  |  Size: 3.8 KiB

View File

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

Before

Width:  |  Height:  |  Size: 3.8 KiB

View File

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

Before

Width:  |  Height:  |  Size: 3.1 KiB

View File

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

Before

Width:  |  Height:  |  Size: 3.1 KiB

View File

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

Before

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 483 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 488 B

View File

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

File diff suppressed because it is too large Load Diff

View File

@@ -3,50 +3,64 @@
@section threads_with_libssh How to use libssh with threads @section threads_with_libssh How to use libssh with threads
libssh may be used in multithreaded applications, but under several conditions : libssh may be used in multithreaded applications, but under several conditions :
- Your system must support libpthread or, in Windows environment, - Threading must be initialized during the initialization of libssh. This
CriticalSection based mutex control. initialization must be done outside of any threading context.
- Since version 0.8.0, threads initialization is called automatically in the - If pthreads is being used by your application (or your framework's backend),
library constructor if libssh is dynamically linked. This means it is no you must link with libssh_threads dynamic library and initialize
longer necessary to call ssh_init()/ssh_finalize(). threading with the ssh_threads_pthreads threading object.
- If libssh is statically linked, threading must be initialized by calling - If an other threading library is being used by your application, you must
ssh_init() before using any of libssh provided functions. This initialization implement all the methods of the ssh_threads_callbacks_struct structure
must be done outside of any threading context. Don't forget to call and initialize libssh with it.
ssh_finalize() to avoid memory leak
- At all times, you may use different sessions inside threads, make parallel - At all times, you may use different sessions inside threads, make parallel
connections, read/write on different sessions and so on. You *cannot* use a connections, read/write on different sessions and so on. You *cannot* use a
single session (or channels for a single session) in several threads at the same single session (or channels for a single session) in several threads at the same
time. This will most likely lead to internal state corruption. This limitation is time. This will most likely lead to internal state corruption. This limitation is
being worked out and will maybe disappear later. being worked out and will maybe disappear later.
@subsection threads_init Initialization of threads @subsection threads_init Initialization of threads
Since version 0.8.0, it is no longer necessary to call ssh_init()/ssh_finalize() To initialize threading, you must first select the threading model you want to
if libssh is dynamically linked. use, using ssh_threads_set_callbacks(), then call ssh_init().
If libssh is statically linked, call ssh_init() before using any of libssh @code
provided functions. #include <libssh/callbacks.h>
...
ssh_threads_set_callbacks(ssh_threads_get_noop());
ssh_init();
@endcode
ssh_threads_noop is the threading structure that does nothing. It's the
threading callbacks being used by default when you're not using threading.
@subsection threads_pthread Using libpthread with libssh @subsection threads_pthread Using libpthread with libssh
Since version 0.8.0, libpthread is the default threads library used by libssh. If your application is using libpthread, you may simply use the libpthread
threading backend:
To use libpthread, simply link it to you application. @code
#include <libssh/callbacks.h>
...
ssh_threads_set_callbacks(ssh_threads_get_pthread());
ssh_init();
@endcode
However, you must be sure to link with the library ssh_threads. If
you're using gcc, you must use the commandline
@code
gcc -o output input.c -lssh -lssh_threads
@endcode
If you are using libssh statically linked, don't forget to call ssh_init()
before using any of libssh provided functions (and ssh_finalize() in the end).
@subsection threads_other Using another threading library @subsection threads_other Using another threading library
Since version 0.8.0, libssh does not support custom threading libraries. You must find your way in the ssh_threads_callbacks_struct structure. You must
The change makes sense since the newer versions for libcrypto (OpenSSL) and implement the following methods :
libgcrypt don't support custom threading libraries. - mutex_lock
- mutex_unlock
The default used threading library is libpthread. - mutex_init
Alternatively, in Windows environment, CriticalSection based mutex control can - mutex_destroy
be used. - thread_id
If your system does not support libpthread nor CriticalSection based mutex
control, unfortunately, you cannot use libssh in multithreaded scenarios.
libgcrypt 1.6 and bigger backend does not support custom callback. Using anything else than pthreads (ssh_threads_get_pthread()) here will fail.
Good luck ! Good luck !
*/ */

View File

@@ -6,94 +6,61 @@ set(examples_SRCS
connect_ssh.c connect_ssh.c
) )
include_directories(${libssh_BINARY_DIR}/include ${libssh_BINARY_DIR}) include_directories(
${LIBSSH_PUBLIC_INCLUDE_DIRS}
${CMAKE_BINARY_DIR}
)
if (ARGP_INCLUDE_DIR) if (BSD OR SOLARIS OR OSX)
include_directories(${ARGP_INCLUDE_DIR}) find_package(Argp)
endif() endif (BSD OR SOLARIS OR OSX)
if (UNIX AND NOT WIN32) if (UNIX AND NOT WIN32)
add_executable(libssh_scp libssh_scp.c ${examples_SRCS}) add_executable(libssh_scp libssh_scp.c ${examples_SRCS})
target_compile_options(libssh_scp PRIVATE ${DEFAULT_C_COMPILE_FLAGS}) target_link_libraries(libssh_scp ${LIBSSH_SHARED_LIBRARY})
target_link_libraries(libssh_scp ssh::ssh)
add_executable(scp_download scp_download.c ${examples_SRCS}) add_executable(scp_download scp_download.c ${examples_SRCS})
target_compile_options(scp_download PRIVATE ${DEFAULT_C_COMPILE_FLAGS}) target_link_libraries(scp_download ${LIBSSH_SHARED_LIBRARY})
target_link_libraries(scp_download ssh::ssh)
add_executable(sshnetcat sshnetcat.c ${examples_SRCS}) add_executable(sshnetcat sshnetcat.c ${examples_SRCS})
target_compile_options(sshnetcat PRIVATE ${DEFAULT_C_COMPILE_FLAGS}) target_link_libraries(sshnetcat ${LIBSSH_SHARED_LIBRARY})
target_link_libraries(sshnetcat ssh::ssh)
if (WITH_SFTP) if (WITH_SFTP)
add_executable(samplesftp samplesftp.c ${examples_SRCS}) add_executable(samplesftp samplesftp.c ${examples_SRCS})
target_compile_options(samplesftp PRIVATE ${DEFAULT_C_COMPILE_FLAGS}) target_link_libraries(samplesftp ${LIBSSH_SHARED_LIBRARY})
target_link_libraries(samplesftp ssh::ssh)
endif (WITH_SFTP) endif (WITH_SFTP)
add_executable(ssh-client ssh_client.c ${examples_SRCS}) add_executable(samplessh sample.c ${examples_SRCS})
target_compile_options(ssh-client PRIVATE ${DEFAULT_C_COMPILE_FLAGS}) target_link_libraries(samplessh ${LIBSSH_SHARED_LIBRARY})
target_link_libraries(ssh-client ssh::ssh)
add_executable(ssh-X11-client ssh_X11_client.c ${examples_SRCS}) if (WITH_SERVER)
target_compile_options(ssh-X11-client PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
target_link_libraries(ssh-X11-client ssh::ssh)
if (WITH_SERVER AND (ARGP_LIBRARY OR HAVE_ARGP_H))
if (HAVE_LIBUTIL) if (HAVE_LIBUTIL)
add_executable(ssh_server_fork ssh_server.c) add_executable(ssh_server_fork ssh_server_fork.c)
target_compile_options(ssh_server_fork PRIVATE ${DEFAULT_C_COMPILE_FLAGS} -DWITH_FORK) target_link_libraries(ssh_server_fork ${LIBSSH_SHARED_LIBRARY} ${ARGP_LIBRARIES} util)
target_link_libraries(ssh_server_fork ssh::ssh ${ARGP_LIBRARY} util)
add_executable(ssh_server_pthread ssh_server.c)
target_compile_options(ssh_server_pthread PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
target_link_libraries(ssh_server_pthread ssh::ssh ${ARGP_LIBRARY} pthread util)
endif (HAVE_LIBUTIL) endif (HAVE_LIBUTIL)
if (WITH_GSSAPI AND GSSAPI_FOUND) if (WITH_GSSAPI AND GSSAPI_FOUND)
add_executable(proxy proxy.c) add_executable(samplesshd-cb samplesshd-cb.c)
target_compile_options(proxy PRIVATE ${DEFAULT_C_COMPILE_FLAGS}) target_link_libraries(samplesshd-cb ${LIBSSH_SHARED_LIBRARY} ${ARGP_LIBRARIES})
target_link_libraries(proxy ssh::ssh ${ARGP_LIBRARY})
add_executable(sshd_direct-tcpip sshd_direct-tcpip.c) add_executable(proxy proxy.c)
target_compile_options(sshd_direct-tcpip PRIVATE ${DEFAULT_C_COMPILE_FLAGS}) target_link_libraries(proxy ${LIBSSH_SHARED_LIBRARY} ${ARGP_LIBRARIES})
target_link_libraries(sshd_direct-tcpip ssh::ssh ${ARGP_LIBRARY})
endif (WITH_GSSAPI AND GSSAPI_FOUND) endif (WITH_GSSAPI AND GSSAPI_FOUND)
add_executable(samplesshd-kbdint samplesshd-kbdint.c) add_executable(samplesshd-kbdint samplesshd-kbdint.c)
target_compile_options(samplesshd-kbdint PRIVATE ${DEFAULT_C_COMPILE_FLAGS}) target_link_libraries(samplesshd-kbdint ${LIBSSH_SHARED_LIBRARY} ${ARGP_LIBRARIES})
target_link_libraries(samplesshd-kbdint ssh::ssh ${ARGP_LIBRARY})
add_executable(keygen2 keygen2.c ${examples_SRCS}) endif (WITH_SERVER)
target_compile_options(keygen2 PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
target_link_libraries(keygen2 ssh::ssh ${ARGP_LIBRARY})
endif()
endif (UNIX AND NOT WIN32) endif (UNIX AND NOT WIN32)
if (WITH_SERVER)
add_executable(samplesshd-cb samplesshd-cb.c)
target_compile_options(samplesshd-cb PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
target_link_libraries(samplesshd-cb ssh::ssh)
if (ARGP_LIBRARY OR HAVE_ARGP_H)
target_link_libraries(samplesshd-cb ${ARGP_LIBRARY})
endif(ARGP_LIBRARY OR HAVE_ARGP_H)
endif()
add_executable(exec exec.c ${examples_SRCS}) add_executable(exec exec.c ${examples_SRCS})
target_compile_options(exec PRIVATE ${DEFAULT_C_COMPILE_FLAGS}) target_link_libraries(exec ${LIBSSH_SHARED_LIBRARY})
target_link_libraries(exec ssh::ssh)
add_executable(senddata senddata.c ${examples_SRCS}) add_executable(senddata senddata.c ${examples_SRCS})
target_compile_options(senddata PRIVATE ${DEFAULT_C_COMPILE_FLAGS}) target_link_libraries(senddata ${LIBSSH_SHARED_LIBRARY})
target_link_libraries(senddata ssh::ssh)
add_executable(keygen keygen.c)
target_compile_options(keygen PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
target_link_libraries(keygen ssh::ssh)
add_executable(libsshpp libsshpp.cpp) add_executable(libsshpp libsshpp.cpp)
target_link_libraries(libsshpp ssh::ssh) target_link_libraries(libsshpp ${LIBSSH_SHARED_LIBRARY})
add_executable(libsshpp_noexcept libsshpp_noexcept.cpp) add_executable(libsshpp_noexcept libsshpp_noexcept.cpp)
target_link_libraries(libsshpp_noexcept ssh::ssh) target_link_libraries(libsshpp_noexcept ${LIBSSH_SHARED_LIBRARY})

View File

@@ -24,8 +24,7 @@ clients must be made or how a client should react.
#include <libssh/libssh.h> #include <libssh/libssh.h>
#include "examples_common.h" #include "examples_common.h"
int authenticate_kbdint(ssh_session session, const char *password) int authenticate_kbdint(ssh_session session, const char *password) {
{
int err; int err;
err = ssh_userauth_kbdint(session, NULL, NULL); err = ssh_userauth_kbdint(session, NULL, NULL);
@@ -100,142 +99,78 @@ int authenticate_kbdint(ssh_session session, const char *password)
return err; return err;
} }
static int auth_keyfile(ssh_session session, char* keyfile) static void error(ssh_session session){
{ fprintf(stderr,"Authentication failed: %s\n",ssh_get_error(session));
ssh_key key = NULL; }
char pubkey[132] = {0}; // +".pub"
int rc;
snprintf(pubkey, sizeof(pubkey), "%s.pub", keyfile); int authenticate_console(ssh_session session){
int rc;
rc = ssh_pki_import_pubkey_file( pubkey, &key); int method;
char password[128] = {0};
if (rc != SSH_OK) char *banner;
return SSH_AUTH_DENIED;
rc = ssh_userauth_try_publickey(session, NULL, key);
ssh_key_free(key);
if (rc!=SSH_AUTH_SUCCESS)
return SSH_AUTH_DENIED;
rc = ssh_pki_import_privkey_file(keyfile, NULL, NULL, NULL, &key);
if (rc != SSH_OK)
return SSH_AUTH_DENIED;
rc = ssh_userauth_publickey(session, NULL, key);
ssh_key_free(key);
// Try to authenticate
rc = ssh_userauth_none(session, NULL);
if (rc == SSH_AUTH_ERROR) {
error(session);
return rc; return rc;
} }
method = ssh_userauth_list(session, NULL);
while (rc != SSH_AUTH_SUCCESS) {
if (method & SSH_AUTH_METHOD_GSSAPI_MIC){
rc = ssh_userauth_gssapi(session);
if(rc == SSH_AUTH_ERROR) {
error(session);
return rc;
} else if (rc == SSH_AUTH_SUCCESS) {
break;
}
}
// Try to authenticate with public key first
if (method & SSH_AUTH_METHOD_PUBLICKEY) {
rc = ssh_userauth_publickey_auto(session, NULL, NULL);
if (rc == SSH_AUTH_ERROR) {
error(session);
return rc;
} else if (rc == SSH_AUTH_SUCCESS) {
break;
}
}
static void error(ssh_session session) // Try to authenticate with keyboard interactive";
{ if (method & SSH_AUTH_METHOD_INTERACTIVE) {
fprintf(stderr,"Authentication failed: %s\n",ssh_get_error(session)); rc = authenticate_kbdint(session, NULL);
} if (rc == SSH_AUTH_ERROR) {
error(session);
int authenticate_console(ssh_session session)
{
int rc;
int method;
char password[128] = {0};
char *banner;
// Try to authenticate
rc = ssh_userauth_none(session, NULL);
if (rc == SSH_AUTH_ERROR) {
error(session);
return rc; return rc;
} else if (rc == SSH_AUTH_SUCCESS) {
break;
}
} }
method = ssh_userauth_list(session, NULL); if (ssh_getpass("Password: ", password, sizeof(password), 0, 0) < 0) {
while (rc != SSH_AUTH_SUCCESS) { return SSH_AUTH_ERROR;
if (method & SSH_AUTH_METHOD_GSSAPI_MIC){
rc = ssh_userauth_gssapi(session);
if(rc == SSH_AUTH_ERROR) {
error(session);
return rc;
} else if (rc == SSH_AUTH_SUCCESS) {
break;
}
}
// Try to authenticate with public key first
if (method & SSH_AUTH_METHOD_PUBLICKEY) {
rc = ssh_userauth_publickey_auto(session, NULL, NULL);
if (rc == SSH_AUTH_ERROR) {
error(session);
return rc;
} else if (rc == SSH_AUTH_SUCCESS) {
break;
}
}
{
char buffer[128] = {0};
char *p = NULL;
printf("Automatic pubkey failed. "
"Do you want to try a specific key? (y/n)\n");
if (fgets(buffer, sizeof(buffer), stdin) == NULL) {
break;
}
if ((buffer[0]=='Y') || (buffer[0]=='y')) {
printf("private key filename: ");
if (fgets(buffer, sizeof(buffer), stdin) == NULL) {
return SSH_AUTH_ERROR;
}
buffer[sizeof(buffer) - 1] = '\0';
if ((p = strchr(buffer, '\n'))) {
*p = '\0';
}
rc = auth_keyfile(session, buffer);
if(rc == SSH_AUTH_SUCCESS) {
break;
}
fprintf(stderr, "failed with key\n");
}
}
// Try to authenticate with keyboard interactive";
if (method & SSH_AUTH_METHOD_INTERACTIVE) {
rc = authenticate_kbdint(session, NULL);
if (rc == SSH_AUTH_ERROR) {
error(session);
return rc;
} else if (rc == SSH_AUTH_SUCCESS) {
break;
}
}
if (ssh_getpass("Password: ", password, sizeof(password), 0, 0) < 0) {
return SSH_AUTH_ERROR;
}
// Try to authenticate with password
if (method & SSH_AUTH_METHOD_PASSWORD) {
rc = ssh_userauth_password(session, NULL, password);
if (rc == SSH_AUTH_ERROR) {
error(session);
return rc;
} else if (rc == SSH_AUTH_SUCCESS) {
break;
}
}
memset(password, 0, sizeof(password));
} }
banner = ssh_get_issue_banner(session); // Try to authenticate with password
if (banner) { if (method & SSH_AUTH_METHOD_PASSWORD) {
printf("%s\n",banner); rc = ssh_userauth_password(session, NULL, password);
SSH_STRING_FREE_CHAR(banner); if (rc == SSH_AUTH_ERROR) {
error(session);
return rc;
} else if (rc == SSH_AUTH_SUCCESS) {
break;
}
} }
memset(password, 0, sizeof(password));
}
return rc; banner = ssh_get_issue_banner(session);
if (banner) {
printf("%s\n",banner);
ssh_string_free_char(banner);
}
return rc;
} }

View File

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

View File

@@ -8,7 +8,7 @@ int main(void) {
ssh_session session; ssh_session session;
ssh_channel channel; ssh_channel channel;
char buffer[256]; char buffer[256];
int rbytes, wbytes, total = 0; int nbytes;
int rc; int rc;
session = connect_ssh("localhost", NULL, 0); session = connect_ssh("localhost", NULL, 0);
@@ -17,7 +17,7 @@ int main(void) {
return 1; return 1;
} }
channel = ssh_channel_new(session); channel = ssh_channel_new(session);;
if (channel == NULL) { if (channel == NULL) {
ssh_disconnect(session); ssh_disconnect(session);
ssh_free(session); ssh_free(session);
@@ -35,30 +35,15 @@ int main(void) {
goto failed; goto failed;
} }
rbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0); nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
if (rbytes <= 0) { while (nbytes > 0) {
goto failed; if (fwrite(buffer, 1, nbytes, stdout) != (unsigned int) nbytes) {
}
do {
wbytes = fwrite(buffer + total, 1, rbytes, stdout);
if (wbytes <= 0) {
goto failed; goto failed;
} }
nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
}
total += wbytes; if (nbytes < 0) {
/* When it was not possible to write the whole buffer to stdout */
if (wbytes < rbytes) {
rbytes -= wbytes;
continue;
}
rbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
total = 0;
} while (rbytes > 0);
if (rbytes < 0) {
goto failed; goto failed;
} }

View File

@@ -1,41 +0,0 @@
/* keygen.c
* Sample implementation of ssh-keygen using libssh
*/
/*
Copyright 2019 Red Hat, Inc.
Author: Jakub Jelen <jjelen@redhat.com>
This file is part of the SSH Library
You are free to copy this file, modify it in any way, consider it being public
domain. This does not apply to the rest of the library though, but it is
allowed to cut-and-paste working code from this file to any license of
program.
*/
#include <libssh/libssh.h>
#include <stdio.h>
int main(void)
{
ssh_key key = NULL;
int rv;
/* Generate a new ED25519 private key file */
rv = ssh_pki_generate(SSH_KEYTYPE_ED25519, 0, &key);
if (rv != SSH_OK) {
fprintf(stderr, "Failed to generate private key");
return -1;
}
/* Write it to a file testkey in the current dirrectory */
rv = ssh_pki_export_privkey_file(key, NULL, NULL, NULL, "testkey");
if (rv != SSH_OK) {
fprintf(stderr, "Failed to write private key file");
return -1;
}
return 0;
}

View File

@@ -1,505 +0,0 @@
/*
* keygen2.c - Generate SSH keys using libssh
* Author: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
*/
/*
* Copyright (c) 2019 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see http://www.gnu.org/licenses/.
*/
#include "config.h"
#include <libssh/libssh.h>
#include <stdio.h>
#include <stdlib.h>
#include <argp.h>
#include <errno.h>
#include <string.h>
#include <ctype.h>
#include <fcntl.h>
#include <sys/stat.h>
struct arguments_st {
enum ssh_keytypes_e type;
unsigned long bits;
char *file;
char *passphrase;
int action_list;
};
static struct argp_option options[] = {
{
.name = "bits",
.key = 'b',
.arg = "BITS",
.flags = 0,
.doc = "The size of the key to be generated. "
"If omitted, a default value is used depending on the TYPE. "
"Accepted values are: "
"1024, 2048, 3072 (default), 4096, and 8192 for TYPE=\"rsa\"; "
"256 (default), 384, and 521 for TYPE=\"ecdsa\"; "
"1024 (default) and 2048 for TYPE=\"dsa\"; "
"can be omitted for TYPE=\"ed25519\" "
"(it will be ignored if provided).\n",
.group = 0
},
{
.name = "file",
.key = 'f',
.arg = "FILE",
.flags = 0,
.doc = "The output file. "
"If not provided, the used file name will be generated "
"according to the key type as \"id_TYPE\" "
"(e.g. \"id_rsa\" for type \"rsa\"). "
"The public key file name is generated from the private key "
"file name by appending \".pub\".\n",
.group = 0
},
{
.name = "passphrase",
.key = 'p',
.arg = "PASSPHRASE",
.flags = 0,
.doc = "The passphrase used to encrypt the private key. "
"If omitted the file will not be encrypted.\n",
.group = 0
},
{
.name = "type",
.key = 't',
.arg = "TYPE",
.flags = 0,
.doc = "The type of the key to be generated. "
"Accepted values are: "
"\"rsa\", \"ecdsa\", \"ed25519\", and \"dsa\".\n",
.group = 0
},
{
.name = "list",
.key = 'l',
.arg = NULL,
.flags = 0,
.doc = "List the Fingerprint of the given key\n",
.group = 0
},
{
/* End of the options */
0
},
};
/* Parse a single option. */
static error_t parse_opt (int key, char *arg, struct argp_state *state)
{
/* Get the input argument from argp_parse, which we
* know is a pointer to our arguments structure.
*/
struct arguments_st *arguments = NULL;
error_t rc = 0;
if (state == NULL) {
return EINVAL;
}
arguments = state->input;
if (arguments == NULL) {
fprintf(stderr, "Error: NULL pointer to arguments structure "
"provided\n");
rc = EINVAL;
goto end;
}
switch (key) {
case 'b':
errno = 0;
arguments->bits = strtoul(arg, NULL, 10);
if (errno != 0) {
rc = errno;
goto end;
}
break;
case 'f':
arguments->file = strdup(arg);
if (arguments->file == NULL) {
fprintf(stderr, "Error: Out of memory\n");
rc = ENOMEM;
goto end;
}
break;
case 'p':
arguments->passphrase = strdup(arg);
if (arguments->passphrase == NULL) {
fprintf(stderr, "Error: Out of memory\n");
rc = ENOMEM;
goto end;
}
break;
case 't':
if (!strcmp(arg, "rsa")) {
arguments->type = SSH_KEYTYPE_RSA;
}
else if (!strcmp(arg, "dsa")) {
arguments->type = SSH_KEYTYPE_DSS;
}
else if (!strcmp(arg, "ecdsa")) {
arguments->type = SSH_KEYTYPE_ECDSA;
}
else if (!strcmp(arg, "ed25519")) {
arguments->type = SSH_KEYTYPE_ED25519;
}
else {
fprintf(stderr, "Error: Invalid key type\n");
argp_usage(state);
rc = EINVAL;
goto end;
}
break;
case 'l':
arguments->action_list = 1;
break;
case ARGP_KEY_ARG:
if (state->arg_num > 0) {
/* Too many arguments. */
printf("Error: Too many arguments\n");
argp_usage(state);
}
break;
case ARGP_KEY_END:
break;
default:
return ARGP_ERR_UNKNOWN;
}
end:
return rc;
}
static int validate_args(struct arguments_st *args)
{
int rc = 0;
if (args == NULL) {
return EINVAL;
}
/* no other arguments needed for listing key fingerprints */
if (args->action_list) {
return 0;
}
switch (args->type) {
case SSH_KEYTYPE_RSA:
switch (args->bits) {
case 0:
/* If not provided, use default value */
args->bits = 3072;
break;
case 1024:
case 2048:
case 3072:
case 4096:
case 8192:
break;
default:
fprintf(stderr, "Error: Invalid bits parameter provided\n");
rc = EINVAL;
break;
}
if (args->file == NULL) {
args->file = strdup("id_rsa");
if (args->file == NULL) {
rc = ENOMEM;
break;
}
}
break;
case SSH_KEYTYPE_ECDSA:
switch (args->bits) {
case 0:
/* If not provided, use default value */
args->bits = 256;
break;
case 256:
case 384:
case 521:
break;
default:
fprintf(stderr, "Error: Invalid bits parameter provided\n");
rc = EINVAL;
break;
}
if (args->file == NULL) {
args->file = strdup("id_ecdsa");
if (args->file == NULL) {
rc = ENOMEM;
break;
}
}
break;
case SSH_KEYTYPE_DSS:
switch (args->bits) {
case 0:
/* If not provided, use default value */
args->bits = 1024;
break;
case 1024:
case 2048:
break;
default:
fprintf(stderr, "Error: Invalid bits parameter provided\n");
rc = EINVAL;
break;
}
if (args->file == NULL) {
args->file = strdup("id_dsa");
if (args->file == NULL) {
rc = ENOMEM;
break;
}
}
break;
case SSH_KEYTYPE_ED25519:
/* Ignore value and overwrite with a zero */
args->bits = 0;
if (args->file == NULL) {
args->file = strdup("id_ed25519");
if (args->file == NULL) {
rc = ENOMEM;
break;
}
}
break;
default:
fprintf(stderr, "Error: unknown key type\n");
rc = EINVAL;
break;
}
return rc;
}
/* Program documentation. */
static char doc[] = "Generate an SSH key pair. "
"The \"--type\" (short: \"-t\") option is required.";
/* Our argp parser */
static struct argp argp = {options, parse_opt, NULL, doc, NULL, NULL, NULL};
static void
list_fingerprint(char *file)
{
ssh_key key = NULL;
unsigned char *hash = NULL;
size_t hlen = 0;
int rc;
rc = ssh_pki_import_privkey_file(file, NULL, NULL, NULL, &key);
if (rc != SSH_OK) {
fprintf(stderr, "Failed to import private key %s\n", file);
return;
}
rc = ssh_get_publickey_hash(key, SSH_PUBLICKEY_HASH_SHA256, &hash, &hlen);
if (rc != SSH_OK) {
fprintf(stderr, "Failed to get key fingerprint\n");
return;
}
ssh_print_hash(SSH_PUBLICKEY_HASH_SHA256, hash, hlen);
ssh_clean_pubkey_hash(&hash);
ssh_key_free(key);
}
int main(int argc, char *argv[])
{
ssh_key key = NULL;
int rc = 0;
char overwrite[1024] = "";
char *pubkey_file = NULL;
struct arguments_st arguments = {
.type = SSH_KEYTYPE_UNKNOWN,
.bits = 0,
.file = NULL,
.passphrase = NULL,
.action_list = 0,
};
if (argc < 2) {
argp_help(&argp, stdout, ARGP_HELP_DOC | ARGP_HELP_USAGE, argv[0]);
goto end;
}
rc = argp_parse(&argp, argc, argv, 0, 0, &arguments);
if (rc != 0) {
goto end;
}
rc = validate_args(&arguments);
if (rc != 0) {
goto end;
}
if (arguments.action_list && arguments.file) {
list_fingerprint(arguments.file);
goto end;
}
errno = 0;
rc = open(arguments.file, O_CREAT | O_EXCL | O_WRONLY, S_IRUSR | S_IWUSR);
if (rc < 0) {
if (errno == EEXIST) {
printf("File \"%s\" exists. Overwrite it? (y|n) ", arguments.file);
rc = scanf("%1023s", overwrite);
if (rc > 0 && tolower(overwrite[0]) == 'y') {
rc = open(arguments.file, O_WRONLY);
if (rc > 0) {
close(rc);
errno = 0;
rc = chmod(arguments.file, S_IRUSR | S_IWUSR);
if (rc != 0) {
fprintf(stderr,
"Error(%d): Could not set file permissions\n",
errno);
goto end;
}
} else {
fprintf(stderr,
"Error: Could not create private key file\n");
goto end;
}
} else {
goto end;
}
} else {
fprintf(stderr, "Error opening \"%s\" file\n", arguments.file);
goto end;
}
} else {
close(rc);
}
/* Generate a new private key */
rc = ssh_pki_generate(arguments.type, arguments.bits, &key);
if (rc != SSH_OK) {
fprintf(stderr, "Error: Failed to generate keys");
goto end;
}
/* Write the private key */
rc = ssh_pki_export_privkey_file(key, arguments.passphrase, NULL, NULL,
arguments.file);
if (rc != SSH_OK) {
fprintf(stderr, "Error: Failed to write private key file");
goto end;
}
/* If a passphrase was provided, overwrite and free it as it is not needed
* anymore */
if (arguments.passphrase != NULL) {
#ifdef HAVE_EXPLICIT_BZERO
explicit_bzero(arguments.passphrase, strlen(arguments.passphrase));
#else
bzero(arguments.passphrase, strlen(arguments.passphrase));
#endif
free(arguments.passphrase);
arguments.passphrase = NULL;
}
pubkey_file = (char *)malloc(strlen(arguments.file) + 5);
if (pubkey_file == NULL) {
rc = ENOMEM;
goto end;
}
sprintf(pubkey_file, "%s.pub", arguments.file);
errno = 0;
rc = open(pubkey_file,
O_CREAT | O_EXCL | O_WRONLY,
S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
if (rc < 0) {
if (errno == EEXIST) {
printf("File \"%s\" exists. Overwrite it? (y|n) ", pubkey_file);
rc = scanf("%1023s", overwrite);
if (rc > 0 && tolower(overwrite[0]) == 'y') {
rc = open(pubkey_file, O_WRONLY);
if (rc > 0) {
close(rc);
errno = 0;
rc = chmod(pubkey_file,
S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
if (rc != 0) {
fprintf(stderr,
"Error(%d): Could not set file permissions\n",
errno);
goto end;
}
} else {
fprintf(stderr,
"Error: Could not create public key file\n");
goto end;
}
} else {
goto end;
}
} else {
fprintf(stderr, "Error opening \"%s\" file\n", pubkey_file);
goto end;
}
} else {
close(rc);
}
/* Write the public key */
rc = ssh_pki_export_pubkey_file(key, pubkey_file);
if (rc != SSH_OK) {
fprintf(stderr, "Error: Failed to write public key file");
goto end;
}
end:
if (key != NULL) {
ssh_key_free(key);
}
if (arguments.file != NULL) {
free(arguments.file);
}
if (arguments.passphrase != NULL) {
#ifdef HAVE_EXPLICIT_BZERO
explicit_bzero(arguments.passphrase, strlen(arguments.passphrase));
#else
bzero(arguments.passphrase, strlen(arguments.passphrase));
#endif
free(arguments.passphrase);
}
if (pubkey_file != NULL) {
free(pubkey_file);
}
return rc;
}

View File

@@ -17,14 +17,11 @@ The goal is to show the API in action. It's not a reference on how terminal
clients must be made or how a client should react. clients must be made or how a client should react.
*/ */
#include "config.h"
#include <errno.h> #include <errno.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "libssh/priv.h"
#include <libssh/libssh.h> #include <libssh/libssh.h>
#include "examples_common.h" #include "examples_common.h"
@@ -32,86 +29,82 @@ clients must be made or how a client should react.
#define strncasecmp _strnicmp #define strncasecmp _strnicmp
#endif #endif
int verify_knownhost(ssh_session session) int verify_knownhost(ssh_session session){
{ char *hexa;
enum ssh_known_hosts_e state; int state;
char buf[10]; char buf[10];
unsigned char *hash = NULL; unsigned char *hash = NULL;
size_t hlen; size_t hlen;
ssh_key srv_pubkey; ssh_key srv_pubkey;
int rc; int rc;
rc = ssh_get_server_publickey(session, &srv_pubkey); state=ssh_is_server_known(session);
if (rc < 0) {
return -1;
}
rc = ssh_get_publickey_hash(srv_pubkey, rc = ssh_get_publickey(session, &srv_pubkey);
SSH_PUBLICKEY_HASH_SHA256, if (rc < 0) {
&hash, return -1;
&hlen); }
ssh_key_free(srv_pubkey);
if (rc < 0) {
return -1;
}
state = ssh_session_is_known_server(session); rc = ssh_get_publickey_hash(srv_pubkey,
SSH_PUBLICKEY_HASH_SHA1,
&hash,
&hlen);
ssh_key_free(srv_pubkey);
if (rc < 0) {
return -1;
}
switch(state) { switch(state){
case SSH_KNOWN_HOSTS_CHANGED: case SSH_SERVER_KNOWN_OK:
fprintf(stderr,"Host key for server changed : server's one is now :\n"); break; /* ok */
ssh_print_hash(SSH_PUBLICKEY_HASH_SHA256, hash, hlen); case SSH_SERVER_KNOWN_CHANGED:
ssh_clean_pubkey_hash(&hash); fprintf(stderr,"Host key for server changed : server's one is now :\n");
fprintf(stderr,"For security reason, connection will be stopped\n"); ssh_print_hexa("Public key hash",hash, hlen);
return -1; ssh_clean_pubkey_hash(&hash);
case SSH_KNOWN_HOSTS_OTHER: fprintf(stderr,"For security reason, connection will be stopped\n");
fprintf(stderr,"The host key for this server was not found but an other type of key exists.\n"); return -1;
fprintf(stderr,"An attacker might change the default server key to confuse your client" case SSH_SERVER_FOUND_OTHER:
"into thinking the key does not exist\n" fprintf(stderr,"The host key for this server was not found but an other type of key exists.\n");
"We advise you to rerun the client with -d or -r for more safety.\n"); fprintf(stderr,"An attacker might change the default server key to confuse your client"
return -1; "into thinking the key does not exist\n"
case SSH_KNOWN_HOSTS_NOT_FOUND: "We advise you to rerun the client with -d or -r for more safety.\n");
fprintf(stderr,"Could not find known host file. If you accept the host key here,\n"); return -1;
fprintf(stderr,"the file will be automatically created.\n"); case SSH_SERVER_FILE_NOT_FOUND:
/* fallback to SSH_SERVER_NOT_KNOWN behavior */ fprintf(stderr,"Could not find known host file. If you accept the host key here,\n");
FALL_THROUGH; fprintf(stderr,"the file will be automatically created.\n");
/* fallback to SSH_SERVER_NOT_KNOWN behavior */
case SSH_SERVER_NOT_KNOWN: case SSH_SERVER_NOT_KNOWN:
fprintf(stderr, hexa = ssh_get_hexa(hash, hlen);
"The server is unknown. Do you trust the host key (yes/no)?\n"); fprintf(stderr,"The server is unknown. Do you trust the host key ?\n");
ssh_print_hash(SSH_PUBLICKEY_HASH_SHA256, hash, hlen); fprintf(stderr, "Public key hash: %s\n", hexa);
ssh_string_free_char(hexa);
if (fgets(buf, sizeof(buf), stdin) == NULL) { if (fgets(buf, sizeof(buf), stdin) == NULL) {
ssh_clean_pubkey_hash(&hash); ssh_clean_pubkey_hash(&hash);
return -1;
}
if(strncasecmp(buf,"yes",3)!=0){
ssh_clean_pubkey_hash(&hash);
return -1;
}
fprintf(stderr,"This new key will be written on disk for further usage. do you agree ?\n");
if (fgets(buf, sizeof(buf), stdin) == NULL) {
ssh_clean_pubkey_hash(&hash);
return -1;
}
if(strncasecmp(buf,"yes",3)==0){
rc = ssh_session_update_known_hosts(session);
if (rc != SSH_OK) {
ssh_clean_pubkey_hash(&hash);
fprintf(stderr, "error %s\n", strerror(errno));
return -1;
}
}
break;
case SSH_KNOWN_HOSTS_ERROR:
ssh_clean_pubkey_hash(&hash);
fprintf(stderr,"%s",ssh_get_error(session));
return -1; return -1;
case SSH_KNOWN_HOSTS_OK: }
break; /* ok */ if(strncasecmp(buf,"yes",3)!=0){
} ssh_clean_pubkey_hash(&hash);
return -1;
}
fprintf(stderr,"This new key will be written on disk for further usage. do you agree ?\n");
if (fgets(buf, sizeof(buf), stdin) == NULL) {
ssh_clean_pubkey_hash(&hash);
return -1;
}
if(strncasecmp(buf,"yes",3)==0){
if (ssh_write_knownhost(session) < 0) {
ssh_clean_pubkey_hash(&hash);
fprintf(stderr, "error %s\n", strerror(errno));
return -1;
}
}
ssh_clean_pubkey_hash(&hash); break;
case SSH_SERVER_ERROR:
return 0; ssh_clean_pubkey_hash(&hash);
fprintf(stderr,"%s",ssh_get_error(session));
return -1;
}
ssh_clean_pubkey_hash(&hash);
return 0;
} }

View File

@@ -22,233 +22,151 @@ program.
#include <libssh/libssh.h> #include <libssh/libssh.h>
#include "examples_common.h" #include "examples_common.h"
#ifndef BUF_SIZE
#define BUF_SIZE 16384
#endif
static char **sources; static char **sources;
static int nsources; static int nsources;
static char *destination; static char *destination;
static int verbosity = 0; static int verbosity=0;
struct location { struct location {
int is_ssh; int is_ssh;
char *user; char *user;
char *host; char *host;
char *path; char *path;
ssh_session session; ssh_session session;
ssh_scp scp; ssh_scp scp;
FILE *file; FILE *file;
}; };
enum { enum {
READ, READ,
WRITE WRITE
}; };
static void usage(const char *argv0) { static void usage(const char *argv0){
fprintf(stderr, "Usage : %s [options] [[user@]host1:]file1 ... \n" fprintf(stderr,"Usage : %s [options] [[user@]host1:]file1 ... \n"
" [[user@]host2:]destination\n" " [[user@]host2:]destination\n"
"sample scp client - libssh-%s\n", "sample scp client - libssh-%s\n",
// "Options :\n", // "Options :\n",
// " -r : use RSA to verify host public key\n", // " -r : use RSA to verify host public key\n",
argv0, argv0,
ssh_version(0)); ssh_version(0));
exit(0); exit(0);
} }
static int opts(int argc, char **argv) { static int opts(int argc, char **argv){
int i; int i;
while((i=getopt(argc,argv,"v"))!=-1){
while((i = getopt(argc, argv, "v")) != -1) { switch(i){
switch(i) { case 'v':
case 'v': verbosity++;
verbosity++; break;
break; default:
default: fprintf(stderr,"unknown option %c\n",optopt);
fprintf(stderr, "unknown option %c\n", optopt);
usage(argv[0]);
return -1;
}
}
nsources = argc - optind - 1;
if (nsources < 1) {
usage(argv[0]); usage(argv[0]);
return -1; return -1;
} }
}
sources = malloc((nsources + 1) * sizeof(char *)); nsources=argc-optind-1;
if (sources == NULL) { if(nsources < 1){
return -1; usage(argv[0]);
}
for(i = 0; i < nsources; ++i) {
sources[i] = argv[optind];
optind++;
}
sources[i] = NULL;
destination = argv[optind];
return 0;
}
static void location_free(struct location *loc)
{
if (loc) {
if (loc->path) {
free(loc->path);
}
loc->path = NULL;
if (loc->is_ssh) {
if (loc->host) {
free(loc->host);
}
loc->host = NULL;
if (loc->user) {
free(loc->user);
}
loc->user = NULL;
}
free(loc);
}
}
static struct location *parse_location(char *loc) {
struct location *location;
char *ptr;
location = malloc(sizeof(struct location));
if (location == NULL) {
return NULL;
}
memset(location, 0, sizeof(struct location));
location->host = location->user = NULL;
ptr = strchr(loc, ':');
if (ptr != NULL) {
location->is_ssh = 1;
location->path = strdup(ptr+1);
*ptr = '\0';
ptr = strchr(loc, '@');
if (ptr != NULL) {
location->host = strdup(ptr+1);
*ptr = '\0';
location->user = strdup(loc);
} else {
location->host = strdup(loc);
}
} else {
location->is_ssh = 0;
location->path = strdup(loc);
}
return location;
}
static void close_location(struct location *loc) {
int rc;
if (loc) {
if (loc->is_ssh) {
if (loc->scp) {
rc = ssh_scp_close(loc->scp);
if (rc == SSH_ERROR) {
fprintf(stderr,
"Error closing scp: %s\n",
ssh_get_error(loc->session));
}
ssh_scp_free(loc->scp);
loc->scp = NULL;
}
if (loc->session) {
ssh_disconnect(loc->session);
ssh_free(loc->session);
loc->session = NULL;
}
} else {
if (loc->file) {
fclose(loc->file);
loc->file = NULL;
}
}
}
}
static int open_location(struct location *loc, int flag) {
if (loc->is_ssh && flag == WRITE) {
loc->session = connect_ssh(loc->host, loc->user, verbosity);
if (!loc->session) {
fprintf(stderr, "Couldn't connect to %s\n", loc->host);
return -1;
}
loc->scp = ssh_scp_new(loc->session, SSH_SCP_WRITE, loc->path);
if (!loc->scp) {
fprintf(stderr, "error : %s\n", ssh_get_error(loc->session));
ssh_disconnect(loc->session);
ssh_free(loc->session);
loc->session = NULL;
return -1;
}
if (ssh_scp_init(loc->scp) == SSH_ERROR) {
fprintf(stderr, "error : %s\n", ssh_get_error(loc->session));
ssh_scp_free(loc->scp);
loc->scp = NULL;
ssh_disconnect(loc->session);
ssh_free(loc->session);
loc->session = NULL;
return -1;
}
return 0;
} else if (loc->is_ssh && flag == READ) {
loc->session = connect_ssh(loc->host, loc->user, verbosity);
if (!loc->session) {
fprintf(stderr, "Couldn't connect to %s\n", loc->host);
return -1;
}
loc->scp = ssh_scp_new(loc->session, SSH_SCP_READ, loc->path);
if (!loc->scp) {
fprintf(stderr, "error : %s\n", ssh_get_error(loc->session));
ssh_disconnect(loc->session);
ssh_free(loc->session);
loc->session = NULL;
return -1;
}
if (ssh_scp_init(loc->scp) == SSH_ERROR) {
fprintf(stderr, "error : %s\n", ssh_get_error(loc->session));
ssh_scp_free(loc->scp);
loc->scp = NULL;
ssh_disconnect(loc->session);
ssh_free(loc->session);
loc->session = NULL;
return -1;
}
return 0;
} else {
loc->file = fopen(loc->path, flag == READ ? "r":"w");
if (!loc->file) {
if (errno == EISDIR) {
if (loc->path != NULL && chdir(loc->path)) {
fprintf(stderr,
"Error changing directory to %s: %s\n",
loc->path, strerror(errno));
return -1;
}
return 0;
}
fprintf(stderr,
"Error opening %s: %s\n",
loc->path, strerror(errno));
return -1;
}
return 0;
}
return -1; return -1;
}
sources=malloc((nsources + 1) * sizeof(char *));
if(sources == NULL)
return -1;
for(i=0;i<nsources;++i){
sources[i] = argv[optind];
optind++;
}
sources[i]=NULL;
destination=argv[optind];
return 0;
}
static struct location *parse_location(char *loc){
struct location *location;
char *ptr;
location = malloc(sizeof(struct location));
if (location == NULL) {
return NULL;
}
memset(location, 0, sizeof(struct location));
location->host=location->user=NULL;
ptr=strchr(loc,':');
if(ptr != NULL){
location->is_ssh=1;
location->path=strdup(ptr+1);
*ptr='\0';
ptr=strchr(loc,'@');
if(ptr != NULL){
location->host=strdup(ptr+1);
*ptr='\0';
location->user=strdup(loc);
} else {
location->host=strdup(loc);
}
} else {
location->is_ssh=0;
location->path=strdup(loc);
}
return location;
}
static int open_location(struct location *loc, int flag){
if(loc->is_ssh && flag==WRITE){
loc->session=connect_ssh(loc->host,loc->user,verbosity);
if(!loc->session){
fprintf(stderr,"Couldn't connect to %s\n",loc->host);
return -1;
}
loc->scp=ssh_scp_new(loc->session,SSH_SCP_WRITE,loc->path);
if(!loc->scp){
fprintf(stderr,"error : %s\n",ssh_get_error(loc->session));
return -1;
}
if(ssh_scp_init(loc->scp)==SSH_ERROR){
fprintf(stderr,"error : %s\n",ssh_get_error(loc->session));
ssh_scp_free(loc->scp);
loc->scp = NULL;
return -1;
}
return 0;
} else if(loc->is_ssh && flag==READ){
loc->session=connect_ssh(loc->host, loc->user,verbosity);
if(!loc->session){
fprintf(stderr,"Couldn't connect to %s\n",loc->host);
return -1;
}
loc->scp=ssh_scp_new(loc->session,SSH_SCP_READ,loc->path);
if(!loc->scp){
fprintf(stderr,"error : %s\n",ssh_get_error(loc->session));
return -1;
}
if(ssh_scp_init(loc->scp)==SSH_ERROR){
fprintf(stderr,"error : %s\n",ssh_get_error(loc->session));
ssh_scp_free(loc->scp);
loc->scp = NULL;
return -1;
}
return 0;
} else {
loc->file=fopen(loc->path,flag==READ ? "r":"w");
if(!loc->file){
if(errno==EISDIR){
if(chdir(loc->path)){
fprintf(stderr,"Error changing directory to %s: %s\n",loc->path,strerror(errno));
return -1;
}
return 0;
}
fprintf(stderr,"Error opening %s: %s\n",loc->path,strerror(errno));
return -1;
}
return 0;
}
return -1;
} }
/** @brief copies files from source location to destination /** @brief copies files from source location to destination
@@ -256,201 +174,155 @@ static int open_location(struct location *loc, int flag) {
* @param dest destination location * @param dest destination location
* @param recursive Copy also directories * @param recursive Copy also directories
*/ */
static int do_copy(struct location *src, struct location *dest, int recursive) { static int do_copy(struct location *src, struct location *dest, int recursive){
size_t size; int size;
socket_t fd; socket_t fd;
struct stat s; struct stat s;
int w, r; int w,r;
char buffer[BUF_SIZE]; char buffer[16384];
size_t total = 0; int total=0;
mode_t mode; int mode;
char *filename = NULL; char *filename = NULL;
/* recursive mode doesn't work yet */
/* recursive mode doesn't work yet */ (void)recursive;
(void)recursive; /* Get the file name and size*/
/* Get the file name and size*/ if(!src->is_ssh){
if (!src->is_ssh) { fd = fileno(src->file);
fd = fileno(src->file); if (fd < 0) {
if (fd < 0) { fprintf(stderr, "Invalid file pointer, error: %s\n", strerror(errno));
fprintf(stderr, return -1;
"Invalid file pointer, error: %s\n",
strerror(errno));
return -1;
}
r = fstat(fd, &s);
if (r < 0) {
return -1;
}
size = s.st_size;
mode = s.st_mode & ~S_IFMT;
filename = ssh_basename(src->path);
} else {
size = 0;
do {
r = ssh_scp_pull_request(src->scp);
if (r == SSH_SCP_REQUEST_NEWDIR) {
ssh_scp_deny_request(src->scp, "Not in recursive mode");
continue;
}
if (r == SSH_SCP_REQUEST_NEWFILE) {
size = ssh_scp_request_get_size(src->scp);
filename = strdup(ssh_scp_request_get_filename(src->scp));
mode = ssh_scp_request_get_permissions(src->scp);
//ssh_scp_accept_request(src->scp);
break;
}
if (r == SSH_ERROR) {
fprintf(stderr,
"Error: %s\n",
ssh_get_error(src->session));
SSH_STRING_FREE_CHAR(filename);
return -1;
}
} while(r != SSH_SCP_REQUEST_NEWFILE);
} }
r = fstat(fd, &s);
if (dest->is_ssh) { if (r < 0) {
r = ssh_scp_push_file(dest->scp, src->path, size, mode); return -1;
// snprintf(buffer, sizeof(buffer), "C0644 %d %s\n", size, src->path);
if (r == SSH_ERROR) {
fprintf(stderr,
"error: %s\n",
ssh_get_error(dest->session));
SSH_STRING_FREE_CHAR(filename);
ssh_scp_free(dest->scp);
dest->scp = NULL;
return -1;
}
} else {
if (!dest->file) {
dest->file = fopen(filename, "w");
if (!dest->file) {
fprintf(stderr,
"Cannot open %s for writing: %s\n",
filename, strerror(errno));
if (src->is_ssh) {
ssh_scp_deny_request(src->scp, "Cannot open local file");
}
SSH_STRING_FREE_CHAR(filename);
return -1;
}
}
if (src->is_ssh) {
ssh_scp_accept_request(src->scp);
}
} }
size=s.st_size;
mode = s.st_mode & ~S_IFMT;
filename=ssh_basename(src->path);
} else {
size=0;
do { do {
if (src->is_ssh) { r=ssh_scp_pull_request(src->scp);
r = ssh_scp_read(src->scp, buffer, sizeof(buffer)); if(r==SSH_SCP_REQUEST_NEWDIR){
if (r == SSH_ERROR) { ssh_scp_deny_request(src->scp,"Not in recursive mode");
fprintf(stderr, continue;
"Error reading scp: %s\n", }
ssh_get_error(src->session)); if(r==SSH_SCP_REQUEST_NEWFILE){
SSH_STRING_FREE_CHAR(filename); size=ssh_scp_request_get_size(src->scp);
return -1; filename=strdup(ssh_scp_request_get_filename(src->scp));
} mode=ssh_scp_request_get_permissions(src->scp);
//ssh_scp_accept_request(src->scp);
break;
}
if(r==SSH_ERROR){
fprintf(stderr,"Error: %s\n",ssh_get_error(src->session));
ssh_string_free_char(filename);
return -1;
}
} while(r != SSH_SCP_REQUEST_NEWFILE);
}
if (r == 0) { if(dest->is_ssh){
break; r=ssh_scp_push_file(dest->scp,src->path, size, mode);
} // snprintf(buffer,sizeof(buffer),"C0644 %d %s\n",size,src->path);
} else { if(r==SSH_ERROR){
r = fread(buffer, 1, sizeof(buffer), src->file); fprintf(stderr,"error: %s\n",ssh_get_error(dest->session));
if (r == 0) { ssh_string_free_char(filename);
break; ssh_scp_free(dest->scp);
} dest->scp = NULL;
return -1;
}
} else {
if(!dest->file){
dest->file=fopen(filename,"w");
if(!dest->file){
fprintf(stderr,"Cannot open %s for writing: %s\n",filename,strerror(errno));
if(src->is_ssh)
ssh_scp_deny_request(src->scp,"Cannot open local file");
ssh_string_free_char(filename);
return -1;
}
}
if(src->is_ssh){
ssh_scp_accept_request(src->scp);
}
}
do {
if(src->is_ssh){
r=ssh_scp_read(src->scp,buffer,sizeof(buffer));
if(r==SSH_ERROR){
fprintf(stderr,"Error reading scp: %s\n",ssh_get_error(src->session));
ssh_string_free_char(filename);
return -1;
}
if(r==0)
break;
} else {
r=fread(buffer,1,sizeof(buffer),src->file);
if(r==0)
break;
if(r<0){
fprintf(stderr,"Error reading file: %s\n",strerror(errno));
ssh_string_free_char(filename);
return -1;
}
}
if(dest->is_ssh){
w=ssh_scp_write(dest->scp,buffer,r);
if(w == SSH_ERROR){
fprintf(stderr,"Error writing in scp: %s\n",ssh_get_error(dest->session));
ssh_scp_free(dest->scp);
dest->scp=NULL;
ssh_string_free_char(filename);
return -1;
}
} else {
w=fwrite(buffer,r,1,dest->file);
if(w<=0){
fprintf(stderr,"Error writing in local file: %s\n",strerror(errno));
ssh_string_free_char(filename);
return -1;
}
}
total+=r;
if (r < 0) { } while(total < size);
fprintf(stderr, ssh_string_free_char(filename);
"Error reading file: %s\n", printf("wrote %d bytes\n",total);
strerror(errno)); return 0;
SSH_STRING_FREE_CHAR(filename);
return -1;
}
}
if (dest->is_ssh) {
w = ssh_scp_write(dest->scp, buffer, r);
if (w == SSH_ERROR) {
fprintf(stderr,
"Error writing in scp: %s\n",
ssh_get_error(dest->session));
ssh_scp_free(dest->scp);
dest->scp = NULL;
SSH_STRING_FREE_CHAR(filename);
return -1;
}
} else {
w = fwrite(buffer, r, 1, dest->file);
if (w <= 0) {
fprintf(stderr,
"Error writing in local file: %s\n",
strerror(errno));
SSH_STRING_FREE_CHAR(filename);
return -1;
}
}
total += r;
} while(total < size);
SSH_STRING_FREE_CHAR(filename);
printf("wrote %zu bytes\n", total);
return 0;
} }
int main(int argc, char **argv) { int main(int argc, char **argv){
struct location *dest, *src; struct location *dest, *src;
int i; int i;
int r; int r;
if (opts(argc, argv) < 0) { if(opts(argc,argv)<0)
return EXIT_FAILURE; return EXIT_FAILURE;
dest=parse_location(destination);
if(open_location(dest,WRITE)<0)
return EXIT_FAILURE;
for(i=0;i<nsources;++i){
src=parse_location(sources[i]);
if(open_location(src,READ)<0){
return EXIT_FAILURE;
} }
if(do_copy(src,dest,0) < 0){
ssh_init(); break;
dest = parse_location(destination);
if (dest == NULL) {
r = EXIT_FAILURE;
goto end;
} }
}
if (open_location(dest, WRITE) < 0) { if (dest->is_ssh && dest->scp != NULL) {
location_free(dest); r=ssh_scp_close(dest->scp);
r = EXIT_FAILURE; if(r == SSH_ERROR){
goto end; fprintf(stderr,"Error closing scp: %s\n",ssh_get_error(dest->session));
} ssh_scp_free(dest->scp);
dest->scp=NULL;
for (i = 0; i < nsources; ++i) { return -1;
src = parse_location(sources[i]); }
if (src == NULL) { } else {
r = EXIT_FAILURE; fclose(dest->file);
goto close_dest; dest->file=NULL;
} }
ssh_disconnect(dest->session);
if (open_location(src, READ) < 0) { ssh_finalize();
location_free(src); return 0;
r = EXIT_FAILURE;
goto close_dest;
}
if (do_copy(src, dest, 0) < 0) {
close_location(src);
location_free(src);
break;
}
close_location(src);
location_free(src);
}
r = 0;
close_dest:
close_location(dest);
location_free(dest);
end:
ssh_finalize();
free(sources);
return r;
} }

View File

@@ -25,10 +25,6 @@ clients must be made or how a client should react.
#include <string.h> #include <string.h>
#include <stdio.h> #include <stdio.h>
#ifndef BUF_SIZE
#define BUF_SIZE 2048
#endif
#define USER "myuser" #define USER "myuser"
#define PASSWORD "mypassword" #define PASSWORD "mypassword"
@@ -229,7 +225,7 @@ int main(int argc, char **argv){
.channel_open_request_session_function = new_session_channel .channel_open_request_session_function = new_session_channel
}; };
char buf[BUF_SIZE]; char buf[2048];
char host[128]=""; char host[128]="";
char *ptr; char *ptr;
int i,r, rc; int i,r, rc;
@@ -295,7 +291,7 @@ int main(int argc, char **argv){
snprintf(buf,sizeof(buf), "Hello %s, welcome to the Sample SSH proxy.\r\nPlease select your destination: ", username); snprintf(buf,sizeof(buf), "Hello %s, welcome to the Sample SSH proxy.\r\nPlease select your destination: ", username);
ssh_channel_write(chan, buf, strlen(buf)); ssh_channel_write(chan, buf, strlen(buf));
do{ do{
i=ssh_channel_read(chan,buf, sizeof(buf), 0); i=ssh_channel_read(chan,buf, 2048, 0);
if(i>0) { if(i>0) {
ssh_channel_write(chan, buf, i); ssh_channel_write(chan, buf, i);
if(strlen(host) + i < sizeof(host)){ if(strlen(host) + i < sizeof(host)){

523
examples/sample.c Normal file
View File

@@ -0,0 +1,523 @@
/* client.c */
/*
Copyright 2003-2009 Aris Adamantiadis
This file is part of the SSH Library
You are free to copy this file, modify it in any way, consider it being public
domain. This does not apply to the rest of the library though, but it is
allowed to cut-and-paste working code from this file to any license of
program.
The goal is to show the API in action. It's not a reference on how terminal
clients must be made or how a client should react.
*/
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/select.h>
#include <sys/time.h>
#ifdef HAVE_TERMIOS_H
#include <termios.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef HAVE_PTY_H
#include <pty.h>
#endif
#include <sys/ioctl.h>
#include <signal.h>
#include <errno.h>
#include <fcntl.h>
#include <libssh/callbacks.h>
#include <libssh/libssh.h>
#include <libssh/sftp.h>
#include "examples_common.h"
#define MAXCMD 10
static char *host;
static char *user;
static char *cmds[MAXCMD];
static struct termios terminal;
static char *pcap_file=NULL;
static char *proxycommand;
static int auth_callback(const char *prompt, char *buf, size_t len,
int echo, int verify, void *userdata) {
(void) verify;
(void) userdata;
return ssh_getpass(prompt, buf, len, echo, verify);
}
struct ssh_callbacks_struct cb = {
.auth_function=auth_callback,
.userdata=NULL
};
static void add_cmd(char *cmd){
int n;
for (n = 0; (n < MAXCMD) && cmds[n] != NULL; n++);
if (n == MAXCMD) {
return;
}
cmds[n]=strdup(cmd);
}
static void usage(){
fprintf(stderr,"Usage : ssh [options] [login@]hostname\n"
"sample client - libssh-%s\n"
"Options :\n"
" -l user : log in as user\n"
" -p port : connect to port\n"
" -d : use DSS to verify host public key\n"
" -r : use RSA to verify host public key\n"
#ifdef WITH_PCAP
" -P file : create a pcap debugging file\n"
#endif
#ifndef _WIN32
" -T proxycommand : command to execute as a socket proxy\n"
#endif
,
ssh_version(0));
exit(0);
}
static int opts(int argc, char **argv){
int i;
// for(i=0;i<argc;i++)
// printf("%d : %s\n",i,argv[i]);
/* insert your own arguments here */
while((i=getopt(argc,argv,"T:P:"))!=-1){
switch(i){
case 'P':
pcap_file=optarg;
break;
#ifndef _WIN32
case 'T':
proxycommand=optarg;
break;
#endif
default:
fprintf(stderr,"unknown option %c\n",optopt);
usage();
}
}
if(optind < argc)
host=argv[optind++];
while(optind < argc)
add_cmd(argv[optind++]);
if(host==NULL)
usage();
return 0;
}
#ifndef HAVE_CFMAKERAW
static void cfmakeraw(struct termios *termios_p){
termios_p->c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
termios_p->c_oflag &= ~OPOST;
termios_p->c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
termios_p->c_cflag &= ~(CSIZE|PARENB);
termios_p->c_cflag |= CS8;
}
#endif
static void do_cleanup(int i) {
/* unused variable */
(void) i;
tcsetattr(0,TCSANOW,&terminal);
}
static void do_exit(int i) {
/* unused variable */
(void) i;
do_cleanup(0);
exit(0);
}
ssh_channel chan;
int signal_delayed=0;
static void sigwindowchanged(int i){
(void) i;
signal_delayed=1;
}
static void setsignal(void){
signal(SIGWINCH, sigwindowchanged);
signal_delayed=0;
}
static void sizechanged(void){
struct winsize win = { 0, 0, 0, 0 };
ioctl(1, TIOCGWINSZ, &win);
ssh_channel_change_pty_size(chan,win.ws_col, win.ws_row);
// printf("Changed pty size\n");
setsignal();
}
/* There are two flavors of select loop: the one based on
* ssh_select and the one based on channel_select.
* The ssh_select one permits you to give your own file descriptors to
* follow. It is thus a complete select loop.
* The second one only selects on channels. It is simplier to use
* but doesn't permit you to fill in your own file descriptor. It is
* more adapted if you can't use ssh_select as a main loop (because
* you already have another main loop system).
*/
#ifdef USE_CHANNEL_SELECT
/* channel_select base main loop, with a standard select(2)
*/
static void select_loop(ssh_session session,ssh_channel channel){
fd_set fds;
struct timeval timeout;
char buffer[4096];
ssh_buffer readbuf=ssh_buffer_new();
ssh_channel channels[2];
int lus;
int eof=0;
int maxfd;
int ret;
while(channel){
/* when a signal is caught, ssh_select will return
* with SSH_EINTR, which means it should be started
* again. It lets you handle the signal the faster you
* can, like in this window changed example. Of course, if
* your signal handler doesn't call libssh at all, you're
* free to handle signals directly in sighandler.
*/
do{
FD_ZERO(&fds);
if(!eof)
FD_SET(0,&fds);
timeout.tv_sec=30;
timeout.tv_usec=0;
FD_SET(ssh_get_fd(session),&fds);
maxfd=ssh_get_fd(session)+1;
ret=select(maxfd,&fds,NULL,NULL,&timeout);
if(ret==EINTR)
continue;
if(FD_ISSET(0,&fds)){
lus=read(0,buffer,sizeof(buffer));
if(lus)
ssh_channel_write(channel,buffer,lus);
else {
eof=1;
ssh_channel_send_eof(channel);
}
}
if(FD_ISSET(ssh_get_fd(session),&fds)){
ssh_set_fd_toread(session);
}
channels[0]=channel; // set the first channel we want to read from
channels[1]=NULL;
ret=ssh_channel_select(channels,NULL,NULL,NULL); // no specific timeout - just poll
if(signal_delayed)
sizechanged();
} while (ret==EINTR || ret==SSH_EINTR);
// we already looked for input from stdin. Now, we are looking for input from the channel
if(channel && ssh_channel_is_closed(channel)){
ssh_channel_free(channel);
channel=NULL;
channels[0]=NULL;
}
if(channels[0]){
while(channel && ssh_channel_is_open(channel) && ssh_channel_poll(channel,0)>0){
lus=channel_read_buffer(channel,readbuf,0,0);
if(lus==-1){
fprintf(stderr, "Error reading channel: %s\n",
ssh_get_error(session));
return;
}
if(lus==0){
ssh_channel_free(channel);
channel=channels[0]=NULL;
} else
if (write(1,ssh_buffer_get_begin(readbuf),lus) < 0) {
fprintf(stderr, "Error writing to buffer\n");
return;
}
}
while(channel && ssh_channel_is_open(channel) && ssh_channel_poll(channel,1)>0){ /* stderr */
lus=channel_read_buffer(channel,readbuf,0,1);
if(lus==-1){
fprintf(stderr, "Error reading channel: %s\n",
ssh_get_error(session));
return;
}
if(lus==0){
ssh_channel_free(channel);
channel=channels[0]=NULL;
} else
if (write(2,ssh_buffer_get_begin(readbuf),lus) < 0) {
fprintf(stderr, "Error writing to buffer\n");
return;
}
}
}
if(channel && ssh_channel_is_closed(channel)){
ssh_channel_free(channel);
channel=NULL;
}
}
ssh_buffer_free(readbuf);
}
#else /* CHANNEL_SELECT */
static void select_loop(ssh_session session,ssh_channel channel){
fd_set fds;
struct timeval timeout;
char buffer[4096];
/* channels will be set to the channels to poll.
* outchannels will contain the result of the poll
*/
ssh_channel channels[2], outchannels[2];
int lus;
int eof=0;
int maxfd;
unsigned int r;
int ret;
while(channel){
do{
int fd;
FD_ZERO(&fds);
if(!eof)
FD_SET(0,&fds);
timeout.tv_sec=30;
timeout.tv_usec=0;
fd = ssh_get_fd(session);
if (fd < 0) {
fprintf(stderr, "Error getting fd\n");
return;
}
FD_SET(fd, &fds);
maxfd = fd + 1;
channels[0]=channel; // set the first channel we want to read from
channels[1]=NULL;
ret=ssh_select(channels,outchannels,maxfd,&fds,&timeout);
if(signal_delayed)
sizechanged();
if(ret==EINTR)
continue;
if(FD_ISSET(0,&fds)){
lus=read(0,buffer,sizeof(buffer));
if(lus)
ssh_channel_write(channel,buffer,lus);
else {
eof=1;
ssh_channel_send_eof(channel);
}
}
if(channel && ssh_channel_is_closed(channel)){
ssh_channel_free(channel);
channel=NULL;
channels[0]=NULL;
}
if(outchannels[0]){
while(channel && ssh_channel_is_open(channel) && (r = ssh_channel_poll(channel,0))!=0){
lus=ssh_channel_read(channel,buffer,sizeof(buffer) > r ? r : sizeof(buffer),0);
if(lus==-1){
fprintf(stderr, "Error reading channel: %s\n",
ssh_get_error(session));
return;
}
if(lus==0){
ssh_channel_free(channel);
channel=channels[0]=NULL;
} else
if (write(1,buffer,lus) < 0) {
fprintf(stderr, "Error writing to buffer\n");
return;
}
}
while(channel && ssh_channel_is_open(channel) && (r = ssh_channel_poll(channel,1))!=0){ /* stderr */
lus=ssh_channel_read(channel,buffer,sizeof(buffer) > r ? r : sizeof(buffer),1);
if(lus==-1){
fprintf(stderr, "Error reading channel: %s\n",
ssh_get_error(session));
return;
}
if(lus==0){
ssh_channel_free(channel);
channel=channels[0]=NULL;
} else
if (write(2,buffer,lus) < 0) {
fprintf(stderr, "Error writing to buffer\n");
return;
}
}
}
if(channel && ssh_channel_is_closed(channel)){
ssh_channel_free(channel);
channel=NULL;
}
} while (ret==EINTR || ret==SSH_EINTR);
}
}
#endif
static void shell(ssh_session session){
ssh_channel channel;
struct termios terminal_local;
int interactive=isatty(0);
channel = ssh_channel_new(session);
if(interactive){
tcgetattr(0,&terminal_local);
memcpy(&terminal,&terminal_local,sizeof(struct termios));
}
if(ssh_channel_open_session(channel)){
printf("error opening channel : %s\n",ssh_get_error(session));
return;
}
chan=channel;
if(interactive){
ssh_channel_request_pty(channel);
sizechanged();
}
if(ssh_channel_request_shell(channel)){
printf("Requesting shell : %s\n",ssh_get_error(session));
return;
}
if(interactive){
cfmakeraw(&terminal_local);
tcsetattr(0,TCSANOW,&terminal_local);
setsignal();
}
signal(SIGTERM,do_cleanup);
select_loop(session,channel);
if(interactive)
do_cleanup(0);
}
static void batch_shell(ssh_session session){
ssh_channel channel;
char buffer[1024];
int i,s=0;
for(i=0;i<MAXCMD && cmds[i];++i) {
s+=snprintf(buffer+s,sizeof(buffer)-s,"%s ",cmds[i]);
free(cmds[i]);
cmds[i] = NULL;
}
channel=ssh_channel_new(session);
ssh_channel_open_session(channel);
if(ssh_channel_request_exec(channel,buffer)){
printf("error executing \"%s\" : %s\n",buffer,ssh_get_error(session));
return;
}
select_loop(session,channel);
}
static int client(ssh_session session){
int auth=0;
char *banner;
int state;
if (user)
if (ssh_options_set(session, SSH_OPTIONS_USER, user) < 0)
return -1;
if (ssh_options_set(session, SSH_OPTIONS_HOST ,host) < 0)
return -1;
if (proxycommand != NULL){
if(ssh_options_set(session, SSH_OPTIONS_PROXYCOMMAND, proxycommand))
return -1;
}
ssh_options_parse_config(session, NULL);
if(ssh_connect(session)){
fprintf(stderr,"Connection failed : %s\n",ssh_get_error(session));
return -1;
}
state=verify_knownhost(session);
if (state != 0)
return -1;
ssh_userauth_none(session, NULL);
banner=ssh_get_issue_banner(session);
if(banner){
printf("%s\n",banner);
free(banner);
}
auth=authenticate_console(session);
if(auth != SSH_AUTH_SUCCESS){
return -1;
}
if(!cmds[0])
shell(session);
else
batch_shell(session);
return 0;
}
ssh_pcap_file pcap;
void set_pcap(ssh_session session);
void set_pcap(ssh_session session){
if(!pcap_file)
return;
pcap=ssh_pcap_file_new();
if(!pcap)
return;
if(ssh_pcap_file_open(pcap,pcap_file) == SSH_ERROR){
printf("Error opening pcap file\n");
ssh_pcap_file_free(pcap);
pcap=NULL;
return;
}
ssh_set_pcap_file(session,pcap);
}
void cleanup_pcap(void);
void cleanup_pcap(){
if(pcap)
ssh_pcap_file_free(pcap);
pcap=NULL;
}
int main(int argc, char **argv){
ssh_session session;
session = ssh_new();
ssh_callbacks_init(&cb);
ssh_set_callbacks(session,&cb);
if(ssh_options_getopt(session, &argc, argv)) {
fprintf(stderr, "error parsing command line :%s\n",
ssh_get_error(session));
usage();
}
opts(argc,argv);
signal(SIGTERM, do_exit);
set_pcap(session);
client(session);
ssh_disconnect(session);
ssh_free(session);
cleanup_pcap();
ssh_finalize();
return 0;
}

View File

@@ -29,265 +29,240 @@ clients must be made or how a client should react.
#include "examples_common.h" #include "examples_common.h"
#ifdef WITH_SFTP #ifdef WITH_SFTP
#ifndef BUF_SIZE
#define BUF_SIZE 65536
#endif
static int verbosity; static int verbosity;
static char *destination; static char *destination;
static void do_sftp(ssh_session session) { #define DATALEN 65536
sftp_session sftp = sftp_new(session); static void do_sftp(ssh_session session){
sftp_session sftp=sftp_new(session);
sftp_dir dir; sftp_dir dir;
sftp_attributes file; sftp_attributes file;
sftp_statvfs_t sftpstatvfs; sftp_statvfs_t sftpstatvfs;
struct statvfs sysstatvfs; struct statvfs sysstatvfs;
sftp_file fichier; sftp_file fichier;
sftp_file to; sftp_file to;
int len = 1; int len=1;
unsigned int i; unsigned int i;
char data[BUF_SIZE] = {0}; char data[DATALEN]={0};
char *lnk; char *lnk;
unsigned int count; unsigned int count;
if (!sftp) { if(!sftp){
fprintf(stderr, "sftp error initialising channel: %s\n", fprintf(stderr, "sftp error initialising channel: %s\n",
ssh_get_error(session)); ssh_get_error(session));
goto end; return;
} }
if(sftp_init(sftp)){
if (sftp_init(sftp)) {
fprintf(stderr, "error initialising sftp: %s\n", fprintf(stderr, "error initialising sftp: %s\n",
ssh_get_error(session)); ssh_get_error(session));
goto end; return;
} }
printf("Additional SFTP extensions provided by the server:\n"); printf("Additional SFTP extensions provided by the server:\n");
count = sftp_extensions_get_count(sftp); count = sftp_extensions_get_count(sftp);
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
printf("\t%s, version: %s\n", printf("\t%s, version: %s\n",
sftp_extensions_get_name(sftp, i), sftp_extensions_get_name(sftp, i),
sftp_extensions_get_data(sftp, i)); sftp_extensions_get_data(sftp, i));
} }
/* test symlink and readlink */ /* test symlink and readlink */
if (sftp_symlink(sftp, "/tmp/this_is_the_link", if (sftp_symlink(sftp, "/tmp/this_is_the_link",
"/tmp/sftp_symlink_test") < 0) "/tmp/sftp_symlink_test") < 0) {
{ fprintf(stderr, "Could not create link (%s)\n", ssh_get_error(session));
fprintf(stderr, "Could not create link (%s)\n", return;
ssh_get_error(session));
goto end;
} }
lnk = sftp_readlink(sftp, "/tmp/sftp_symlink_test"); lnk = sftp_readlink(sftp, "/tmp/sftp_symlink_test");
if (lnk == NULL) { if (lnk == NULL) {
fprintf(stderr, "Could not read link (%s)\n", ssh_get_error(session)); fprintf(stderr, "Could not read link (%s)\n", ssh_get_error(session));
goto end; return;
} }
printf("readlink /tmp/sftp_symlink_test: %s\n", lnk); printf("readlink /tmp/sftp_symlink_test: %s\n", lnk);
sftp_unlink(sftp, "/tmp/sftp_symlink_test"); sftp_unlink(sftp, "/tmp/sftp_symlink_test");
if (sftp_extension_supported(sftp, "statvfs@openssh.com", "2")) { if (sftp_extension_supported(sftp, "statvfs@openssh.com", "2")) {
sftpstatvfs = sftp_statvfs(sftp, "/tmp"); sftpstatvfs = sftp_statvfs(sftp, "/tmp");
if (sftpstatvfs == NULL) { if (sftpstatvfs == NULL) {
fprintf(stderr, "statvfs failed (%s)\n", ssh_get_error(session)); fprintf(stderr, "statvfs failed (%s)\n", ssh_get_error(session));
goto end; return;
} }
printf("sftp statvfs:\n" printf("sftp statvfs:\n"
"\tfile system block size: %llu\n" "\tfile system block size: %llu\n"
"\tfundamental fs block size: %llu\n" "\tfundamental fs block size: %llu\n"
"\tnumber of blocks (unit f_frsize): %llu\n" "\tnumber of blocks (unit f_frsize): %llu\n"
"\tfree blocks in file system: %llu\n" "\tfree blocks in file system: %llu\n"
"\tfree blocks for non-root: %llu\n" "\tfree blocks for non-root: %llu\n"
"\ttotal file inodes: %llu\n" "\ttotal file inodes: %llu\n"
"\tfree file inodes: %llu\n" "\tfree file inodes: %llu\n"
"\tfree file inodes for to non-root: %llu\n" "\tfree file inodes for to non-root: %llu\n"
"\tfile system id: %llu\n" "\tfile system id: %llu\n"
"\tbit mask of f_flag values: %llu\n" "\tbit mask of f_flag values: %llu\n"
"\tmaximum filename length: %llu\n", "\tmaximum filename length: %llu\n",
(unsigned long long) sftpstatvfs->f_bsize, (unsigned long long) sftpstatvfs->f_bsize,
(unsigned long long) sftpstatvfs->f_frsize, (unsigned long long) sftpstatvfs->f_frsize,
(unsigned long long) sftpstatvfs->f_blocks, (unsigned long long) sftpstatvfs->f_blocks,
(unsigned long long) sftpstatvfs->f_bfree, (unsigned long long) sftpstatvfs->f_bfree,
(unsigned long long) sftpstatvfs->f_bavail, (unsigned long long) sftpstatvfs->f_bavail,
(unsigned long long) sftpstatvfs->f_files, (unsigned long long) sftpstatvfs->f_files,
(unsigned long long) sftpstatvfs->f_ffree, (unsigned long long) sftpstatvfs->f_ffree,
(unsigned long long) sftpstatvfs->f_favail, (unsigned long long) sftpstatvfs->f_favail,
(unsigned long long) sftpstatvfs->f_fsid, (unsigned long long) sftpstatvfs->f_fsid,
(unsigned long long) sftpstatvfs->f_flag, (unsigned long long) sftpstatvfs->f_flag,
(unsigned long long) sftpstatvfs->f_namemax); (unsigned long long) sftpstatvfs->f_namemax);
sftp_statvfs_free(sftpstatvfs); sftp_statvfs_free(sftpstatvfs);
if (statvfs("/tmp", &sysstatvfs) < 0) { if (statvfs("/tmp", &sysstatvfs) < 0) {
fprintf(stderr, "statvfs failed (%s)\n", strerror(errno)); fprintf(stderr, "statvfs failed (%s)\n", strerror(errno));
goto end; return;
} }
printf("sys statvfs:\n" printf("sys statvfs:\n"
"\tfile system block size: %llu\n" "\tfile system block size: %llu\n"
"\tfundamental fs block size: %llu\n" "\tfundamental fs block size: %llu\n"
"\tnumber of blocks (unit f_frsize): %llu\n" "\tnumber of blocks (unit f_frsize): %llu\n"
"\tfree blocks in file system: %llu\n" "\tfree blocks in file system: %llu\n"
"\tfree blocks for non-root: %llu\n" "\tfree blocks for non-root: %llu\n"
"\ttotal file inodes: %llu\n" "\ttotal file inodes: %llu\n"
"\tfree file inodes: %llu\n" "\tfree file inodes: %llu\n"
"\tfree file inodes for to non-root: %llu\n" "\tfree file inodes for to non-root: %llu\n"
"\tfile system id: %llu\n" "\tfile system id: %llu\n"
"\tbit mask of f_flag values: %llu\n" "\tbit mask of f_flag values: %llu\n"
"\tmaximum filename length: %llu\n", "\tmaximum filename length: %llu\n",
(unsigned long long) sysstatvfs.f_bsize, (unsigned long long) sysstatvfs.f_bsize,
(unsigned long long) sysstatvfs.f_frsize, (unsigned long long) sysstatvfs.f_frsize,
(unsigned long long) sysstatvfs.f_blocks, (unsigned long long) sysstatvfs.f_blocks,
(unsigned long long) sysstatvfs.f_bfree, (unsigned long long) sysstatvfs.f_bfree,
(unsigned long long) sysstatvfs.f_bavail, (unsigned long long) sysstatvfs.f_bavail,
(unsigned long long) sysstatvfs.f_files, (unsigned long long) sysstatvfs.f_files,
(unsigned long long) sysstatvfs.f_ffree, (unsigned long long) sysstatvfs.f_ffree,
(unsigned long long) sysstatvfs.f_favail, (unsigned long long) sysstatvfs.f_favail,
(unsigned long long) sysstatvfs.f_fsid, (unsigned long long) sysstatvfs.f_fsid,
(unsigned long long) sysstatvfs.f_flag, (unsigned long long) sysstatvfs.f_flag,
(unsigned long long) sysstatvfs.f_namemax); (unsigned long long) sysstatvfs.f_namemax);
} }
/* the connection is made */ /* the connection is made */
/* opening a directory */ /* opening a directory */
dir = sftp_opendir(sftp, "./"); dir=sftp_opendir(sftp,"./");
if (!dir) { if(!dir) {
fprintf(stderr, "Directory not opened(%s)\n", ssh_get_error(session)); fprintf(stderr, "Directory not opened(%s)\n", ssh_get_error(session));
goto end; return ;
} }
/* reading the whole directory, file by file */ /* reading the whole directory, file by file */
while ((file = sftp_readdir(sftp, dir))) { while((file=sftp_readdir(sftp,dir))){
fprintf(stderr, "%30s(%.8o) : %s(%.5d) %s(%.5d) : %.10llu bytes\n", fprintf(stderr, "%30s(%.8o) : %s(%.5d) %s(%.5d) : %.10llu bytes\n",
file->name, file->name,
file->permissions, file->permissions,
file->owner, file->owner,
file->uid, file->uid,
file->group, file->group,
file->gid, file->gid,
(long long unsigned int) file->size); (long long unsigned int) file->size);
sftp_attributes_free(file); sftp_attributes_free(file);
} }
/* when file=NULL, an error has occured OR the directory listing is end of file */
/* when file = NULL, an error has occured OR the directory listing is end of if(!sftp_dir_eof(dir)){
* file */
if (!sftp_dir_eof(dir)) {
fprintf(stderr, "Error: %s\n", ssh_get_error(session)); fprintf(stderr, "Error: %s\n", ssh_get_error(session));
goto end; return;
} }
if(sftp_closedir(dir)){
if (sftp_closedir(dir)) {
fprintf(stderr, "Error: %s\n", ssh_get_error(session)); fprintf(stderr, "Error: %s\n", ssh_get_error(session));
goto end; return;
} }
/* this will open a file and copy it into your /home directory */ /* this will open a file and copy it into your /home directory */
/* the small buffer size was intended to stress the library. of course, you /* the small buffer size was intended to stress the library. of course, you can use a buffer till 20kbytes without problem */
* can use a buffer till 20kbytes without problem */
fichier = sftp_open(sftp, "/usr/bin/ssh", O_RDONLY, 0); fichier=sftp_open(sftp,"/usr/bin/ssh",O_RDONLY, 0);
if (!fichier) { if(!fichier){
fprintf(stderr, "Error opening /usr/bin/ssh: %s\n", fprintf(stderr, "Error opening /usr/bin/ssh: %s\n",
ssh_get_error(session)); ssh_get_error(session));
goto end; return;
} }
/* open a file for writing... */ /* open a file for writing... */
to = sftp_open(sftp, "ssh-copy", O_WRONLY | O_CREAT, 0700); to=sftp_open(sftp,"ssh-copy",O_WRONLY | O_CREAT, 0700);
if (!to) { if(!to){
fprintf(stderr, "Error opening ssh-copy for writing: %s\n", fprintf(stderr, "Error opening ssh-copy for writing: %s\n",
ssh_get_error(session)); ssh_get_error(session));
sftp_close(fichier); return;
goto end;
} }
while((len=sftp_read(fichier,data,4096)) > 0){
while ((len = sftp_read(fichier, data, 4096)) > 0) { if(sftp_write(to,data,len)!=len){
if (sftp_write(to, data, len) != len) {
fprintf(stderr, "Error writing %d bytes: %s\n", fprintf(stderr, "Error writing %d bytes: %s\n",
len, ssh_get_error(session)); len, ssh_get_error(session));
sftp_close(to); return;
sftp_close(fichier);
goto end;
} }
} }
printf("finished\n"); printf("finished\n");
if (len < 0) { if(len<0)
fprintf(stderr, "Error reading file: %s\n", ssh_get_error(session)); fprintf(stderr, "Error reading file: %s\n", ssh_get_error(session));
}
sftp_close(fichier); sftp_close(fichier);
sftp_close(to); sftp_close(to);
printf("fichiers ferm\n"); printf("fichiers ferm\n");
to = sftp_open(sftp, "/tmp/grosfichier", O_WRONLY|O_CREAT, 0644); to=sftp_open(sftp,"/tmp/grosfichier",O_WRONLY|O_CREAT, 0644);
for(i=0;i<1000;++i){
for (i = 0; i < 1000; ++i) { len=sftp_write(to,data,DATALEN);
len = sftp_write(to, data, sizeof(data)); printf("wrote %d bytes\n",len);
printf("wrote %d bytes\n", len); if(len != DATALEN){
if (len != sizeof(data)) { printf("chunk %d : %d (%s)\n",i,len,ssh_get_error(session));
printf("chunk %d : %d (%s)\n", i, len, ssh_get_error(session));
} }
} }
sftp_close(to); sftp_close(to);
end:
/* close the sftp session */ /* close the sftp session */
sftp_free(sftp); sftp_free(sftp);
printf("sftp session terminated\n"); printf("sftp session terminated\n");
} }
static void usage(const char *argv0) { static void usage(const char *argv0){
fprintf(stderr, "Usage : %s [-v] remotehost\n" fprintf(stderr,"Usage : %s [-v] remotehost\n"
"sample sftp test client - libssh-%s\n" "sample sftp test client - libssh-%s\n"
"Options :\n" "Options :\n"
" -v : increase log verbosity\n", " -v : increase log verbosity\n",
argv0, argv0,
ssh_version(0)); ssh_version(0));
exit(0); exit(0);
} }
static int opts(int argc, char **argv) { static int opts(int argc, char **argv){
int i; int i;
while((i=getopt(argc,argv,"v"))!=-1){
while ((i = getopt(argc, argv, "v")) != -1) { switch(i){
switch(i) { case 'v':
case 'v': verbosity++;
verbosity++; break;
break; default:
default: fprintf(stderr,"unknown option %c\n",optopt);
fprintf(stderr, "unknown option %c\n", optopt);
usage(argv[0]);
return -1;
}
}
destination = argv[optind];
if (destination == NULL) {
usage(argv[0]); usage(argv[0]);
return -1; return -1;
} }
return 0; }
destination=argv[optind];
if(destination == NULL){
usage(argv[0]);
return -1;
}
return 0;
} }
int main(int argc, char **argv) { int main(int argc, char **argv){
ssh_session session; ssh_session session;
if(opts(argc,argv)<0)
if (opts(argc, argv) < 0) { return EXIT_FAILURE;
return EXIT_FAILURE; session=connect_ssh(destination,NULL,verbosity);
} if(session == NULL)
return EXIT_FAILURE;
session = connect_ssh(destination, NULL, verbosity); do_sftp(session);
if (session == NULL) { ssh_disconnect(session);
return EXIT_FAILURE; ssh_free(session);
} return 0;
do_sftp(session);
ssh_disconnect(session);
ssh_free(session);
return 0;
} }
#endif #endif

View File

@@ -25,14 +25,6 @@ clients must be made or how a client should react.
#include <string.h> #include <string.h>
#include <stdio.h> #include <stdio.h>
#ifdef _WIN32
#include <io.h>
#endif
#ifndef BUF_SIZE
#define BUF_SIZE 2049
#endif
#ifndef KEYS_FOLDER #ifndef KEYS_FOLDER
#ifdef _WIN32 #ifdef _WIN32
#define KEYS_FOLDER #define KEYS_FOLDER
@@ -49,27 +41,6 @@ static int tries = 0;
static int error = 0; static int error = 0;
static ssh_channel chan=NULL; static ssh_channel chan=NULL;
static int auth_none(ssh_session session,
const char *user,
void *userdata)
{
ssh_string banner = NULL;
(void)user; /* unused */
(void)userdata; /* unused */
ssh_set_auth_methods(session,
SSH_AUTH_METHOD_PASSWORD | SSH_AUTH_METHOD_GSSAPI_MIC);
banner = ssh_string_from_char("Banner Example\n");
if (banner != NULL) {
ssh_send_issue_banner(session, banner);
}
ssh_string_free(banner);
return SSH_AUTH_DENIED;
}
static int auth_password(ssh_session session, const char *user, static int auth_password(ssh_session session, const char *user,
const char *password, void *userdata){ const char *password, void *userdata){
(void)userdata; (void)userdata;
@@ -89,7 +60,6 @@ static int auth_password(ssh_session session, const char *user,
return SSH_AUTH_DENIED; return SSH_AUTH_DENIED;
} }
#ifdef WITH_GSSAPI
static int auth_gssapi_mic(ssh_session session, const char *user, const char *principal, void *userdata){ static int auth_gssapi_mic(ssh_session session, const char *user, const char *principal, void *userdata){
ssh_gssapi_creds creds = ssh_gssapi_get_creds(session); ssh_gssapi_creds creds = ssh_gssapi_get_creds(session);
(void)userdata; (void)userdata;
@@ -102,7 +72,6 @@ static int auth_gssapi_mic(ssh_session session, const char *user, const char *pr
authenticated = 1; authenticated = 1;
return SSH_AUTH_SUCCESS; return SSH_AUTH_SUCCESS;
} }
#endif
static int pty_request(ssh_session session, ssh_channel channel, const char *term, static int pty_request(ssh_session session, ssh_channel channel, const char *term,
int x,int y, int px, int py, void *userdata){ int x,int y, int px, int py, void *userdata){
@@ -196,14 +165,6 @@ static struct argp_option options[] = {
.doc = "Get verbose output.", .doc = "Get verbose output.",
.group = 0 .group = 0
}, },
{
.name = "config",
.key = 'f',
.arg = "FILE",
.flags = 0,
.doc = "Configuration file to use.",
.group = 0
},
{NULL, 0, NULL, 0, NULL, 0} {NULL, 0, NULL, 0, NULL, 0}
}; };
@@ -230,9 +191,6 @@ static error_t parse_opt (int key, char *arg, struct argp_state *state) {
case 'v': case 'v':
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_LOG_VERBOSITY_STR, "3"); ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_LOG_VERBOSITY_STR, "3");
break; break;
case 'f':
ssh_bind_options_parse_config(sshbind, arg);
break;
case ARGP_KEY_ARG: case ARGP_KEY_ARG:
if (state->arg_num >= 1) { if (state->arg_num >= 1) {
/* Too many arguments. */ /* Too many arguments. */
@@ -263,15 +221,12 @@ int main(int argc, char **argv){
ssh_event mainloop; ssh_event mainloop;
struct ssh_server_callbacks_struct cb = { struct ssh_server_callbacks_struct cb = {
.userdata = NULL, .userdata = NULL,
.auth_none_function = auth_none,
.auth_password_function = auth_password, .auth_password_function = auth_password,
#ifdef WITH_GSSAPI
.auth_gssapi_mic_function = auth_gssapi_mic, .auth_gssapi_mic_function = auth_gssapi_mic,
#endif
.channel_open_request_session_function = new_session_channel .channel_open_request_session_function = new_session_channel
}; };
char buf[BUF_SIZE]; char buf[2048];
int i; int i;
int r; int r;
@@ -327,24 +282,19 @@ int main(int argc, char **argv){
} else } else
printf("Authenticated and got a channel\n"); printf("Authenticated and got a channel\n");
do{ do{
i=ssh_channel_read(chan, buf, sizeof(buf) - 1, 0); i=ssh_channel_read(chan,buf, 2048, 0);
if(i>0) { if(i>0) {
if (ssh_channel_write(chan, buf, i) == SSH_ERROR) { ssh_channel_write(chan, buf, i);
printf("error writing to channel\n"); if (write(1,buf,i) < 0) {
printf("error writing to buffer\n");
return 1; return 1;
} }
buf[i] = '\0';
printf("%s", buf);
fflush(stdout);
if (buf[0] == '\x0d') { if (buf[0] == '\x0d') {
if (ssh_channel_write(chan, "\n", 1) == SSH_ERROR) { if (write(1, "\n", 1) < 0) {
printf("error writing to channel\n"); printf("error writing to buffer\n");
return 1; return 1;
} }
ssh_channel_write(chan, "\n", 1);
printf("\n");
} }
} }
} while (i>0); } while (i>0);

View File

@@ -23,11 +23,6 @@ clients must be made or how a client should react.
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <stdio.h> #include <stdio.h>
#include <stdbool.h>
#ifndef BUF_SIZE
#define BUF_SIZE 2048
#endif
#define SSHD_USER "libssh" #define SSHD_USER "libssh"
#define SSHD_PASSWORD "libssh" #define SSHD_PASSWORD "libssh"
@@ -41,7 +36,6 @@ clients must be made or how a client should react.
#endif #endif
static int port = 22; static int port = 22;
static bool authenticated = false;
#ifdef WITH_PCAP #ifdef WITH_PCAP
static const char *pcap_file = "debug.server.pcap"; static const char *pcap_file = "debug.server.pcap";
@@ -67,20 +61,11 @@ static void cleanup_pcap(void) {
#endif #endif
static int auth_password(const char *user, const char *password) static int auth_password(const char *user, const char *password){
{ if(strcmp(user, SSHD_USER))
int cmp;
cmp = strcmp(user, SSHD_USER);
if (cmp != 0) {
return 0; return 0;
} if(strcmp(password, SSHD_PASSWORD))
cmp = strcmp(password, SSHD_PASSWORD);
if (cmp != 0) {
return 0; return 0;
}
authenticated = true;
return 1; // authenticated return 1; // authenticated
} }
#ifdef HAVE_ARGP_H #ifdef HAVE_ARGP_H
@@ -215,7 +200,6 @@ static int kbdint_check_response(ssh_session session) {
return 0; return 0;
} }
authenticated = true;
return 1; return 1;
} }
@@ -297,7 +281,7 @@ int main(int argc, char **argv){
ssh_bind sshbind; ssh_bind sshbind;
ssh_message message; ssh_message message;
ssh_channel chan=0; ssh_channel chan=0;
char buf[BUF_SIZE]; char buf[2048];
int auth=0; int auth=0;
int shell=0; int shell=0;
int i; int i;
@@ -344,7 +328,7 @@ int main(int argc, char **argv){
/* proceed to authentication */ /* proceed to authentication */
auth = authenticate(session); auth = authenticate(session);
if (!auth || !authenticated) { if(!auth){
printf("Authentication error: %s\n", ssh_get_error(session)); printf("Authentication error: %s\n", ssh_get_error(session));
ssh_disconnect(session); ssh_disconnect(session);
return 1; return 1;
@@ -403,7 +387,7 @@ int main(int argc, char **argv){
printf("it works !\n"); printf("it works !\n");
do{ do{
i=ssh_channel_read(chan,buf, sizeof(buf), 0); i=ssh_channel_read(chan,buf, 2048, 0);
if(i>0) { if(i>0) {
if(*buf == '' || *buf == '') if(*buf == '' || *buf == '')
break; break;

View File

@@ -22,16 +22,9 @@ program.
#include <libssh/libssh.h> #include <libssh/libssh.h>
#include "examples_common.h" #include "examples_common.h"
#ifndef BUF_SIZE int verbosity=0;
#define BUF_SIZE 16384 const char *createcommand="rm -fr /tmp/libssh_tests && mkdir /tmp/libssh_tests && cd /tmp/libssh_tests && date > a && date > b && mkdir c && date > d";
#endif char *host=NULL;
static int verbosity = 0;
static const char *createcommand =
"rm -fr /tmp/libssh_tests && mkdir /tmp/libssh_tests && "
"cd /tmp/libssh_tests && date > a && date > b && mkdir c && date > d";
static char *host = NULL;
static void usage(const char *argv0){ static void usage(const char *argv0){
fprintf(stderr,"Usage : %s [options] host\n" fprintf(stderr,"Usage : %s [options] host\n"
"sample tiny scp downloader client - libssh-%s\n" "sample tiny scp downloader client - libssh-%s\n"
@@ -106,7 +99,7 @@ static void create_files(ssh_session session){
static int fetch_files(ssh_session session){ static int fetch_files(ssh_session session){
int size; int size;
char buffer[BUF_SIZE]; char buffer[16384];
int mode; int mode;
char *filename; char *filename;
int r; int r;

View File

@@ -3,7 +3,7 @@
#include <libssh/libssh.h> #include <libssh/libssh.h>
#include "examples_common.h" #include "examples_common.h"
#define LIMIT 0x100000000UL #define LIMIT 0x100000000
int main(void) { int main(void) {
ssh_session session; ssh_session session;
@@ -17,7 +17,7 @@ int main(void) {
return 1; return 1;
} }
channel = ssh_channel_new(session); channel = ssh_channel_new(session);;
if (channel == NULL) { if (channel == NULL) {
ssh_disconnect(session); ssh_disconnect(session);
return 1; return 1;

View File

@@ -1,866 +0,0 @@
/*
* ssh.c - Simple example of SSH X11 client using libssh
*
* Copyright (C) 2022 Marco Fortina
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*
* In addition, as a special exception, the copyright holders give
* permission to link the code of portions of this program with the
* OpenSSL library under certain conditions as described in each
* individual source file, and distribute linked combinations
* including the two.
* You must obey the GNU General Public License in all respects
* for all of the code used other than OpenSSL. * If you modify
* file(s) with this exception, you may extend this exception to your
* version of the file(s), but you are not obligated to do so. * If you
* do not wish to do so, delete this exception statement from your
* version. * If you delete this exception statement from all source
* files in the program, then also delete it here.
*
*
*
* ssh_X11_client
* ==============
*
* AUTHOR URL
* https://gitlab.com/marco.fortina/libssh-x11-client/
*
* This is a simple example of SSH X11 client using libssh.
*
* Features:
*
* - support local display (e.g. :0)
* - support remote display (e.g. localhost:10.0)
* - using callbacks and event polling to significantly reduce CPU utilization
* - use X11 forwarding with authentication spoofing (like openssh)
*
* Note:
*
* - part of this code was inspired by openssh's one.
*
* Dependencies:
*
* - gcc >= 7.5.0
* - libssh >= 0.8.0
* - libssh-dev >= 0.8.0
*
* To Build:
* gcc -o ssh_X11_client ssh_X11_client.c -lssh -g
*
* Donations:
*
* If you liked this work and wish to support the developer please donate to:
* Bitcoin: 1N2rQimKbeUQA8N2LU5vGopYQJmZsBM2d6
*
*/
#include <errno.h>
#include <fcntl.h>
#include <poll.h>
#include <pthread.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <termios.h>
#include <time.h>
#include <libssh/libssh.h>
#include <libssh/callbacks.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <sys/un.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
/*
* Data Structures and Macros
*/
#define _PATH_UNIX_X "/tmp/.X11-unix/X%d"
#define _XAUTH_CMD "/usr/bin/xauth list %s 2>/dev/null"
typedef struct item {
ssh_channel channel;
int fd_in;
int fd_out;
int protected;
struct item *next;
} node_t;
node_t *node = NULL;
/*
* Mutex
*/
pthread_mutex_t mutex;
/*
* Function declarations
*/
/* Linked nodes to manage channel/fd tuples */
static void insert_item(ssh_channel channel, int fd_in, int fd_out, int protected);
static void delete_item(ssh_channel channel);
static node_t * search_item(ssh_channel channel);
/* X11 Display */
const char * ssh_gai_strerror(int gaierr);
static int x11_get_proto(const char *display, char **_proto, char **_data);
static void set_nodelay(int fd);
static int connect_local_xsocket_path(const char *pathname);
static int connect_local_xsocket(int display_number);
static int x11_connect_display(void);
/* Send data to channel */
static int copy_fd_to_channel_callback(int fd, int revents, void *userdata);
/* Read data from channel */
static int copy_channel_to_fd_callback(ssh_session session, ssh_channel channel, void *data, uint32_t len, int is_stderr, void *userdata);
/* EOF&Close channel */
static void channel_close_callback(ssh_session session, ssh_channel channel, void *userdata);
/* X11 Request */
static ssh_channel x11_open_request_callback(ssh_session session, const char *shost, int sport, void *userdata);
/* Main loop */
static int main_loop(ssh_channel channel);
/* Internals */
int64_t _current_timestamp(void);
/* Global variables */
const char *hostname = NULL;
int enableX11 = 1;
/*
* Callbacks Data Structures
*/
/* SSH Channel Callbacks */
struct ssh_channel_callbacks_struct channel_cb =
{
.channel_data_function = copy_channel_to_fd_callback,
.channel_eof_function = channel_close_callback,
.channel_close_function = channel_close_callback,
.userdata = NULL
};
/* SSH Callbacks */
struct ssh_callbacks_struct cb =
{
.channel_open_request_x11_function = x11_open_request_callback,
.userdata = NULL
};
/*
* SSH Event Context
*/
short events = POLLIN | POLLPRI | POLLERR | POLLHUP | POLLNVAL;
ssh_event event;
/*
* Internal data structures
*/
struct termios _saved_tio;
/*
* Internal functions
*/
int64_t
_current_timestamp(void) {
struct timeval tv;
int64_t milliseconds;
gettimeofday(&tv, NULL);
milliseconds = (int64_t)(tv.tv_sec) * 1000 + (tv.tv_usec / 1000);
return milliseconds;
}
static void
_logging_callback(int priority, const char *function, const char *buffer, void *userdata)
{
FILE *fp = NULL;
char buf[100];
int64_t milliseconds;
time_t now = time (0);
(void)userdata;
strftime(buf, 100, "%Y-%m-%d %H:%M:%S", localtime (&now));
fp = fopen("debug.log","a");
if(fp == NULL)
{
printf("Error!");
exit(-11);
}
milliseconds = _current_timestamp();
fprintf(fp, "[%s.%jd, %d] %s: %s\n", buf, milliseconds, priority, function, buffer);
fclose(fp);
}
static int
_enter_term_raw_mode(void)
{
struct termios tio;
int ret = tcgetattr(fileno(stdin), &tio);
if (ret != -1) {
_saved_tio = tio;
tio.c_iflag |= IGNPAR;
tio.c_iflag &= ~(ISTRIP | INLCR | IGNCR | ICRNL | IXON | IXANY | IXOFF);
#ifdef IUCLC
tio.c_iflag &= ~IUCLC;
#endif
tio.c_lflag &= ~(ISIG | ICANON | ECHO | ECHOE | ECHOK | ECHONL);
#ifdef IEXTEN
tio.c_lflag &= ~IEXTEN;
#endif
tio.c_oflag &= ~OPOST;
tio.c_cc[VMIN] = 1;
tio.c_cc[VTIME] = 0;
ret = tcsetattr(fileno(stdin), TCSADRAIN, &tio);
}
return ret;
}
static int
_leave_term_raw_mode(void)
{
int ret = tcsetattr(fileno(stdin), TCSADRAIN, &_saved_tio);
return ret;
}
/*
* Functions
*/
static void
insert_item(ssh_channel channel, int fd_in, int fd_out, int protected)
{
node_t *node_iterator = NULL, *new = NULL;
pthread_mutex_lock(&mutex);
if (node == NULL) {
/* Calloc ensure that node is full of 0 */
node = (node_t *) calloc(1, sizeof(node_t));
node->channel = channel;
node->fd_in = fd_in;
node->fd_out = fd_out;
node->protected = protected;
node->next = NULL;
} else {
node_iterator = node;
while (node_iterator->next != NULL)
node_iterator = node_iterator->next;
/* Create the new node */
new = (node_t *) malloc(sizeof(node_t));
new->channel = channel;
new->fd_in = fd_in;
new->fd_out = fd_out;
new->protected = protected;
new->next = NULL;
node_iterator->next = new;
}
pthread_mutex_unlock(&mutex);
}
static void
delete_item(ssh_channel channel)
{
node_t *current = NULL, *previous = NULL;
pthread_mutex_lock(&mutex);
for (current = node; current; previous = current, current = current->next) {
if (current->channel != channel)
continue;
if (previous == NULL)
node = current->next;
else
previous->next = current->next;
free(current);
pthread_mutex_unlock(&mutex);
return;
}
pthread_mutex_unlock(&mutex);
}
static node_t *
search_item(ssh_channel channel)
{
node_t *current = node;
pthread_mutex_lock(&mutex);
while (current != NULL) {
if (current->channel == channel) {
pthread_mutex_unlock(&mutex);
return current;
} else {
current = current->next;
}
}
pthread_mutex_unlock(&mutex);
return NULL;
}
static void
set_nodelay(int fd)
{
int opt;
socklen_t optlen;
optlen = sizeof(opt);
if (getsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &opt, &optlen) == -1) {
_ssh_log(SSH_LOG_FUNCTIONS, __func__, "getsockopt TCP_NODELAY: %.100s", strerror(errno));
return;
}
if (opt == 1) {
_ssh_log(SSH_LOG_FUNCTIONS, __func__, "fd %d is TCP_NODELAY", fd);
return;
}
opt = 1;
_ssh_log(SSH_LOG_FUNCTIONS, __func__, "fd %d setting TCP_NODELAY", fd);
if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt)) == -1)
_ssh_log(SSH_LOG_FUNCTIONS, __func__, "setsockopt TCP_NODELAY: %.100s", strerror(errno));
}
const char *
ssh_gai_strerror(int gaierr)
{
if (gaierr == EAI_SYSTEM && errno != 0)
return strerror(errno);
return gai_strerror(gaierr);
}
static int
x11_get_proto(const char *display, char **_proto, char **_cookie)
{
char cmd[1024], line[512], xdisplay[512];
static char proto[512], cookie[512];
FILE *f = NULL;
int ret = 0;
*_proto = proto;
*_cookie = cookie;
proto[0] = cookie[0] = '\0';
if (strncmp(display, "localhost:", 10) == 0) {
if ((ret = snprintf(xdisplay, sizeof(xdisplay), "unix:%s", display + 10)) < 0 || (size_t)ret >= sizeof(xdisplay)) {
_ssh_log(SSH_LOG_FUNCTIONS, __func__, "display name too long. display: %s", display);
return -1;
}
display = xdisplay;
}
snprintf(cmd, sizeof(cmd), _XAUTH_CMD, display);
_ssh_log(SSH_LOG_FUNCTIONS, __func__, "xauth cmd: %s", cmd);
f = popen(cmd, "r");
if (f && fgets(line, sizeof(line), f) && sscanf(line, "%*s %511s %511s", proto, cookie) == 2) {
ret = 0;
} else {
ret = 1;
}
if (f) pclose(f);
_ssh_log(SSH_LOG_FUNCTIONS, __func__, "proto: %s - cookie: %s - ret: %d", proto, cookie, ret);
return ret;
}
static int
connect_local_xsocket_path(const char *pathname)
{
int sock;
struct sockaddr_un addr;
sock = socket(AF_UNIX, SOCK_STREAM, 0);
if (sock == -1) {
_ssh_log(SSH_LOG_FUNCTIONS, __func__, "socket: %.100s", strerror(errno));
return -1;
}
memset(&addr, 0, sizeof(addr));
addr.sun_family = AF_UNIX;
addr.sun_path[0] = '\0';
/* pathname is guaranteed to be initialized and larger than addr.sun_path[108] */
memcpy(addr.sun_path + 1, pathname, sizeof(addr.sun_path) - 1);
if (connect(sock, (struct sockaddr *)&addr, offsetof(struct sockaddr_un, sun_path) + 1 + strlen(pathname)) == 0)
return sock;
close(sock);
_ssh_log(SSH_LOG_FUNCTIONS, __func__, "connect %.100s: %.100s", addr.sun_path, strerror(errno));
return -1;
}
static int
connect_local_xsocket(int display_number)
{
char buf[1024] = {0};
snprintf(buf, sizeof(buf), _PATH_UNIX_X, display_number);
return connect_local_xsocket_path(buf);
}
static int
x11_connect_display()
{
int display_number;
const char *display = NULL;
char buf[1024], *cp = NULL;
struct addrinfo hints, *ai = NULL, *aitop = NULL;
char strport[NI_MAXSERV];
int gaierr = 0, sock = 0;
/* Try to open a socket for the local X server. */
display = getenv("DISPLAY");
_ssh_log(SSH_LOG_FUNCTIONS, __func__, "display: %s", display);
if (!display) {
return -1;
}
/* Check if it is a unix domain socket. */
if (strncmp(display, "unix:", 5) == 0 || display[0] == ':') {
/* Connect to the unix domain socket. */
if (sscanf(strrchr(display, ':') + 1, "%d", &display_number) != 1) {
_ssh_log(SSH_LOG_FUNCTIONS, __func__, "Could not parse display number from DISPLAY: %.100s", display);
return -1;
}
_ssh_log(SSH_LOG_FUNCTIONS, __func__, "display_number: %d", display_number);
/* Create a socket. */
sock = connect_local_xsocket(display_number);
_ssh_log(SSH_LOG_FUNCTIONS, __func__, "socket: %d", sock);
if (sock < 0)
return -1;
/* OK, we now have a connection to the display. */
return sock;
}
/* Connect to an inet socket. */
strncpy(buf, display, sizeof(buf) - 1);
cp = strchr(buf, ':');
if (!cp) {
_ssh_log(SSH_LOG_FUNCTIONS, __func__, "Could not find ':' in DISPLAY: %.100s", display);
return -1;
}
*cp = 0;
if (sscanf(cp + 1, "%d", &display_number) != 1) {
_ssh_log(SSH_LOG_FUNCTIONS, __func__, "Could not parse display number from DISPLAY: %.100s", display);
return -1;
}
/* Look up the host address */
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
snprintf(strport, sizeof(strport), "%u", 6000 + display_number);
if ((gaierr = getaddrinfo(buf, strport, &hints, &aitop)) != 0) {
_ssh_log(SSH_LOG_FUNCTIONS, __func__, "%.100s: unknown host. (%s)", buf, ssh_gai_strerror(gaierr));
return -1;
}
for (ai = aitop; ai; ai = ai->ai_next) {
/* Create a socket. */
sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
if (sock == -1) {
_ssh_log(SSH_LOG_FUNCTIONS, __func__, "socket: %.100s", strerror(errno));
continue;
}
/* Connect it to the display. */
if (connect(sock, ai->ai_addr, ai->ai_addrlen) == -1) {
_ssh_log(SSH_LOG_FUNCTIONS, __func__, "connect %.100s port %u: %.100s", buf, 6000 + display_number, strerror(errno));
close(sock);
continue;
}
/* Success */
break;
}
freeaddrinfo(aitop);
if (!ai) {
_ssh_log(SSH_LOG_FUNCTIONS, __func__, "connect %.100s port %u: %.100s", buf, 6000 + display_number, strerror(errno));
return -1;
}
set_nodelay(sock);
return sock;
}
static int
copy_fd_to_channel_callback(int fd, int revents, void *userdata)
{
ssh_channel channel = (ssh_channel)userdata;
char buf[2097152];
int sz = 0, ret = 0;
node_t *temp_node = search_item(channel);
_ssh_log(SSH_LOG_FUNCTIONS, __func__, "event: %d - fd: %d", revents, fd);
if (!channel) {
_ssh_log(SSH_LOG_FUNCTIONS, __func__, "channel does not exist.");
if (temp_node->protected == 0) {
close(fd);
}
return -1;
}
if (fcntl(fd, F_GETFD) == -1) {
_ssh_log(SSH_LOG_FUNCTIONS, __func__, "fcntl error. fd: %d", fd);
ssh_channel_close(channel);
return -1;
}
if ((revents & POLLIN) || (revents & POLLPRI)) {
sz = read(fd, buf, sizeof(buf));
_ssh_log(SSH_LOG_FUNCTIONS, __func__, "sz: %d", sz);
if (sz > 0) {
ret = ssh_channel_write(channel, buf, sz);
_ssh_log(SSH_LOG_FUNCTIONS, __func__, "channel_write ret: %d", ret);
} else if (sz < 0) {
ssh_channel_close(channel);
return -1;
} else {
/* sz = 0. Why the hell I'm here? */
_ssh_log(SSH_LOG_FUNCTIONS, __func__, "Why the hell am I here?: sz: %d", sz);
if (temp_node->protected == 0) {
close(fd);
}
return -1;
}
}
if ((revents & POLLHUP) || (revents & POLLNVAL) || (revents & POLLERR)) {
ssh_channel_close(channel);
return -1;
}
return sz;
}
static int
copy_channel_to_fd_callback(ssh_session session, ssh_channel channel, void *data, uint32_t len, int is_stderr, void *userdata)
{
node_t *temp_node = NULL;
int fd, sz;
(void)session;
(void)is_stderr;
(void)userdata;
temp_node = search_item(channel);
fd = temp_node->fd_out;
_ssh_log(SSH_LOG_FUNCTIONS, __func__, "len: %d - fd: %d - is_stderr: %d", len, fd, is_stderr);
sz = write(fd, data, len);
return sz;
}
static void
channel_close_callback(ssh_session session, ssh_channel channel, void *userdata)
{
node_t *temp_node = NULL;
(void)session;
(void)userdata;
temp_node = search_item(channel);
if (temp_node != NULL) {
int fd = temp_node->fd_in;
_ssh_log(SSH_LOG_FUNCTIONS, __func__, "fd: %d", fd);
delete_item(channel);
ssh_event_remove_fd(event, fd);
if (temp_node->protected == 0) {
close(fd);
}
}
}
static ssh_channel
x11_open_request_callback(ssh_session session, const char *shost, int sport, void *userdata)
{
ssh_channel channel = NULL;
int sock;
(void)shost;
(void)sport;
(void)userdata;
channel = ssh_channel_new(session);
sock = x11_connect_display();
_ssh_log(SSH_LOG_FUNCTIONS, __func__, "sock: %d", sock);
insert_item(channel, sock, sock, 0);
ssh_event_add_fd(event, sock, events, copy_fd_to_channel_callback, channel);
ssh_event_add_session(event, session);
ssh_add_channel_callbacks(channel, &channel_cb);
return channel;
}
/*
* MAIN LOOP
*/
static int
main_loop(ssh_channel channel)
{
ssh_session session = ssh_channel_get_session(channel);
insert_item(channel, fileno(stdin), fileno(stdout), 1);
ssh_callbacks_init(&channel_cb);
ssh_set_channel_callbacks(channel, &channel_cb);
event = ssh_event_new();
if (event == NULL) {
printf("Couldn't get a event\n");
return -1;
}
if (ssh_event_add_fd(event, fileno(stdin), events, copy_fd_to_channel_callback, channel) != SSH_OK) {
printf("Couldn't add an fd to the event\n");
return -1;
}
if(ssh_event_add_session(event, session) != SSH_OK) {
printf("Couldn't add the session to the event\n");
return -1;
}
do {
if (ssh_event_dopoll(event, 1000) == SSH_ERROR) {
printf("Error : %s\n", ssh_get_error(session));
/* fall through */
}
} while (!ssh_channel_is_closed(channel));
delete_item(channel);
ssh_event_remove_fd(event, fileno(stdin));
ssh_event_remove_session(event, session);
ssh_event_free(event);
return 0;
}
/*
* USAGE
*/
static void
usage(void)
{
fprintf(stderr,
"Usage : ssh-X11-client [options] [login@]hostname\n"
"sample X11 client - libssh-%s\n"
"Options :\n"
" -l user : Specifies the user to log in as on the remote machine.\n"
" -p port : Port to connect to on the remote host.\n"
" -v : Verbose mode. Multiple -v options increase the verbosity. The maximum is 5.\n"
" -C : Requests compression of all data.\n"
" -x : Disables X11 forwarding.\n"
"\n",
ssh_version(0));
exit(0);
}
static int opts(int argc, char **argv)
{
int i;
while ((i = getopt(argc,argv,"x")) != -1) {
switch(i) {
case 'x':
enableX11 = 0;
break;
default:
fprintf(stderr, "Unknown option %c\n", optopt);
return -1;
}
}
if (optind < argc) {
hostname = argv[optind++];
}
if (hostname == NULL) {
return -1;
}
return 0;
}
/*
* MAIN
*/
int
main(int argc, char **argv)
{
char *password = NULL;
ssh_session session = NULL;
ssh_channel channel = NULL;
int ret;
const char *display = NULL;
char *proto = NULL, *cookie = NULL;
ssh_set_log_callback(_logging_callback);
ret = ssh_init();
if (ret != SSH_OK) return ret;
session = ssh_new();
if (session == NULL) exit(-1);
if (ssh_options_getopt(session, &argc, argv) || opts(argc, argv)) {
fprintf(stderr, "Error parsing command line: %s\n", ssh_get_error(session));
ssh_free(session);
ssh_finalize();
usage();
}
if (ssh_options_set(session, SSH_OPTIONS_HOST, hostname) < 0) {
return -1;
}
ret = ssh_connect(session);
if (ret != SSH_OK) {
fprintf(stderr, "Connection failed : %s\n", ssh_get_error(session));
exit(-1);
}
password = getpass("Password: ");
ret = ssh_userauth_password(session, NULL, password);
if (ret != SSH_AUTH_SUCCESS) {
fprintf(stderr, "Error authenticating with password: %s\n", ssh_get_error(session));
exit(-1);
}
channel = ssh_channel_new(session);
if (channel == NULL) return SSH_ERROR;
ret = ssh_channel_open_session(channel);
if (ret != SSH_OK) return ret;
ret = ssh_channel_request_pty(channel);
if (ret != SSH_OK) return ret;
ret = ssh_channel_change_pty_size(channel, 80, 24);
if (ret != SSH_OK) return ret;
if (enableX11 == 1) {
display = getenv("DISPLAY");
_ssh_log(SSH_LOG_FUNCTIONS, __func__, "display: %s", display);
if (display) {
ssh_callbacks_init(&cb);
ret = ssh_set_callbacks(session, &cb);
if (ret != SSH_OK) return ret;
if (x11_get_proto(display, &proto, &cookie) != 0) {
_ssh_log(SSH_LOG_FUNCTIONS, __func__, "Using fake authentication data for X11 forwarding");
proto = NULL;
cookie = NULL;
}
_ssh_log(SSH_LOG_FUNCTIONS, __func__, "proto: %s - cookie: %s", proto, cookie);
/* See https://gitlab.com/libssh/libssh-mirror/-/blob/master/src/channels.c#L2062 for details. */
ret = ssh_channel_request_x11(channel, 0, proto, cookie, 0);
if (ret != SSH_OK) return ret;
}
}
ret = _enter_term_raw_mode();
if (ret != 0) exit(-1);
ret = ssh_channel_request_shell(channel);
if (ret != SSH_OK) return ret;
ret = main_loop(channel);
if (ret != SSH_OK) return ret;
_leave_term_raw_mode();
ssh_channel_close(channel);
ssh_channel_free(channel);
ssh_disconnect(session);
ssh_free(session);
ssh_finalize();
}

View File

@@ -1,439 +0,0 @@
/* ssh_client.c */
/*
* Copyright 2003-2015 Aris Adamantiadis
*
* This file is part of the SSH Library
*
* You are free to copy this file, modify it in any way, consider it being public
* domain. This does not apply to the rest of the library though, but it is
* allowed to cut-and-paste working code from this file to any license of
* program.
* The goal is to show the API in action. It's not a reference on how terminal
* clients must be made or how a client should react.
*/
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <sys/select.h>
#include <sys/time.h>
#ifdef HAVE_TERMIOS_H
#include <termios.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef HAVE_PTY_H
#include <pty.h>
#endif
#include <sys/ioctl.h>
#include <signal.h>
#include <errno.h>
#include <fcntl.h>
#include <libssh/callbacks.h>
#include <libssh/libssh.h>
#include <libssh/sftp.h>
#include "examples_common.h"
#define MAXCMD 10
static char *host = NULL;
static char *user = NULL;
static char *cmds[MAXCMD];
static char *config_file = NULL;
static struct termios terminal;
static char *pcap_file = NULL;
static char *proxycommand;
static int auth_callback(const char *prompt,
char *buf,
size_t len,
int echo,
int verify,
void *userdata)
{
(void) verify;
(void) userdata;
return ssh_getpass(prompt, buf, len, echo, verify);
}
struct ssh_callbacks_struct cb = {
.auth_function = auth_callback,
.userdata = NULL,
};
static void add_cmd(char *cmd)
{
int n;
for (n = 0; (n < MAXCMD) && cmds[n] != NULL; n++);
if (n == MAXCMD) {
return;
}
cmds[n] = cmd;
}
static void usage(void)
{
fprintf(stderr,
"Usage : ssh [options] [login@]hostname\n"
"sample client - libssh-%s\n"
"Options :\n"
" -l user : log in as user\n"
" -p port : connect to port\n"
" -d : use DSS to verify host public key\n"
" -r : use RSA to verify host public key\n"
" -F file : parse configuration file instead of default one\n"
#ifdef WITH_PCAP
" -P file : create a pcap debugging file\n"
#endif
#ifndef _WIN32
" -T proxycommand : command to execute as a socket proxy\n"
#endif
"\n",
ssh_version(0));
exit(0);
}
static int opts(int argc, char **argv)
{
int i;
while((i = getopt(argc,argv,"T:P:F:")) != -1) {
switch(i){
case 'P':
pcap_file = optarg;
break;
case 'F':
config_file = optarg;
break;
#ifndef _WIN32
case 'T':
proxycommand = optarg;
break;
#endif
default:
fprintf(stderr, "Unknown option %c\n", optopt);
return -1;
}
}
if (optind < argc) {
host = argv[optind++];
}
while(optind < argc) {
add_cmd(argv[optind++]);
}
if (host == NULL) {
return -1;
}
return 0;
}
#ifndef HAVE_CFMAKERAW
static void cfmakeraw(struct termios *termios_p)
{
termios_p->c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
termios_p->c_oflag &= ~OPOST;
termios_p->c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
termios_p->c_cflag &= ~(CSIZE|PARENB);
termios_p->c_cflag |= CS8;
}
#endif
static void do_cleanup(int i)
{
/* unused variable */
(void) i;
tcsetattr(0, TCSANOW, &terminal);
}
static void do_exit(int i)
{
/* unused variable */
(void) i;
do_cleanup(0);
exit(0);
}
static int signal_delayed = 0;
#ifdef SIGWINCH
static void sigwindowchanged(int i)
{
(void) i;
signal_delayed = 1;
}
#endif
static void setsignal(void)
{
#ifdef SIGWINCH
signal(SIGWINCH, sigwindowchanged);
#endif
signal_delayed = 0;
}
static void sizechanged(ssh_channel chan)
{
struct winsize win = {
.ws_row = 0,
};
ioctl(1, TIOCGWINSZ, &win);
ssh_channel_change_pty_size(chan,win.ws_col, win.ws_row);
setsignal();
}
static void select_loop(ssh_session session,ssh_channel channel)
{
ssh_connector connector_in, connector_out, connector_err;
int rc;
ssh_event event = ssh_event_new();
/* stdin */
connector_in = ssh_connector_new(session);
ssh_connector_set_out_channel(connector_in, channel, SSH_CONNECTOR_STDINOUT);
ssh_connector_set_in_fd(connector_in, 0);
ssh_event_add_connector(event, connector_in);
/* stdout */
connector_out = ssh_connector_new(session);
ssh_connector_set_out_fd(connector_out, 1);
ssh_connector_set_in_channel(connector_out, channel, SSH_CONNECTOR_STDINOUT);
ssh_event_add_connector(event, connector_out);
/* stderr */
connector_err = ssh_connector_new(session);
ssh_connector_set_out_fd(connector_err, 2);
ssh_connector_set_in_channel(connector_err, channel, SSH_CONNECTOR_STDERR);
ssh_event_add_connector(event, connector_err);
while (ssh_channel_is_open(channel)) {
if (signal_delayed) {
sizechanged(channel);
}
rc = ssh_event_dopoll(event, 60000);
if (rc == SSH_ERROR) {
fprintf(stderr, "Error in ssh_event_dopoll()\n");
break;
}
}
ssh_event_remove_connector(event, connector_in);
ssh_event_remove_connector(event, connector_out);
ssh_event_remove_connector(event, connector_err);
ssh_connector_free(connector_in);
ssh_connector_free(connector_out);
ssh_connector_free(connector_err);
ssh_event_free(event);
}
static void shell(ssh_session session)
{
ssh_channel channel;
struct termios terminal_local;
int interactive=isatty(0);
channel = ssh_channel_new(session);
if (channel == NULL) {
return;
}
if (interactive) {
tcgetattr(0, &terminal_local);
memcpy(&terminal, &terminal_local, sizeof(struct termios));
}
if (ssh_channel_open_session(channel)) {
printf("Error opening channel : %s\n", ssh_get_error(session));
ssh_channel_free(channel);
return;
}
if (interactive) {
ssh_channel_request_pty(channel);
sizechanged(channel);
}
if (ssh_channel_request_shell(channel)) {
printf("Requesting shell : %s\n", ssh_get_error(session));
ssh_channel_free(channel);
return;
}
if (interactive) {
cfmakeraw(&terminal_local);
tcsetattr(0, TCSANOW, &terminal_local);
setsignal();
}
signal(SIGTERM, do_cleanup);
select_loop(session, channel);
if (interactive) {
do_cleanup(0);
}
ssh_channel_free(channel);
}
static void batch_shell(ssh_session session)
{
ssh_channel channel;
char buffer[PATH_MAX];
size_t i;
int s = 0;
for (i = 0; i < MAXCMD && cmds[i]; ++i) {
s += snprintf(buffer + s, sizeof(buffer) - s, "%s ", cmds[i]);
}
channel = ssh_channel_new(session);
if (channel == NULL) {
return;
}
ssh_channel_open_session(channel);
if (ssh_channel_request_exec(channel, buffer)) {
printf("Error executing '%s' : %s\n", buffer, ssh_get_error(session));
ssh_channel_free(channel);
return;
}
select_loop(session, channel);
ssh_channel_free(channel);
}
static int client(ssh_session session)
{
int auth = 0;
char *banner;
int state;
if (user) {
if (ssh_options_set(session, SSH_OPTIONS_USER, user) < 0) {
return -1;
}
}
if (ssh_options_set(session, SSH_OPTIONS_HOST, host) < 0) {
return -1;
}
if (proxycommand != NULL) {
if (ssh_options_set(session, SSH_OPTIONS_PROXYCOMMAND, proxycommand)) {
return -1;
}
}
/* Parse configuration file if specified: The command-line options will
* overwrite items loaded from configuration file */
if (config_file != NULL) {
ssh_options_parse_config(session, config_file);
} else {
ssh_options_parse_config(session, NULL);
}
if (ssh_connect(session)) {
fprintf(stderr, "Connection failed : %s\n", ssh_get_error(session));
return -1;
}
state = verify_knownhost(session);
if (state != 0) {
return -1;
}
ssh_userauth_none(session, NULL);
banner = ssh_get_issue_banner(session);
if (banner) {
printf("%s\n", banner);
free(banner);
}
auth = authenticate_console(session);
if (auth != SSH_AUTH_SUCCESS) {
return -1;
}
if (cmds[0] == NULL) {
shell(session);
} else {
batch_shell(session);
}
return 0;
}
static ssh_pcap_file pcap;
static void set_pcap(ssh_session session)
{
if (pcap_file == NULL) {
return;
}
pcap = ssh_pcap_file_new();
if (pcap == NULL) {
return;
}
if (ssh_pcap_file_open(pcap, pcap_file) == SSH_ERROR) {
printf("Error opening pcap file\n");
ssh_pcap_file_free(pcap);
pcap = NULL;
return;
}
ssh_set_pcap_file(session, pcap);
}
static void cleanup_pcap(void)
{
if (pcap != NULL) {
ssh_pcap_file_free(pcap);
}
pcap = NULL;
}
int main(int argc, char **argv)
{
ssh_session session;
ssh_init();
session = ssh_new();
ssh_callbacks_init(&cb);
ssh_set_callbacks(session,&cb);
if (ssh_options_getopt(session, &argc, argv) || opts(argc, argv)) {
fprintf(stderr,
"Error parsing command line: %s\n",
ssh_get_error(session));
ssh_free(session);
ssh_finalize();
usage();
}
signal(SIGTERM, do_exit);
set_pcap(session);
client(session);
ssh_disconnect(session);
ssh_free(session);
cleanup_pcap();
ssh_finalize();
return 0;
}

View File

@@ -14,9 +14,9 @@ The goal is to show the API in action.
#include "config.h" #include "config.h"
#include <libssh/callbacks.h> #include <libssh/callbacks.h>
#include <libssh/poll.h>
#include <libssh/server.h> #include <libssh/server.h>
#include <poll.h>
#ifdef HAVE_ARGP_H #ifdef HAVE_ARGP_H
#include <argp.h> #include <argp.h>
#endif #endif
@@ -24,7 +24,6 @@ The goal is to show the API in action.
#ifdef HAVE_LIBUTIL_H #ifdef HAVE_LIBUTIL_H
#include <libutil.h> #include <libutil.h>
#endif #endif
#include <pthread.h>
#ifdef HAVE_PTY_H #ifdef HAVE_PTY_H
#include <pty.h> #include <pty.h>
#endif #endif
@@ -38,13 +37,8 @@ The goal is to show the API in action.
#endif #endif
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <sys/wait.h> #include <sys/wait.h>
#include <sys/stat.h>
#include <stdio.h> #include <stdio.h>
#ifndef BUF_SIZE
#define BUF_SIZE 1048576
#endif
#ifndef KEYS_FOLDER #ifndef KEYS_FOLDER
#ifdef _WIN32 #ifdef _WIN32
#define KEYS_FOLDER #define KEYS_FOLDER
@@ -53,6 +47,9 @@ The goal is to show the API in action.
#endif #endif
#endif #endif
#define USER "myuser"
#define PASS "mypassword"
#define BUF_SIZE 1048576
#define SESSION_END (SSH_CLOSED | SSH_CLOSED_ERROR) #define SESSION_END (SSH_CLOSED | SSH_CLOSED_ERROR)
#define SFTP_SERVER_PATH "/usr/lib/sftp-server" #define SFTP_SERVER_PATH "/usr/lib/sftp-server"
@@ -72,13 +69,8 @@ static void set_default_keys(ssh_bind sshbind,
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_ECDSAKEY, ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_ECDSAKEY,
KEYS_FOLDER "ssh_host_ecdsa_key"); KEYS_FOLDER "ssh_host_ecdsa_key");
} }
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_HOSTKEY,
KEYS_FOLDER "ssh_host_ed25519_key");
} }
#define DEF_STR_SIZE 1024
char authorizedkeys[DEF_STR_SIZE] = {0};
char username[128] = "myuser";
char password[128] = "mypassword";
#ifdef HAVE_ARGP_H #ifdef HAVE_ARGP_H
const char *argp_program_version = "libssh server example " const char *argp_program_version = "libssh server example "
SSH_STRINGIFY(LIBSSH_VERSION); SSH_STRINGIFY(LIBSSH_VERSION);
@@ -133,30 +125,6 @@ static struct argp_option options[] = {
.doc = "Set the ecdsa key.", .doc = "Set the ecdsa key.",
.group = 0 .group = 0
}, },
{
.name = "authorizedkeys",
.key = 'a',
.arg = "FILE",
.flags = 0,
.doc = "Set the authorized keys file.",
.group = 0
},
{
.name = "user",
.key = 'u',
.arg = "USERNAME",
.flags = 0,
.doc = "Set expected username.",
.group = 0
},
{
.name = "pass",
.key = 'P',
.arg = "PASSWORD",
.flags = 0,
.doc = "Set expected password.",
.group = 0
},
{ {
.name = "no-default-keys", .name = "no-default-keys",
.key = 'n', .key = 'n',
@@ -210,15 +178,6 @@ static error_t parse_opt (int key, char *arg, struct argp_state *state) {
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_ECDSAKEY, arg); ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_ECDSAKEY, arg);
ecdsa_already_set = 1; ecdsa_already_set = 1;
break; break;
case 'a':
strncpy(authorizedkeys, arg, DEF_STR_SIZE-1);
break;
case 'u':
strncpy(username, arg, sizeof(username) - 1);
break;
case 'P':
strncpy(password, arg, sizeof(password) - 1);
break;
case 'v': case 'v':
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_LOG_VERBOSITY_STR, ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_LOG_VERBOSITY_STR,
"3"); "3");
@@ -252,89 +211,6 @@ static error_t parse_opt (int key, char *arg, struct argp_state *state) {
/* Our argp parser. */ /* Our argp parser. */
static struct argp argp = {options, parse_opt, args_doc, doc, NULL, NULL, NULL}; static struct argp argp = {options, parse_opt, args_doc, doc, NULL, NULL, NULL};
#else
static int parse_opt(int argc, char **argv, ssh_bind sshbind) {
int no_default_keys = 0;
int rsa_already_set = 0;
int dsa_already_set = 0;
int ecdsa_already_set = 0;
int key;
while((key = getopt(argc, argv, "a:d:e:k:np:P:r:u:v")) != -1) {
if (key == 'n') {
no_default_keys = 1;
} else if (key == 'p') {
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_BINDPORT_STR, optarg);
} else if (key == 'd') {
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_DSAKEY, optarg);
dsa_already_set = 1;
} else if (key == 'k') {
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_HOSTKEY, optarg);
/* We can't track the types of keys being added with this
option, so let's ensure we keep the keys we're adding
by just not setting the default keys */
no_default_keys = 1;
} else if (key == 'r') {
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_RSAKEY, optarg);
rsa_already_set = 1;
} else if (key == 'e') {
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_ECDSAKEY, optarg);
ecdsa_already_set = 1;
} else if (key == 'a') {
strncpy(authorizedkeys, optarg, DEF_STR_SIZE-1);
} else if (key == 'u') {
strncpy(username, optarg, sizeof(username) - 1);
} else if (key == 'P') {
strncpy(password, optarg, sizeof(password) - 1);
} else if (key == 'v') {
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_LOG_VERBOSITY_STR,
"3");
} else {
break;
}
}
if (key != -1) {
printf("Usage: %s [OPTION...] BINDADDR\n"
"libssh %s -- a Secure Shell protocol implementation\n"
"\n"
" -a, --authorizedkeys=FILE Set the authorized keys file.\n"
" -d, --dsakey=FILE Set the dsa key.\n"
" -e, --ecdsakey=FILE Set the ecdsa key.\n"
" -k, --hostkey=FILE Set a host key. Can be used multiple times.\n"
" Implies no default keys.\n"
" -n, --no-default-keys Do not set default key locations.\n"
" -p, --port=PORT Set the port to bind.\n"
" -P, --pass=PASSWORD Set expected password.\n"
" -r, --rsakey=FILE Set the rsa key.\n"
" -u, --user=USERNAME Set expected username.\n"
" -v, --verbose Get verbose output.\n"
" -?, --help Give this help list\n"
"\n"
"Mandatory or optional arguments to long options are also mandatory or optional\n"
"for any corresponding short options.\n"
"\n"
"Report bugs to <libssh@libssh.org>.\n",
argv[0], SSH_STRINGIFY(LIBSSH_VERSION));
return -1;
}
if (optind != argc - 1) {
printf("Usage: %s [OPTION...] BINDADDR\n", argv[0]);
return -1;
}
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_BINDADDR, argv[optind]);
if (!no_default_keys) {
set_default_keys(sshbind,
rsa_already_set,
dsa_already_set,
ecdsa_already_set);
}
return 0;
}
#endif /* HAVE_ARGP_H */ #endif /* HAVE_ARGP_H */
/* A userdata struct for channel. */ /* A userdata struct for channel. */
@@ -549,7 +425,7 @@ static int auth_password(ssh_session session, const char *user,
(void) session; (void) session;
if (strcmp(user, username) == 0 && strcmp(pass, password) == 0) { if (strcmp(user, USER) == 0 && strcmp(pass, PASS) == 0) {
sdata->authenticated = 1; sdata->authenticated = 1;
return SSH_AUTH_SUCCESS; return SSH_AUTH_SUCCESS;
} }
@@ -558,53 +434,6 @@ static int auth_password(ssh_session session, const char *user,
return SSH_AUTH_DENIED; return SSH_AUTH_DENIED;
} }
static int auth_publickey(ssh_session session,
const char *user,
struct ssh_key_struct *pubkey,
char signature_state,
void *userdata)
{
struct session_data_struct *sdata = (struct session_data_struct *) userdata;
(void) user;
(void) session;
if (signature_state == SSH_PUBLICKEY_STATE_NONE) {
return SSH_AUTH_SUCCESS;
}
if (signature_state != SSH_PUBLICKEY_STATE_VALID) {
return SSH_AUTH_DENIED;
}
// valid so far. Now look through authorized keys for a match
if (authorizedkeys[0]) {
ssh_key key = NULL;
int result;
struct stat buf;
if (stat(authorizedkeys, &buf) == 0) {
result = ssh_pki_import_pubkey_file( authorizedkeys, &key );
if ((result != SSH_OK) || (key==NULL)) {
fprintf(stderr,
"Unable to import public key file %s\n",
authorizedkeys);
} else {
result = ssh_key_cmp( key, pubkey, SSH_KEY_CMP_PUBLIC );
ssh_key_free(key);
if (result == 0) {
sdata->authenticated = 1;
return SSH_AUTH_SUCCESS;
}
}
}
}
// no matches
sdata->authenticated = 0;
return SSH_AUTH_DENIED;
}
static ssh_channel channel_open(ssh_session session, void *userdata) { static ssh_channel channel_open(ssh_session session, void *userdata) {
struct session_data_struct *sdata = (struct session_data_struct *) userdata; struct session_data_struct *sdata = (struct session_data_struct *) userdata;
@@ -643,8 +472,7 @@ static int process_stderr(socket_t fd, int revents, void *userdata) {
} }
static void handle_session(ssh_event event, ssh_session session) { static void handle_session(ssh_event event, ssh_session session) {
int n; int n, rc;
int rc = 0;
/* Structure for storing the pty size. */ /* Structure for storing the pty size. */
struct winsize wsize = { struct winsize wsize = {
@@ -689,12 +517,6 @@ static void handle_session(ssh_event event, ssh_session session) {
.channel_open_request_session_function = channel_open, .channel_open_request_session_function = channel_open,
}; };
if (authorizedkeys[0]) {
server_cb.auth_pubkey_function = auth_publickey;
ssh_set_auth_methods(session, SSH_AUTH_METHOD_PASSWORD | SSH_AUTH_METHOD_PUBLICKEY);
} else
ssh_set_auth_methods(session, SSH_AUTH_METHOD_PASSWORD);
ssh_callbacks_init(&server_cb); ssh_callbacks_init(&server_cb);
ssh_callbacks_init(&channel_cb); ssh_callbacks_init(&channel_cb);
@@ -705,6 +527,7 @@ static void handle_session(ssh_event event, ssh_session session) {
return; return;
} }
ssh_set_auth_methods(session, SSH_AUTH_METHOD_PASSWORD);
ssh_event_add_session(event, session); ssh_event_add_session(event, session);
n = 0; n = 0;
@@ -787,37 +610,16 @@ static void handle_session(ssh_event event, ssh_session session) {
} }
} }
#ifdef WITH_FORK
/* SIGCHLD handler for cleaning up dead children. */ /* SIGCHLD handler for cleaning up dead children. */
static void sigchld_handler(int signo) { static void sigchld_handler(int signo) {
(void) signo; (void) signo;
while (waitpid(-1, NULL, WNOHANG) > 0); while (waitpid(-1, NULL, WNOHANG) > 0);
} }
#else
static void *session_thread(void *arg) {
ssh_session session = arg;
ssh_event event;
event = ssh_event_new();
if (event != NULL) {
/* Blocks until the SSH session ends by either
* child thread exiting, or client disconnecting. */
handle_session(event, session);
ssh_event_free(event);
} else {
fprintf(stderr, "Could not create polling context\n");
}
ssh_disconnect(session);
ssh_free(session);
return NULL;
}
#endif
int main(int argc, char **argv) { int main(int argc, char **argv) {
ssh_bind sshbind; ssh_bind sshbind;
ssh_session session; ssh_session session;
int rc; ssh_event event;
#ifdef WITH_FORK
struct sigaction sa; struct sigaction sa;
/* Set up SIGCHLD handler. */ /* Set up SIGCHLD handler. */
@@ -828,35 +630,21 @@ int main(int argc, char **argv) {
fprintf(stderr, "Failed to register SIGCHLD handler\n"); fprintf(stderr, "Failed to register SIGCHLD handler\n");
return 1; return 1;
} }
#endif
rc = ssh_init();
if (rc < 0) {
fprintf(stderr, "ssh_init failed\n");
return 1;
}
ssh_init();
sshbind = ssh_bind_new(); sshbind = ssh_bind_new();
if (sshbind == NULL) {
fprintf(stderr, "ssh_bind_new failed\n");
ssh_finalize();
return 1;
}
#ifdef HAVE_ARGP_H #ifdef HAVE_ARGP_H
argp_parse(&argp, argc, argv, 0, 0, sshbind); argp_parse(&argp, argc, argv, 0, 0, sshbind);
#else #else
if (parse_opt(argc, argv, sshbind) < 0) { (void) argc;
ssh_bind_free(sshbind); (void) argv;
ssh_finalize();
return 1; set_default_keys(sshbind, 0, 0, 0);
}
#endif /* HAVE_ARGP_H */ #endif /* HAVE_ARGP_H */
if(ssh_bind_listen(sshbind) < 0) { if(ssh_bind_listen(sshbind) < 0) {
fprintf(stderr, "%s\n", ssh_get_error(sshbind)); fprintf(stderr, "%s\n", ssh_get_error(sshbind));
ssh_bind_free(sshbind);
ssh_finalize();
return 1; return 1;
} }
@@ -869,9 +657,6 @@ int main(int argc, char **argv) {
/* Blocks until there is a new incoming connection. */ /* Blocks until there is a new incoming connection. */
if(ssh_bind_accept(sshbind, session) != SSH_ERROR) { if(ssh_bind_accept(sshbind, session) != SSH_ERROR) {
#ifdef WITH_FORK
ssh_event event;
switch(fork()) { switch(fork()) {
case 0: case 0:
/* Remove the SIGCHLD handler inherited from parent. */ /* Remove the SIGCHLD handler inherited from parent. */
@@ -897,16 +682,6 @@ int main(int argc, char **argv) {
case -1: case -1:
fprintf(stderr, "Failed to fork\n"); fprintf(stderr, "Failed to fork\n");
} }
#else
pthread_t tid;
rc = pthread_create(&tid, NULL, session_thread, session);
if (rc == 0) {
pthread_detach(tid);
continue;
}
fprintf(stderr, "Failed to pthread_create\n");
#endif
} else { } else {
fprintf(stderr, "%s\n", ssh_get_error(sshbind)); fprintf(stderr, "%s\n", ssh_get_error(sshbind));
} }

View File

@@ -1,754 +0,0 @@
/* This is a sample implementation of a libssh based SSH server */
/*
Copyright 2003-2009 Aris Adamantiadis
Copyright 2018 T. Wimmer
This file is part of the SSH Library
You are free to copy this file, modify it in any way, consider it being public
domain. This does not apply to the rest of the library though, but it is
allowed to cut-and-paste working code from this file to any license of
program.
The goal is to show the API in action. It's not a reference on how terminal
clients must be made or how a client should react.
*/
/*
Example:
./sshd_direct-tcpip -v -p 2022 -d serverkey.dsa -r serverkey.rsa 127.0.0.1
*/
#include "config.h"
#include <libssh/libssh.h>
#include <libssh/server.h>
#include <libssh/callbacks.h>
#ifdef HAVE_ARGP_H
#include <argp.h>
#endif
#include <sys/types.h>
#include <sys/socket.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <poll.h>
#ifndef BUF_SIZE
#define BUF_SIZE 16384
#endif
#define SAFE_FREE(x) do { if ((x) != NULL) {free(x); x=NULL;} } while(0)
#ifndef __unused__
# ifdef HAVE_UNUSED_ATTRIBUTE
# define __unused__ __attribute__((unused))
# else /* HAVE_UNUSED_ATTRIBUTE */
# define __unused__
# endif /* HAVE_UNUSED_ATTRIBUTE */
#endif /* __unused__ */
#ifndef UNUSED_PARAM
#define UNUSED_PARAM(param) param __unused__
#endif /* UNUSED_PARAM */
#ifndef KEYS_FOLDER
#ifdef _WIN32
#define KEYS_FOLDER
#else
#define KEYS_FOLDER "/etc/ssh/"
#endif
#endif
#define USER "user"
#define PASSWORD "pwd"
struct event_fd_data_struct {
int *p_fd;
ssh_channel channel;
struct ssh_channel_callbacks_struct *cb_chan;
int stacked;
};
struct cleanup_node_struct {
struct event_fd_data_struct *data;
struct cleanup_node_struct *next;
};
static bool authenticated = false;
static int tries = 0;
static bool error_set = false;
static int sockets_cnt = 0;
static ssh_event mainloop = NULL;
static struct cleanup_node_struct *cleanup_stack = NULL;
static void _close_socket(struct event_fd_data_struct event_fd_data);
static void
cleanup_push(struct cleanup_node_struct** head_ref,
struct event_fd_data_struct *new_data)
{
// Allocate memory for node
struct cleanup_node_struct *new_node = malloc(sizeof *new_node);
if (*head_ref != NULL) {
new_node->next = *head_ref;
} else {
new_node->next = NULL;
}
// Copy new_data
new_node->data = new_data;
// Change head pointer as new node is added at the beginning
(*head_ref) = new_node;
}
static void
do_cleanup(struct cleanup_node_struct **head_ref)
{
struct cleanup_node_struct *current = (*head_ref);
struct cleanup_node_struct *previous = NULL, *gone = NULL;
while (current != NULL) {
if (ssh_channel_is_closed(current->data->channel)) {
if (current == (*head_ref)) {
(*head_ref) = current->next;
}
if (previous != NULL) {
previous->next = current->next;
}
gone = current;
current = current->next;
if (gone->data->channel) {
_close_socket(*gone->data);
ssh_remove_channel_callbacks(gone->data->channel, gone->data->cb_chan);
ssh_channel_free(gone->data->channel);
gone->data->channel = NULL;
SAFE_FREE(gone->data->p_fd);
SAFE_FREE(gone->data->cb_chan);
SAFE_FREE(gone->data);
SAFE_FREE(gone);
}
else {
fprintf(stderr, "channel already freed!\n");
}
_ssh_log(SSH_LOG_FUNCTIONS, "=== do_cleanup", "Freed.");
}
else {
ssh_channel_close(current->data->channel);
previous = current;
current = current->next;
}
}
}
static int
auth_password(ssh_session session,
const char *user,
const char *password,
UNUSED_PARAM(void *userdata))
{
_ssh_log(SSH_LOG_PROTOCOL,
"=== auth_password", "Authenticating user %s pwd %s",
user,
password);
if (strcmp(user, USER) == 0 && strcmp(password, PASSWORD) == 0) {
authenticated = true;
printf("Authenticated\n");
return SSH_AUTH_SUCCESS;
}
if (tries >= 3) {
printf("Too many authentication tries\n");
ssh_disconnect(session);
error_set = true;
return SSH_AUTH_DENIED;
}
tries++;
return SSH_AUTH_DENIED;
}
static int
auth_gssapi_mic(ssh_session session,
const char *user,
const char *principal,
UNUSED_PARAM(void *userdata))
{
ssh_gssapi_creds creds = ssh_gssapi_get_creds(session);
printf("Authenticating user %s with gssapi principal %s\n",
user, principal);
if (creds != NULL) {
printf("Received some gssapi credentials\n");
} else {
printf("Not received any forwardable creds\n");
}
printf("authenticated\n");
authenticated = true;
return SSH_AUTH_SUCCESS;
}
static int
subsystem_request(UNUSED_PARAM(ssh_session session),
UNUSED_PARAM(ssh_channel channel),
const char *subsystem,
UNUSED_PARAM(void *userdata))
{
_ssh_log(SSH_LOG_PROTOCOL,
"=== subsystem_request", "Channel subsystem reqeuest: %s",
subsystem);
return 0;
}
struct ssh_channel_callbacks_struct channel_cb = {
.channel_subsystem_request_function = subsystem_request
};
static ssh_channel
new_session_channel(UNUSED_PARAM(ssh_session session),
UNUSED_PARAM(void *userdata))
{
_ssh_log(SSH_LOG_PROTOCOL, "=== subsystem_request", "Session channel request");
/* For TCP forward only there seems to be no need for a session channel */
/*if(chan != NULL)
return NULL;
printf("Session channel request\n");
chan = ssh_channel_new(session);
ssh_callbacks_init(&channel_cb);
ssh_set_channel_callbacks(chan, &channel_cb);
return chan;*/
return NULL;
}
static void
stack_socket_close(UNUSED_PARAM(ssh_session session),
struct event_fd_data_struct *event_fd_data)
{
if (event_fd_data->stacked != 1) {
_ssh_log(SSH_LOG_FUNCTIONS, "=== stack_socket_close",
"Closing fd = %d sockets_cnt = %d", *event_fd_data->p_fd,
sockets_cnt);
event_fd_data->stacked = 1;
cleanup_push(&cleanup_stack, event_fd_data);
}
}
static void
_close_socket(struct event_fd_data_struct event_fd_data)
{
_ssh_log(SSH_LOG_FUNCTIONS, "=== close_socket",
"Closing fd = %d sockets_cnt = %d", *event_fd_data.p_fd,
sockets_cnt);
ssh_event_remove_fd(mainloop, *event_fd_data.p_fd);
sockets_cnt--;
#ifdef _WIN32
closesocket(*event_fd_data.p_fd);
#else
close(*event_fd_data.p_fd);
#endif // _WIN32
(*event_fd_data.p_fd) = SSH_INVALID_SOCKET;
}
static int
service_request(UNUSED_PARAM(ssh_session session),
const char *service,
UNUSED_PARAM(void *userdata))
{
_ssh_log(SSH_LOG_PROTOCOL, "=== service_request", "Service request: %s", service);
return 0;
}
static void
global_request(UNUSED_PARAM(ssh_session session),
ssh_message message,
UNUSED_PARAM(void *userdata))
{
_ssh_log(SSH_LOG_PROTOCOL,
"=== global_request", "Global request, message type: %d",
ssh_message_type(message));
}
static void
my_channel_close_function(ssh_session session,
UNUSED_PARAM(ssh_channel channel),
void *userdata)
{
struct event_fd_data_struct *event_fd_data = (struct event_fd_data_struct *)userdata;
_ssh_log(SSH_LOG_PROTOCOL,
"=== my_channel_close_function",
"Channel closed by remote.");
stack_socket_close(session, event_fd_data);
}
static void
my_channel_eof_function(ssh_session session,
UNUSED_PARAM(ssh_channel channel),
void *userdata)
{
struct event_fd_data_struct *event_fd_data = (struct event_fd_data_struct *)userdata;
_ssh_log(SSH_LOG_PROTOCOL,
"=== my_channel_eof_function",
"Got EOF on channel. Shuting down write on socket (fd = %d).",
*event_fd_data->p_fd);
stack_socket_close(session, event_fd_data);
}
static void
my_channel_exit_status_function(UNUSED_PARAM(ssh_session session),
UNUSED_PARAM(ssh_channel channel),
int exit_status,
void *userdata)
{
struct event_fd_data_struct *event_fd_data = (struct event_fd_data_struct *)userdata;
_ssh_log(SSH_LOG_PROTOCOL,
"=== my_channel_exit_status_function",
"Got exit status %d on channel fd = %d.",
exit_status, *event_fd_data->p_fd);
}
static int
my_channel_data_function(ssh_session session,
UNUSED_PARAM(ssh_channel channel),
void *data,
uint32_t len,
UNUSED_PARAM(int is_stderr),
void *userdata)
{
int i = 0;
struct event_fd_data_struct *event_fd_data = (struct event_fd_data_struct *)userdata;
if (event_fd_data->channel == NULL) {
fprintf(stderr, "Why we're here? Stacked = %d\n", event_fd_data->stacked);
}
_ssh_log(SSH_LOG_PROTOCOL,
"=== my_channel_data_function",
"%d bytes waiting on channel for reading. Fd = %d",
len,
*event_fd_data->p_fd);
if (len > 0) {
i = send(*event_fd_data->p_fd, data, len, 0);
}
if (i < 0) {
_ssh_log(SSH_LOG_WARNING, "=== my_channel_data_function",
"Writing to tcp socket %d: %s", *event_fd_data->p_fd,
strerror(errno));
stack_socket_close(session, event_fd_data);
}
else {
_ssh_log(SSH_LOG_FUNCTIONS, "=== my_channel_data_function", "Sent %d bytes", i);
}
return i;
}
static int
my_fd_data_function(UNUSED_PARAM(socket_t fd),
int revents,
void *userdata)
{
struct event_fd_data_struct *event_fd_data = (struct event_fd_data_struct *)userdata;
ssh_channel channel = event_fd_data->channel;
ssh_session session;
int len, i, wr;
char buf[BUF_SIZE];
int blocking;
if (channel == NULL) {
_ssh_log(SSH_LOG_FUNCTIONS, "=== my_fd_data_function", "channel == NULL!");
return 0;
}
session = ssh_channel_get_session(channel);
if (ssh_channel_is_closed(channel)) {
_ssh_log(SSH_LOG_FUNCTIONS, "=== my_fd_data_function", "channel is closed!");
stack_socket_close(session, event_fd_data);
return 0;
}
if (!(revents & POLLIN)) {
if (revents & POLLPRI) {
_ssh_log(SSH_LOG_PROTOCOL, "=== my_fd_data_function", "poll revents & POLLPRI");
}
if (revents & POLLOUT) {
_ssh_log(SSH_LOG_PROTOCOL, "=== my_fd_data_function", "poll revents & POLLOUT");
}
if (revents & POLLHUP) {
_ssh_log(SSH_LOG_PROTOCOL, "=== my_fd_data_function", "poll revents & POLLHUP");
}
if (revents & POLLNVAL) {
_ssh_log(SSH_LOG_PROTOCOL, "=== my_fd_data_function", "poll revents & POLLNVAL");
}
if (revents & POLLERR) {
_ssh_log(SSH_LOG_PROTOCOL, "=== my_fd_data_function", "poll revents & POLLERR");
}
return 0;
}
blocking = ssh_is_blocking(session);
ssh_set_blocking(session, 0);
_ssh_log(SSH_LOG_FUNCTIONS,
"=== my_fd_data_function",
"Trying to read from tcp socket fd = %d",
*event_fd_data->p_fd);
#ifdef _WIN32
struct sockaddr from;
int fromlen = sizeof(from);
len = recvfrom(*event_fd_data->p_fd, buf, sizeof(buf), 0, &from, &fromlen);
#else
len = recv(*event_fd_data->p_fd, buf, sizeof(buf), 0);
#endif // _WIN32
if (len < 0) {
_ssh_log(SSH_LOG_WARNING, "=== my_fd_data_function", "Reading from tcp socket: %s", strerror(errno));
ssh_channel_send_eof(channel);
}
else if (len > 0) {
if (ssh_channel_is_open(channel)) {
wr = 0;
do {
i = ssh_channel_write(channel, buf, len);
if (i < 0) {
_ssh_log(SSH_LOG_WARNING, "=== my_fd_data_function", "Error writing on the direct-tcpip channel: %d", i);
len = wr;
break;
}
wr += i;
_ssh_log(SSH_LOG_FUNCTIONS, "=== my_fd_data_function", "ssh_channel_write (%d from %d)", wr, len);
} while (i > 0 && wr < len);
}
else {
_ssh_log(SSH_LOG_WARNING, "=== my_fd_data_function", "Can't write on closed channel!");
}
}
else {
_ssh_log(SSH_LOG_PROTOCOL, "=== my_fd_data_function", "The destination host has disconnected!");
ssh_channel_close(channel);
#ifdef _WIN32
shutdown(*event_fd_data->p_fd, SD_RECEIVE);
#else
shutdown(*event_fd_data->p_fd, SHUT_RD);
#endif // _WIN32
}
ssh_set_blocking(session, blocking);
return len;
}
static int
open_tcp_socket(ssh_message msg)
{
struct sockaddr_in sin;
int forwardsock = -1;
struct hostent *host;
const char *dest_hostname;
int dest_port;
forwardsock = socket(AF_INET, SOCK_STREAM, 0);
if (forwardsock < 0) {
_ssh_log(SSH_LOG_WARNING, "=== open_tcp_socket", "ERROR opening socket: %s", strerror(errno));
return -1;
}
dest_hostname = ssh_message_channel_request_open_destination(msg);
dest_port = ssh_message_channel_request_open_destination_port(msg);
_ssh_log(SSH_LOG_PROTOCOL, "=== open_tcp_socket", "Connecting to %s on port %d", dest_hostname, dest_port);
host = gethostbyname(dest_hostname);
if (host == NULL) {
close(forwardsock);
_ssh_log(SSH_LOG_WARNING, "=== open_tcp_socket", "ERROR, no such host: %s", dest_hostname);
return -1;
}
memset((char *)&sin, '\0', sizeof(sin));
sin.sin_family = AF_INET;
memcpy((char *)&sin.sin_addr.s_addr, (char *)host->h_addr, host->h_length);
sin.sin_port = htons(dest_port);
if (connect(forwardsock, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
close(forwardsock);
_ssh_log(SSH_LOG_WARNING, "=== open_tcp_socket", "ERROR connecting: %s", strerror(errno));
return -1;
}
sockets_cnt++;
_ssh_log(SSH_LOG_FUNCTIONS, "=== open_tcp_socket", "Connected. sockets_cnt = %d", sockets_cnt);
return forwardsock;
}
static int
message_callback(UNUSED_PARAM(ssh_session session),
ssh_message message,
UNUSED_PARAM(void *userdata))
{
ssh_channel channel;
int socket_fd, *pFd;
struct ssh_channel_callbacks_struct *cb_chan;
struct event_fd_data_struct *event_fd_data;
_ssh_log(SSH_LOG_PACKET, "=== message_callback", "Message type: %d",
ssh_message_type(message));
_ssh_log(SSH_LOG_PACKET, "=== message_callback", "Message Subtype: %d",
ssh_message_subtype(message));
if (ssh_message_type(message) == SSH_REQUEST_CHANNEL_OPEN) {
_ssh_log(SSH_LOG_PROTOCOL, "=== message_callback", "channel_request_open");
if (ssh_message_subtype(message) == SSH_CHANNEL_DIRECT_TCPIP) {
channel = ssh_message_channel_request_open_reply_accept(message);
if (channel == NULL) {
_ssh_log(SSH_LOG_WARNING, "=== message_callback", "Accepting direct-tcpip channel failed!");
return 1;
}
else {
_ssh_log(SSH_LOG_PROTOCOL, "=== message_callback", "Connected to channel!");
socket_fd = open_tcp_socket(message);
if (-1 == socket_fd) {
return 1;
}
pFd = malloc(sizeof *pFd);
cb_chan = malloc(sizeof *cb_chan);
event_fd_data = malloc(sizeof *event_fd_data);
if (pFd == NULL || cb_chan == NULL || event_fd_data == NULL) {
SAFE_FREE(pFd);
SAFE_FREE(cb_chan);
SAFE_FREE(event_fd_data);
close(socket_fd);
return 1;
}
(*pFd) = socket_fd;
event_fd_data->channel = channel;
event_fd_data->p_fd = pFd;
event_fd_data->stacked = 0;
event_fd_data->cb_chan = cb_chan;
cb_chan->userdata = event_fd_data;
cb_chan->channel_eof_function = my_channel_eof_function;
cb_chan->channel_close_function = my_channel_close_function;
cb_chan->channel_data_function = my_channel_data_function;
cb_chan->channel_exit_status_function = my_channel_exit_status_function;
ssh_callbacks_init(cb_chan);
ssh_set_channel_callbacks(channel, cb_chan);
ssh_event_add_fd(mainloop, (socket_t)*pFd, POLLIN, my_fd_data_function, event_fd_data);
return 0;
}
}
}
return 1;
}
#ifdef HAVE_ARGP_H
const char *argp_program_version = "libssh server example "
SSH_STRINGIFY(LIBSSH_VERSION);
const char *argp_program_bug_address = "<libssh@libssh.org>";
/* Program documentation. */
static char doc[] = "libssh -- a Secure Shell protocol implementation";
/* A description of the arguments we accept. */
static char args_doc[] = "BINDADDR";
/* The options we understand. */
static struct argp_option options[] = {
{
.name = "port",
.key = 'p',
.arg = "PORT",
.flags = 0,
.doc = "Set the port to bind.",
.group = 0
},
{
.name = "hostkey",
.key = 'k',
.arg = "FILE",
.flags = 0,
.doc = "Set the host key.",
.group = 0
},
{
.name = "dsakey",
.key = 'd',
.arg = "FILE",
.flags = 0,
.doc = "Set the dsa key.",
.group = 0
},
{
.name = "rsakey",
.key = 'r',
.arg = "FILE",
.flags = 0,
.doc = "Set the rsa key.",
.group = 0
},
{
.name = "verbose",
.key = 'v',
.arg = NULL,
.flags = 0,
.doc = "Get verbose output.",
.group = 0
},
{NULL, 0, NULL, 0, NULL, 0}
};
/* Parse a single option. */
static error_t
parse_opt (int key, char *arg, struct argp_state *state)
{
/* Get the input argument from argp_parse, which we
* know is a pointer to our arguments structure.
*/
ssh_bind sshbind = state->input;
switch (key) {
case 'p':
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_BINDPORT_STR, arg);
break;
case 'd':
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_DSAKEY, arg);
break;
case 'k':
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_HOSTKEY, arg);
break;
case 'r':
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_RSAKEY, arg);
break;
case 'v':
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_LOG_VERBOSITY_STR, "1");
break;
case ARGP_KEY_ARG:
if (state->arg_num >= 1) {
/* Too many arguments. */
argp_usage (state);
}
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_BINDADDR, arg);
break;
case ARGP_KEY_END:
if (state->arg_num < 1) {
/* Not enough arguments. */
argp_usage (state);
}
break;
default:
return ARGP_ERR_UNKNOWN;
}
return 0;
}
/* Our argp parser. */
static struct argp argp = {options, parse_opt, args_doc, doc, NULL, NULL, NULL};
#endif /* HAVE_ARGP_H */
int
main(int argc, char **argv)
{
ssh_session session;
ssh_bind sshbind;
struct ssh_server_callbacks_struct cb = {
.userdata = NULL,
.auth_password_function = auth_password,
.auth_gssapi_mic_function = auth_gssapi_mic,
.channel_open_request_session_function = new_session_channel,
.service_request_function = service_request
};
struct ssh_callbacks_struct cb_gen = {
.userdata = NULL,
.global_request_function = global_request
};
int ret = 1;
sshbind = ssh_bind_new();
session = ssh_new();
mainloop = ssh_event_new();
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_DSAKEY, KEYS_FOLDER "ssh_host_dsa_key");
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_RSAKEY, KEYS_FOLDER "ssh_host_rsa_key");
#ifdef HAVE_ARGP_H
/*
* Parse our arguments; every option seen by parse_opt will
* be reflected in arguments.
*/
argp_parse (&argp, argc, argv, 0, 0, sshbind);
#else
(void)argc;
(void)argv;
#endif
if (ssh_bind_listen(sshbind) < 0) {
printf("Error listening to socket: %s\n", ssh_get_error(sshbind));
return 1;
}
if (ssh_bind_accept(sshbind, session) == SSH_ERROR) {
printf("error accepting a connection : %s\n", ssh_get_error(sshbind));
ret = 1;
goto shutdown;
}
ssh_callbacks_init(&cb);
ssh_callbacks_init(&cb_gen);
ssh_set_server_callbacks(session, &cb);
ssh_set_callbacks(session, &cb_gen);
ssh_set_message_callback(session, message_callback, (void *)NULL);
if (ssh_handle_key_exchange(session)) {
printf("ssh_handle_key_exchange: %s\n", ssh_get_error(session));
ret = 1;
goto shutdown;
}
ssh_set_auth_methods(session, SSH_AUTH_METHOD_PASSWORD | SSH_AUTH_METHOD_GSSAPI_MIC);
ssh_event_add_session(mainloop, session);
while (!authenticated) {
if (error_set) {
break;
}
if (ssh_event_dopoll(mainloop, -1) == SSH_ERROR) {
printf("Error : %s\n", ssh_get_error(session));
ret = 1;
goto shutdown;
}
}
if (error_set) {
printf("Error, exiting loop\n");
} else {
printf("Authenticated and got a channel\n");
while (!error_set) {
if (ssh_event_dopoll(mainloop, 100) == SSH_ERROR) {
printf("Error : %s\n", ssh_get_error(session));
ret = 1;
goto shutdown;
}
do_cleanup(&cleanup_stack);
}
}
shutdown:
ssh_disconnect(session);
ssh_bind_free(sshbind);
ssh_finalize();
return ret;
}

View File

@@ -34,11 +34,6 @@ clients must be made or how a client should react.
#include <fcntl.h> #include <fcntl.h>
#include "examples_common.h" #include "examples_common.h"
#ifndef BUF_SIZE
#define BUF_SIZE 4096
#endif
char *host; char *host;
const char *desthost="localhost"; const char *desthost="localhost";
const char *port="22"; const char *port="22";
@@ -48,8 +43,7 @@ const char *port="22";
char *pcap_file=NULL; char *pcap_file=NULL;
#endif #endif
static void usage(void) static void usage(){
{
fprintf(stderr,"Usage : sshnetcat [user@]host forwarded_host forwarded_port\n"); fprintf(stderr,"Usage : sshnetcat [user@]host forwarded_host forwarded_port\n");
exit(1); exit(1);
} }
@@ -82,7 +76,7 @@ static int opts(int argc, char **argv){
static void select_loop(ssh_session session,ssh_channel channel){ static void select_loop(ssh_session session,ssh_channel channel){
fd_set fds; fd_set fds;
struct timeval timeout; struct timeval timeout;
char buffer[BUF_SIZE]; char buffer[4096];
/* channels will be set to the channels to poll. /* channels will be set to the channels to poll.
* outchannels will contain the result of the poll * outchannels will contain the result of the poll
*/ */
@@ -95,7 +89,6 @@ static void select_loop(ssh_session session,ssh_channel channel){
do{ do{
int fd; int fd;
ZERO_STRUCT(fds);
FD_ZERO(&fds); FD_ZERO(&fds);
if(!eof) if(!eof)
FD_SET(0,&fds); FD_SET(0,&fds);

View File

@@ -1,3 +1,3 @@
project(libssh-headers-x C) project(headers C)
add_subdirectory(libssh) add_subdirectory(libssh)

View File

@@ -15,6 +15,13 @@ if (WITH_SFTP)
) )
endif (WITH_SFTP) endif (WITH_SFTP)
if (WITH_SSH1)
set(libssh_HDRS
${libssh_HDRS}
ssh1.h
)
endif (WITH_SSH1)
if (WITH_SERVER) if (WITH_SERVER)
set(libssh_HDRS set(libssh_HDRS
${libssh_HDRS} ${libssh_HDRS}
@@ -26,14 +33,8 @@ install(
FILES FILES
${libssh_HDRS} ${libssh_HDRS}
DESTINATION DESTINATION
${CMAKE_INSTALL_INCLUDEDIR}/${APPLICATION_NAME} ${INCLUDE_INSTALL_DIR}/${APPLICATION_NAME}
COMPONENT COMPONENT
headers headers
) )
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/libssh_version.h.cmake
${libssh_BINARY_DIR}/include/libssh/libssh_version.h
@ONLY)
install(FILES ${libssh_BINARY_DIR}/include/libssh/libssh_version.h
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${APPLICATION_NAME}
COMPONENT headers)

View File

@@ -66,9 +66,6 @@
#define SSH_COM_AGENT2_FAILURE 102 #define SSH_COM_AGENT2_FAILURE 102
#define SSH_AGENT_OLD_SIGNATURE 0x01 #define SSH_AGENT_OLD_SIGNATURE 0x01
/* Signature flags from draft-miller-ssh-agent-02 */
#define SSH_AGENT_RSA_SHA2_256 0x02
#define SSH_AGENT_RSA_SHA2_512 0x04
struct ssh_agent_struct { struct ssh_agent_struct {
struct ssh_socket_struct *sock; struct ssh_socket_struct *sock;
@@ -77,22 +74,23 @@ struct ssh_agent_struct {
ssh_channel channel; ssh_channel channel;
}; };
#ifndef _WIN32
/* agent.c */ /* agent.c */
/** /**
* @brief Create a new ssh agent structure. * @brief Create a new ssh agent structure.
* *
* @return An allocated ssh agent structure or NULL on error. * @return An allocated ssh agent structure or NULL on error.
*/ */
struct ssh_agent_struct *ssh_agent_new(struct ssh_session_struct *session); struct ssh_agent_struct *agent_new(struct ssh_session_struct *session);
void ssh_agent_close(struct ssh_agent_struct *agent); void agent_close(struct ssh_agent_struct *agent);
/** /**
* @brief Free an allocated ssh agent structure. * @brief Free an allocated ssh agent structure.
* *
* @param agent The ssh agent structure to free. * @param agent The ssh agent structure to free.
*/ */
void ssh_agent_free(struct ssh_agent_struct *agent); void agent_free(struct ssh_agent_struct *agent);
/** /**
* @brief Check if the ssh agent is running. * @brief Check if the ssh agent is running.
@@ -101,9 +99,9 @@ void ssh_agent_free(struct ssh_agent_struct *agent);
* *
* @return 1 if it is running, 0 if not. * @return 1 if it is running, 0 if not.
*/ */
int ssh_agent_is_running(struct ssh_session_struct *session); int agent_is_running(struct ssh_session_struct *session);
uint32_t ssh_agent_get_ident_count(struct ssh_session_struct *session); int ssh_agent_get_ident_count(struct ssh_session_struct *session);
ssh_key ssh_agent_get_next_ident(struct ssh_session_struct *session, ssh_key ssh_agent_get_next_ident(struct ssh_session_struct *session,
char **comment); char **comment);
@@ -114,5 +112,7 @@ ssh_key ssh_agent_get_first_ident(struct ssh_session_struct *session,
ssh_string ssh_agent_sign_data(ssh_session session, ssh_string ssh_agent_sign_data(ssh_session session,
const ssh_key pubkey, const ssh_key pubkey,
struct ssh_buffer_struct *data); struct ssh_buffer_struct *data);
#endif
#endif /* __AGENT_H */ #endif /* __AGENT_H */
/* vim: set ts=2 sw=2 et cindent: */

View File

@@ -49,6 +49,20 @@ ssh_kbdint ssh_kbdint_new(void);
void ssh_kbdint_clean(ssh_kbdint kbd); void ssh_kbdint_clean(ssh_kbdint kbd);
void ssh_kbdint_free(ssh_kbdint kbd); void ssh_kbdint_free(ssh_kbdint kbd);
#ifdef WITH_SSH1
void ssh_auth1_handler(ssh_session session, uint8_t type);
/* auth1.c */
int ssh_userauth1_none(ssh_session session, const char *username);
int ssh_userauth1_offer_pubkey(ssh_session session, const char *username,
int type, ssh_string pubkey);
int ssh_userauth1_password(ssh_session session, const char *username,
const char *password);
#endif
/** @internal /** @internal
* States of authentication in the client-side. They describe * States of authentication in the client-side. They describe
* what was the last response from the server * what was the last response from the server
@@ -76,14 +90,6 @@ enum ssh_auth_state_e {
SSH_AUTH_STATE_GSSAPI_TOKEN, SSH_AUTH_STATE_GSSAPI_TOKEN,
/** We have sent the MIC and expecting to be authenticated */ /** We have sent the MIC and expecting to be authenticated */
SSH_AUTH_STATE_GSSAPI_MIC_SENT, SSH_AUTH_STATE_GSSAPI_MIC_SENT,
/** We have offered a pubkey to check if it is supported */
SSH_AUTH_STATE_PUBKEY_OFFER_SENT,
/** We have sent pubkey and signature expecting to be authenticated */
SSH_AUTH_STATE_PUBKEY_AUTH_SENT,
/** We have sent a password expecting to be authenticated */
SSH_AUTH_STATE_PASSWORD_AUTH_SENT,
/** We have sent a request without auth information (method 'none') */
SSH_AUTH_STATE_AUTH_NONE_SENT,
}; };
/** @internal /** @internal
@@ -98,6 +104,8 @@ enum ssh_auth_service_state_e {
SSH_AUTH_SERVICE_ACCEPTED, SSH_AUTH_SERVICE_ACCEPTED,
/** Access to service denied (fatal) */ /** Access to service denied (fatal) */
SSH_AUTH_SERVICE_DENIED, SSH_AUTH_SERVICE_DENIED,
/** Specific to SSH1 */
SSH_AUTH_SERVICE_USER_SENT
}; };
#endif /* AUTH_H_ */ #endif /* AUTH_H_ */

View File

@@ -23,11 +23,11 @@
#include "libssh/libcrypto.h" #include "libssh/libcrypto.h"
#include "libssh/libgcrypt.h" #include "libssh/libgcrypt.h"
#include "libssh/libmbedcrypto.h"
bignum ssh_make_string_bn(ssh_string string); bignum make_string_bn(ssh_string string);
ssh_string ssh_make_bignum_string(bignum num); void make_string_bn_inplace(ssh_string string, bignum bnout);
void ssh_print_bignum(const char *which, const_bignum num); ssh_string make_bignum_string(bignum num);
void ssh_print_bignum(const char *which,bignum num);
#endif /* BIGNUM_H_ */ #endif /* BIGNUM_H_ */

View File

@@ -22,7 +22,6 @@
#define BIND_H_ #define BIND_H_
#include "libssh/priv.h" #include "libssh/priv.h"
#include "libssh/kex.h"
#include "libssh/session.h" #include "libssh/session.h"
struct ssh_bind_struct { struct ssh_bind_struct {
@@ -32,7 +31,7 @@ struct ssh_bind_struct {
struct ssh_poll_handle_struct *poll; struct ssh_poll_handle_struct *poll;
/* options */ /* options */
char *wanted_methods[SSH_KEX_METHODS]; char *wanted_methods[10];
char *banner; char *banner;
char *ecdsakey; char *ecdsakey;
char *dsakey; char *dsakey;
@@ -47,11 +46,6 @@ struct ssh_bind_struct {
unsigned int bindport; unsigned int bindport;
int blocking; int blocking;
int toaccept; int toaccept;
bool config_processed;
char *config_dir;
char *pubkey_accepted_key_types;
char* moduli_file;
int rsa_min_size;
}; };
struct ssh_poll_handle_struct *ssh_bind_get_poll(struct ssh_bind_struct struct ssh_poll_handle_struct *ssh_bind_get_poll(struct ssh_bind_struct

View File

@@ -1,74 +0,0 @@
/*
* bind_config.h - Parse the SSH server configuration file
*
* This file is part of the SSH Library
*
* Copyright (c) 2019 by Red Hat, Inc.
*
* Author: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
*
* The SSH Library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or (at your
* option) any later version.
*
* The SSH Library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with the SSH Library; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
* MA 02111-1307, USA.
*/
#ifndef BIND_CONFIG_H_
#define BIND_CONFIG_H_
#include "libssh/server.h"
enum ssh_bind_config_opcode_e {
/* Known but not allowed in Match block */
BIND_CFG_NOT_ALLOWED_IN_MATCH = -4,
/* Unknown opcode */
BIND_CFG_UNKNOWN = -3,
/* Known and not applicable to libssh */
BIND_CFG_NA = -2,
/* Known but not supported by current libssh version */
BIND_CFG_UNSUPPORTED = -1,
BIND_CFG_INCLUDE,
BIND_CFG_HOSTKEY,
BIND_CFG_LISTENADDRESS,
BIND_CFG_PORT,
BIND_CFG_LOGLEVEL,
BIND_CFG_CIPHERS,
BIND_CFG_MACS,
BIND_CFG_KEXALGORITHMS,
BIND_CFG_MATCH,
BIND_CFG_PUBKEY_ACCEPTED_KEY_TYPES,
BIND_CFG_HOSTKEY_ALGORITHMS,
BIND_CFG_MAX /* Keep this one last in the list */
};
/* @brief Parse configuration file and set the options to the given ssh_bind
*
* @params[in] sshbind The ssh_bind context to be configured
* @params[in] filename The path to the configuration file
*
* @returns 0 on successful parsing the configuration file, -1 on error
*/
int ssh_bind_config_parse_file(ssh_bind sshbind, const char *filename);
/* @brief Parse configuration string and set the options to the given bind session
*
* @params[in] bind The ssh bind session
* @params[in] input Null terminated string containing the configuration
*
* @returns SSH_OK on successful parsing the configuration string,
* SSH_ERROR on error
*/
int ssh_bind_config_parse_string(ssh_bind bind, const char *input);
#endif /* BIND_CONFIG_H_ */

View File

@@ -53,7 +53,7 @@
typedef struct BlowfishContext { typedef struct BlowfishContext {
uint32_t S[4][256]; /* S-Boxes */ uint32_t S[4][256]; /* S-Boxes */
uint32_t P[BLF_N + 2]; /* Subkeys */ uint32_t P[BLF_N + 2]; /* Subkeys */
} ssh_blf_ctx; } blf_ctx;
/* Raw access to customized Blowfish /* Raw access to customized Blowfish
* blf_key is just: * blf_key is just:
@@ -61,24 +61,24 @@ typedef struct BlowfishContext {
* Blowfish_expand0state( state, key, keylen ) * Blowfish_expand0state( state, key, keylen )
*/ */
void Blowfish_encipher(ssh_blf_ctx *, uint32_t *, uint32_t *); void Blowfish_encipher(blf_ctx *, uint32_t *, uint32_t *);
void Blowfish_decipher(ssh_blf_ctx *, uint32_t *, uint32_t *); void Blowfish_decipher(blf_ctx *, uint32_t *, uint32_t *);
void Blowfish_initstate(ssh_blf_ctx *); void Blowfish_initstate(blf_ctx *);
void Blowfish_expand0state(ssh_blf_ctx *, const uint8_t *, uint16_t); void Blowfish_expand0state(blf_ctx *, const uint8_t *, uint16_t);
void Blowfish_expandstate void Blowfish_expandstate
(ssh_blf_ctx *, const uint8_t *, uint16_t, const uint8_t *, uint16_t); (blf_ctx *, const uint8_t *, uint16_t, const uint8_t *, uint16_t);
/* Standard Blowfish */ /* Standard Blowfish */
void ssh_blf_key(ssh_blf_ctx *, const uint8_t *, uint16_t); void blf_key(blf_ctx *, const uint8_t *, uint16_t);
void ssh_blf_enc(ssh_blf_ctx *, uint32_t *, uint16_t); void blf_enc(blf_ctx *, uint32_t *, uint16_t);
void ssh_blf_dec(ssh_blf_ctx *, uint32_t *, uint16_t); void blf_dec(blf_ctx *, uint32_t *, uint16_t);
void ssh_blf_ecb_encrypt(ssh_blf_ctx *, uint8_t *, uint32_t); void blf_ecb_encrypt(blf_ctx *, uint8_t *, uint32_t);
void ssh_blf_ecb_decrypt(ssh_blf_ctx *, uint8_t *, uint32_t); void blf_ecb_decrypt(blf_ctx *, uint8_t *, uint32_t);
void ssh_blf_cbc_encrypt(ssh_blf_ctx *, uint8_t *, uint8_t *, uint32_t); void blf_cbc_encrypt(blf_ctx *, uint8_t *, uint8_t *, uint32_t);
void ssh_blf_cbc_decrypt(ssh_blf_ctx *, uint8_t *, uint8_t *, uint32_t); void blf_cbc_decrypt(blf_ctx *, uint8_t *, uint8_t *, uint32_t);
/* Converts uint8_t to uint32_t */ /* Converts uint8_t to uint32_t */
uint32_t Blowfish_stream2word(const uint8_t *, uint16_t , uint16_t *); uint32_t Blowfish_stream2word(const uint8_t *, uint16_t , uint16_t *);

View File

@@ -24,54 +24,77 @@
#include <stdarg.h> #include <stdarg.h>
#include "libssh/libssh.h" #include "libssh/libssh.h"
/*
* Describes a buffer state
* [XXXXXXXXXXXXDATA PAYLOAD XXXXXXXXXXXXXXXXXXXXXXXX]
* ^ ^ ^ ^]
* \_data points\_pos points here \_used points here | /
* here Allocated
*/
struct ssh_buffer_struct {
char *data;
uint32_t used;
uint32_t allocated;
uint32_t pos;
int secure;
};
#define SSH_BUFFER_PACK_END ((uint32_t) 0x4f65feb3) #define SSH_BUFFER_PACK_END ((uint32_t) 0x4f65feb3)
LIBSSH_API void ssh_buffer_free(ssh_buffer buffer);
LIBSSH_API void *ssh_buffer_get_begin(ssh_buffer buffer);
LIBSSH_API uint32_t ssh_buffer_get_len(ssh_buffer buffer);
LIBSSH_API ssh_buffer ssh_buffer_new(void);
void ssh_buffer_set_secure(ssh_buffer buffer); void ssh_buffer_set_secure(ssh_buffer buffer);
int ssh_buffer_add_ssh_string(ssh_buffer buffer, ssh_string string); int buffer_add_ssh_string(ssh_buffer buffer, ssh_string string);
int ssh_buffer_add_u8(ssh_buffer buffer, uint8_t data); int buffer_add_u8(ssh_buffer buffer, uint8_t data);
int ssh_buffer_add_u16(ssh_buffer buffer, uint16_t data); int buffer_add_u16(ssh_buffer buffer, uint16_t data);
int ssh_buffer_add_u32(ssh_buffer buffer, uint32_t data); int buffer_add_u32(ssh_buffer buffer, uint32_t data);
int ssh_buffer_add_u64(ssh_buffer buffer, uint64_t data); int buffer_add_u64(ssh_buffer buffer, uint64_t data);
int ssh_buffer_add_data(ssh_buffer buffer, const void *data, uint32_t len);
int ssh_buffer_validate_length(struct ssh_buffer_struct *buffer, size_t len);
void *ssh_buffer_allocate(struct ssh_buffer_struct *buffer, uint32_t len);
int ssh_buffer_allocate_size(struct ssh_buffer_struct *buffer, uint32_t len);
int ssh_buffer_pack_va(struct ssh_buffer_struct *buffer, int ssh_buffer_pack_va(struct ssh_buffer_struct *buffer,
const char *format, const char *format,
size_t argc, int argc,
va_list ap); va_list ap);
int _ssh_buffer_pack(struct ssh_buffer_struct *buffer, int _ssh_buffer_pack(struct ssh_buffer_struct *buffer,
const char *format, const char *format,
size_t argc, int argc,
...); ...);
#define ssh_buffer_pack(buffer, format, ...) \ #define ssh_buffer_pack(buffer, format, ...) \
_ssh_buffer_pack((buffer), (format), __VA_NARG__(__VA_ARGS__), __VA_ARGS__, SSH_BUFFER_PACK_END) _ssh_buffer_pack((buffer), (format), __VA_NARG__(__VA_ARGS__), __VA_ARGS__, SSH_BUFFER_PACK_END)
int ssh_buffer_unpack_va(struct ssh_buffer_struct *buffer, int ssh_buffer_unpack_va(struct ssh_buffer_struct *buffer,
const char *format, size_t argc, const char *format, int argc,
va_list ap); va_list ap);
int _ssh_buffer_unpack(struct ssh_buffer_struct *buffer, int _ssh_buffer_unpack(struct ssh_buffer_struct *buffer,
const char *format, const char *format,
size_t argc, int argc,
...); ...);
#define ssh_buffer_unpack(buffer, format, ...) \ #define ssh_buffer_unpack(buffer, format, ...) \
_ssh_buffer_unpack((buffer), (format), __VA_NARG__(__VA_ARGS__), __VA_ARGS__, SSH_BUFFER_PACK_END) _ssh_buffer_unpack((buffer), (format), __VA_NARG__(__VA_ARGS__), __VA_ARGS__, SSH_BUFFER_PACK_END)
int ssh_buffer_prepend_data(ssh_buffer buffer, const void *data, uint32_t len); int buffer_prepend_data(ssh_buffer buffer, const void *data, uint32_t len);
int ssh_buffer_add_buffer(ssh_buffer buffer, ssh_buffer source); int buffer_add_buffer(ssh_buffer buffer, ssh_buffer source);
int ssh_buffer_reinit(ssh_buffer buffer);
/* buffer_get_rest returns a pointer to the current position into the buffer */
void *buffer_get_rest(ssh_buffer buffer);
/* buffer_get_rest_len returns the number of bytes which can be read */
uint32_t buffer_get_rest_len(ssh_buffer buffer);
/* buffer_read_*() returns the number of bytes read, except for ssh strings */ /* buffer_read_*() returns the number of bytes read, except for ssh strings */
uint32_t ssh_buffer_get_u8(ssh_buffer buffer, uint8_t *data); int buffer_get_u8(ssh_buffer buffer, uint8_t *data);
uint32_t ssh_buffer_get_u32(ssh_buffer buffer, uint32_t *data); int buffer_get_u32(ssh_buffer buffer, uint32_t *data);
uint32_t ssh_buffer_get_u64(ssh_buffer buffer, uint64_t *data); int buffer_get_u64(ssh_buffer buffer, uint64_t *data);
/* ssh_buffer_get_ssh_string() is an exception. if the String read is too large or invalid, it will answer NULL. */ uint32_t buffer_get_data(ssh_buffer buffer, void *data, uint32_t requestedlen);
ssh_string ssh_buffer_get_ssh_string(ssh_buffer buffer); /* buffer_get_ssh_string() is an exception. if the String read is too large or invalid, it will answer NULL. */
ssh_string buffer_get_ssh_string(ssh_buffer buffer);
/* ssh_buffer_pass_bytes acts as if len bytes have been read (used for padding) */ /* gets a string out of a SSH-1 mpint */
uint32_t ssh_buffer_pass_bytes_end(ssh_buffer buffer, uint32_t len); ssh_string buffer_get_mpint(ssh_buffer buffer);
uint32_t ssh_buffer_pass_bytes(ssh_buffer buffer, uint32_t len); /* buffer_pass_bytes acts as if len bytes have been read (used for padding) */
uint32_t buffer_pass_bytes_end(ssh_buffer buffer, uint32_t len);
uint32_t buffer_pass_bytes(ssh_buffer buffer, uint32_t len);
#endif /* BUFFER_H_ */ #endif /* BUFFER_H_ */

View File

@@ -1,90 +0,0 @@
/*
* This file is part of the SSH Library
*
* Copyright (c) 2018 Andreas Schneider <asn@cryptomilk.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _BYTEARRAY_H
#define _BYTEARRAY_H
#define _DATA_BYTE_CONST(data, pos) \
((uint8_t)(((const uint8_t *)(data))[(pos)]))
#define _DATA_BYTE(data, pos) \
(((uint8_t *)(data))[(pos)])
/*
* These macros pull or push integer values from byte arrays stored in
* little-endian byte order.
*/
#define PULL_LE_U8(data, pos) \
(_DATA_BYTE_CONST(data, pos))
#define PULL_LE_U16(data, pos) \
((uint16_t)PULL_LE_U8(data, pos) | ((uint16_t)(PULL_LE_U8(data, (pos) + 1))) << 8)
#define PULL_LE_U32(data, pos) \
((uint32_t)(PULL_LE_U16(data, pos) | ((uint32_t)PULL_LE_U16(data, (pos) + 2)) << 16))
#define PULL_LE_U64(data, pos) \
((uint64_t)(PULL_LE_U32(data, pos) | ((uint64_t)PULL_LE_U32(data, (pos) + 4)) << 32))
#define PUSH_LE_U8(data, pos, val) \
(_DATA_BYTE(data, pos) = ((uint8_t)(val)))
#define PUSH_LE_U16(data, pos, val) \
(PUSH_LE_U8((data), (pos), (uint8_t)((uint16_t)(val) & 0xff)), PUSH_LE_U8((data), (pos) + 1, (uint8_t)((uint16_t)(val) >> 8)))
#define PUSH_LE_U32(data, pos, val) \
(PUSH_LE_U16((data), (pos), (uint16_t)((uint32_t)(val) & 0xffff)), PUSH_LE_U16((data), (pos) + 2, (uint16_t)((uint32_t)(val) >> 16)))
#define PUSH_LE_U64(data, pos, val) \
(PUSH_LE_U32((data), (pos), (uint32_t)((uint64_t)(val) & 0xffffffff)), PUSH_LE_U32((data), (pos) + 4, (uint32_t)((uint64_t)(val) >> 32)))
/*
* These macros pull or push integer values from byte arrays stored in
* big-endian byte order (network byte order).
*/
#define PULL_BE_U8(data, pos) \
(_DATA_BYTE_CONST(data, pos))
#define PULL_BE_U16(data, pos) \
((((uint16_t)(PULL_BE_U8(data, pos))) << 8) | (uint16_t)PULL_BE_U8(data, (pos) + 1))
#define PULL_BE_U32(data, pos) \
((((uint32_t)PULL_BE_U16(data, pos)) << 16) | (uint32_t)(PULL_BE_U16(data, (pos) + 2)))
#define PULL_BE_U64(data, pos) \
((((uint64_t)PULL_BE_U32(data, pos)) << 32) | (uint64_t)(PULL_BE_U32(data, (pos) + 4)))
#define PUSH_BE_U8(data, pos, val) \
(_DATA_BYTE(data, pos) = ((uint8_t)(val)))
#define PUSH_BE_U16(data, pos, val) \
(PUSH_BE_U8((data), (pos), (uint8_t)(((uint16_t)(val)) >> 8)), PUSH_BE_U8((data), (pos) + 1, (uint8_t)((val) & 0xff)))
#define PUSH_BE_U32(data, pos, val) \
(PUSH_BE_U16((data), (pos), (uint16_t)(((uint32_t)(val)) >> 16)), PUSH_BE_U16((data), (pos) + 2, (uint16_t)((val) & 0xffff)))
#define PUSH_BE_U64(data, pos, val) \
(PUSH_BE_U32((data), (pos), (uint32_t)(((uint64_t)(val)) >> 32)), PUSH_BE_U32((data), (pos) + 4, (uint32_t)((val) & 0xffffffff)))
#endif /* _BYTEARRAY_H */

View File

@@ -56,7 +56,7 @@ typedef void (*ssh_callback_int) (int code, void *user);
* @returns number of bytes processed by the callee. The remaining bytes will * @returns number of bytes processed by the callee. The remaining bytes will
* be sent in the next callback message, when more data is available. * be sent in the next callback message, when more data is available.
*/ */
typedef size_t (*ssh_callback_data) (const void *data, size_t len, void *user); typedef int (*ssh_callback_data) (const void *data, size_t len, void *user);
typedef void (*ssh_callback_int_int) (int code, int errno_code, void *user); typedef void (*ssh_callback_int_int) (int code, int errno_code, void *user);
@@ -124,18 +124,6 @@ typedef void (*ssh_global_request_callback) (ssh_session session,
typedef ssh_channel (*ssh_channel_open_request_x11_callback) (ssh_session session, typedef ssh_channel (*ssh_channel_open_request_x11_callback) (ssh_session session,
const char * originator_address, int originator_port, void *userdata); const char * originator_address, int originator_port, void *userdata);
/**
* @brief Handles an SSH new channel open "auth-agent" request. This happens when the server
* sends back an "auth-agent" connection attempt. This is a client-side API
* @param session current session handler
* @param userdata Userdata to be passed to the callback function.
* @returns a valid ssh_channel handle if the request is to be allowed
* @returns NULL if the request should not be allowed
* @warning The channel pointer returned by this callback must be closed by the application.
*/
typedef ssh_channel (*ssh_channel_open_request_auth_agent_callback) (ssh_session session,
void *userdata);
/** /**
* The structure to replace libssh functions with appropriate callbacks. * The structure to replace libssh functions with appropriate callbacks.
*/ */
@@ -166,9 +154,6 @@ struct ssh_callbacks_struct {
/** This function will be called when an incoming X11 request is received. /** This function will be called when an incoming X11 request is received.
*/ */
ssh_channel_open_request_x11_callback channel_open_request_x11_function; ssh_channel_open_request_x11_callback channel_open_request_x11_function;
/** This function will be called when an incoming "auth-agent" request is received.
*/
ssh_channel_open_request_auth_agent_callback channel_open_request_auth_agent_function;
}; };
typedef struct ssh_callbacks_struct *ssh_callbacks; typedef struct ssh_callbacks_struct *ssh_callbacks;
@@ -221,8 +206,8 @@ typedef int (*ssh_auth_gssapi_mic_callback) (ssh_session session, const char *us
* @param user User that wants to authenticate * @param user User that wants to authenticate
* @param pubkey public key used for authentication * @param pubkey public key used for authentication
* @param signature_state SSH_PUBLICKEY_STATE_NONE if the key is not signed (simple public key probe), * @param signature_state SSH_PUBLICKEY_STATE_NONE if the key is not signed (simple public key probe),
* SSH_PUBLICKEY_STATE_VALID if the signature is valid. Others values should be * SSH_PUBLICKEY_STATE_VALID if the signature is valid. Others values should be
* replied with a SSH_AUTH_DENIED. * replied with a SSH_AUTH_DENIED.
* @param userdata Userdata to be passed to the callback function. * @param userdata Userdata to be passed to the callback function.
* @returns SSH_AUTH_SUCCESS Authentication is accepted. * @returns SSH_AUTH_SUCCESS Authentication is accepted.
* @returns SSH_AUTH_PARTIAL Partial authentication, more authentication means are needed. * @returns SSH_AUTH_PARTIAL Partial authentication, more authentication means are needed.
@@ -272,7 +257,7 @@ typedef ssh_string (*ssh_gssapi_select_oid_callback) (ssh_session session, const
* @param session current session handler * @param session current session handler
* @param[in] input_token input token provided by client * @param[in] input_token input token provided by client
* @param[out] output_token output of the gssapi accept_sec_context method, * @param[out] output_token output of the gssapi accept_sec_context method,
* NULL after completion. * NULL after completion.
* @returns SSH_OK if the token was generated correctly or accept_sec_context * @returns SSH_OK if the token was generated correctly or accept_sec_context
* returned GSS_S_COMPLETE * returned GSS_S_COMPLETE
* @returns SSH_ERROR in case of error * @returns SSH_ERROR in case of error
@@ -354,9 +339,6 @@ typedef struct ssh_server_callbacks_struct *ssh_server_callbacks;
* This functions sets the callback structure to use your own callback * This functions sets the callback structure to use your own callback
* functions for user authentication, new channels and requests. * functions for user authentication, new channels and requests.
* *
* Note, that the structure is not copied to the session structure so it needs
* to be valid for the whole session lifetime.
*
* @code * @code
* struct ssh_server_callbacks_struct cb = { * struct ssh_server_callbacks_struct cb = {
* .userdata = data, * .userdata = data,
@@ -438,69 +420,6 @@ typedef struct ssh_socket_callbacks_struct *ssh_socket_callbacks;
((p)-> c != NULL) \ ((p)-> c != NULL) \
) )
/**
* @internal
*
* @brief Iterate through a list of callback structures
*
* This tests for their validity and executes them. The userdata argument is
* automatically passed through.
*
* @param list list of callbacks
*
* @param cbtype type of the callback
*
* @param c callback name
*
* @param va_args parameters to be passed
*/
#define ssh_callbacks_execute_list(list, cbtype, c, ...) \
do { \
struct ssh_iterator *i = ssh_list_get_iterator(list); \
cbtype cb; \
while (i != NULL){ \
cb = ssh_iterator_value(cbtype, i); \
if (ssh_callbacks_exists(cb, c)) \
cb-> c (__VA_ARGS__, cb->userdata); \
i = i->next; \
} \
} while(0)
/**
* @internal
*
* @brief iterate through a list of callback structures.
*
* This tests for their validity and give control back to the calling code to
* execute them. Caller can decide to break the loop or continue executing the
* callbacks with different parameters
*
* @code
* ssh_callbacks_iterate(channel->callbacks, ssh_channel_callbacks,
* channel_eof_function){
* rc = ssh_callbacks_iterate_exec(session, channel);
* if (rc != SSH_OK){
* break;
* }
* }
* ssh_callbacks_iterate_end();
* @endcode
*/
#define ssh_callbacks_iterate(_cb_list, _cb_type, _cb_name) \
do { \
struct ssh_iterator *_cb_i = ssh_list_get_iterator(_cb_list); \
_cb_type _cb; \
for (; _cb_i != NULL; _cb_i = _cb_i->next) { \
_cb = ssh_iterator_value(_cb_type, _cb_i); \
if (ssh_callbacks_exists(_cb, _cb_name))
#define ssh_callbacks_iterate_exec(_cb_name, ...) \
_cb->_cb_name(__VA_ARGS__, _cb->userdata)
#define ssh_callbacks_iterate_end() \
} \
} while(0)
/** @brief Prototype for a packet callback, to be called when a new packet arrives /** @brief Prototype for a packet callback, to be called when a new packet arrives
* @param session The current session of the packet * @param session The current session of the packet
* @param type packet type (see ssh2.h) * @param type packet type (see ssh2.h)
@@ -551,9 +470,6 @@ typedef struct ssh_packet_callbacks_struct *ssh_packet_callbacks;
* This functions sets the callback structure to use your own callback * This functions sets the callback structure to use your own callback
* functions for auth, logging and status. * functions for auth, logging and status.
* *
* Note, that the callback structure is not copied into the session so it needs
* to be valid for the whole session lifetime.
*
* @code * @code
* struct ssh_callbacks_struct cb = { * struct ssh_callbacks_struct cb = {
* .userdata = data, * .userdata = data,
@@ -763,22 +679,6 @@ typedef int (*ssh_channel_subsystem_request_callback) (ssh_session session,
const char *subsystem, const char *subsystem,
void *userdata); void *userdata);
/**
* @brief SSH channel write will not block (flow control).
*
* @param channel the channel
*
* @param[in] bytes size of the remote window in bytes. Writing as much data
* will not block.
*
* @param[in] userdata Userdata to be passed to the callback function.
*
* @returns 0 default return value (other return codes may be added in future).
*/
typedef int (*ssh_channel_write_wontblock_callback) (ssh_session session,
ssh_channel channel,
uint32_t bytes,
void *userdata);
struct ssh_channel_callbacks_struct { struct ssh_channel_callbacks_struct {
/** DON'T SET THIS use ssh_callbacks_init() instead. */ /** DON'T SET THIS use ssh_callbacks_init() instead. */
@@ -843,10 +743,6 @@ struct ssh_channel_callbacks_struct {
* (like sftp). * (like sftp).
*/ */
ssh_channel_subsystem_request_callback channel_subsystem_request_function; ssh_channel_subsystem_request_callback channel_subsystem_request_function;
/** This function will be called when the channel write is guaranteed
* not to block.
*/
ssh_channel_write_wontblock_callback channel_write_wontblock_function;
}; };
typedef struct ssh_channel_callbacks_struct *ssh_channel_callbacks; typedef struct ssh_channel_callbacks_struct *ssh_channel_callbacks;
@@ -855,16 +751,12 @@ typedef struct ssh_channel_callbacks_struct *ssh_channel_callbacks;
* @brief Set the channel callback functions. * @brief Set the channel callback functions.
* *
* This functions sets the callback structure to use your own callback * This functions sets the callback structure to use your own callback
* functions for channel data and exceptions. * functions for channel data and exceptions
*
* Note, that the structure is not copied to the channel structure so it needs
* to be valid as for the whole life of the channel or until it is removed with
* ssh_remove_channel_callbacks().
* *
* @code * @code
* struct ssh_channel_callbacks_struct cb = { * struct ssh_channel_callbacks_struct cb = {
* .userdata = data, * .userdata = data,
* .channel_data_function = my_channel_data_function * .channel_data = my_channel_data_function
* }; * };
* ssh_callbacks_init(&cb); * ssh_callbacks_init(&cb);
* ssh_set_channel_callbacks(channel, &cb); * ssh_set_channel_callbacks(channel, &cb);
@@ -875,46 +767,10 @@ typedef struct ssh_channel_callbacks_struct *ssh_channel_callbacks;
* @param cb The callback structure itself. * @param cb The callback structure itself.
* *
* @return SSH_OK on success, SSH_ERROR on error. * @return SSH_OK on success, SSH_ERROR on error.
* @warning this function will not replace existing callbacks but set the
* new one atop of them.
*/ */
LIBSSH_API int ssh_set_channel_callbacks(ssh_channel channel, LIBSSH_API int ssh_set_channel_callbacks(ssh_channel channel,
ssh_channel_callbacks cb); ssh_channel_callbacks cb);
/**
* @brief Add channel callback functions
*
* This function will add channel callback functions to the channel callback
* list.
* Callbacks missing from a callback structure will be probed in the next
* on the list.
*
* @param channel The channel to set the callback structure.
*
* @param cb The callback structure itself.
*
* @return SSH_OK on success, SSH_ERROR on error.
*
* @see ssh_set_channel_callbacks
*/
LIBSSH_API int ssh_add_channel_callbacks(ssh_channel channel,
ssh_channel_callbacks cb);
/**
* @brief Remove a channel callback.
*
* The channel has been added with ssh_add_channel_callbacks or
* ssh_set_channel_callbacks in this case.
*
* @param channel The channel to remove the callback structure from.
*
* @param cb The callback structure to remove
*
* @returns SSH_OK on success, SSH_ERROR on error.
*/
LIBSSH_API int ssh_remove_channel_callbacks(ssh_channel channel,
ssh_channel_callbacks cb);
/** @} */ /** @} */
/** @group libssh_threads /** @group libssh_threads
@@ -954,20 +810,9 @@ LIBSSH_API int ssh_threads_set_callbacks(struct ssh_threads_callbacks_struct
*cb); *cb);
/** /**
* @brief Returns a pointer to the appropriate callbacks structure for the * @brief returns a pointer on the pthread threads callbacks, to be used with
* environment, to be used with ssh_threads_set_callbacks.
*
* @returns A pointer to a ssh_threads_callbacks_struct to be used with
* ssh_threads_set_callbacks. * ssh_threads_set_callbacks.
* * @warning you have to link with the library ssh_threads.
* @see ssh_threads_set_callbacks
*/
LIBSSH_API struct ssh_threads_callbacks_struct *ssh_threads_get_default(void);
/**
* @brief Returns a pointer on the pthread threads callbacks, to be used with
* ssh_threads_set_callbacks.
*
* @see ssh_threads_set_callbacks * @see ssh_threads_set_callbacks
*/ */
LIBSSH_API struct ssh_threads_callbacks_struct *ssh_threads_get_pthread(void); LIBSSH_API struct ssh_threads_callbacks_struct *ssh_threads_get_pthread(void);

View File

@@ -1,40 +0,0 @@
/* $OpenBSD: chacha.h,v 1.3 2014/05/02 03:27:54 djm Exp $ */
/*
chacha-merged.c version 20080118
D. J. Bernstein
Public domain.
*/
#ifndef CHACHA_H
#define CHACHA_H
struct chacha_ctx {
uint32_t input[16];
};
#define CHACHA_MINKEYLEN 16
#define CHACHA_NONCELEN 8
#define CHACHA_CTRLEN 8
#define CHACHA_STATELEN (CHACHA_NONCELEN+CHACHA_CTRLEN)
void chacha_keysetup(struct chacha_ctx *x, const uint8_t *k, uint32_t kbits)
#ifdef HAVE_GCC_BOUNDED_ATTRIBUTE
__attribute__((__bounded__(__minbytes__, 2, CHACHA_MINKEYLEN)))
#endif
;
void chacha_ivsetup(struct chacha_ctx *x, const uint8_t *iv, const uint8_t *ctr)
#ifdef HAVE_GCC_BOUNDED_ATTRIBUTE
__attribute__((__bounded__(__minbytes__, 2, CHACHA_NONCELEN)))
__attribute__((__bounded__(__minbytes__, 3, CHACHA_CTRLEN)))
#endif
;
void chacha_encrypt_bytes(struct chacha_ctx *x, const uint8_t *m,
uint8_t *c, uint32_t bytes)
#ifdef HAVE_GCC_BOUNDED_ATTRIBUTE
__attribute__((__bounded__(__buffer__, 2, 4)))
__attribute__((__bounded__(__buffer__, 3, 4)))
#endif
;
#endif /* CHACHA_H */

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