Compare commits

..

41 Commits

Author SHA1 Message Date
Andreas Schneider
d672dde342 Increase version number and update Changelog. 2009-08-18 10:06:02 +02:00
Vic Lee
86f983962c Fix double free pointer crash in dsa_public_to_string
Signed-off-by: Andreas Schneider <mail@cynapses.org>
2009-08-16 14:41:41 +02:00
Aris Adamantiadis
b0d6307d41 Fix channel_get_exit_status bug reported by VicLee
It would return -1 if the channel received the exit status
and the close message at same time.
2009-08-16 14:41:22 +02:00
Aris Adamantiadis
10920fc678 fix ssh_finalize which didn't clear the flag 2009-08-13 23:30:02 +02:00
Aris Adamantiadis
c87b247e01 Fix memory leak introduced by previous bugfix 2009-08-12 22:12:18 +02:00
Aris Adamantiadis
9abdc5ae2a Fixed channel_poll broken when delayed EOF recvd
Previous code returned SSH_EOF even if data was left in buffer
2009-08-10 23:37:53 +02:00
Aris Adamantiadis
e8e874909f Fixed stupid "can't parse known host key" bug
due to a dangling \n in the base64 ...
2009-08-10 22:53:27 +02:00
milo
74eff86a6b Fix possible memory corruption (#14)
Signed-off-by: Andreas Schneider <mail@cynapses.org>
2009-08-07 11:38:18 +02:00
Andreas Schneider
232aca8969 Update ChangeLog. 2009-08-04 15:24:06 +02:00
Andreas Schneider
48deb0ca46 Update version number of the package. 2009-08-04 15:17:46 +02:00
Andreas Schneider
59889da5a5 Update version numbers. 2009-08-01 11:22:09 +02:00
Andreas Schneider
a958f6498b Cleanup the libssh.map file and order it alphabetically. 2009-07-30 12:25:27 +02:00
Andreas Schneider
3ec11b46e9 Add gitignore file to branch. 2009-07-29 22:52:21 +02:00
Andreas Schneider
c17ce2697b Add ssh_init to the map file. 2009-07-29 17:50:53 +02:00
Aris Adamantiadis
7fa1804cf1 ssh_init()
fixes in client.c and server.c for this

git-svn-id: svn+ssh://svn.berlios.de/svnroot/repos/libssh/trunk@778 7dcaeef0-15fb-0310-b436-a5af3365683c
2009-07-29 17:50:04 +02:00
Andreas Schneider
ad86a378d9 moved try_publickey_from_file in priv.h
Had nothing to do in libssh.h. 100% sure nobody
used it since one of the structure declaration
was not public.
2009-07-29 17:40:17 +02:00
Andreas Schneider
ed660c29c3 Check for OpenSSH and implement sftp_symlink correct.
When OpenSSH's sftp-server was implemented, the order of the arguments
to the SSH_FXP_SYMLINK method was inadvertently reversed. Unfortunately,
the reversal was not noticed until the server was widely deployed.
Since fixing this to follow the specification would cause
incompatibility, the current order was retained.
2009-07-29 16:05:45 +02:00
Andreas Schneider
6f47401173 Fix SSH1 compilation. 2009-07-29 16:02:52 +02:00
Andreas Schneider
d247b86202 Update map file. 2009-07-25 12:34:49 +02:00
Andreas Schneider
a1c7dd99be Add sftp_readlink function. 2009-07-25 12:34:25 +02:00
Andreas Schneider
11a6ed907d Add sftp_symlink function. 2009-07-25 12:32:51 +02:00
Andreas Schneider
a8ce546f69 Fix a segfault if a NULL pointer is passed to ssh_disconnect(). 2009-07-23 09:07:49 +02:00
Andreas Schneider
6e56d1dfb2 Don't segfault if the session or the answer is NULL. 2009-07-23 09:07:36 +02:00
Andreas Schneider
b07ec7a3d1 Fix ssh_write_knownhost() which always returned -1.
fwrite() return the the number of items written not the size of the
buffer.
2009-07-23 09:07:26 +02:00
Andreas Schneider
09d4029ac1 Add compile flags and test for compiler options only if we use gcc. 2009-07-23 09:07:12 +02:00
Andreas Schneider
b62d0732d2 Only add additional warnings if we have a GNU compiler. 2009-07-23 09:07:00 +02:00
Andreas Schneider
90a6d431a7 Make the ssh_userauth_kbdint functions to get the prompts const.
They shouldn't be modified or free'd by a user.
2009-07-23 09:06:47 +02:00
Andreas Schneider
f7448eeb1c Fix sol8 + ss11 compile errors.
Thanks to tysonite@gmail.com.
2009-07-23 09:06:22 +02:00
Andreas Schneider
d411260a68 Fix build on windows, missing include. 2009-07-14 10:52:18 +02:00
Aris Adamantiadis
f8f0663eb9 Fix doxygen to match SSH_SERVER_FILE_NOT_FOUND fix 2009-07-14 10:22:17 +02:00
Andreas Schneider
cedc635ed0 Add changelog entries for 0.3.1. 2009-07-14 09:51:49 +02:00
Andreas Schneider
ff819489b7 Set version to 0.3.1. 2009-07-14 09:51:36 +02:00
Aris Adamantiadis
37dc2a5279 Reflect the SSH_SERVER_NOT_KNOWN add-on in sample 2009-07-13 12:07:31 +02:00
Aris Adamantiadis
50ebbe636e Added return code SSH_SERVER_FILE_NOT_FOUND
This error is returned by ssh_is_server_known when known_hosts
file does not exist and gives more action to the developer.
2009-07-13 12:07:19 +02:00
Aris Adamantiadis
101bf21d41 Fixed Could not write as much data as expected msg
Bug caused by verifying the size of the buffer in the wrong place
2009-07-02 10:37:32 +02:00
Aris Adamantiadis
ae3bb42da5 Fixed memory leak in ssh_is_server_known() 2009-06-23 09:13:26 +02:00
Aris Adamantiadis
918a912cd5 Fixed yet another read-after-free bug
read of a buffer len after free in sftp_write()
2009-06-23 09:13:15 +02:00
Aris Adamantiadis
7ba81b974e Fixed a use-after-free in match_hashed_host() 2009-06-21 22:18:43 +02:00
Aris Adamantiadis
b5e868fb8b Fix doublefree bug found by Cyril 2009-06-21 22:18:38 +02:00
Andreas Schneider
693c041ba9 Fix a memory leak in ssh_message_free(). 2009-06-20 11:30:09 +02:00
Aris Adamantiadis
39c7e3c7dd Fixed potential format string attacks
Potential format string attacks on error reporting in channels.c
2009-06-20 11:25:23 +02:00
557 changed files with 31148 additions and 169852 deletions

View File

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

View File

@@ -1,29 +0,0 @@
---
# https://clang.llvm.org/docs/ClangFormatStyleOptions.html
BasedOnStyle: LLVM
IndentWidth: 4
UseTab: Never
AllowShortIfStatementsOnASingleLine: false
BreakBeforeBraces: Custom
BraceWrapping:
AfterEnum: false
AfterFunction: true
AfterStruct: false
AfterUnion: false
AfterExternBlock: false
BeforeElse: false
BeforeWhile: false
IndentCaseLabels: false
IndentCaseBlocks: false
ColumnLimit: 80
AlignAfterOpenBracket: Align
AllowAllParametersOfDeclarationOnNextLine: false
BinPackArguments: false
BinPackParameters: false
AllowAllArgumentsOnNextLine: false
AllowShortFunctionsOnASingleLine: Empty
BreakAfterReturnType: ExceptShortType
AlwaysBreakAfterReturnType: AllDefinitions
AlignEscapedNewlines: Left
ForEachMacros: ['ssh_callbacks_iterate']
AlignConsecutiveMacros: 'Consecutive'

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

11
.gitignore vendored
View File

@@ -1,13 +1,6 @@
*.a
*.o
.*
*.swp
*~$
build
cscope.*
compile_commands.json
/.cache
/.clangd
tags
/build
/obj*
doc/tags.xml
.DS_Store

View File

@@ -1,765 +0,0 @@
---
variables:
BUILD_IMAGES_PROJECT: libssh/build-images
CENTOS8_BUILD: buildenv-c8s
CENTOS9_BUILD: buildenv-c9s
CENTOS10_BUILD: buildenv-c10s
FEDORA_BUILD: buildenv-fedora
MINGW_BUILD: buildenv-mingw
TUMBLEWEED_BUILD: buildenv-tumbleweed
UBUNTU_BUILD: buildenv-ubuntu
ALPINE_BUILD: buildenv-alpine
stages:
- review
- build
- test
- analysis
# This is some black magic to select between branch pipelines and
# merge request pipelines to avoid running same pipelines in twice
workflow:
rules:
- if: '$CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS && $CI_PIPELINE_SOURCE == "push"'
when: never
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
- if: '$CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS'
when: never
- if: '$CI_COMMIT_BRANCH'
.build_options:
variables:
CMAKE_DEFAULT_OPTIONS: "-DCMAKE_BUILD_TYPE=RelWithDebInfo -DPICKY_DEVELOPER=ON"
CMAKE_DEFAULT_DEBUG_OPTIONS: "-DCMAKE_C_FLAGS='-O0 -g -ggdb' -DPICKY_DEVELOPER=ON"
CMAKE_BUILD_OPTIONS: "-DWITH_BLOWFISH_CIPHER=ON -DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON -DWITH_DEBUG_CRYPTO=ON -DWITH_DEBUG_PACKET=ON -DWITH_DEBUG_CALLTRACE=ON"
CMAKE_TEST_OPTIONS: "-DUNIT_TESTING=ON -DCLIENT_TESTING=ON -DSERVER_TESTING=ON -DGSSAPI_TESTING=ON -DWITH_BENCHMARKS=ON -DFUZZ_TESTING=ON"
CMAKE_OPTIONS: $CMAKE_DEFAULT_OPTIONS $CMAKE_BUILD_OPTIONS $CMAKE_TEST_OPTIONS
.build:
extends: .build_options
stage: build
before_script: &build
- uname -a
- cat /etc/os-release
- 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:
- saas-linux-small-amd64
only:
- merge_requests
- branches
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
.tumbleweed:
extends: .tests
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$TUMBLEWEED_BUILD
.fips:
extends: .tests
variables:
CMAKE_ADDITIONAL_OPTIONS: -DWITH_PKCS11_URI=ON
before_script:
- *build
- 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
###############################################################################
# Review #
###############################################################################
review:
variables:
GIT_DEPTH: 100
stage: review
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD
script:
- ERROR=0
codespell --ignore-words-list=keypair,sorce,ned,nd,ue,pendin || ERROR=1;
./.gitlab-ci/clang-format-check.sh || ERROR=1;
./.gitlab-ci/git-check-signoff-trailer.sh ${CI_MERGE_REQUEST_DIFF_BASE_SHA} || ERROR=1;
./.gitlab-ci/shellcheck.sh || ERROR=1;
exit $ERROR
# the format is not always matching our intentions
allow_failure: true
tags:
- saas-linux-small-amd64
only:
- merge_requests
###############################################################################
# CentOS builds #
###############################################################################
centos10s/openssl_3.5.x/x86_64:
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$CENTOS10_BUILD
extends: .tests
variables:
CMAKE_ADDITIONAL_OPTIONS: -DWITH_PKCS11_URI=ON -DWITH_PKCS11_PROVIDER=ON
script:
- export OPENSSL_ENABLE_SHA1_SIGNATURES=1
- cmake $CMAKE_OPTIONS $CMAKE_ADDITIONAL_OPTIONS .. &&
make -j$(nproc) &&
ctest --output-on-failure
centos10s/openssl_3.5.x/x86_64/fips:
extends: .fips
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$CENTOS10_BUILD
variables:
CMAKE_ADDITIONAL_OPTIONS: -DWITH_PKCS11_URI=ON -DWITH_PKCS11_PROVIDER=ON
script:
- export OPENSSL_ENABLE_SHA1_SIGNATURES=1
- cmake $CMAKE_OPTIONS $CMAKE_ADDITIONAL_OPTIONS .. &&
make -j$(nproc) &&
OPENSSL_FORCE_FIPS_MODE=1 ctest --output-on-failure
centos9s/openssl_3.5.x/x86_64:
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$CENTOS9_BUILD
extends: .tests
variables:
CMAKE_ADDITIONAL_OPTIONS: -DWITH_PKCS11_URI=ON
script:
- export OPENSSL_ENABLE_SHA1_SIGNATURES=1
- cmake $CMAKE_OPTIONS $CMAKE_ADDITIONAL_OPTIONS .. &&
make -j$(nproc) &&
ctest --output-on-failure
centos9s/mbedtls_2.x/x86_64:
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$CENTOS9_BUILD
extends: .tests
variables:
CMAKE_ADDITIONAL_OPTIONS: "-DWITH_MBEDTLS=ON -DWITH_DEBUG_CRYPTO=ON -DWITH_BLOWFISH_CIPHER=OFF"
centos9s/openssl_3.5.x/x86_64/fips:
extends: .fips
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$CENTOS9_BUILD
script:
- export OPENSSL_ENABLE_SHA1_SIGNATURES=1
- cmake $CMAKE_OPTIONS $CMAKE_ADDITIONAL_OPTIONS .. &&
make -j$(nproc) &&
OPENSSL_FORCE_FIPS_MODE=1 ctest --output-on-failure
centos8s/openssl_1.1.1/x86_64:
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$CENTOS8_BUILD
extends: .tests
variables:
CMAKE_ADDITIONAL_OPTIONS: -DWITH_PKCS11_URI=ON
script:
- cmake $CMAKE_OPTIONS $CMAKE_ADDITIONAL_OPTIONS .. &&
make -j$(nproc) &&
ctest --output-on-failure
centos8s/openssl_1.1.1/x86_64/fips:
extends: .fips
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$CENTOS8_BUILD
script:
- cmake $CMAKE_OPTIONS $CMAKE_ADDITIONAL_OPTIONS .. &&
make -j$(nproc) &&
OPENSSL_FORCE_FIPS_MODE=1 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_coverage && make docs
coverage: '/^Documentation coverage is \d+.\d+%/'
fedora/ninja:
extends: .fedora
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD
script:
- cmake -G Ninja $CMAKE_OPTIONS ../ && ninja && CTEST_OUTPUT_ON_FAILURE=1 ninja test
fedora/coverage:
extends: .fedora
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD
variables:
CMAKE_ADDITIONAL_OPTIONS: "-DCMAKE_BUILD_TYPE=Debug -DWITH_COVERAGE=ON"
script:
- cmake $CMAKE_OPTIONS $CMAKE_ADDITIONAL_OPTIONS .. &&
make -j$(nproc) &&
make coverage_xml
coverage: /^\s*lines:\s*\d+.\d+\%/
artifacts:
name: ${CI_JOB_NAME}-${CI_COMMIT_REF_NAME}-${CI_COMMIT_SHA}
expire_in: 1 week
reports:
coverage_report:
coverage_format: cobertura
path: obj/coverage_xml.xml
fedora/openssl_3.x/x86_64:
extends: .fedora
fedora/openssl_3.x/x86_64/pkcs11-provider:
variables:
CMAKE_ADDITIONAL_OPTIONS: -DWITH_PKCS11_URI=ON -DWITH_PKCS11_PROVIDER=ON
extends: .fedora
fedora/openssl_3.x/x86_64/minimal:
extends: .fedora
variables:
script:
- cmake $CMAKE_DEFAULT_OPTIONS
-DWITH_EXEC=OFF
-DWITH_SFTP=OFF
-DWITH_SERVER=OFF
-DWITH_ZLIB=OFF
-DWITH_PCAP=OFF
-DUNIT_TESTING=ON
-DCLIENT_TESTING=ON
-DWITH_GEX=OFF .. &&
make -j$(nproc)
.valgrind:
extends: .fedora
stage: analysis
script:
- cmake $CMAKE_OPTIONS $CMAKE_ADDITIONAL_OPTIONS .. &&
make -j$(nproc) &&
make test_memcheck
- cat Testing/Temporary/MemoryChecker.*.log | wc -l | grep "^0$"
# The PKCS#11 support is turned off as it brings dozens of memory issues from
# engine_pkcs11 or openssl itself
fedora/valgrind/openssl:
variables:
CMAKE_ADDITIONAL_OPTIONS: -DWITH_PKCS11_URI=OFF
extends: .valgrind
fedora/valgrind/mbedtls:
variables:
CMAKE_ADDITIONAL_OPTIONS: -DWITH_MBEDTLS=ON
extends: .valgrind
fedora/valgrind/libgcrypt:
variables:
CMAKE_ADDITIONAL_OPTIONS: -DWITH_GCRYPT=ON
extends: .valgrind
# 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_2.x/x86_64:
extends: .fedora
variables:
CMAKE_ADDITIONAL_OPTIONS: "-DWITH_MBEDTLS=ON -DWITH_DEBUG_CRYPTO=ON "
# Unit testing only, no client and pkd testing, because cwrap is not available
# for MinGW
fedora/mingw64:
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$MINGW_BUILD
extends: .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 -E torture_rand
# 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 -E torture_rand
###############################################################################
# Fedora csbuild #
###############################################################################
.csbuild:
stage: analysis
variables:
GIT_DEPTH: "100"
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD
before_script:
- |
# for merge requests
if [[ -n "$CI_MERGE_REQUEST_DIFF_BASE_SHA" ]]; then
export CI_COMMIT_BEFORE_SHA="$CI_MERGE_REQUEST_DIFF_BASE_SHA"
fi
# for branches run
if [[ -z "$CI_COMMIT_BEFORE_SHA" ]]; then
export CI_COMMIT_BEFORE_SHA=$(git rev-parse "${CI_COMMIT_SHA}~20")
fi
# Check if the commit exists in this branch
# This is not the case for a force push
git branch --contains $CI_COMMIT_BEFORE_SHA 2>/dev/null || export CI_COMMIT_BEFORE_SHA=$(git rev-parse "${CI_COMMIT_SHA}~20")
export CI_COMMIT_RANGE="$CI_COMMIT_BEFORE_SHA..$CI_COMMIT_SHA"
tags:
- saas-linux-small-amd64
except:
- tags
only:
- merge_requests
artifacts:
expire_in: 1 week
when: on_failure
paths:
- obj-csbuild/
fedora/csbuild/openssl_3.x:
extends: .csbuild
script:
- csbuild
--build-dir=obj-csbuild
--build-cmd "rm -rf CMakeFiles CMakeCache.txt && cmake -DCMAKE_BUILD_TYPE=Debug -DPICKY_DEVELOPER=ON -DUNIT_TESTING=ON -DCLIENT_TESTING=ON -DSERVER_TESTING=ON -DFUZZ_TESTING=ON @SRCDIR@ && make clean && make -j$(nproc)"
--git-commit-range $CI_COMMIT_RANGE
--color
--print-current --print-fixed
fedora/csbuild/libgcrypt:
extends: .csbuild
script:
- csbuild
--build-dir=obj-csbuild
--build-cmd "rm -rf CMakeFiles CMakeCache.txt && cmake -DCMAKE_BUILD_TYPE=Debug -DPICKY_DEVELOPER=ON -DUNIT_TESTING=ON -DCLIENT_TESTING=ON -DSERVER_TESTING=ON -DFUZZ_TESTING=ON -DWITH_GCRYPT=ON @SRCDIR@ && make clean && make -j$(nproc)"
--git-commit-range $CI_COMMIT_RANGE
--color
--print-current --print-fixed
fedora/csbuild/mbedtls:
extends: .csbuild
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
###############################################################################
# Fedora abidiff #
###############################################################################
fedora/abidiff:
stage: analysis
variables:
GIT_DEPTH: "100"
CMAKE_OPTIONS: $CMAKE_DEFAULT_DEBUG_OPTIONS $CMAKE_BUILD_OPTIONS
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD
before_script:
- uname -a
- cat /etc/os-release
- mount
- df -h
- cat /proc/swaps
- free -h
- |
# for merge requests
if [[ -n "$CI_MERGE_REQUEST_DIFF_BASE_SHA" ]]; then
export CI_COMMIT_BEFORE_SHA="$CI_MERGE_REQUEST_DIFF_BASE_SHA"
fi
# for branches run
if [[ -z "$CI_COMMIT_BEFORE_SHA" ]]; then
export CI_COMMIT_BEFORE_SHA=$(git rev-parse "${CI_COMMIT_SHA}~20")
fi
# Check if the commit exists in this branch
# This is not the case for a force push
git branch --contains $CI_COMMIT_BEFORE_SHA 2>/dev/null || export CI_COMMIT_BEFORE_SHA=$(git rev-parse "${CI_COMMIT_SHA}~20")
- mkdir -p obj-${CI_COMMIT_BEFORE_SHA}
- mkdir -p obj-${CI_COMMIT_SHA}
- export INSTALL_DIR1=$(pwd)/install/${CI_COMMIT_BEFORE_SHA}
- export INSTALL_DIR2=$(pwd)/install/${CI_COMMIT_SHA}
script:
- git checkout ${CI_COMMIT_BEFORE_SHA}
- pushd obj-${CI_COMMIT_BEFORE_SHA}
- cmake ${CMAKE_OPTIONS} -DCMAKE_INSTALL_PREFIX=${INSTALL_DIR1} .. &&
make -j$(nproc) && make -j$(nproc) install
- popd
- ls -l ${INSTALL_DIR1}/lib*/
- git checkout ${CI_COMMIT_SHA}
- pushd obj-${CI_COMMIT_SHA}
- cmake ${CMAKE_OPTIONS} -DCMAKE_INSTALL_PREFIX=${INSTALL_DIR2} .. &&
make -j$(nproc) && make -j$(nproc) install
- popd
- ls -l ${INSTALL_DIR2}/lib*/
- ./.gitlab-ci/checkabi.sh ${INSTALL_DIR1} ${INSTALL_DIR2}
tags:
- saas-linux-small-amd64
except:
- tags
only:
- merge_requests
###############################################################################
# Ubuntu builds #
###############################################################################
ubuntu/openssl_3.0.x/x86_64:
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$UBUNTU_BUILD
extends: .tests
###############################################################################
# Alpine builds #
###############################################################################
alpine/openssl_3.x/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_3.x/x86_64/gcc:
extends: .tumbleweed
tumbleweed/openssl_3.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
-DUNIT_TESTING=ON .. &&
make -j$(nproc)
tumbleweed/openssl_3.x/x86_64/gcc7:
extends: .tumbleweed
variables:
CMAKE_ADDITIONAL_OPTIONS: "-DCMAKE_C_COMPILER=gcc-7 -DCMAKE_CXX_COMPILER=g++-7"
tumbleweed/openssl_3.x/x86/gcc7:
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
-DUNIT_TESTING=ON .. &&
make -j$(nproc) &&
ctest --output-on-failure
tumbleweed/openssl_3.x/x86_64/clang:
extends: .tumbleweed
variables:
CMAKE_ADDITIONAL_OPTIONS: "-DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++"
tumbleweed/mbedtls-3.6.x/x86_64/gcc:
extends: .tumbleweed
variables:
CMAKE_ADDITIONAL_OPTIONS: "-DKRB5_CONFIG=/usr/lib/mit/bin/krb5-config -DWITH_MBEDTLS=ON -DWITH_DEBUG_CRYPTO=ON -DWITH_BLOWFISH_CIPHER=OFF "
tumbleweed/mbedtls-3.6.x/x86_64/clang:
extends: .tumbleweed
variables:
CMAKE_ADDITIONAL_OPTIONS: "-DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DKRB5_CONFIG=/usr/lib/mit/bin/krb5-config -DWITH_MBEDTLS=ON -DWITH_DEBUG_CRYPTO=ON -DWITH_BLOWFISH_CIPHER=OFF "
tumbleweed/static-analysis:
extends: .tests
stage: analysis
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$TUMBLEWEED_BUILD
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/openssl_1.1.1/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 #
###############################################################################
# 2024-05-13: These jobs run out of the stages as they take extremely long and
# usually timeout with the update to Gitlab 17.0
.vs:
stage: test
cache:
key: vcpkg.${CI_JOB_NAME}
paths:
- .vcpkg
variables:
ErrorActionPreference: STOP
script:
- cmake --build .
- ctest --output-on-failure
tags:
- saas-windows-medium-amd64
only:
- merge_requests
- branches
except:
- tags
artifacts:
expire_in: 1 week
when: on_failure
paths:
- obj/
before_script:
- 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:$CENTOS9_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:
- saas-linux-small-amd64
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
###############################################################################
# MacOS #
###############################################################################
.macos:
tags:
- saas-macos-medium-m1
image: macos-14-xcode-15
before_script:
- echo "MacOS runner started"
- brew update
- brew install cmake openssl cmocka doxygen
- mkdir obj && cd obj
only:
- branches@libssh/libssh-mirror
- branches@cryptomilk/libssh-mirror
- branches@jjelen/libssh-mirror
- branches@marco.fortina/libssh-mirror
# TODO add -DFUZZ_TESTING=ON clang cant find _LLVMFuzzerInitialize on arm64
macos-m1:
extends: .macos
variables:
HOMEBREW_NO_AUTO_UPDATE: 1
CMAKE_DEFAULT_OPTIONS: "-DCMAKE_BUILD_TYPE=RelWithDebInfo -DPICKY_DEVELOPER=ON"
CMAKE_BUILD_OPTIONS: "-DWITH_BLOWFISH_CIPHER=ON -DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON -DWITH_DEBUG_CRYPTO=ON -DWITH_DEBUG_PACKET=ON -DWITH_DEBUG_CALLTRACE=ON"
CMAKE_TEST_OPTIONS: "-DUNIT_TESTING=ON"
CMAKE_OPTIONS: $CMAKE_DEFAULT_OPTIONS $CMAKE_BUILD_OPTIONS $CMAKE_TEST_OPTIONS
stage: test
script:
- cmake $CMAKE_OPTIONS .. &&
make -j$(sysctl -n hw.logicalcpu) &&
ctest --output-on-failure
artifacts:
expire_in: 1 week
when: on_failure
paths:
- obj/

View File

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

View File

@@ -1,12 +0,0 @@
#!/bin/sh
# Based on Github Action
# https://github.com/yshui/git-clang-format-lint
diff=$(git-clang-format --diff --commit "$CI_MERGE_REQUEST_DIFF_BASE_SHA")
[ "$diff" = "no modified files to format" ] && exit 0
[ "$diff" = "clang-format did not modify any files" ] && exit 0
printf "You have introduced coding style breakages, suggested changes:\n\n"
echo "${diff}" | colordiff
exit 1

View File

@@ -1,36 +0,0 @@
#!/bin/bash
if [ $# != 1 ]; then
echo "Usage: $0 UPSTREAM_COMMIT_SHA"
exit 1
fi
failed=0
if [ -z "$CI_COMMIT_SHA" ]; then
echo "CI_COMMIT_SHA is not set"
exit 1
fi
CI_COMMIT_RANGE="$1..$CI_COMMIT_SHA"
red='\033[0;31m'
blue='\033[0;34m'
echo -e "${blue}Checking commit range: $CI_COMMIT_RANGE"
echo
echo
for commit in $(git rev-list "$CI_COMMIT_RANGE"); do
git show -s --format=%B "$commit" | grep "^Signed-off-by: " >/dev/null 2>&1
ret=$?
if [ $ret -eq 1 ]; then
echo -e "${red} >>> Missing Signed-off-by trailer in commit $commit"
failed=$(("$failed" + 1))
fi
done
echo
echo
exit $failed

View File

@@ -1,56 +0,0 @@
#!/bin/bash
# Simplified and de-github-ed version of
# https://github.com/ludeeus/action-shellcheck/blob/master/action.yaml
statuscode=0
declare -a filepaths
shebangregex="^#! */[^ ]*/(env *)?[abk]*sh"
set -f # temporarily disable globbing so that globs in inputs aren't expanded
while IFS= read -r -d '' file; do
filepaths+=("$file")
done < <(find . \
-type f \
'(' \
-name '*.bash' \
-o -name '.bashrc' \
-o -name 'bashrc' \
-o -name '.bash_aliases' \
-o -name '.bash_completion' \
-o -name '.bash_login' \
-o -name '.bash_logout' \
-o -name '.bash_profile' \
-o -name 'bash_profile' \
-o -name '*.ksh' \
-o -name 'suid_profile' \
-o -name '*.zsh' \
-o -name '.zlogin' \
-o -name 'zlogin' \
-o -name '.zlogout' \
-o -name 'zlogout' \
-o -name '.zprofile' \
-o -name 'zprofile' \
-o -name '.zsenv' \
-o -name 'zsenv' \
-o -name '.zshrc' \
-o -name 'zshrc' \
-o -name '*.sh' \
-o -path '*/.profile' \
-o -path '*/profile' \
-o -name '*.shlib' \
')' \
-print0)
while IFS= read -r -d '' file; do
head -n1 "$file" | grep -Eqs "$shebangregex" || continue
filepaths+=("$file")
done < <(find . \
-type f ! -name '*.*' -perm /111 \
-print0)
shellcheck "${filepaths[@]}" || statuscode=$?
set +f # re-enable globbing
exit "$statuscode"

View File

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

View File

@@ -1,10 +0,0 @@
#
# GitLeaks Repo Specific Configuration
#
# This allowlist is used to help Red Hat ignore false positives during its code
# scans.
[allowlist]
paths = [
'''tests/*''',
]

View File

@@ -1,7 +1,7 @@
Author(s):
Aris Adamantiadis <aris@0xbadc0de.be> (project initiator)
Andreas Schneider <asn@cryptomilk.org> (developer)
Andreas Schneider <mail@cynapses.org> (developer)
Nick Zitzmann <seiryu (at) comcast (dot) net> (mostly client SFTP stuff)

689
CHANGELOG
View File

@@ -1,689 +0,0 @@
CHANGELOG
=========
version 0.11.0 (released 2024-07-31)
* Deprecations and Removals:
* Dropped support for DSA
* Deprecated Blowfish cipher (will be removed in next release)
* Deprecated SSH_BIND_OPTIONS_{RSA,ECDSA}KEY in favor of generic HOSTKEY
* Removed the usage of deprecated OpenSSL APIs (Note: Minimum supported
OpenSSL version is 1.1.1)
* Disabled preauth compression (zlib) by default
* Support for pkcs#11 engines are deprecated, pkcs11-provider is used instead
* Deprecation of old async SFTP API
* libgcrypt cryptographic backend is deprecated
* Deprecation of knownhosts hashing
* SFTP Improvements:
* Added support for async SFTP IO
* Added support for sftp_limits() and applied capping to SFTP read/write
operations accordingly
* Added sftp_home_directory() API support for sftp extension "home-directory"
* Added sftp_lsetstat() API for lsetstat extensions
* Added sftp_expand_path() to canonicalize path using expand-path@openssh.com
extension
* Implemented stat and realpath in sftpserver
* Added sftp_readlink() API to support hardlink@openssh.com
* New extensible callback based SFTP server
* Introduced the posix-rename@openssh.com extension
* New functions and features:
* Added support for PKCS #11 provider for OpenSSL 3.0
* Added testing for GSSAPI Authentication
* Implemented proxy jump using libssh
* Recategorized loglevels to show fatal errors and alignment with OpenSSH
log levels
* Added ssh_channel_request_pty_size_modes() API to set terminal modes for
PTYs
* Added function to check username syntax
* Added support to check all keys in authorized_keys instead of one in
example server implementation
* Handled hostkey similar to OpenSSH
* Added ssh_session_socket_close() API in order to not close socket passed
through options on error conditions
* Added option SSH_BIND_OPTIONS_IMPORT_KEY_STR to read user-supplied key
string in ssh_bind_options_set()
* Improved log handling around ssh_set_callbacks
* Added ssh_set_error_invalid in ssh_options_set()
* Prevented signature blob to start with 1 bit in libgcrypt
* Added support to unbreak key comparison of Ed25519 keys imported from PEM
or OpenSSH container
* Added support to calculate missing CRT parameters when building RSA key
* Added ssh_pki_export_privkey_base64_format() and
ssh_pki_export_privkey_file_format() to support exporting keys in different
formats (PEM, OpenSSH)
* Added support to compare certificates and handle automatic certificate
authentication
* Added support to make compile-commands generation conditional
* Built fuzzers for normal testing
* Avoided passing other events to callbacks when called recursively
* Added control master and path options
* Refactored channel_rcv_data, check for errors and report more useful errors
* Added support to connect to other host addresses than just the first one
* Terminated the server properly when the MaxAuthTries is reached
* Added support for no-more-sessions@openssh.com request in both client and
server
* Added callback to support forwarded-tcpip requests
* Bumped minimal CMake version to 3.12
* Added support for MBedTLS 3.6.x
* Added support for +,-,^ modifiers in front of algorithm lists in options
* Added callbacks for channel open response, and channel request response
* Replaced chroot() from chroot_wrapper internal library with chroot()
from priv_wrapper package
* Added a placeholder for non-expanded identities
* Improved handling of channel transfer window sizes
version 0.10.6 (released 2023-12-18)
* Fix CVE-2023-6004: Command injection using proxycommand
* Fix CVE-2023-48795: Potential downgrade attack using strict kex
* Fix CVE-2023-6918: Missing checks for return values of MD functions
* Fix ssh_send_issue_banner() for CMD(PowerShell)
* Avoid passing other events to callbacks when poll is called recursively (#202)
* Allow @ in usernames when parsing from URI composes
version 0.10.5 (released 2023-05-04)
* Fix CVE-2023-1667: a NULL dereference during rekeying with algorithm guessing
* Fix CVE-2023-2283: a possible authorization bypass in
pki_verify_data_signature under low-memory conditions.
* Fix several memory leaks in GSSAPI handling code
* Escape braces in ProxyCommand created from ProxyJump options for zsh
compatibility.
* Fix pkg-config path relocation for MinGW
* Improve doxygen documentation
* Fix build with cygwin due to the glob support
* Do not enqueue outgoing packets after sending SSH2_MSG_NEWKEYS
* Add support for SSH_SUPPRESS_DEPRECATED
* Avoid functions declarations without prototype to build with clang 15
* Fix spelling issues
* Avoid expanding KnownHosts, ProxyCommands and IdentityFiles repetitively
* Add support sk-* keys through configuration
* Improve checking for Argp library
* Log information about received extensions
* Correctly handle rekey with delayed compression
* Move the EC keys handling to OpenSSL 3.0 API
* Record peer disconnect message
* Avoid deadlock when write buffering occurs and we call poll recursively to
flush the output buffer
* Disable preauthentication compression by default
* Add CentOS 8 Stream / OpenSSL 1.1.1 to CI
* Add accidentally removed default compile flags
* Solve incorrect parsing of ProxyCommand option
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
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 several 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)
* Added support for ed25519 keys
* Added SHA2 algorithms for HMAC
* Added improved and more secure buffer handling code
* Added callback for auth_none_function
* Added support for ECDSA private key signing
* Added more tests
* Fixed a lot of bugs
* Improved API documentation
version 0.6.5 (released 2015-04-29)
* Fixed CVE-2015-3146
* Fixed port handling in config file
* Fixed the build with libgcrypt
* Fixed SFTP endian issues (rlo #179)
* Fixed uninitilized sig variable (rlo #167)
* Fixed polling issues which could result in a hang
* Fixed handling of EINTR in ssh_poll() (rlo #186)
* Fixed C99 issues with __func__
* Fixed some memory leaks
* Improved macro detection on Windows
version 0.6.4 (released 2014-12-19)
* Fixed CVE-2014-8132.
* Added SHA-2 for session ID signing with ECDSA keys.
* Added support for ECDSA host keys.
* Added support for more ECDSA hostkey algorithms.
* Added ssh_pki_key_ecdsa_name() API.
* Fixed setting the bindfd only after successful listen.
* Fixed issues with user created sockets.
* Fixed several issues in libssh C++ wrapper.
* Fixed several documentation issues.
* Fixed channel exit-signal request.
* Fixed X11 request screen number in messages.
* Fixed several memory leaks.
version 0.6.3 (released 2014-03-04)
* Fixed CVE-2014-0017.
* Fixed memory leak with ecdsa signatures.
version 0.6.2 (released 2014-03-04)
* security: fix for vulnerability CVE-2014-0017
version 0.6.1 (released 2014-02-08)
* Added support for libgcrypt 1.6.
* Added ssh_channel_accept_forward().
* Added known_hosts heuristic during connection (#138).
* Added getters for session cipher names.
* Fixed decrypt of zero length buffer.
* Fixed padding in RSA signature blobs.
* Fixed DSA signature extraction.
* Fixed some memory leaks.
* Fixed read of non-connected socket.
* Fixed thread detection.
version 0.6.0 (released 2014-01-08)
* Added new publicy key API.
* Added new userauth API.
* Added ssh_get_publickey_hash() function.
* Added ssh_get_poll_flags() function.
* Added gssapi-mic userauth.
* Added GSSAPIServerIdentity option.
* Added GSSAPIClientIdentity option.
* Added GSSAPIDelegateCredentials option.
* Added new callback based server API.
* Added Elliptic Curve DSA (ECDSA) support (with OpenSSL).
* Added Elliptic Curve Diffie Hellman (ECDH) support.
* Added Curve25519 for ECDH key exchange.
* Added improved logging system.
* Added SSH-agent forwarding.
* Added key-reexchange.
* Added more unit tests.
* Improved documentation.
* Fixed timeout handling.
version 0.5.5 (released 2013-07-26)
* BUG 103: Fix ProxyCommand parsing.
* Fix setting -D_FORTIFY_SOURCE=2.
* Fix pollset error return if empty.
* Fix NULL pointer checks in channel functions.
* Several bugfixes.
version 0.5.4 (released 2013-01-22)
* CVE-2013-0176 - NULL dereference leads to denial of service
* Fixed several NULL pointer dereferences in SSHv1.
* Fixed a free crash bug in options parsing.
version 0.5.3 (released 2012-11-20)
* CVE-2012-4559 Fixed multiple double free() flaws.
* CVE-2012-4560 Fixed multiple buffer overflow flaws.
* CVE-2012-4561 Fixed multiple invalid free() flaws.
* BUG #84 - Fix bug in sftp_mkdir not returning on error.
* BUG #85 - Fixed a possible channel infinite loop if the connection dropped.
* BUG #88 - Added missing channel request_state and set it to accepted.
* BUG #89 - Reset error state to no error on successful SSHv1 authentication.
* Fixed a possible use after free in ssh_free().
* Fixed multiple possible NULL pointer dereferences.
* Fixed multiple memory leaks in error paths.
* Fixed timeout handling.
* Fixed regression in pre-connected socket setting.
* Handle all unknown global messages.
version 0.5.2 (released 2011-09-17)
* Increased window size x10.
* Fixed SSHv1.
* Fixed bugged lists.
* Fixed use-after-free + inconsistent callbacks call in poll.
* Fixed scp documentation.
* Fixed possible infinite loop in channel_read().
* Fixed handling of short reads of sftp_async_read().
* Fixed handling request service timeout in blocking mode.
* Fixed ssh_auth_list() documentation.
* Fixed incorrect return values in ssh_channel_write().
* Fixed an infinite loop in the termination callback.
* Fixed handling of SSH_AGAIN in channel_open().
* Fixed "status -5 inflating zlib packet"
version 0.5.1 (released 2011-08-09)
* Added checks for NULL pointers in string.c.
* Set the channel max packet size to 32768.
* Don't (de)compress empty buffers.
* Fixed ssh_scp_write so it works when doing recursive copy.
* Fixed another source of endless wait.
* Fixed an endless loop in case of a channel_open error.
* Fixed session timeout handling.
* Fixed ssh_channel_from_local() loop.
* Fixed permissions of scp example when we copy a file.
* Workaround ssh_get_user_home_dir on LDAP users.
* Added pkg-config support for libssh_threads.
* Fixed compilation without server and sftp modes.
* Fix static .lib overwriting on Windows.
version 0.5.0 (released 2011-06-01)
* Added ssh_ prefix to all functions.
* Added complete Windows support.
* Added improved server support.
* Added unit tests for a lot of functions.
* Added asynchronous service request.
* Added a multiplatform ssh_getpass() function.
* Added a tutorial.
* Added a lot of documentation.
* Fixed a lot of bugs.
* Fixed several memory leaks.
version 0.4.8 (released 2011-01-15)
* Fixed memory leaks in session signing.
* Fixed memory leak in ssh_print_hexa.
* Fixed problem with ssh_connect w/ timeout and fd > 1024.
* Fixed some warnings on OS/2.
* Fixed installation path for OS/2.
version 0.4.7 (released 2010-12-28)
* Fixed a possible memory leak in ssh_get_user_home().
* Fixed a memory leak in sftp_xstat.
* Fixed uninitialized fd->revents member.
* Fixed timeout value in ssh_channel_accept().
* Fixed length checks in ssh_analyze_banner().
* Fixed a possible data overread and crash bug.
* Fixed setting max_fd which breaks ssh_select().
* Fixed some pedantic build warnings.
* Fixed a memory leak with session->bindaddr.
version 0.4.6 (released 2010-09-03)
* Added a cleanup function to free the ws2_32 library.
* Fixed build with gcc 3.4.
* Fixed the Windows build on Vista and newer.
* Fixed the usage of WSAPoll() on Windows.
* Fixed "@deprecated" in doxygen
* Fixed some mingw warnings.
* Fixed handling of opened channels.
* Fixed keepalive problem on older openssh servers.
* Fixed testing for big endian on Windows.
* Fixed the Windows preprocessor macros and defines.
version 0.4.5 (released 2010-07-13)
* Added option to bind a client to an ip address.
* Fixed the ssh socket polling function.
* Fixed Windows related bugs in bsd_poll().
* Fixed several build warnings.
version 0.4.4 (released 2010-06-01)
* Fixed a bug in the expand function for escape sequences.
* Fixed a bug in the tilde expand function.
* Fixed a bug in setting the options.
version 0.4.3 (released 2010-05-18)
* Added global/keepalive responses.
* Added runtime detection of WSAPoll().
* Added a select(2) based poll-emulation if poll(2) is not available.
* Added a function to expand an escaped string.
* Added a function to expand the tilde from a path.
* Added a proxycommand support.
* Added ssh_privatekey_type public function
* Added the possibility to define _OPENSSL_DIR and _ZLIB_DIR.
* Fixed sftp_chown.
* Fixed sftp_rename on protocol version 3.
* Fixed a blocking bug in channel_poll.
* Fixed config parsing which has overwritten user specified values.
* Fixed hashed [host]:port format in knownhosts
* Fixed Windows build.
* Fixed doublefree happening after a negotiation error.
* Fixed aes*-ctr with <= OpenSSL 0.9.7b.
* Fixed some documentation.
* Fixed exec example which has broken read usage.
* Fixed broken algorithm choice for server.
* Fixed a typo that we don't export all symbols.
* Removed the unneeded dependency to doxygen.
* Build examples only on the Linux platform.
version 0.4.2 (released 2010-03-15)
* Added owner and group information in sftp attributes.
* Added missing SSH_OPTIONS_FD option.
* Added printout of owner and group in the sftp example.
* Added a prepend function for ssh_list.
* Added send back replies to openssh's keepalives.
* Fixed documentation in scp code
* Fixed longname parsing, this only workings with readdir.
* Fixed and added support for several identity files.
* Fixed sftp_parse_longname() on Windows.
* Fixed a race condition bug in ssh_scp_close()
* Remove config support for SSHv1 Cipher variable.
* Rename ssh_list_add to ssh_list_append.
* Rename ssh_list_get_head to ssh_list_pop_head
version 0.4.1 (released 2010-02-13)
* Added support for aes128-ctr, aes192-ctr and aes256-ctr encryption.
* Added an example for exec.
* Added private key type detection feature in privatekey_from_file().
* Fixed zlib compression fallback.
* Fixed kex bug that client preference should be priority
* Fixed known_hosts file set by the user.
* Fixed a memleak in channel_accept().
* Fixed underflow when leave_function() are unbalanced
* Fixed memory corruption in handle_channel_request_open().
* Fixed closing of a file handle case of errors in privatekey_from_file().
* Fixed ssh_get_user_home_dir() to be thread safe.
* Fixed the doxygen documentation.
version 0.4.0 (released 2009-12-10)
* Added scp support.
* Added support for sending signals (RFC 4254, section 6.9).
* Added MSVC support.
* Added support for ~/.ssh/config.
* Added sftp extension support.
* Added X11 forwarding support for client.
* Added forward listening.
* Added support for openssh extensions (statvfs, fstatvfs).
* Added a cleaned up interface for setting options.
* Added a generic way to handle sockets asynchronously.
* Added logging of the sftp flags used to open a file.
* Added full poll() support and poll-emulation for win32.
* Added missing 64bit functions in sftp.
* Added support for ~/ and SSH_DIR/ in filenames instead of %s/.
* Fixed Fix channel_get_exit_status bug.
* Fixed calltrace logging to make it optional.
* Fixed compilation on Solaris.
* Fixed resolving of ip addresses.
* Fixed libssh compilation without server support.
* Fixed possible memory corruptions (ticket #14).
version 0.3.4 (released 2009-09-14)
* Added ssh_basename and ssh_dirname.
* Added a portable ssh_mkdir function.
* Added a sftp_tell64() function.
* Added missing NULL pointer checks to crypt_set_algorithms_server.
* Fixed ssh_write_knownhost if ~/.ssh doesn't exist.
* Fixed a possible integer overflow in buffer_get_data().
* Fixed possible security bug in packet_decrypt().
* Fixed a possible stack overflow in agent code.
version 0.3.3 (released 2009-08-18)
* Fixed double free pointer crash in dsa_public_to_string.
* Fixed channel_get_exit_status bug.
* Fixed ssh_finalize which didn't clear the flag.
* Fixed memory leak introduced by previous bugfix.
* Fixed channel_poll broken when delayed EOF recvd.
* Fixed stupid "can't parse known host key" bug.
* Fixed possible memory corruption (ticket #14).
version 0.3.2 (released 2009-08-05)
* Added ssh_init() function.
* Added sftp_readlink() function.
* Added sftp_symlink() function.
* Fixed ssh_write_knownhost().
* Fixed compilation on Solaris.
* 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 (released 2009-05-21)
* Added support for ssh-agent authentication.
* Added POSIX like sftp implementation.
* Added error checking to all functions.
* Added const to arguments where it was needed.
* Added a channel_get_exit_status() function.
* Added a channel_read_buffer() function, channel_read() is now
a POSIX like function.
* Added a more generic auth callback function.
* Added printf attribute checking for log and error functions.
* Added runtime function tracer support.
* Added NSIS build support with CPack.
* Added openssh hashed host support.
* Added API documentation for all public functions.
* Added asynchronous SFTP read function.
* Added a ssh_bind_set_fd() function.
* Fixed known_hosts parsing.
* Fixed a lot of build warnings.
* Fixed the Windows build.
* Fixed a lot of memory leaks.
* Fixed a double free corruption in the server support.
* Fixed the "ssh_accept:" bug in server support.
* Fixed important channel bugs.
* Refactored the socket handling.
* Switched to CMake build system.
* Improved performance.
version 0.2 (released 2007-11-29)
* General cleanup
* More comprehensive API
* Up-to-date Doxygen documentation of each public function
* Basic server-based support
* Libgcrypt support (alternative to openssl and its license)
* SSH1 support (disabled by default)
* Added 3des-cbc
* A lot of bugfixes
version 0.11-dev
* Server implementation development.
* Small bug corrected when connecting to sun ssh servers.
* Channel weirdness corrected (writing huge data packets)
* Channel_read_nonblocking added
* Channel bug where stderr wasn't correctly read fixed.
* Added sftp_file_set_nonblocking(), which is nonblocking SFTP IO
* Connect_status callback.
* Priv.h contains the internal functions, libssh.h the public interface
* Options_set_timeout (thx marcelo) really working.
* Tcp tunneling through channel_open_forward.
* Channel_request_exec()
* Channel_request_env()
* Ssh_get_pubkey_hash()
* Ssh_is_server_known()
* Ssh_write_known_host()
* Options_set_ssh_dir
* How could this happen ! there weren't any channel_close !
* Nasty channel_free bug resolved.
* Removed the unsigned long all around the code. use only u8,u32 & u64.
* It now compiles and runs under amd64 !
* Channel_request_pty_size
* Channel_change_pty_size
* Options_copy()
* Ported the doc to an HTML file.
* Small bugfix in packet.c
* Prefixed error constants with SSH_
* Sftp_stat, sftp_lstat, sftp_fstat. thanks Michel Bardiaux for the patch.
* Again channel number mismatch fixed.
* Fixed a bug in ssh_select making the select fail when a signal has been
caught.
* Keyboard-interactive authentication working.
version 0.1 (released 2004-03-05)
* Beginning of sftp subsystem implementation.
* Some cleanup into channels implementation
* Now every channel functions is called by its CHANNEL handler.
* Added channel_poll() and channel_read().
* Changed the client so it uses the new channel_poll and channel_read interface
* Small use-after-free bug with channels resolved
* Changed stupidities in lot of function names.
* Removed a debug output file opened by default.
* Added API.txt, the libssh programmer handbook.
* Various bug fixes from Nick Zitzmann.
* Developed a cryptographic structure for handling protocols.
* An autoconf script which took me half of a day to set up.
* A ssh_select wrapper has been written.
version 0.0.4 (released 2003-10-10)
* Some terminal code (eof handling) added
* Channels bugfix (it still needs some tweaking though)
* Zlib support
* Added a wrapper.c file. The goal is to provide a similar API to every
cryptographic functions. bignums and sha/md5 are wrapped now.
* More work than it first looks.
* Support for other crypto libs planned (lighter libs)
* Fixed stupid select() bug.
* Libssh now compiles and links with openssl 0.9.6
* RSA pubkey authentication code now works !
version 0.0.3 (released 2003-09-15)
* Added install target in makefile
* Some cleanup in headers files and source code
* Change default banner and project name to libssh.
* New file auth.c to support more and more authentication ways
* Bugfix(read offbyone) in send_kex
* A base64 parser. don't read the source, it's awful. pure 0xbadc0de.
* Changed the client filename to "ssh". logic isn't it ?
* Dss publickey authentication ! still need to wait for the rsa one
* Bugfix in packet.c
* New misc.c contains misc functions
version 0.0.2 (released 2003-09-03)
* Initial release.
* Client supports both ssh and dss hostkey verification, but doesn't compare them to openssh's files. (~/.ssh/known_hosts)
* The only supported authentication method is password.
* Compiles on linux and openbsd. freebsd and netbsd should work, too
* Lot of work which hasn't been discussed here.

View File

@@ -1,266 +1,70 @@
cmake_minimum_required(VERSION 3.12.0)
project(libssh C)
# Specify search path for CMake modules to be loaded by include()
# and find_package()
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules")
# Required cmake version
cmake_minimum_required(VERSION 2.6.0)
# Add defaults for cmake
# Those need to be set before the project() call.
include(DefineCMakeDefaults)
include(DefineCompilerFlags)
project(libssh VERSION 0.11.00 LANGUAGES C)
# global needed variable
# global needed variables
set(APPLICATION_NAME ${PROJECT_NAME})
# SOVERSION scheme: CURRENT.AGE.REVISION
# If there was an incompatible interface change:
# Increment CURRENT. Set AGE and REVISION to 0
# If there was a compatible interface change:
# Increment AGE. Set REVISION to 0
# If the source code was changed, but there were no interface changes:
# Increment REVISION.
set(LIBRARY_VERSION "4.10.0")
set(LIBRARY_SOVERSION "4")
set(APPLICATION_VERSION "0.3.3")
set(APPLICATION_VERSION_MAJOR "0")
set(APPLICATION_VERSION_MINOR "3")
set(APPLICATION_VERSION_PATCH "3")
set(LIBRARY_VERSION "3.3.0")
set(LIBRARY_SOVERSION "3")
# where to look first for cmake modules, before ${CMAKE_ROOT}/Modules/ is checked
set(CMAKE_MODULE_PATH
${CMAKE_SOURCE_DIR}/cmake/Modules
)
# add definitions
include(DefinePlatformDefaults)
include(DefineCMakeDefaults)
include(DefineCompilerFlags)
include(DefineInstallationPaths)
include(DefineOptions.cmake)
include(CPackConfig.cmake)
include(GNUInstallDirs)
include(CompilerChecks.cmake)
# disallow in-source build
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.")
# Copy library files to a lib sub-directory
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib")
set(LIBSSSH_PC_REQUIRES_PRIVATE "")
# add macros
include(MacroAddPlugin)
include(MacroCopyFile)
# search for libraries
if (WITH_ZLIB)
find_package(ZLIB REQUIRED)
endif (WITH_ZLIB)
find_package(ZLIB REQUIRED)
if (WITH_GCRYPT)
find_package(GCrypt 1.5.0 REQUIRED)
message(WARNING "libgcrypt cryptographic backend is deprecated and will be removed in future releases.")
elseif(WITH_MBEDTLS)
find_package(MbedTLS REQUIRED)
else()
find_package(OpenSSL 1.1.1 REQUIRED)
endif()
find_package(OpenSSL)
if (UNIT_TESTING)
find_package(CMocka REQUIRED)
endif ()
# Find out if we have threading available
set(CMAKE_THREAD_PREFER_PTHREADS ON)
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads)
if (WITH_GSSAPI)
find_package(GSSAPI)
list(APPEND LIBSSH_PC_REQUIRES_PRIVATE ${GSSAPI_PC_REQUIRES})
endif (WITH_GSSAPI)
if (WITH_NACL)
find_package(NaCl)
if (NOT NACL_FOUND)
set(WITH_NACL OFF)
endif (NOT NACL_FOUND)
endif (WITH_NACL)
# Disable symbol versioning in non UNIX platforms
if (UNIX)
find_package(ABIMap 0.3.1)
else (UNIX)
set(WITH_SYMBOL_VERSIONING OFF)
endif (UNIX)
if (NOT CRYPTO_FOUND)
find_package(GCrypt)
if (NOT GCRYPT_FOUND)
message(FATAL_ERROR "Could not find OpenSSL or GCrypt")
endif (NOT GCRYPT_FOUND)
endif (NOT CRYPTO_FOUND)
# config.h checks
include(ConfigureChecks.cmake)
configure_file(config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config.h)
if (NOT HAVE_ARGP_PARSE)
find_package(Argp)
endif (NOT HAVE_ARGP_PARSE)
# check subdirectories
add_subdirectory(doc)
add_subdirectory(include)
add_subdirectory(src)
add_subdirectory(libssh)
# pkg-config file
if (UNIX OR MINGW)
configure_file(libssh.pc.cmake ${CMAKE_CURRENT_BINARY_DIR}/libssh.pc @ONLY)
install(
FILES
${CMAKE_CURRENT_BINARY_DIR}/libssh.pc
DESTINATION
${CMAKE_INSTALL_LIBDIR}/pkgconfig
COMPONENT
pkgconfig
)
endif (UNIX OR MINGW)
# build samples
include_directories(${CMAKE_SOURCE_DIR}/include)
# CMake config files
include(CMakePackageConfigHelpers)
set(LIBSSH_LIBRARY_NAME ${CMAKE_SHARED_LIBRARY_PREFIX}ssh${CMAKE_SHARED_LIBRARY_SUFFIX})
# libssh-config-version.cmake
write_basic_package_version_file(libssh-config-version.cmake
VERSION ${PROJECT_VERSION}
COMPATIBILITY SameMajorVersion)
install(
FILES
${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config-version.cmake
DESTINATION
${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}
COMPONENT
devel)
if (WITH_EXAMPLES)
add_subdirectory(examples)
endif (WITH_EXAMPLES)
if (UNIT_TESTING)
include(AddCMockaTest)
add_subdirectory(tests)
endif (UNIT_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)
# Coverage
if (WITH_COVERAGE)
ENABLE_LANGUAGE(CXX)
include(CodeCoverage)
setup_target_for_coverage_lcov(
NAME "coverage"
EXECUTABLE make test
DEPENDENCIES ssh tests)
set(GCOVR_ADDITIONAL_ARGS --xml-pretty --exclude-unreachable-branches --print-summary)
setup_target_for_coverage_gcovr_xml(
NAME "coverage_xml"
EXECUTABLE make test
DEPENDENCIES ssh tests)
endif (WITH_COVERAGE)
add_custom_target(dist COMMAND ${CMAKE_MAKE_PROGRAM} package_source DEPENDS ${_SYMBOL_TARGET} VERBATIM)
get_directory_property(hasParent PARENT_DIRECTORY)
if(NOT(hasParent))
# Link compile database for clangd if we are the master project
execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink
"${CMAKE_BINARY_DIR}/compile_commands.json"
"${CMAKE_SOURCE_DIR}/compile_commands.json")
endif()
message(STATUS "********************************************")
message(STATUS "********** ${PROJECT_NAME} build options : **********")
message(STATUS "Build type: ${CMAKE_BUILD_TYPE}")
message(STATUS "Coverage: ${WITH_COVERAGE}")
message(STATUS "zlib support: ${WITH_ZLIB}")
message(STATUS "libgcrypt support: ${WITH_GCRYPT}")
message(STATUS "libmbedTLS support: ${WITH_MBEDTLS}")
message(STATUS "libnacl support: ${WITH_NACL}")
message(STATUS "SFTP support: ${WITH_SFTP}")
message(STATUS "Server support : ${WITH_SERVER}")
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 "Support exec : ${WITH_EXEC}")
message(STATUS "Pcap debugging support : ${WITH_PCAP}")
message(STATUS "Build shared library: ${BUILD_SHARED_LIBS}")
message(STATUS "Unit testing: ${UNIT_TESTING}")
message(STATUS "Client code testing: ${CLIENT_TESTING}")
message(STATUS "Blowfish cipher support: ${HAVE_BLOWFISH}")
message(STATUS "PKCS #11 URI support: ${WITH_PKCS11_URI}")
message(STATUS "With PKCS #11 provider support: ${WITH_PKCS11_PROVIDER}")
set(_SERVER_TESTING OFF)
if (WITH_SERVER)
set(_SERVER_TESTING ${SERVER_TESTING})
endif()
message(STATUS "Server code testing: ${_SERVER_TESTING}")
if (WITH_INTERNAL_DOC)
message(STATUS "Internal documentation generation")
else (WITH_INTERNAL_DOC)
message(STATUS "Public API documentation generation")
endif (WITH_INTERNAL_DOC)
message(STATUS "Benchmarks: ${WITH_BENCHMARKS}")
message(STATUS "Symbol versioning: ${WITH_SYMBOL_VERSIONING}")
message(STATUS "Allow ABI break: ${WITH_ABI_BREAK}")
message(STATUS "Release is final: ${WITH_FINAL}")
if (WITH_HERMETIC_USR)
message(STATUS "User global client config: ${USR_GLOBAL_CLIENT_CONFIG}")
endif ()
message(STATUS "Global client config: ${GLOBAL_CLIENT_CONFIG}")
if (WITH_SERVER)
if (WITH_HERMETIC_USR)
message(STATUS "User global bind config: ${USR_GLOBAL_BIND_CONFIG}")
endif ()
message(STATUS "Global bind config: ${GLOBAL_BIND_CONFIG}")
endif()
message(STATUS "********************************************")
if (UNIX AND NOT WIN32)
if (WITH_SFTP AND WITH_SERVER)
add_executable(samplessh sample.c)
add_executable(samplesshd samplesshd.c)
target_link_libraries(samplessh ${LIBSSH_SHARED_LIBRARY})
target_link_libraries(samplesshd ${LIBSSH_SHARED_LIBRARY})
endif (WITH_SFTP AND WITH_SERVER)
endif (UNIX AND NOT WIN32)

View File

@@ -1,573 +0,0 @@
# How to contribute a patch to libssh
Please checkout the libssh source code using git.
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.
## Continuous Integration
Contributing patches through Merge Request workflow on Gitlab allows us to run
various checks on various configuration as part of Gitlab CI. Unfortunately,
some pipelines are slower (as they involve building dependencies) so the default
timeout of 1 hour needs to be extended at least to 2 hours. This can be done in
project settings of your libssh fork:
https://docs.gitlab.com/ee/ci/pipelines/settings.html#set-a-limit-for-how-long-jobs-can-run
Otherwise you will encounter errors like these, usually on visualstudio builds:
```
ERROR: Job failed: execution took longer than 1h0m0s seconds
The script exceeded the maximum execution time set for the job
```
Note, that the built dependencies are cached so after successful build in your
namespace, the rebuilds should be much faster.
# Coding conventions in the libssh tree
## Quick Start
Coding style guidelines are about reducing the number of unnecessary
reformatting patches and making things easier for developers to work together.
You don't have to like them or even agree with them, but once put in place we
all have to abide by them (or vote to change them). However, coding style
should never outweigh coding itself and so the guidelines described here are
hopefully easy enough to follow as they are very common and supported by tools
and editors.
The basic style for C code, is the Linux kernel coding style (See
Documentation/CodingStyle in the kernel source tree). This closely matches what
libssh developers use already anyways, with a few exceptions as mentioned
below.
But to save you the trouble of reading the Linux kernel style guide, here
are the highlights.
* Maximum Line Width is 80 Characters
The reason is not about people with low-res screens but rather sticking
to 80 columns prevents you from easily nesting more than one level of
if statements or other code blocks.
* Use 4 Spaces to Indent
* No Trailing Whitespace
Clean up your files before committing.
* Follow the K&R guidelines. We won't go through all of them here. Do you
have a copy of "The C Programming Language" anyways right?
## Editor Hints
### Emacs
Add the follow to your $HOME/.emacs file:
(add-hook 'c-mode-hook
(lambda ()
(c-set-style "linux")
(c-toggle-auto-state)))
## Neovim/VIM
For the basic vi editor included with all variants of \*nix, add the
following to ~/.config/nvim/init.rc or ~/.vimrc:
set ts=4 sw=4 et cindent
You can use the Vim gitmodline plugin to store this in the git config:
https://git.cryptomilk.org/projects/vim-gitmodeline.git/
For Vim, the following settings in $HOME/.vimrc will also deal with
displaying trailing whitespace:
if has("syntax") && (&t_Co > 2 || has("gui_running"))
syntax on
function! ActivateInvisibleCharIndicator()
syntax match TrailingSpace "[ \t]\+$" display containedin=ALL
highlight TrailingSpace ctermbg=Red
endf
autocmd BufNewFile,BufRead * call ActivateInvisibleCharIndicator()
endif
" Show tabs, trailing whitespace, and continued lines visually
set list listchars=tab:»·,trail:·,extends:…
" highlight overly long lines same as TODOs.
set textwidth=80
autocmd BufNewFile,BufRead *.c,*.h exec 'match Todo /\%>' . &textwidth . 'v.\+/'
## FAQ & Statement Reference
### Comments
Comments should always use the standard C syntax. C++ style comments are not
currently allowed.
The lines before a comment should be empty. If the comment directly belongs to
the following code, there should be no empty line after the comment, except if
the comment contains a summary of multiple following code blocks.
This is good:
...
int i;
/*
* This is a multi line comment,
* which explains the logical steps we have to do:
*
* 1. We need to set i=5, because...
* 2. We need to call complex_fn1
*/
/* This is a one line comment about i = 5. */
i = 5;
/*
* This is a multi line comment,
* explaining the call to complex_fn1()
*/
ret = complex_fn1();
if (ret != 0) {
...
/**
* @brief This is a doxygen comment.
*
* This is a more detailed explanation of
* this simple function.
*
* @param[in] param1 The parameter value of the function.
*
* @param[out] result1 The result value of the function.
*
* @return 0 on success and -1 on error.
*/
int example(int param1, int *result1);
This is bad:
...
int i;
/*
* This is a multi line comment,
* which explains the logical steps we have to do:
*
* 1. We need to set i=5, because...
* 2. We need to call complex_fn1
*/
/* This is a one line comment about i = 5. */
i = 5;
/*
* This is a multi line comment,
* explaining the call to complex_fn1()
*/
ret = complex_fn1();
if (ret != 0) {
...
/*This is a one line comment.*/
/* This is a multi line comment,
with some more words...*/
/*
* This is a multi line comment,
* with some more words...*/
### Indentation & Whitespace & 80 columns
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
parameter on the previous line. For example,
var1 = foo(arg1,
arg2,
arg3);
The previous example is intended to illustrate alignment of function
parameters across lines and not as encourage for gratuitous line
splitting. Never split a line before columns 70 - 79 unless you
have a really good reason. Be smart about formatting.
### If, switch, & Code blocks
Always follow an 'if' keyword with a space but don't include additional
spaces following or preceding the parentheses in the conditional.
This is good:
if (x == 1)
This is bad:
if ( x == 1 )
or
if (x==1)
Yes we have a lot of code that uses the second and third form and we are trying
to clean it up without being overly intrusive.
Note that this is a rule about parentheses following keywords and not
functions. Don't insert a space between the name and left parentheses when
invoking functions.
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.
You should always include braces, even if the block only contains one
statement. **NOTE**: Functions are different and the beginning left brace should
be located in the first column on the next line.
If the beginning statement has to be broken across lines due to length, the
beginning brace should be on a line of its own.
The exception to the ending rule is when the closing brace is followed by
another language keyword such as else or the closing while in a do..while loop.
Good examples:
if (x == 1) {
printf("good\n");
}
for (x = 1; x < 10; x++) {
print("%d\n", x);
}
for (really_really_really_really_long_var_name = 0;
really_really_really_really_long_var_name < 10;
really_really_really_really_long_var_name++)
{
print("%d\n", really_really_really_really_long_var_name);
}
do {
printf("also good\n");
} while (1);
Bad examples:
while (1)
{
print("I'm in a loop!\n"); }
for (x=1;
x<10;
x++)
{
print("no good\n");
}
if (i < 10)
print("I should be in braces.\n");
### Goto
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
the single exit point from a function. But in no libssh world what so ever is a
goto outside of a function or block of code a good idea.
Good Examples:
int function foo(int y)
{
int *z = NULL;
int rc = 0;
if (y < 10) {
z = malloc(sizeof(int)*y);
if (z == NULL) {
rc = 1;
goto done;
}
}
print("Allocated %d elements.\n", y);
done:
if (z != NULL) {
free(z);
}
return rc;
}
### Initialize pointers
All pointer variables **MUST** be initialized to `NULL`. History has
demonstrated that uninitialized pointer variables have lead to various
bugs and security issues.
Pointers **MUST** be initialized even if the assignment directly follows
the declaration, like pointer2 in the example below, because the
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.
### Make use of helper variables
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"
command within gdb.
Good Example:
char *name;
name = get_some_name();
if (name == NULL) {
...
}
rc = some_function_my_name(name);
...
Bad Example:
rc = some_function_my_name(get_some_name());
...
Please try to avoid passing function return values to if- or while-conditions.
The reason for this is better handling of code under a debugger.
Good example:
x = malloc(sizeof(short) * 10);
if (x == NULL) {
fprintf(stderr, "Unable to alloc memory!\n");
}
Bad example:
if ((x = malloc(sizeof(short)*10)) == NULL ) {
fprintf(stderr, "Unable to alloc memory!\n");
}
There are exceptions to this rule. One example is walking a data structure in
an iterator style:
while ((opt = poptGetNextOpt(pc)) != -1) {
... do something with opt ...
}
But in general, please try to avoid this pattern.
### Control-Flow changing macros
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
that never change control flow. Please do not introduce them.
### Switch/case indentation
The `case` should not be indented to avoid wasting too much horizontal space.
When the case block contains local variables that need to be wrapped in braces,
they should not be indented again either.
Good example:
switch (x) {
case 0:
do_stuff();
break;
case 1: {
int y;
do_stuff();
break;
}
default:
do_other_stuff();
break;
}
Bad example:
switch (x) {
case 0:
do_stuff();
break;
case 1:
{
int y;
do_stuff();
break;
}
default:
do_other_stuff();
break;
}
## ABI Versioning and Symbol Management
To maintain [ABI](https://en.wikipedia.org/wiki/Application_binary_interface) stability
and ensure backward compatibility, libssh uses **symbol versioning** to track and manage
exported functions and variables. This allows libssh to introduce new symbols or modify
existing functions in an ABI-compatible way.
When introducing a new symbol:
1. Use the `LIBSSH_API` macro to mark the symbol as part of the public API.
2. If you have [abimap](https://github.com/ansasaki/abimap) installed, the new symbols are
automatically generated in the `src/libssh_dev.map` file in the **build** directory and used automatically for building the updated library. But, depending on the version of `abimap` under use, you may face linker errors like: `unable to find version dependency LIBSSH_4_9_0`. In this case, you need to manually replace the existing `src/libssh.map` file with the generated `libssh_dev.map` file to update the symbol versioning.
3. If you do not have abimap installed, the modified/added symbols must manually be added to the
`src/libssh.map` file. The symbols must be added in the following format (assuming that 4_10_0 is the latest released version):
```
LIBSSH_AFTER_4_10_0
{
global:
new_function;
new_variable;
} LIBSSH_4_10_0;
```
4. After following either of the above steps, the library can be successfully built and
tested without any linker errors.
5. When submitting the patch, make sure that any new symbols have been added to `libssh.map` as described in step 3, so that the new additions may not be excluded from the next release due to human error.
Also, to maintain ABI compatibility, existing symbols must not be removed. Instead, they can
be marked as deprecated using the `LIBSSH_DEPRECATED` macro. This allows the symbol to be
removed in a future release without breaking the ABI.
Have fun and happy libssh hacking!
The libssh Team

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
DAMAGES.
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.
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.
END OF TERMS AND CONDITIONS

View File

@@ -1,34 +1,39 @@
### GENERAL SETTINGS
set(CPACK_PACKAGE_NAME ${PROJECT_NAME})
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "The SSH Library")
set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/README")
include(InstallRequiredSystemLibraries)
# For help take a look at:
# http://www.cmake.org/Wiki/CMake:CPackConfiguration
### 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_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
set(CPACK_SOURCE_GENERATOR "TXZ")
set(CPACK_SOURCE_IGNORE_FILES "~$;[.]swp$;/[.]bare/;/[.]git/;/[.]git;/[.]clangd/;/[.]cache/;.gitignore;/build*;/obj*;tags;cscope.*;compile_commands.json;.*\.patch")
### versions
set(CPACK_PACKAGE_VERSION_MAJOR "0")
set(CPACK_PACKAGE_VERSION_MINOR "3")
set(CPACK_PACKAGE_VERSION_PATCH "3")
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/;tags;cscope.*")
set(CPACK_SOURCE_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}")
### NSIS INSTALLER
if (WIN32)
set(CPACK_GENERATOR "ZIP")
### nsis generator
find_package(NSIS)
if (NSIS_MAKE)
set(CPACK_GENERATOR "${CPACK_GENERATOR};NSIS")
set(CPACK_NSIS_DISPLAY_NAME "The SSH Library")
set(CPACK_NSIS_COMPRESSOR "/SOLID zlib")
set(CPACK_NSIS_MENU_LINKS "https://www.libssh.org/" "libssh homepage")
endif (NSIS_MAKE)
endif (WIN32)
### nsis generator
set(CPACK_GENERATOR "NSIS")
set(CPACK_PACKAGE_INSTALL_DIRECTORY "libssh")
set(CPACK_NSIS_DISPLAY_NAME "The SSH Library")
set(CPACK_NSIS_COMPRESSOR "/SOLID zlib")
set(CPACK_NSIS_MENU_LINKS "http://www.libssh.org/" "libssh homepage")
set(CPACK_PACKAGE_FILE_NAME ${APPLICATION_NAME}-${CPACK_PACKAGE_VERSION})
set(CPACK_COMPONENT_LIBRARIES_DISPLAY_NAME "Libraries")
@@ -38,6 +43,7 @@ set(CPACK_COMPONENT_LIBRARIES_DESCRIPTION
set(CPACK_COMPONENT_HEADERS_DESCRIPTION
"C/C++ header files for use with libssh")
set(CPACK_COMPONENT_HEADERS_DEPENDS libraries)
#set(CPACK_COMPONENT_APPLICATIONS_GROUP "Runtime")
set(CPACK_COMPONENT_LIBRARIES_GROUP "Development")
set(CPACK_COMPONENT_HEADERS_GROUP "Development")

View File

@@ -1,9 +0,0 @@
set(UPDATE_TYPE "true")
set(CTEST_PROJECT_NAME "libssh")
set(CTEST_NIGHTLY_START_TIME "01:00:00 UTC")
set(CTEST_DROP_METHOD "https")
set(CTEST_DROP_SITE "test.libssh.org")
set(CTEST_DROP_LOCATION "/submit.php?project=libssh")
set(CTEST_DROP_SITE_CDASH TRUE)

144
ChangeLog Normal file
View File

@@ -0,0 +1,144 @@
ChangeLog
==========
version 0.3.3 (released 2009-08-18)
* Fixed double free pointer crash in dsa_public_to_string.
* Fixed channel_get_exit_status bug.
* Fixed ssh_finalize which didn't clear the flag.
* Fixed memory leak introduced by previous bugfix.
* Fixed channel_poll broken when delayed EOF recvd.
* Fixed stupid "can't parse known host key" bug.
* Fixed possible memory corruption (ticket #14).
version 0.3.2 (released 2009-08-05)
* Added ssh_init() function.
* Added sftp_readlink() function.
* Added sftp_symlink() function.
* Fixed ssh_write_knownhost().
* Fixed compilation on Solaris.
* 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 (released 2009-05-21)
* Added support for ssh-agent authentication.
* Added POSIX like sftp implementation.
* Added error checking to all functions.
* Added const to arguments where it was needed.
* Added a channel_get_exit_status() function.
* Added a channel_read_buffer() function, channel_read() is now
a POSIX like function.
* Added a more generic auth callback function.
* Added printf attribute checking for log and error functions.
* Added runtime function tracer support.
* Added NSIS build support with CPack.
* Added openssh hashed host support.
* Added API documentation for all public functions.
* Added asynchronous SFTP read function.
* Added a ssh_bind_set_fd() function.
* Fixed known_hosts parsing.
* Fixed a lot of build warnings.
* Fixed the Windows build.
* Fixed a lot of memory leaks.
* Fixed a double free corruption in the server support.
* Fixed the "ssh_accept:" bug in server support.
* Fixed important channel bugs.
* Refactored the socket handling.
* Switched to CMake build system.
* Improved performance.
version 0.2 (released 2007-11-29)
* General cleanup
* More comprehensive API
* Up-to-date Doxygen documentation of each public function
* Basic server-based support
* Libgcrypt support (alternative to openssl and its license)
* SSH1 support (disabled by default)
* Added 3des-cbc
* A lot of bugfixes
version 0.11-dev
* Server implementation development.
* Small bug corrected when connecting to sun ssh servers.
* Channel wierdness corrected (writing huge data packets)
* Channel_read_nonblocking added
* Channel bug where stderr wasn't correctly read fixed.
* Added sftp_file_set_nonblocking(), which is nonblocking SFTP IO
* Connect_status callback.
* Priv.h contains the internal functions, libssh.h the public interface
* Options_set_timeout (thx marcelo) really working.
* Tcp tunneling through channel_open_forward.
* Channel_request_exec()
* Channel_request_env()
* Ssh_get_pubkey_hash()
* Ssh_is_server_known()
* Ssh_write_known_host()
* Options_set_ssh_dir
* How could this happen ! there weren't any channel_close !
* Nasty channel_free bug resolved.
* Removed the unsigned long all around the code. use only u8,u32 & u64.
* It now compiles and runs under amd64 !
* Channel_request_pty_size
* Channel_change_pty_size
* Options_copy()
* Ported the doc to an HTML file.
* Small bugfix in packet.c
* Prefixed error constants with SSH_
* Sftp_stat, sftp_lstat, sftp_fstat. thanks Michel Bardiaux for the patch.
* Again channel number mismatch fixed.
* Fixed a bug in ssh_select making the select fail when a signal has been
caught.
* Keyboard-interactive authentication working.
version 0.1 (released 2004-03-05)
* Begining of sftp subsystem implementation.
* Some cleanup into channels implementation
* Now every channel functions is called by its CHANNEL handler.
* Added channel_poll() and channel_read().
* Changed the client so it uses the new channel_poll and channel_read interface
* Small use-after-free bug with channels resolved
* Changed stupidities in lot of function names.
* Removed a debug output file opened by default.
* Added API.txt, the libssh programmer handbook.
* Various bug fixes from Nick Zitzmann.
* Developed a cryptographic structure for handling protocols.
* An autoconf script which took me half of a day to set up.
* A ssh_select wrapper has been written.
version 0.0.4 (released 2003-10-10)
* Some terminal code (eof handling) added
* Channels bugfix (it still needs some tweaking though)
* Zlib support
* Added a wrapper.c file. The goal is to provide a similar API to every
cryptographic functions. bignums and sha/md5 are wrapped now.
* More work than it first looks.
* Support for other crypto libs planed (lighter libs)
* Fixed stupid select() bug.
* Libssh now compiles and links with openssl 0.9.6
* RSA pubkey authentication code now works !
version 0.0.3 (released 2003-09-15)
* Added install target in makefile
* Some cleanup in headers files and source code
* Change default banner and project name to libssh.
* New file auth.c to support more and more authentication ways
* Bugfix(read offbyone) in send_kex
* A base64 parser. don't read the source, it's awful. pure 0xbadc0de.
* Changed the client filename to "ssh". logic isn't it ?
* Dss publickey authentication ! still need to wait for the rsa one
* Bugfix in packet.c
* New misc.c contains misc functions
version 0.0.2 (released 2003-09-03)
* Initial release.
* Client supports both ssh and dss hostkey verification, but doesn't compare them to openssh's files. (~/.ssh/known_hosts)
* The only supported authentication method is password.
* Compiles on linux and openbsd. freebsd and netbsd should work, too
* Lot of work which hasn't been discussed here.

View File

@@ -1,133 +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("-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)
add_c_compiler_flag("-Wold-style-definition" SUPPORTED_COMPILER_FLAGS)
add_c_compiler_flag("-Werror=old-style-definition" SUPPORTED_COMPILER_FLAGS)
add_c_compiler_flag("-Wimplicit-int" SUPPORTED_COMPILER_FLAGS)
add_c_compiler_flag("-Werror=implicit-int" SUPPORTED_COMPILER_FLAGS)
add_c_compiler_flag("-Wint-conversion" SUPPORTED_COMPILER_FLAGS)
add_c_compiler_flag("-Werror=int-conversion" SUPPORTED_COMPILER_FLAGS)
add_c_compiler_flag("-Werror=unused-variable" 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 separate 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 separate libssp
if (SOLARIS)
list(APPEND SUPPORTED_LINKER_FLAGS "-fstack-protector")
endif()
endif()
endif (WITH_STACK_PROTECTOR_STRONG)
if (NOT WINDOWS AND NOT CYGWIN)
# apple m* chips do not support this option
if (NOT ${CMAKE_SYSTEM_PROCESSOR} STREQUAL arm64)
check_c_compiler_flag_ssp("-fstack-clash-protection" WITH_STACK_CLASH_PROTECTION)
if (WITH_STACK_CLASH_PROTECTION)
list(APPEND SUPPORTED_COMPILER_FLAGS "-fstack-clash-protection")
endif()
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,476 +1,56 @@
include(CheckIncludeFile)
include(CheckIncludeFiles)
include(CheckSymbolExists)
include(CheckFunctionExists)
include(CheckLibraryExists)
include(CheckTypeSize)
include(CheckStructHasMember)
include(TestBigEndian)
include(CheckCXXSourceCompiles)
set(PACKAGE ${PROJECT_NAME})
set(VERSION ${PROJECT_VERSION})
set(SYSCONFDIR ${CMAKE_INSTALL_SYSCONFDIR})
set(PACKAGE ${APPLICATION_NAME})
set(VERSION ${APPLICATION_VERSION})
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(SOURCEDIR ${CMAKE_SOURCE_DIR})
function(COMPILER_DUMPVERSION _OUTPUT_VERSION)
# Remove whitespaces from the argument.
# This is needed for CC="ccache gcc" cmake ..
string(REPLACE " " "" _C_COMPILER_ARG "${CMAKE_C_COMPILER_ARG1}")
execute_process(
COMMAND
${CMAKE_C_COMPILER} ${_C_COMPILER_ARG} -dumpversion
OUTPUT_VARIABLE _COMPILER_VERSION
)
string(REGEX REPLACE "([0-9])\\.([0-9])(\\.[0-9])?" "\\1\\2"
_COMPILER_VERSION "${_COMPILER_VERSION}")
set(${_OUTPUT_VERSION} ${_COMPILER_VERSION} PARENT_SCOPE)
endfunction()
if(CMAKE_COMPILER_IS_GNUCC AND NOT MINGW AND NOT OS2)
compiler_dumpversion(GNUCC_VERSION)
if (NOT GNUCC_VERSION EQUAL 34)
set(CMAKE_REQUIRED_FLAGS "-fvisibility=hidden")
check_c_source_compiles(
"void __attribute__((visibility(\"default\"))) test() {}
int main(void){ return 0; }
" WITH_VISIBILITY_HIDDEN)
unset(CMAKE_REQUIRED_FLAGS)
endif (NOT GNUCC_VERSION EQUAL 34)
endif(CMAKE_COMPILER_IS_GNUCC AND NOT MINGW AND NOT OS2)
# HEADER FILES
check_function_exists(argp_parse HAVE_ARGP_PARSE)
set(CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES} ${ARGP_INCLUDE_DIR})
check_include_file(argp.h HAVE_ARGP_H)
unset(CMAKE_REQUIRED_INCLUDES)
check_include_file(pty.h HAVE_PTY_H)
check_include_file(utmp.h HAVE_UTMP_H)
check_include_file(termios.h HAVE_TERMIOS_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(libutil.h HAVE_LIBUTIL_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(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)
check_include_file(ifaddrs.h HAVE_IFADDRS_H)
check_include_file(terminos.h HAVE_TERMIOS_H)
if (WIN32)
check_include_file(io.h HAVE_IO_H)
check_include_files("winsock2.h;ws2tcpip.h;wspiapi.h" 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")
endif (NOT HAVE_WSPIAPI_H)
check_include_files("winsock2.h;ws2tcpip.h" HAVE_WS2TCPIP_H)
endif (WIN32)
if (OPENSSL_FOUND)
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
set(CMAKE_REQUIRED_LIBRARIES OpenSSL::Crypto)
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()
check_include_file(openssl/aes.h HAVE_OPENSSL_AES_H)
if (NOT HAVE_OPENSSL_AES_H)
message(FATAL_ERROR "Could not detect openssl/aes.h")
endif()
if (WITH_BLOWFISH_CIPHER)
check_include_file(openssl/blowfish.h HAVE_BLOWFISH)
endif()
check_include_file(openssl/ecdh.h HAVE_OPENSSL_ECDH_H)
check_include_file(openssl/ec.h HAVE_OPENSSL_EC_H)
check_include_file(openssl/ecdsa.h HAVE_OPENSSL_ECDSA_H)
check_function_exists(EVP_KDF_CTX_new_id HAVE_OPENSSL_EVP_KDF_CTX_NEW_ID)
check_function_exists(EVP_KDF_CTX_new HAVE_OPENSSL_EVP_KDF_CTX_NEW)
check_function_exists(FIPS_mode HAVE_OPENSSL_FIPS_MODE)
check_function_exists(RAND_priv_bytes HAVE_OPENSSL_RAND_PRIV_BYTES)
check_function_exists(EVP_chacha20 HAVE_OPENSSL_EVP_CHACHA20)
unset(CMAKE_REQUIRED_INCLUDES)
unset(CMAKE_REQUIRED_LIBRARIES)
endif()
if (CMAKE_HAVE_PTHREAD_H)
set(HAVE_PTHREAD_H 1)
endif (CMAKE_HAVE_PTHREAD_H)
if (NOT WITH_GCRYPT AND NOT WITH_MBEDTLS)
if (HAVE_OPENSSL_EC_H AND HAVE_OPENSSL_ECDSA_H)
set(HAVE_OPENSSL_ECC 1)
endif (HAVE_OPENSSL_EC_H AND HAVE_OPENSSL_ECDSA_H)
if (HAVE_OPENSSL_ECC)
set(HAVE_ECC 1)
endif (HAVE_OPENSSL_ECC)
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 ()
check_include_file(openssl/aes.h HAVE_OPENSSL_AES_H)
check_include_file(openssl/blowfish.h HAVE_OPENSSL_BLOWFISH_H)
check_include_file(openssl/des.h HAVE_OPENSSL_DES_H)
# FUNCTIONS
check_function_exists(isblank HAVE_ISBLANK)
check_function_exists(strncpy HAVE_STRNCPY)
check_function_exists(strndup HAVE_STRNDUP)
check_function_exists(strtoull HAVE_STRTOULL)
check_function_exists(explicit_bzero HAVE_EXPLICIT_BZERO)
check_function_exists(memset_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)
check_function_exists(cfmakeraw HAVE_CFMAKERAW)
if (WIN32)
check_symbol_exists(vsnprintf "stdio.h" HAVE_VSNPRINTF)
check_symbol_exists(snprintf "stdio.h" HAVE_SNPRINTF)
check_symbol_exists(_vsnprintf_s "stdio.h" HAVE__VSNPRINTF_S)
check_symbol_exists(_vsnprintf "stdio.h" HAVE__VSNPRINTF)
check_symbol_exists(_snprintf "stdio.h" HAVE__SNPRINTF)
check_symbol_exists(_snprintf_s "stdio.h" HAVE__SNPRINTF_S)
if (HAVE_WSPIAPI_H OR HAVE_WS2TCPIP_H)
check_symbol_exists(ntohll winsock2.h HAVE_NTOHLL)
check_symbol_exists(htonll winsock2.h HAVE_HTONLL)
set(CMAKE_REQUIRED_LIBRARIES ws2_32)
check_symbol_exists(select "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
check_symbol_exists(getaddrinfo "winsock2.h;ws2tcpip.h" HAVE_GETADDRINFO)
unset(CMAKE_REQUIRED_LIBRARIES)
endif (HAVE_WSPIAPI_H OR HAVE_WS2TCPIP_H)
check_function_exists(_strtoui64 HAVE__STRTOUI64)
set(HAVE_SELECT TRUE)
check_symbol_exists(SecureZeroMemory "windows.h" HAVE_SECURE_ZERO_MEMORY)
set(HAVE_GETADDRINFO TRUE)
set(HAVE_GETHOSTBYNAME TRUE)
set(HAVE_SELECT TRUE)
else (WIN32)
check_function_exists(poll HAVE_POLL)
check_function_exists(select HAVE_SELECT)
check_function_exists(getaddrinfo HAVE_GETADDRINFO)
check_symbol_exists(ntohll arpa/inet.h HAVE_NTOHLL)
check_symbol_exists(htonll arpa/inet.h HAVE_HTONLL)
check_function_exists(getaddrinfo HAVE_GETADDRINFO)
check_function_exists(gethostbyname HAVE_GETHOSTBYNAME)
check_function_exists(poll HAVE_POLL)
check_function_exists(select HAVE_SELECT)
endif (WIN32)
if (UNIX)
if (NOT LINUX)
# libsocket (Solaris)
check_library_exists(socket getaddrinfo "" HAVE_LIBSOCKET)
if (HAVE_LIBSOCKET)
set(HAVE_GETADDRINFO TRUE)
set(_REQUIRED_LIBRARIES ${_REQUIRED_LIBRARIES} socket)
endif (HAVE_LIBSOCKET)
# libnsl/inet_pton (Solaris)
check_library_exists(nsl inet_pton "" HAVE_LIBNSL)
if (HAVE_LIBNSL)
set(_REQUIRED_LIBRARIES ${_REQUIRED_LIBRARIES} nsl)
endif (HAVE_LIBNSL)
# librt
check_library_exists(rt nanosleep "" HAVE_LIBRT)
endif (NOT LINUX)
check_library_exists(rt clock_gettime "" HAVE_CLOCK_GETTIME)
if (HAVE_LIBRT OR HAVE_CLOCK_GETTIME)
set(_REQUIRED_LIBRARIES ${_REQUIRED_LIBRARIES} rt)
endif (HAVE_LIBRT OR HAVE_CLOCK_GETTIME)
check_library_exists(util forkpty "" HAVE_LIBUTIL)
check_function_exists(cfmakeraw HAVE_CFMAKERAW)
check_function_exists(__strtoull HAVE___STRTOULL)
endif (UNIX)
set(LIBSSH_REQUIRED_LIBRARIES ${_REQUIRED_LIBRARIES} CACHE INTERNAL "libssh required system libraries")
# LIBRARIES
if (OPENSSL_FOUND)
if (CRYPTO_FOUND)
set(HAVE_LIBCRYPTO 1)
endif (OPENSSL_FOUND)
endif (CRYPTO_FOUND)
if (GCRYPT_FOUND)
set(HAVE_LIBGCRYPT 1)
if (GCRYPT_VERSION VERSION_GREATER "1.4.6")
set(HAVE_GCRYPT_ECC 1)
set(HAVE_ECC 1)
endif (GCRYPT_VERSION VERSION_GREATER "1.4.6")
if (NOT GCRYPT_VERSION VERSION_LESS "1.7.0")
set(HAVE_GCRYPT_CHACHA_POLY 1)
set(HAVE_GCRYPT_CURVE25519 1)
endif (NOT GCRYPT_VERSION VERSION_LESS "1.7.0")
set(HAVE_LIBGCRYPT 1)
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)
if (MBEDTLS_VERSION VERSION_LESS "3.0.0")
check_symbol_exists(MBEDTLS_ECP_DP_CURVE25519_ENABLED "config.h" HAVE_MBEDTLS_CURVE25519)
else()
check_symbol_exists(MBEDTLS_ECP_DP_CURVE25519_ENABLED "mbedtls_config.h" HAVE_MBEDTLS_CURVE25519)
endif()
if (WITH_BLOWFISH_CIPHER)
check_include_file(blowfish.h HAVE_BLOWFISH)
endif()
unset(CMAKE_REQUIRED_INCLUDES)
endif (MBEDTLS_FOUND)
if (CMAKE_USE_PTHREADS_INIT)
set(HAVE_PTHREAD 1)
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 ()
if (Z_LIBRARY)
set(HAVE_LIBZ 1)
endif (Z_LIBRARY)
# OPTIONS
check_c_source_compiles("
__thread int tls;
int main(void) {
return 0;
}" HAVE_GCC_THREAD_LOCAL_STORAGE)
check_c_source_compiles("
__declspec(thread) int tls;
int main(void) {
return 0;
}" HAVE_MSC_THREAD_LOCAL_STORAGE)
###########################################################
# For detecting attributes we need to treat warnings as
# errors
if (UNIX OR MINGW)
# Get warnings for attributes
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("
#include <string.h>
int main(void)
{
char buf[] = \"This is some content\";
memset(buf, '\\\\0', sizeof(buf)); __asm__ volatile(\"\" : : \"g\"(&buf) : \"memory\");
return 0;
}" HAVE_GCC_VOLATILE_MEMORY_PROTECTION)
check_c_source_compiles("
#include <stdio.h>
int main(void) {
printf(\"%s\", __func__);
return 0;
}" HAVE_COMPILER__FUNC__)
check_c_source_compiles("
#include <stdio.h>
int main(void) {
printf(\"%s\", __FUNCTION__);
return 0;
}" 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)
set(DEBUG_CRYPTO 1)
endif (WITH_DEBUG_CRYPTO)
if (WITH_DEBUG_PACKET)
set(DEBUG_PACKET 1)
endif (WITH_DEBUG_PACKET)
if (WITH_DEBUG_CALLTRACE)
set(DEBUG_CALLTRACE 1)
endif (WITH_DEBUG_CALLTRACE)
if (WITH_GSSAPI AND NOT GSSAPI_FOUND)
set(WITH_GSSAPI 0)
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)
elseif (WITH_MBEDTLS)
message(FATAL_ERROR "PKCS #11 is not supported for mbedcrypto")
set(WITH_PKCS11_URI 0)
elseif (OPENSSL_FOUND AND OPENSSL_VERSION VERSION_GREATER_EQUAL "3.0.0")
find_library(PKCS11_PROVIDER
NAMES
pkcs11.so
PATH_SUFFIXES
ossl-modules
)
if (NOT PKCS11_PROVIDER)
set(WITH_PKCS11_PROVIDER 0)
message(WARNING "Could not find pkcs11 provider! Falling back to engines")
message(WARNING "The support for engines is deprecated in OpenSSL and will be removed from libssh in the future releases.")
endif (NOT PKCS11_PROVIDER)
endif ()
endif()
# ENDIAN
if (NOT WIN32)
test_big_endian(WORDS_BIGENDIAN)
endif (NOT WIN32)

View File

@@ -1,74 +1,6 @@
option(WITH_GSSAPI "Build with GSSAPI support" ON)
option(WITH_ZLIB "Build with ZLIB support" ON)
option(WITH_LIBZ "Build with ZLIB support" ON)
option(WITH_SSH1 "Build with SSH1 support" OFF)
option(WITH_SFTP "Build with SFTP support" ON)
option(WITH_SERVER "Build with SSH server support" ON)
option(WITH_DEBUG_CRYPTO "Build with crypto 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_GCRYPT "Compile against libgcrypt (deprecated)" 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_INTERNAL_DOC "Compile doxygen internal documentation" OFF)
option(BUILD_SHARED_LIBS "Build shared libraries" ON)
option(WITH_PKCS11_URI "Build with PKCS#11 URI support" OFF)
option(WITH_PKCS11_PROVIDER "Use the PKCS#11 provider for accessing pkcs11 objects" OFF)
option(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(GSSAPI_TESTING "Build with GSSAPI tests; requires krb5-server,krb5-libs and krb5-workstation" OFF)
option(WITH_BENCHMARKS "Build benchmarks tools; enables unit testing and client tests" OFF)
option(WITH_EXAMPLES "Build examples" 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(WITH_EXEC "Enable libssh to execute arbitrary commands from configuration files or options (match exec, proxy commands and OpenSSH-based proxy-jumps)." ON)
option(FUZZ_TESTING "Build with fuzzer for the server and client (automatically enables none cipher!)" OFF)
option(PICKY_DEVELOPER "Build with picky developer flags" OFF)
option(WITH_HERMETIC_USR "Build with support for hermetic /usr/" OFF)
if (WITH_ZLIB)
set(WITH_LIBZ ON)
else (WITH_ZLIB)
set(WITH_LIBZ OFF)
endif (WITH_ZLIB)
if (WITH_BENCHMARKS)
set(UNIT_TESTING ON)
set(CLIENT_TESTING ON)
endif()
if (UNIT_TESTING OR CLIENT_TESTING OR SERVER_TESTING OR GSSAPI_TESTING)
set(BUILD_STATIC_LIB ON)
endif()
if (WITH_NACL)
set(WITH_NACL ON)
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 (WITH_HERMETIC_USR)
set(USR_GLOBAL_BIND_CONFIG "/usr${GLOBAL_BIND_CONFIG}")
set(USR_GLOBAL_CLIENT_CONFIG "/usr${GLOBAL_CLIENT_CONFIG}")
endif (WITH_HERMETIC_USR)
if (FUZZ_TESTING)
set(WITH_INSECURE_NONE ON)
endif (FUZZ_TESTING)
if (WIN32)
set(WITH_EXEC 0)
endif(WIN32)
option(WITH_STATIC_LIB "Build with a static library" OFF)
option(WITH_DEBUG_CRYPTO "Build with cryto debut output" OFF)

1272
Doxyfile Normal file

File diff suppressed because it is too large Load Diff

1272
Doxyfile.internal Normal file

File diff suppressed because it is too large Load Diff

65
INSTALL
View File

@@ -7,61 +7,27 @@
In order to build libssh, you need to install several components:
- A C compiler
- [CMake](https://www.cmake.org) >= 3.12.0
- [libz](https://www.zlib.net) >= 1.2
- [openssl](https://www.openssl.org) >= 1.1.1
- [CMake](http://www.cmake.org) >= 2.6.0.
- [openssl](http://www.openssl.org) >= 0.9.8
or
- [gcrypt](https://www.gnu.org/directory/Security/libgcrypt.html) >= 1.5
or
- [Mbed TLS](https://www.trustedfirmware.org/projects/mbed-tls/)
- [gcrypt](http://www.gnu.org/directory/Security/libgcrypt.html) >= 1.4
optional:
- [cmocka](https://cmocka.org/) >= 1.1.0
- [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
- [priv_wrapper](https://cwrap.org/) >= 1.0.0
- [libz](http://www.zlib.net) >= 1.2
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.
For Windows use vcpkg:
https://github.com/Microsoft/vcpkg
which you can use to install openssl and zlib. libssh itself is also part of
vcpkg!
## Building
First, you need to configure the compilation, using CMake. Go inside the
`build` dir. Create it if it doesn't exist.
GNU/Linux, MacOS X, MSYS/MinGW:
GNU/Linux and MacOS X:
cmake -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Debug ..
make
On Windows you should choose a makefile generator with -G or use
cmake-gui.exe ..
To enable building tests use -DUNIT_TESTING=ON. For this, the
[cmocka](https://cmocka.org) dependency is required.
To enable additional client tests against a local OpenSSH server, add the
compile option -DCLIENT_TESTING=ON. These tests require an OpenSSH
server package and some wrapper libraries (see optional requirements) to
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
Here is a list of the most interesting options provided out of the box by
CMake.
@@ -81,7 +47,7 @@ Options are defined in the following files:
They can be changed with the -D option:
`cmake -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Debug -DWITH_ZLIB=OFF ..`
`cmake -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Debug -DWITH_LIBZ=OFF ..`
### Browsing/editing CMake options
@@ -93,17 +59,6 @@ and MacOS X).
- On Windows: run `cmakesetup`
- On GNU/Linux and MacOS X: run `ccmake ..`
### Useful Windows options:
If you have installed OpenSSL or ZLIB in non standard directories, maybe you
want to set:
OPENSSL_ROOT_DIR
and
ZLIB_ROOT_DIR
## Installing
If you want to install libssh after compilation run:
@@ -112,9 +67,7 @@ If you want to install libssh after compilation run:
## Running
The libssh binary can be found in the `build/src` directory.
You can use `build/examples/samplessh` which is a sample client to
test libssh on UNIX.
The libssh binary can be found in the `build/libssh` directory.
## About this document
@@ -122,4 +75,4 @@ This document is written using [Markdown][] syntax, making it possible to
provide usable information in both plain text and HTML format. Whenever
modifying this document please use [Markdown][] syntax.
[markdown]: https://www.daringfireball.net/projects/markdown
[markdown]: http://www.daringfireball.net/projects/markdown

45
README
View File

@@ -1,21 +1,14 @@
_ _ _ _
(_) (_) (_) (_)
(_) _ (_) _ _ _ _ _ (_) _
(_) (_) (_)(_) _ (_)(_) (_)(_) (_)(_) _
(_) (_) (_) (_) _ (_) _ (_) (_) (_)
(_) (_) (_)(_)(_) (_)(_) (_)(_) (_) (_).org
The SSH library
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The libSSH and its client
~~~~~~~~~~~~~~~~~~~~~~~~~
-Aris Adamantiadis
1* 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.
Not any allow you to import and use the functions as a library, and so i
worked on a library-based SSH implementation.
2* How/Who ?
@@ -23,22 +16,24 @@ in the free and open source software world.
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.
The client is there as a programming example and isn't at all doing its job
correctly (doesn't verify public key hashes with the ones in ~/.ssh/
and doesn't handle TERM - yet)
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.
3* What ?
-_-_-_-_-_
3* Where ?
The SSH library features :
-Full C library functions for manipulating a client-side SSH connection
-Fully configurable sessions
-Support for AES-128,AES-192,AES-256,blowfish, in cbc mode
-use multiple SSH connections in a same process, at same time.
-usable SFTP implementation
-Public key and password authentication
4* Where ?
-_-_-_-_-_-_
https://www.libssh.org
4* 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
http://0xbadc0de.be/?part=libssh

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

152
build/build_make.sh Executable file
View File

@@ -0,0 +1,152 @@
#!/bin/bash
#
# Last Change: 2008-06-18 14:13:46
#
# Script to build libssh on UNIX.
#
# Copyright (c) 2006-2007 Andreas Schneider <mail@cynapses.org>
#
SOURCE_DIR=".."
LANG=C
export LANG
SCRIPT="$0"
COUNT=0
while [ -L "${SCRIPT}" ]
do
SCRIPT=$(readlink ${SCRIPT})
COUNT=$(expr ${COUNT} + 1)
if [ ${COUNT} -gt 100 ]; then
echo "Too many symbolic links"
exit 1
fi
done
BUILDDIR=$(dirname ${SCRIPT})
cleanup_and_exit () {
if test "$1" = 0 -o -z "$1" ; then
exit 0
else
exit $1
fi
}
function configure() {
cmake "$@" ${SOURCE_DIR} || cleanup_and_exit $?
}
function compile() {
CPUCOUNT=$(grep -c processor /proc/cpuinfo)
if [ "${CPUCOUNT}" -gt "1" ]; then
make -j${CPUCOUNT} $1 || cleanup_and_exit $?
else
make $1 || exit $?
fi
}
function clean_build_dir() {
find ! -path "*.svn*" ! -name "*.bat" ! -name "*.sh" ! -name "." -print0 | xargs -0 rm -rf
}
function usage () {
echo "Usage: `basename $0` [--prefix /install_prefix|--build [debug|final]|--clean|--verbose|--libsuffix (32|64)|--help]"
cleanup_and_exit
}
cd ${BUILDDIR}
OPTIONS="--graphviz=${BUILDDIR}/libssh.dot -DUNIT_TESTING=ON -DWITH_SSH1=ON -DWITH_SERVER=ON"
while test -n "$1"; do
PARAM="$1"
ARG="$2"
shift
case ${PARAM} in
*-*=*)
ARG=${PARAM#*=}
PARAM=${PARAM%%=*}
set -- "----noarg=${PARAM}" "$@"
esac
case ${PARAM} in
*-help|-h)
#echo_help
usage
cleanup_and_exit
;;
*-build)
DOMAKE="1"
BUILD_TYPE="${ARG}"
test -n "${BUILD_TYPE}" && shift
;;
*-clean)
clean_build_dir
cleanup_and_exit
;;
*-verbose)
DOVERBOSE="1"
;;
*-memtest)
OPTIONS="${OPTIONS} -DMEM_NULL_TESTS=ON"
;;
*-libsuffix)
OPTIONS="${OPTIONS} -DLIB_SUFFIX=${ARG}"
shift
;;
*-prefix)
OPTIONS="${OPTIONS} -DCMAKE_INSTALL_PREFIX=${ARG}"
shift
;;
*-sysconfdir)
OPTIONS="${OPTIONS} -DSYSCONF_INSTALL_DIR=${ARG}"
shift
;;
----noarg)
echo "$ARG does not take an argument"
cleanup_and_exit
;;
-*)
echo Unknown Option "$PARAM". Exit.
cleanup_and_exit 1
;;
*)
usage
;;
esac
done
if [ ${DOMAKE} -eq 1 ]; then
OPTIONS="${OPTIONS} -DCMAKE_BUILD_TYPE=${BUILD_TYPE}"
fi
if [ -n "${DOVERBOSE}" ]; then
OPTIONS="${OPTIONS} -DCMAKE_VERBOSE_MAKEFILE=1"
else
OPTIONS="${OPTIONS} -DCMAKE_VERBOSE_MAKEFILE=0"
fi
test -f "${BUILDDIR}/.build.log" && rm -f ${BUILDDIR}/.build.log
touch ${BUILDDIR}/.build.log
# log everything from here to .build.log
exec 1> >(exec -a 'build logging tee' tee -a ${BUILDDIR}/.build.log) 2>&1
echo "${HOST} started build at $(date)."
echo
configure ${OPTIONS} "$@"
if [ -n "${DOMAKE}" ]; then
test -n "${DOVERBOSE}" && compile VERBOSE=1 || compile
fi
DOT=$(which dot 2>/dev/null)
if [ -n "${DOT}" ]; then
${DOT} -Tpng -o${BUILDDIR}/libssh.png ${BUILDDIR}/libssh.dot
${DOT} -Tsvg -o${BUILDDIR}/libssh.svg ${BUILDDIR}/libssh.dot
fi
exec >&0 2>&0 # so that the logging tee finishes
sleep 1 # wait till tee terminates
cleanup_and_exit 0

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,125 +0,0 @@
#
# Copyright (c) 2007 Daniel Gollub <dgollub@suse.de>
# Copyright (c) 2007-2018 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.
# 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()
include(CTest)
if (CMAKE_CROSSCOMPILING)
if (WIN32)
find_program(WINE_EXECUTABLE
NAMES wine)
set(TARGET_SYSTEM_EMULATOR ${WINE_EXECUTABLE})
endif()
endif()
function(ADD_CMOCKA_TEST _TARGET_NAME)
set(one_value_arguments
)
set(multi_value_arguments
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}
)
if (WITH_COVERAGE)
ENABLE_LANGUAGE(CXX)
include(CodeCoverage)
append_coverage_compiler_flags_to_target(${_TARGET_NAME})
endif (WITH_COVERAGE)
endfunction (ADD_CMOCKA_TEST)

View File

@@ -1,29 +0,0 @@
# - Check whether the C compiler supports a given flag in the
# context of a stack checking compiler option.
# CHECK_C_COMPILER_FLAG_SSP(FLAG VARIABLE)
#
# FLAG - the compiler flag
# VARIABLE - variable to store the result
#
# This actually calls check_c_source_compiles.
# See help for CheckCSourceCompiles for a listing of variables
# that can modify the build.
# Copyright (c) 2006, Alexander Neundorf, <neundorf@kde.org>
#
# Redistribution and use is allowed according to the terms of the BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
# Requires cmake 3.10
#include_guard(GLOBAL)
include(CheckCSourceCompiles)
macro(CHECK_C_COMPILER_FLAG_SSP _FLAG _RESULT)
set(SAFE_CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS}")
set(CMAKE_REQUIRED_FLAGS "${_FLAG}")
check_c_source_compiles("int main(int argc, char **argv) { char buffer[256]; return buffer[argc]=0;}" ${_RESULT})
set(CMAKE_REQUIRED_FLAGS "${SAFE_CMAKE_REQUIRED_FLAGS}")
endmacro(CHECK_C_COMPILER_FLAG_SSP)

View File

@@ -1,750 +0,0 @@
# Copyright (c) 2012 - 2017, Lars Bilke
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without modification,
# are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice, this
# list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# 3. Neither the name of the copyright holder nor the names of its contributors
# may be used to endorse or promote products derived from this software without
# specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# CHANGES:
#
# 2012-01-31, Lars Bilke
# - Enable Code Coverage
#
# 2013-09-17, Joakim Söderberg
# - Added support for Clang.
# - Some additional usage instructions.
#
# 2016-02-03, Lars Bilke
# - Refactored functions to use named parameters
#
# 2017-06-02, Lars Bilke
# - Merged with modified version from github.com/ufz/ogs
#
# 2019-05-06, Anatolii Kurotych
# - Remove unnecessary --coverage flag
#
# 2019-12-13, FeRD (Frank Dana)
# - Deprecate COVERAGE_LCOVR_EXCLUDES and COVERAGE_GCOVR_EXCLUDES lists in favor
# of tool-agnostic COVERAGE_EXCLUDES variable, or EXCLUDE setup arguments.
# - CMake 3.4+: All excludes can be specified relative to BASE_DIRECTORY
# - All setup functions: accept BASE_DIRECTORY, EXCLUDE list
# - Set lcov basedir with -b argument
# - Add automatic --demangle-cpp in lcovr, if 'c++filt' is available (can be
# overridden with NO_DEMANGLE option in setup_target_for_coverage_lcovr().)
# - Delete output dir, .info file on 'make clean'
# - Remove Python detection, since version mismatches will break gcovr
# - Minor cleanup (lowercase function names, update examples...)
#
# 2019-12-19, FeRD (Frank Dana)
# - Rename Lcov outputs, make filtered file canonical, fix cleanup for targets
#
# 2020-01-19, Bob Apthorpe
# - Added gfortran support
#
# 2020-02-17, FeRD (Frank Dana)
# - Make all add_custom_target()s VERBATIM to auto-escape wildcard characters
# in EXCLUDEs, and remove manual escaping from gcovr targets
#
# 2021-01-19, Robin Mueller
# - Add CODE_COVERAGE_VERBOSE option which will allow to print out commands which are run
# - Added the option for users to set the GCOVR_ADDITIONAL_ARGS variable to supply additional
# flags to the gcovr command
#
# 2020-05-04, Mihchael Davis
# - Add -fprofile-abs-path to make gcno files contain absolute paths
# - Fix BASE_DIRECTORY not working when defined
# - Change BYPRODUCT from folder to index.html to stop ninja from complaining about double defines
#
# 2021-05-10, Martin Stump
# - Check if the generator is multi-config before warning about non-Debug builds
#
# 2022-02-22, Marko Wehle
# - Change gcovr output from -o <filename> for --xml <filename> and --html <filename> output respectively.
# This will allow for Multiple Output Formats at the same time by making use of GCOVR_ADDITIONAL_ARGS, e.g. GCOVR_ADDITIONAL_ARGS "--txt".
#
# 2022-09-28, Sebastian Mueller
# - fix append_coverage_compiler_flags_to_target to correctly add flags
# - replace "-fprofile-arcs -ftest-coverage" with "--coverage" (equivalent)
#
# USAGE:
#
# 1. Copy this file into your cmake modules path.
#
# 2. Add the following line to your CMakeLists.txt (best inside an if-condition
# using a CMake option() to enable it just optionally):
# include(CodeCoverage)
#
# 3. Append necessary compiler flags for all supported source files:
# append_coverage_compiler_flags()
# Or for specific target:
# append_coverage_compiler_flags_to_target(YOUR_TARGET_NAME)
#
# 3.a (OPTIONAL) Set appropriate optimization flags, e.g. -O0, -O1 or -Og
#
# 4. If you need to exclude additional directories from the report, specify them
# using full paths in the COVERAGE_EXCLUDES variable before calling
# setup_target_for_coverage_*().
# Example:
# set(COVERAGE_EXCLUDES
# '${PROJECT_SOURCE_DIR}/src/dir1/*'
# '/path/to/my/src/dir2/*')
# Or, use the EXCLUDE argument to setup_target_for_coverage_*().
# Example:
# setup_target_for_coverage_lcov(
# NAME coverage
# EXECUTABLE testrunner
# EXCLUDE "${PROJECT_SOURCE_DIR}/src/dir1/*" "/path/to/my/src/dir2/*")
#
# 4.a NOTE: With CMake 3.4+, COVERAGE_EXCLUDES or EXCLUDE can also be set
# relative to the BASE_DIRECTORY (default: PROJECT_SOURCE_DIR)
# Example:
# set(COVERAGE_EXCLUDES "dir1/*")
# setup_target_for_coverage_gcovr_html(
# NAME coverage
# EXECUTABLE testrunner
# BASE_DIRECTORY "${PROJECT_SOURCE_DIR}/src"
# EXCLUDE "dir2/*")
#
# 5. Use the functions described below to create a custom make target which
# runs your test executable and produces a code coverage report.
#
# 6. Build a Debug build:
# cmake -DCMAKE_BUILD_TYPE=Debug ..
# make
# make my_coverage_target
#
include(CMakeParseArguments)
option(CODE_COVERAGE_VERBOSE "Verbose information" FALSE)
# Check prereqs
find_program( GCOV_PATH gcov )
find_program( LCOV_PATH NAMES lcov lcov.bat lcov.exe lcov.perl)
find_program( FASTCOV_PATH NAMES fastcov fastcov.py )
find_program( GENHTML_PATH NAMES genhtml genhtml.perl genhtml.bat )
find_program( GCOVR_PATH gcovr PATHS ${CMAKE_SOURCE_DIR}/scripts/test)
find_program( CPPFILT_PATH NAMES c++filt )
if(NOT GCOV_PATH)
message(FATAL_ERROR "gcov not found! Aborting...")
endif() # NOT GCOV_PATH
# Check supported compiler (Clang, GNU and Flang)
get_property(LANGUAGES GLOBAL PROPERTY ENABLED_LANGUAGES)
foreach(LANG ${LANGUAGES})
if("${CMAKE_${LANG}_COMPILER_ID}" MATCHES "(Apple)?[Cc]lang")
if("${CMAKE_${LANG}_COMPILER_VERSION}" VERSION_LESS 3)
message(FATAL_ERROR "Clang version must be 3.0.0 or greater! Aborting...")
endif()
elseif(NOT "${CMAKE_${LANG}_COMPILER_ID}" MATCHES "GNU"
AND NOT "${CMAKE_${LANG}_COMPILER_ID}" MATCHES "(LLVM)?[Ff]lang")
message(FATAL_ERROR "Compiler is not GNU or Flang! Aborting...")
endif()
endforeach()
set(COVERAGE_COMPILER_FLAGS "-g --coverage -fprofile-update=atomic"
CACHE INTERNAL "")
if(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang)")
include(CheckCXXCompilerFlag)
check_cxx_compiler_flag(-fprofile-abs-path HAVE_cxx_fprofile_abs_path)
if(HAVE_cxx_fprofile_abs_path)
set(COVERAGE_CXX_COMPILER_FLAGS "${COVERAGE_COMPILER_FLAGS} -fprofile-abs-path")
endif()
endif()
if(CMAKE_C_COMPILER_ID MATCHES "(GNU|Clang)")
include(CheckCCompilerFlag)
check_c_compiler_flag(-fprofile-abs-path HAVE_c_fprofile_abs_path)
if(HAVE_c_fprofile_abs_path)
set(COVERAGE_C_COMPILER_FLAGS "${COVERAGE_COMPILER_FLAGS} -fprofile-abs-path")
endif()
endif()
set(CMAKE_Fortran_FLAGS_COVERAGE
${COVERAGE_COMPILER_FLAGS}
CACHE STRING "Flags used by the Fortran compiler during coverage builds."
FORCE )
set(CMAKE_CXX_FLAGS_COVERAGE
${COVERAGE_COMPILER_FLAGS}
CACHE STRING "Flags used by the C++ compiler during coverage builds."
FORCE )
set(CMAKE_C_FLAGS_COVERAGE
${COVERAGE_COMPILER_FLAGS}
CACHE STRING "Flags used by the C compiler during coverage builds."
FORCE )
set(CMAKE_EXE_LINKER_FLAGS_COVERAGE
""
CACHE STRING "Flags used for linking binaries during coverage builds."
FORCE )
set(CMAKE_SHARED_LINKER_FLAGS_COVERAGE
""
CACHE STRING "Flags used by the shared libraries linker during coverage builds."
FORCE )
mark_as_advanced(
CMAKE_Fortran_FLAGS_COVERAGE
CMAKE_CXX_FLAGS_COVERAGE
CMAKE_C_FLAGS_COVERAGE
CMAKE_EXE_LINKER_FLAGS_COVERAGE
CMAKE_SHARED_LINKER_FLAGS_COVERAGE )
get_property(GENERATOR_IS_MULTI_CONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
if(NOT (CMAKE_BUILD_TYPE STREQUAL "Debug" OR GENERATOR_IS_MULTI_CONFIG))
message(WARNING "Code coverage results with an optimised (non-Debug) build may be misleading")
endif() # NOT (CMAKE_BUILD_TYPE STREQUAL "Debug" OR GENERATOR_IS_MULTI_CONFIG)
if(CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_Fortran_COMPILER_ID STREQUAL "GNU")
link_libraries(gcov)
endif()
# Defines a target for running and collection code coverage information
# Builds dependencies, runs the given executable and outputs reports.
# NOTE! The executable should always have a ZERO as exit code otherwise
# the coverage generation will not complete.
#
# setup_target_for_coverage_lcov(
# NAME testrunner_coverage # New target name
# EXECUTABLE testrunner -j ${PROCESSOR_COUNT} # Executable in PROJECT_BINARY_DIR
# DEPENDENCIES testrunner # Dependencies to build first
# BASE_DIRECTORY "../" # Base directory for report
# # (defaults to PROJECT_SOURCE_DIR)
# EXCLUDE "src/dir1/*" "src/dir2/*" # Patterns to exclude (can be relative
# # to BASE_DIRECTORY, with CMake 3.4+)
# NO_DEMANGLE # Don't demangle C++ symbols
# # even if c++filt is found
# )
function(setup_target_for_coverage_lcov)
set(options NO_DEMANGLE SONARQUBE)
set(oneValueArgs BASE_DIRECTORY NAME)
set(multiValueArgs EXCLUDE EXECUTABLE EXECUTABLE_ARGS DEPENDENCIES LCOV_ARGS GENHTML_ARGS)
cmake_parse_arguments(Coverage "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
if(NOT LCOV_PATH)
message(FATAL_ERROR "lcov not found! Aborting...")
endif() # NOT LCOV_PATH
if(NOT GENHTML_PATH)
message(FATAL_ERROR "genhtml not found! Aborting...")
endif() # NOT GENHTML_PATH
# Set base directory (as absolute path), or default to PROJECT_SOURCE_DIR
if(DEFINED Coverage_BASE_DIRECTORY)
get_filename_component(BASEDIR ${Coverage_BASE_DIRECTORY} ABSOLUTE)
else()
set(BASEDIR ${PROJECT_SOURCE_DIR})
endif()
# Collect excludes (CMake 3.4+: Also compute absolute paths)
set(LCOV_EXCLUDES "")
foreach(EXCLUDE ${Coverage_EXCLUDE} ${COVERAGE_EXCLUDES} ${COVERAGE_LCOV_EXCLUDES})
if(CMAKE_VERSION VERSION_GREATER 3.4)
get_filename_component(EXCLUDE ${EXCLUDE} ABSOLUTE BASE_DIR ${BASEDIR})
endif()
list(APPEND LCOV_EXCLUDES "${EXCLUDE}")
endforeach()
list(REMOVE_DUPLICATES LCOV_EXCLUDES)
# Conditional arguments
if(CPPFILT_PATH AND NOT ${Coverage_NO_DEMANGLE})
set(GENHTML_EXTRA_ARGS "--demangle-cpp")
endif()
# Setting up commands which will be run to generate coverage data.
# Cleanup lcov
set(LCOV_CLEAN_CMD
${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} -directory .
-b ${BASEDIR} --zerocounters
)
# Create baseline to make sure untouched files show up in the report
set(LCOV_BASELINE_CMD
${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} -c -i -d . -b
${BASEDIR} -o ${Coverage_NAME}.base
)
# Run tests
set(LCOV_EXEC_TESTS_CMD
${Coverage_EXECUTABLE} ${Coverage_EXECUTABLE_ARGS}
)
# Capturing lcov counters and generating report
set(LCOV_CAPTURE_CMD
${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} --directory . -b
${BASEDIR} --capture --output-file ${Coverage_NAME}.capture
)
# add baseline counters
set(LCOV_BASELINE_COUNT_CMD
${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} -a ${Coverage_NAME}.base
-a ${Coverage_NAME}.capture --output-file ${Coverage_NAME}.total
)
# filter collected data to final coverage report
set(LCOV_FILTER_CMD
${LCOV_PATH} ${Coverage_LCOV_ARGS} --gcov-tool ${GCOV_PATH} --remove
${Coverage_NAME}.total ${LCOV_EXCLUDES} --output-file ${Coverage_NAME}.info
)
# Generate HTML output
set(LCOV_GEN_HTML_CMD
${GENHTML_PATH} ${GENHTML_EXTRA_ARGS} ${Coverage_GENHTML_ARGS} -o
${Coverage_NAME} ${Coverage_NAME}.info
)
if(${Coverage_SONARQUBE})
# Generate SonarQube output
set(GCOVR_XML_CMD
${GCOVR_PATH} --sonarqube ${Coverage_NAME}_sonarqube.xml -r ${BASEDIR} ${GCOVR_ADDITIONAL_ARGS}
${GCOVR_EXCLUDE_ARGS} --object-directory=${PROJECT_BINARY_DIR}
)
set(GCOVR_XML_CMD_COMMAND
COMMAND ${GCOVR_XML_CMD}
)
set(GCOVR_XML_CMD_BYPRODUCTS ${Coverage_NAME}_sonarqube.xml)
set(GCOVR_XML_CMD_COMMENT COMMENT "SonarQube code coverage info report saved in ${Coverage_NAME}_sonarqube.xml.")
endif()
if(CODE_COVERAGE_VERBOSE)
message(STATUS "Executed command report")
message(STATUS "Command to clean up lcov: ")
string(REPLACE ";" " " LCOV_CLEAN_CMD_SPACED "${LCOV_CLEAN_CMD}")
message(STATUS "${LCOV_CLEAN_CMD_SPACED}")
message(STATUS "Command to create baseline: ")
string(REPLACE ";" " " LCOV_BASELINE_CMD_SPACED "${LCOV_BASELINE_CMD}")
message(STATUS "${LCOV_BASELINE_CMD_SPACED}")
message(STATUS "Command to run the tests: ")
string(REPLACE ";" " " LCOV_EXEC_TESTS_CMD_SPACED "${LCOV_EXEC_TESTS_CMD}")
message(STATUS "${LCOV_EXEC_TESTS_CMD_SPACED}")
message(STATUS "Command to capture counters and generate report: ")
string(REPLACE ";" " " LCOV_CAPTURE_CMD_SPACED "${LCOV_CAPTURE_CMD}")
message(STATUS "${LCOV_CAPTURE_CMD_SPACED}")
message(STATUS "Command to add baseline counters: ")
string(REPLACE ";" " " LCOV_BASELINE_COUNT_CMD_SPACED "${LCOV_BASELINE_COUNT_CMD}")
message(STATUS "${LCOV_BASELINE_COUNT_CMD_SPACED}")
message(STATUS "Command to filter collected data: ")
string(REPLACE ";" " " LCOV_FILTER_CMD_SPACED "${LCOV_FILTER_CMD}")
message(STATUS "${LCOV_FILTER_CMD_SPACED}")
message(STATUS "Command to generate lcov HTML output: ")
string(REPLACE ";" " " LCOV_GEN_HTML_CMD_SPACED "${LCOV_GEN_HTML_CMD}")
message(STATUS "${LCOV_GEN_HTML_CMD_SPACED}")
if(${Coverage_SONARQUBE})
message(STATUS "Command to generate SonarQube XML output: ")
string(REPLACE ";" " " GCOVR_XML_CMD_SPACED "${GCOVR_XML_CMD}")
message(STATUS "${GCOVR_XML_CMD_SPACED}")
endif()
endif()
# Setup target
add_custom_target(${Coverage_NAME}
COMMAND ${LCOV_CLEAN_CMD}
COMMAND ${LCOV_BASELINE_CMD}
COMMAND ${LCOV_EXEC_TESTS_CMD}
COMMAND ${LCOV_CAPTURE_CMD}
COMMAND ${LCOV_BASELINE_COUNT_CMD}
COMMAND ${LCOV_FILTER_CMD}
COMMAND ${LCOV_GEN_HTML_CMD}
${GCOVR_XML_CMD_COMMAND}
# Set output files as GENERATED (will be removed on 'make clean')
BYPRODUCTS
${Coverage_NAME}.base
${Coverage_NAME}.capture
${Coverage_NAME}.total
${Coverage_NAME}.info
${GCOVR_XML_CMD_BYPRODUCTS}
${Coverage_NAME}/index.html
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
DEPENDS ${Coverage_DEPENDENCIES}
VERBATIM # Protect arguments to commands
COMMENT "Resetting code coverage counters to zero.\nProcessing code coverage counters and generating report."
)
# Show where to find the lcov info report
add_custom_command(TARGET ${Coverage_NAME} POST_BUILD
COMMAND ;
COMMENT "Lcov code coverage info report saved in ${Coverage_NAME}.info."
${GCOVR_XML_CMD_COMMENT}
)
# Show info where to find the report
add_custom_command(TARGET ${Coverage_NAME} POST_BUILD
COMMAND ;
COMMENT "Open ./${Coverage_NAME}/index.html in your browser to view the coverage report."
)
endfunction() # setup_target_for_coverage_lcov
# Defines a target for running and collection code coverage information
# Builds dependencies, runs the given executable and outputs reports.
# NOTE! The executable should always have a ZERO as exit code otherwise
# the coverage generation will not complete.
#
# setup_target_for_coverage_gcovr_xml(
# NAME ctest_coverage # New target name
# EXECUTABLE ctest -j ${PROCESSOR_COUNT} # Executable in PROJECT_BINARY_DIR
# DEPENDENCIES executable_target # Dependencies to build first
# BASE_DIRECTORY "../" # Base directory for report
# # (defaults to PROJECT_SOURCE_DIR)
# EXCLUDE "src/dir1/*" "src/dir2/*" # Patterns to exclude (can be relative
# # to BASE_DIRECTORY, with CMake 3.4+)
# )
# The user can set the variable GCOVR_ADDITIONAL_ARGS to supply additional flags to the
# GCVOR command.
function(setup_target_for_coverage_gcovr_xml)
set(options NONE)
set(oneValueArgs BASE_DIRECTORY NAME)
set(multiValueArgs EXCLUDE EXECUTABLE EXECUTABLE_ARGS DEPENDENCIES)
cmake_parse_arguments(Coverage "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
if(NOT GCOVR_PATH)
message(FATAL_ERROR "gcovr not found! Aborting...")
endif() # NOT GCOVR_PATH
# Set base directory (as absolute path), or default to PROJECT_SOURCE_DIR
if(DEFINED Coverage_BASE_DIRECTORY)
get_filename_component(BASEDIR ${Coverage_BASE_DIRECTORY} ABSOLUTE)
else()
set(BASEDIR ${PROJECT_SOURCE_DIR})
endif()
# Collect excludes (CMake 3.4+: Also compute absolute paths)
set(GCOVR_EXCLUDES "")
foreach(EXCLUDE ${Coverage_EXCLUDE} ${COVERAGE_EXCLUDES} ${COVERAGE_GCOVR_EXCLUDES})
if(CMAKE_VERSION VERSION_GREATER 3.4)
get_filename_component(EXCLUDE ${EXCLUDE} ABSOLUTE BASE_DIR ${BASEDIR})
endif()
list(APPEND GCOVR_EXCLUDES "${EXCLUDE}")
endforeach()
list(REMOVE_DUPLICATES GCOVR_EXCLUDES)
# Combine excludes to several -e arguments
set(GCOVR_EXCLUDE_ARGS "")
foreach(EXCLUDE ${GCOVR_EXCLUDES})
list(APPEND GCOVR_EXCLUDE_ARGS "-e")
list(APPEND GCOVR_EXCLUDE_ARGS "${EXCLUDE}")
endforeach()
# Set up commands which will be run to generate coverage data
# Run tests
set(GCOVR_XML_EXEC_TESTS_CMD
${Coverage_EXECUTABLE} ${Coverage_EXECUTABLE_ARGS}
)
# Running gcovr
set(GCOVR_XML_CMD
${GCOVR_PATH} --xml ${Coverage_NAME}.xml -r ${BASEDIR} ${GCOVR_ADDITIONAL_ARGS}
${GCOVR_EXCLUDE_ARGS} --object-directory=${PROJECT_BINARY_DIR}
)
if(CODE_COVERAGE_VERBOSE)
message(STATUS "Executed command report")
message(STATUS "Command to run tests: ")
string(REPLACE ";" " " GCOVR_XML_EXEC_TESTS_CMD_SPACED "${GCOVR_XML_EXEC_TESTS_CMD}")
message(STATUS "${GCOVR_XML_EXEC_TESTS_CMD_SPACED}")
message(STATUS "Command to generate gcovr XML coverage data: ")
string(REPLACE ";" " " GCOVR_XML_CMD_SPACED "${GCOVR_XML_CMD}")
message(STATUS "${GCOVR_XML_CMD_SPACED}")
endif()
add_custom_target(${Coverage_NAME}
COMMAND ${GCOVR_XML_EXEC_TESTS_CMD}
COMMAND ${GCOVR_XML_CMD}
BYPRODUCTS ${Coverage_NAME}.xml
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
DEPENDS ${Coverage_DEPENDENCIES}
VERBATIM # Protect arguments to commands
COMMENT "Running gcovr to produce Cobertura code coverage report."
)
# Show info where to find the report
add_custom_command(TARGET ${Coverage_NAME} POST_BUILD
COMMAND ;
COMMENT "Cobertura code coverage report saved in ${Coverage_NAME}.xml."
)
endfunction() # setup_target_for_coverage_gcovr_xml
# Defines a target for running and collection code coverage information
# Builds dependencies, runs the given executable and outputs reports.
# NOTE! The executable should always have a ZERO as exit code otherwise
# the coverage generation will not complete.
#
# setup_target_for_coverage_gcovr_html(
# NAME ctest_coverage # New target name
# EXECUTABLE ctest -j ${PROCESSOR_COUNT} # Executable in PROJECT_BINARY_DIR
# DEPENDENCIES executable_target # Dependencies to build first
# BASE_DIRECTORY "../" # Base directory for report
# # (defaults to PROJECT_SOURCE_DIR)
# EXCLUDE "src/dir1/*" "src/dir2/*" # Patterns to exclude (can be relative
# # to BASE_DIRECTORY, with CMake 3.4+)
# )
# The user can set the variable GCOVR_ADDITIONAL_ARGS to supply additional flags to the
# GCVOR command.
function(setup_target_for_coverage_gcovr_html)
set(options NONE)
set(oneValueArgs BASE_DIRECTORY NAME)
set(multiValueArgs EXCLUDE EXECUTABLE EXECUTABLE_ARGS DEPENDENCIES)
cmake_parse_arguments(Coverage "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
if(NOT GCOVR_PATH)
message(FATAL_ERROR "gcovr not found! Aborting...")
endif() # NOT GCOVR_PATH
# Set base directory (as absolute path), or default to PROJECT_SOURCE_DIR
if(DEFINED Coverage_BASE_DIRECTORY)
get_filename_component(BASEDIR ${Coverage_BASE_DIRECTORY} ABSOLUTE)
else()
set(BASEDIR ${PROJECT_SOURCE_DIR})
endif()
# Collect excludes (CMake 3.4+: Also compute absolute paths)
set(GCOVR_EXCLUDES "")
foreach(EXCLUDE ${Coverage_EXCLUDE} ${COVERAGE_EXCLUDES} ${COVERAGE_GCOVR_EXCLUDES})
if(CMAKE_VERSION VERSION_GREATER 3.4)
get_filename_component(EXCLUDE ${EXCLUDE} ABSOLUTE BASE_DIR ${BASEDIR})
endif()
list(APPEND GCOVR_EXCLUDES "${EXCLUDE}")
endforeach()
list(REMOVE_DUPLICATES GCOVR_EXCLUDES)
# Combine excludes to several -e arguments
set(GCOVR_EXCLUDE_ARGS "")
foreach(EXCLUDE ${GCOVR_EXCLUDES})
list(APPEND GCOVR_EXCLUDE_ARGS "-e")
list(APPEND GCOVR_EXCLUDE_ARGS "${EXCLUDE}")
endforeach()
# Set up commands which will be run to generate coverage data
# Run tests
set(GCOVR_HTML_EXEC_TESTS_CMD
${Coverage_EXECUTABLE} ${Coverage_EXECUTABLE_ARGS}
)
# Create folder
set(GCOVR_HTML_FOLDER_CMD
${CMAKE_COMMAND} -E make_directory ${PROJECT_BINARY_DIR}/${Coverage_NAME}
)
# Running gcovr
set(GCOVR_HTML_CMD
${GCOVR_PATH} --html ${Coverage_NAME}/index.html --html-details -r ${BASEDIR} ${GCOVR_ADDITIONAL_ARGS}
${GCOVR_EXCLUDE_ARGS} --object-directory=${PROJECT_BINARY_DIR}
)
if(CODE_COVERAGE_VERBOSE)
message(STATUS "Executed command report")
message(STATUS "Command to run tests: ")
string(REPLACE ";" " " GCOVR_HTML_EXEC_TESTS_CMD_SPACED "${GCOVR_HTML_EXEC_TESTS_CMD}")
message(STATUS "${GCOVR_HTML_EXEC_TESTS_CMD_SPACED}")
message(STATUS "Command to create a folder: ")
string(REPLACE ";" " " GCOVR_HTML_FOLDER_CMD_SPACED "${GCOVR_HTML_FOLDER_CMD}")
message(STATUS "${GCOVR_HTML_FOLDER_CMD_SPACED}")
message(STATUS "Command to generate gcovr HTML coverage data: ")
string(REPLACE ";" " " GCOVR_HTML_CMD_SPACED "${GCOVR_HTML_CMD}")
message(STATUS "${GCOVR_HTML_CMD_SPACED}")
endif()
add_custom_target(${Coverage_NAME}
COMMAND ${GCOVR_HTML_EXEC_TESTS_CMD}
COMMAND ${GCOVR_HTML_FOLDER_CMD}
COMMAND ${GCOVR_HTML_CMD}
BYPRODUCTS ${PROJECT_BINARY_DIR}/${Coverage_NAME}/index.html # report directory
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
DEPENDS ${Coverage_DEPENDENCIES}
VERBATIM # Protect arguments to commands
COMMENT "Running gcovr to produce HTML code coverage report."
)
# Show info where to find the report
add_custom_command(TARGET ${Coverage_NAME} POST_BUILD
COMMAND ;
COMMENT "Open ./${Coverage_NAME}/index.html in your browser to view the coverage report."
)
endfunction() # setup_target_for_coverage_gcovr_html
# Defines a target for running and collection code coverage information
# Builds dependencies, runs the given executable and outputs reports.
# NOTE! The executable should always have a ZERO as exit code otherwise
# the coverage generation will not complete.
#
# setup_target_for_coverage_fastcov(
# NAME testrunner_coverage # New target name
# EXECUTABLE testrunner -j ${PROCESSOR_COUNT} # Executable in PROJECT_BINARY_DIR
# DEPENDENCIES testrunner # Dependencies to build first
# BASE_DIRECTORY "../" # Base directory for report
# # (defaults to PROJECT_SOURCE_DIR)
# EXCLUDE "src/dir1/" "src/dir2/" # Patterns to exclude.
# NO_DEMANGLE # Don't demangle C++ symbols
# # even if c++filt is found
# SKIP_HTML # Don't create html report
# POST_CMD perl -i -pe s!${PROJECT_SOURCE_DIR}/!!g ctest_coverage.json # E.g. for stripping source dir from file paths
# )
function(setup_target_for_coverage_fastcov)
set(options NO_DEMANGLE SKIP_HTML)
set(oneValueArgs BASE_DIRECTORY NAME)
set(multiValueArgs EXCLUDE EXECUTABLE EXECUTABLE_ARGS DEPENDENCIES FASTCOV_ARGS GENHTML_ARGS POST_CMD)
cmake_parse_arguments(Coverage "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
if(NOT FASTCOV_PATH)
message(FATAL_ERROR "fastcov not found! Aborting...")
endif()
if(NOT Coverage_SKIP_HTML AND NOT GENHTML_PATH)
message(FATAL_ERROR "genhtml not found! Aborting...")
endif()
# Set base directory (as absolute path), or default to PROJECT_SOURCE_DIR
if(Coverage_BASE_DIRECTORY)
get_filename_component(BASEDIR ${Coverage_BASE_DIRECTORY} ABSOLUTE)
else()
set(BASEDIR ${PROJECT_SOURCE_DIR})
endif()
# Collect excludes (Patterns, not paths, for fastcov)
set(FASTCOV_EXCLUDES "")
foreach(EXCLUDE ${Coverage_EXCLUDE} ${COVERAGE_EXCLUDES} ${COVERAGE_FASTCOV_EXCLUDES})
list(APPEND FASTCOV_EXCLUDES "${EXCLUDE}")
endforeach()
list(REMOVE_DUPLICATES FASTCOV_EXCLUDES)
# Conditional arguments
if(CPPFILT_PATH AND NOT ${Coverage_NO_DEMANGLE})
set(GENHTML_EXTRA_ARGS "--demangle-cpp")
endif()
# Set up commands which will be run to generate coverage data
set(FASTCOV_EXEC_TESTS_CMD ${Coverage_EXECUTABLE} ${Coverage_EXECUTABLE_ARGS})
set(FASTCOV_CAPTURE_CMD ${FASTCOV_PATH} ${Coverage_FASTCOV_ARGS} --gcov ${GCOV_PATH}
--search-directory ${BASEDIR}
--process-gcno
--output ${Coverage_NAME}.json
--exclude ${FASTCOV_EXCLUDES}
)
set(FASTCOV_CONVERT_CMD ${FASTCOV_PATH}
-C ${Coverage_NAME}.json --lcov --output ${Coverage_NAME}.info
)
if(Coverage_SKIP_HTML)
set(FASTCOV_HTML_CMD ";")
else()
set(FASTCOV_HTML_CMD ${GENHTML_PATH} ${GENHTML_EXTRA_ARGS} ${Coverage_GENHTML_ARGS}
-o ${Coverage_NAME} ${Coverage_NAME}.info
)
endif()
set(FASTCOV_POST_CMD ";")
if(Coverage_POST_CMD)
set(FASTCOV_POST_CMD ${Coverage_POST_CMD})
endif()
if(CODE_COVERAGE_VERBOSE)
message(STATUS "Code coverage commands for target ${Coverage_NAME} (fastcov):")
message(" Running tests:")
string(REPLACE ";" " " FASTCOV_EXEC_TESTS_CMD_SPACED "${FASTCOV_EXEC_TESTS_CMD}")
message(" ${FASTCOV_EXEC_TESTS_CMD_SPACED}")
message(" Capturing fastcov counters and generating report:")
string(REPLACE ";" " " FASTCOV_CAPTURE_CMD_SPACED "${FASTCOV_CAPTURE_CMD}")
message(" ${FASTCOV_CAPTURE_CMD_SPACED}")
message(" Converting fastcov .json to lcov .info:")
string(REPLACE ";" " " FASTCOV_CONVERT_CMD_SPACED "${FASTCOV_CONVERT_CMD}")
message(" ${FASTCOV_CONVERT_CMD_SPACED}")
if(NOT Coverage_SKIP_HTML)
message(" Generating HTML report: ")
string(REPLACE ";" " " FASTCOV_HTML_CMD_SPACED "${FASTCOV_HTML_CMD}")
message(" ${FASTCOV_HTML_CMD_SPACED}")
endif()
if(Coverage_POST_CMD)
message(" Running post command: ")
string(REPLACE ";" " " FASTCOV_POST_CMD_SPACED "${FASTCOV_POST_CMD}")
message(" ${FASTCOV_POST_CMD_SPACED}")
endif()
endif()
# Setup target
add_custom_target(${Coverage_NAME}
# Cleanup fastcov
COMMAND ${FASTCOV_PATH} ${Coverage_FASTCOV_ARGS} --gcov ${GCOV_PATH}
--search-directory ${BASEDIR}
--zerocounters
COMMAND ${FASTCOV_EXEC_TESTS_CMD}
COMMAND ${FASTCOV_CAPTURE_CMD}
COMMAND ${FASTCOV_CONVERT_CMD}
COMMAND ${FASTCOV_HTML_CMD}
COMMAND ${FASTCOV_POST_CMD}
# Set output files as GENERATED (will be removed on 'make clean')
BYPRODUCTS
${Coverage_NAME}.info
${Coverage_NAME}.json
${Coverage_NAME}/index.html # report directory
WORKING_DIRECTORY ${PROJECT_BINARY_DIR}
DEPENDS ${Coverage_DEPENDENCIES}
VERBATIM # Protect arguments to commands
COMMENT "Resetting code coverage counters to zero. Processing code coverage counters and generating report."
)
set(INFO_MSG "fastcov code coverage info report saved in ${Coverage_NAME}.info and ${Coverage_NAME}.json.")
if(NOT Coverage_SKIP_HTML)
string(APPEND INFO_MSG " Open ${PROJECT_BINARY_DIR}/${Coverage_NAME}/index.html in your browser to view the coverage report.")
endif()
# Show where to find the fastcov info report
add_custom_command(TARGET ${Coverage_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E echo ${INFO_MSG}
)
endfunction() # setup_target_for_coverage_fastcov
function(append_coverage_compiler_flags)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${COVERAGE_COMPILER_FLAGS}" PARENT_SCOPE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${COVERAGE_COMPILER_FLAGS}" PARENT_SCOPE)
set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} ${COVERAGE_COMPILER_FLAGS}" PARENT_SCOPE)
message(STATUS "Appending code coverage compiler flags: ${COVERAGE_COMPILER_FLAGS}")
endfunction() # append_coverage_compiler_flags
# Setup coverage for specific library
function(append_coverage_compiler_flags_to_target name)
separate_arguments(_flag_list NATIVE_COMMAND "${COVERAGE_COMPILER_FLAGS}")
target_compile_options(${name} PRIVATE ${_flag_list})
if(CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_Fortran_COMPILER_ID STREQUAL "GNU")
target_link_libraries(${name} PRIVATE gcov)
endif()
endfunction()

View File

@@ -6,7 +6,7 @@ set(CMAKE_INCLUDE_CURRENT_DIR ON)
# Put the include dirs which are in the source or build tree
# before all other include dirs, so the headers in the sources
# are preferred over the already installed ones
# are prefered over the already installed ones
# since cmake 2.4.1
set(CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE ON)
@@ -14,8 +14,14 @@ set(CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE ON)
# since cmake 2.4.0
set(CMAKE_COLOR_MAKEFILE ON)
# Create the compile command database for clang by default
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
# Define the generic version of the libraries here
set(GENERIC_LIB_VERSION "0.1.0")
set(GENERIC_LIB_SOVERSION "0")
# Always build with -fPIC
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
# 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)

View File

@@ -1,49 +1,50 @@
# define system dependent compiler flags
include(CheckCCompilerFlag)
if (UNIX AND NOT WIN32)
# Activate with: -DCMAKE_BUILD_TYPE=Profiling
set(CMAKE_C_FLAGS_PROFILING "-O0 -g -fprofile-arcs -ftest-coverage"
CACHE STRING "Flags used by the C compiler during PROFILING builds.")
set(CMAKE_CXX_FLAGS_PROFILING "-O0 -g -fprofile-arcs -ftest-coverage"
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.")
if (CMAKE_COMPILER_IS_GNUCC)
add_definitions(-Wall -Wextra -Wmissing-prototypes -Wdeclaration-after-statement -Wunused)
# Activate with: -DCMAKE_BUILD_TYPE=AddressSanitizer
set(CMAKE_C_FLAGS_ADDRESSSANITIZER "-g -O1 -fsanitize=address -fno-omit-frame-pointer"
CACHE STRING "Flags used by the C compiler during ADDRESSSANITIZER builds.")
set(CMAKE_CXX_FLAGS_ADDRESSSANITIZER "-g -O1 -fsanitize=address -fno-omit-frame-pointer"
CACHE STRING "Flags used by the CXX compiler during ADDRESSSANITIZER builds.")
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.")
# with -fPIC
check_c_compiler_flag("-fPIC" WITH_FPIC)
if (WITH_FPIC)
add_definitions(-fPIC)
endif (WITH_FPIC)
# Activate with: -DCMAKE_BUILD_TYPE=MemorySanitizer
set(CMAKE_C_FLAGS_MEMORYSANITIZER "-g -O2 -fsanitize=memory -fsanitize-memory-track-origins=2 -fno-omit-frame-pointer"
CACHE STRING "Flags used by the C compiler during MEMORYSANITIZER builds.")
set(CMAKE_CXX_FLAGS_MEMORYSANITIZER "-g -O2 -fsanitize=memory -fsanitize-memory-track-origins=2 -fno-omit-frame-pointer"
CACHE STRING "Flags used by the CXX compiler during MEMORYSANITIZER builds.")
set(CMAKE_SHARED_LINKER_FLAGS_MEMORYSANITIZER "-fsanitize=memory"
CACHE STRING "Flags used by the linker during the creation of shared libraries during MEMORYSANITIZER builds.")
set(CMAKE_MODULE_LINKER_FLAGS_MEMORYSANITIZER "-fsanitize=memory"
CACHE STRING "Flags used by the linker during the creation of shared libraries during MEMORYSANITIZER builds.")
set(CMAKE_EXEC_LINKER_FLAGS_MEMORYSANITIZER "-fsanitize=memory"
CACHE STRING "Flags used by the linker during MEMORYSANITIZER builds.")
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
)
string(REGEX REPLACE "[\r\n]" " " "${_lfs_CFLAGS}" "${${_lfs_CFLAGS}}")
# 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()
add_definitions(${_lfs_CFLAGS})
endif (CMAKE_SIZEOF_VOID_P MATCHES "8")
check_c_compiler_flag("-fstack-protector" WITH_STACK_PROTECTOR)
if (WITH_STACK_PROTECTOR)
add_definitions(-fstack-protector)
endif (WITH_STACK_PROTECTOR)
check_c_compiler_flag("-D_FORTIFY_SOURCE=2" WITH_FORTIFY_SOURCE)
if (WITH_FORTIFY_SOURCE)
add_definitions(-D_FORTIFY_SOURCE=2)
endif (WITH_FORTIFY_SOURCE)
endif (CMAKE_COMPILER_IS_GNUCC)
endif (UNIX AND NOT WIN32)

View File

@@ -0,0 +1,107 @@
if (UNIX)
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(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)"
)
endif (UNIX)
if (WIN32)
# Same same
set(BIN_INSTALL_DIR "." CACHE PATH "-")
set(SBIN_INSTALL_DIR "." CACHE PATH "-")
set(LIB_INSTALL_DIR "lib" CACHE PATH "-")
set(INCLUDE_INSTALL_DIR "include" CACHE PATH "-")
set(PLUGIN_INSTALL_DIR "plugins" CACHE PATH "-")
set(HTML_INSTALL_DIR "doc/HTML" CACHE PATH "-")
set(ICON_INSTALL_DIR "." CACHE PATH "-")
set(SOUND_INSTALL_DIR "." CACHE PATH "-")
set(LOCALE_INSTALL_DIR "lang" CACHE PATH "-")
endif (WIN32)

View File

@@ -1,32 +0,0 @@
# Set system vars
if (CMAKE_SYSTEM_NAME MATCHES "Linux")
set(LINUX TRUE)
endif(CMAKE_SYSTEM_NAME MATCHES "Linux")
if (CMAKE_SYSTEM_NAME MATCHES "FreeBSD")
set(FREEBSD TRUE)
set(BSD TRUE)
endif (CMAKE_SYSTEM_NAME MATCHES "FreeBSD")
if (CMAKE_SYSTEM_NAME MATCHES "OpenBSD")
set(OPENBSD TRUE)
set(BSD TRUE)
endif (CMAKE_SYSTEM_NAME MATCHES "OpenBSD")
if (CMAKE_SYSTEM_NAME MATCHES "NetBSD")
set(NETBSD TRUE)
set(BSD TRUE)
endif (CMAKE_SYSTEM_NAME MATCHES "NetBSD")
if (CMAKE_SYSTEM_NAME MATCHES "(Solaris|SunOS)")
set(SOLARIS TRUE)
endif (CMAKE_SYSTEM_NAME MATCHES "(Solaris|SunOS)")
if (CMAKE_SYSTEM_NAME MATCHES "OS2")
set(OS2 TRUE)
endif (CMAKE_SYSTEM_NAME MATCHES "OS2")
if (CMAKE_SYSTEM_NAME MATCHES "Darwin")
set (OSX TRUE)
endif (CMAKE_SYSTEM_NAME MATCHES "Darwin")

View File

@@ -1,105 +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})
file(READ ${header} header_content)
# Filter only lines containing the FILTER_PATTERN
# separated from the function name with one optional newline
string(REGEX MATCHALL
"${FILTER_PATTERN}[^(\n]*\n?[^(\n]*[(]"
contain_filter
"${header_content}"
)
# Remove the optional newline now
string(REGEX REPLACE
"(.+)\n?(.*)"
"\\1\\2"
oneline
"${contain_filter}"
)
# Remove function-like macros
# and anything with two underscores that sounds suspicious
foreach(line ${oneline})
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,491 +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(Python REQUIRED)
else()
find_package(Python)
endif()
if (TARGET Python::Interpreter)
# 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,70 +0,0 @@
# - Try to find ARGP
#
# The argp can be either shipped as part of libc (ex. glibc) or as a separate
# library that requires additional linking (ex. Windows, Mac, musl libc, ...)
#
# Once done this will define
#
# ARGP_ROOT_DIR - Set this variable to the root installation of ARGP
#
# Read-Only variables:
# 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
#
#=============================================================================
# Copyright (c) 2011-2016 Andreas Schneider <asn@cryptomilk.org>
#
# 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
"$ENV{PROGRAMFILES}/argp"
)
find_path(ARGP_ROOT_DIR
NAMES
include/argp.h
HINTS
${_ARGP_ROOT_HINTS}
PATHS
${_ARGP_ROOT_PATHS}
)
mark_as_advanced(ARGP_ROOT_DIR)
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_package_handle_standard_args(Argp DEFAULT_MSG ARGP_LIBRARIES ARGP_INCLUDE_DIR)
# show the ARGP_INCLUDE_DIR and ARGP_LIBRARIES variables only in the advanced view
mark_as_advanced(ARGP_INCLUDE_DIR ARGP_LIBRARIES)

View File

@@ -1,66 +0,0 @@
# - Try to find CMocka
# Once done this will define
#
# CMOCKA_ROOT_DIR - Set this variable to the root installation of CMocka
#
# Read-Only variables:
# CMOCKA_FOUND - system has CMocka
# CMOCKA_INCLUDE_DIR - the CMocka include directory
# CMOCKA_LIBRARIES - Link these to use CMocka
# CMOCKA_DEFINITIONS - Compiler switches required for using CMocka
#
#=============================================================================
# Copyright (c) 2011-2012 Andreas Schneider <asn@cryptomilk.org>
#
# 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(_CMOCKA_ROOT_HINTS
)
set(_CMOCKA_ROOT_PATHS
"$ENV{PROGRAMFILES}/cmocka"
)
find_path(CMOCKA_ROOT_DIR
NAMES
include/cmocka.h
HINTS
${_CMOCKA_ROOT_HINTS}
PATHS
${_CMOCKA_ROOT_PATHS}
)
mark_as_advanced(CMOCKA_ROOT_DIR)
find_path(CMOCKA_INCLUDE_DIR
NAMES
cmocka.h
PATHS
${CMOCKA_ROOT_DIR}/include
)
find_library(CMOCKA_LIBRARY
NAMES
cmocka
PATHS
${CMOCKA_ROOT_DIR}/lib
)
if (CMOCKA_LIBRARY)
set(CMOCKA_LIBRARIES
${CMOCKA_LIBRARIES}
${CMOCKA_LIBRARY}
)
endif (CMOCKA_LIBRARY)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(CMocka DEFAULT_MSG CMOCKA_LIBRARIES CMOCKA_INCLUDE_DIR)
# show the CMOCKA_INCLUDE_DIR and CMOCKA_LIBRARIES variables only in the advanced view
mark_as_advanced(CMOCKA_INCLUDE_DIR CMOCKA_LIBRARIES)

View File

@@ -6,113 +6,72 @@
# GCRYPT_LIBRARIES - Link these to use GCrypt
# GCRYPT_DEFINITIONS - Compiler switches required for using GCrypt
#
#=============================================================================
# Copyright (c) 2009-2012 Andreas Schneider <asn@cryptomilk.org>
# Copyright (c) 2009 Andreas Schneider <mail@cynapses.org>
#
# 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.
#=============================================================================
# Redistribution and use is allowed according to the terms of the New
# BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
#
set(_GCRYPT_ROOT_HINTS
$ENV{GCRYTPT_ROOT_DIR}
${GCRYPT_ROOT_DIR})
set(_GCRYPT_ROOT_PATHS
"$ENV{PROGRAMFILES}/libgcrypt")
if (GCRYPT_LIBRARIES AND GCRYPT_INCLUDE_DIRS)
# in cache already
set(GCRYPT_FOUND TRUE)
else (GCRYPT_LIBRARIES AND GCRYPT_INCLUDE_DIRS)
set(_GCRYPT_ROOT_HINTS_AND_PATHS
HINTS ${_GCRYPT_ROOT_HINTS}
PATHS ${_GCRYPT_ROOT_PATHS})
find_path(GCRYPT_INCLUDE_DIR
find_path(GCRYPT_INCLUDE_DIR
NAMES
gcrypt.h
HINTS
${_GCRYPT_ROOT_HINTS_AND_PATHS}
PATH_SUFFIXES
include
)
gcrypt.h
PATHS
/usr/include
/usr/local/include
/opt/local/include
/sw/include
)
mark_as_advanced(GCRYPT_INCLUDE_DIR)
find_path(GCRYPT_ERROR_INCLUDE_DIR
find_library(GCRYPT_LIBRARY
NAMES
gpg-error.h
HINTS
${_GCRYPT_ROOT_HINTS_AND_PATHS}
PATH_SUFFIXES
include
)
gcrypt
PATHS
/usr/lib
/usr/local/lib
/opt/local/lib
/sw/lib
)
mark_as_advanced(GCRYPT_LIBRARY)
find_library(GCRYPT_LIBRARY
NAMES
gcrypt
gcrypt11
libgcrypt-11
HINTS
${_GCRYPT_ROOT_HINTS_AND_PATHS}
PATH_SUFFIXES
lib
)
find_library(GCRYPT_ERROR_LIBRARY
NAMES
gpg-error
libgpg-error-0
libgpg-error6-0
HINTS
${_GCRYPT_ROOT_HINTS_AND_PATHS}
PATH_SUFFIXES
lib
)
set(GCRYPT_LIBRARIES ${GCRYPT_ERROR_LIBRARY} ${GCRYPT_LIBRARY})
if (GCRYPT_LIBRARY)
set(GCRYPT_FOUND TRUE CACHE INTERNAL "Wether the gcrypt library has been found" FORCE)
endif (GCRYPT_LIBRARY)
if (GCRYPT_INCLUDE_DIR)
file(STRINGS "${GCRYPT_INCLUDE_DIR}/gcrypt.h" _gcrypt_version_str REGEX "^#define GCRYPT_VERSION \"[0-9]+\\.[0-9]+\\.[0-9]")
set(GCRYPT_INCLUDE_DIRS
${GCRYPT_INCLUDE_DIR}
)
string(REGEX REPLACE "^.*GCRYPT_VERSION.*([0-9]+\\.[0-9]+\\.[0-9]+).*" "\\1" GCRYPT_VERSION "${_gcrypt_version_str}")
endif (GCRYPT_INCLUDE_DIR)
include(FindPackageHandleStandardArgs)
if (GCRYPT_VERSION)
find_package_handle_standard_args(GCrypt
REQUIRED_VARS
GCRYPT_INCLUDE_DIR
GCRYPT_LIBRARIES
VERSION_VAR
GCRYPT_VERSION
FAIL_MESSAGE
"Could NOT find GCrypt, try to set the path to GCrypt root folder in the system variable GCRYPT_ROOT_DIR"
if (GCRYPT_FOUND)
set(GCRYPT_LIBRARIES
${GCRYPT_LIBRARIES}
${GCRYPT_LIBRARY}
)
else (GCRYPT_VERSION)
find_package_handle_standard_args(GCrypt
"Could NOT find GCrypt, try to set the path to GCrypt root folder in the system variable GCRYPT_ROOT_DIR"
GCRYPT_INCLUDE_DIR
GCRYPT_LIBRARIES)
endif (GCRYPT_VERSION)
endif (GCRYPT_FOUND)
# show the GCRYPT_INCLUDE_DIRS, GCRYPT_LIBRARIES and GCRYPT_ERROR_INCLUDE_DIR variables only in the advanced view
mark_as_advanced(GCRYPT_INCLUDE_DIR GCRYPT_ERROR_INCLUDE_DIR GCRYPT_LIBRARIES)
if (GCRYPT_INCLUDE_DIRS AND GCRYPT_LIBRARIES)
set(GCRYPT_FOUND TRUE)
endif (GCRYPT_INCLUDE_DIRS AND GCRYPT_LIBRARIES)
if (GCRYPT_FOUND)
if (NOT GCrypt_FIND_QUIETLY)
message(STATUS "Found GCrypt: ${GCRYPT_LIBRARIES}")
endif (NOT GCrypt_FIND_QUIETLY)
else (GCRYPT_FOUND)
if (GCrypt_FIND_REQUIRED)
message(FATAL_ERROR "Could not find GCrypt")
endif (GCrypt_FIND_REQUIRED)
endif (GCRYPT_FOUND)
# show the GCRYPT_INCLUDE_DIRS and GCRYPT_LIBRARIES variables only in the advanced view
mark_as_advanced(GCRYPT_INCLUDE_DIRS GCRYPT_LIBRARIES)
endif (GCRYPT_LIBRARIES AND GCRYPT_INCLUDE_DIRS)
if(GCRYPT_FOUND)
if(NOT TARGET libgcrypt::libgcrypt)
add_library(libgcrypt::libgcrypt UNKNOWN IMPORTED)
set_target_properties(libgcrypt::libgcrypt PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${GCRYPT_INCLUDE_DIR}"
INTERFACE_LINK_LIBRARIES libgcrypt::libgcrypt
IMPORTED_LINK_INTERFACE_LANGUAGES "C"
IMPORTED_LOCATION "${GCRYPT_LIBRARY}")
endif()
if(NOT TARGET libgpg-error::libgpg-error)
add_library(libgpg-error::libgpg-error UNKNOWN IMPORTED)
set_target_properties(libgpg-error::libgpg-error PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${GCRYPT_ERROR_INCLUDE_DIR}"
INTERFACE_LINK_LIBRARIES libgpg-error::libgpg-error
IMPORTED_LINK_INTERFACE_LANGUAGES "C"
IMPORTED_LOCATION "${GCRYPT_ERROR_LIBRARY}")
endif()
endif()

View File

@@ -1,344 +0,0 @@
# - Try to find GSSAPI
# Once done this will define
#
# KRB5_CONFIG - Path to krb5-config
# GSSAPI_ROOT_DIR - Set this variable to the root installation of GSSAPI
#
# Read-Only variables:
# GSSAPI_FLAVOR_MIT - set to TRUE if MIT Kerberos has been found
# GSSAPI_FLAVOR_HEIMDAL - set to TRUE if Heimdal Keberos has been found
# GSSAPI_FOUND - system has GSSAPI
# GSSAPI_INCLUDE_DIR - the GSSAPI include directory
# GSSAPI_LIBRARIES - Link these to use GSSAPI
# GSSAPI_DEFINITIONS - Compiler switches required for using GSSAPI
# GSSAPI_PC_REQUIRES - pkg-config module name if found, needed for
# Requires.private for static linking
#
#=============================================================================
# Copyright (c) 2013 Andreas Schneider <asn@cryptomilk.org>
#
# 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(_mit_modname "mit-krb5-gssapi")
set(_heimdal_modname "heimdal-gssapi")
if(NOT _GSSAPI_ROOT_HINTS AND NOT _GSSAPI_ROOT_PATHS)
find_package(PkgConfig QUIET)
if (PKG_CONFIG_FOUND)
pkg_search_module(_GSSAPI ${_mit_modname} ${_heimdal_modname})
endif()
endif()
find_path(GSSAPI_ROOT_DIR
NAMES
include/gssapi.h
include/gssapi/gssapi.h
HINTS
${_GSSAPI_ROOT_HINTS}
"${_GSSAPI_INCLUDEDIR}"
PATHS
${_GSSAPI_ROOT_PATHS}
)
mark_as_advanced(GSSAPI_ROOT_DIR)
if (UNIX)
find_program(KRB5_CONFIG
NAMES
krb5-config
PATHS
${GSSAPI_ROOT_DIR}/bin
/opt/local/bin)
mark_as_advanced(KRB5_CONFIG)
if (KRB5_CONFIG)
# Check if we have MIT KRB5
execute_process(
COMMAND
${KRB5_CONFIG} --vendor
RESULT_VARIABLE
_GSSAPI_VENDOR_RESULT
OUTPUT_VARIABLE
_GSSAPI_VENDOR_STRING)
if ((_GSSAPI_VENDOR_STRING MATCHES ".*Massachusetts.*") OR (_GSSAPI_VENDOR_STRING
MATCHES ".*MITKerberosShim.*"))
set(GSSAPI_FLAVOR_MIT TRUE)
else()
execute_process(
COMMAND
${KRB5_CONFIG} --libs gssapi
RESULT_VARIABLE
_GSSAPI_LIBS_RESULT
OUTPUT_VARIABLE
_GSSAPI_LIBS_STRING)
if (_GSSAPI_LIBS_STRING MATCHES ".*roken.*")
set(GSSAPI_FLAVOR_HEIMDAL TRUE)
endif()
endif()
# Get the include dir
execute_process(
COMMAND
${KRB5_CONFIG} --cflags gssapi
RESULT_VARIABLE
_GSSAPI_INCLUDE_RESULT
OUTPUT_VARIABLE
_GSSAPI_INCLUDE_STRING)
string(REGEX REPLACE "(\r?\n)+$" "" _GSSAPI_INCLUDE_STRING "${_GSSAPI_INCLUDE_STRING}")
string(REGEX REPLACE " *-I" "" _GSSAPI_INCLUDEDIR "${_GSSAPI_INCLUDE_STRING}")
endif()
if (NOT GSSAPI_FLAVOR_MIT AND NOT GSSAPI_FLAVOR_HEIMDAL)
# Check for HEIMDAL
find_package(PkgConfig)
if (PKG_CONFIG_FOUND)
pkg_check_modules(_GSSAPI heimdal-gssapi)
endif (PKG_CONFIG_FOUND)
if (_GSSAPI_FOUND)
set(GSSAPI_FLAVOR_HEIMDAL TRUE)
else()
find_path(_GSSAPI_ROKEN
NAMES
roken.h
PATHS
${GSSAPI_ROOT_DIR}/include
${_GSSAPI_INCLUDEDIR})
if (_GSSAPI_ROKEN)
set(GSSAPI_FLAVOR_HEIMDAL TRUE)
endif()
endif ()
endif()
endif (UNIX)
find_path(GSSAPI_INCLUDE_DIR
NAMES
gssapi.h
gssapi/gssapi.h
PATHS
${GSSAPI_ROOT_DIR}/include
${_GSSAPI_INCLUDEDIR}
)
if (GSSAPI_FLAVOR_MIT)
find_library(GSSAPI_LIBRARY
NAMES
gssapi_krb5
PATHS
${GSSAPI_ROOT_DIR}/lib
${_GSSAPI_LIBDIR}
)
find_library(KRB5_LIBRARY
NAMES
krb5
PATHS
${GSSAPI_ROOT_DIR}/lib
${_GSSAPI_LIBDIR}
)
find_library(K5CRYPTO_LIBRARY
NAMES
k5crypto
PATHS
${GSSAPI_ROOT_DIR}/lib
${_GSSAPI_LIBDIR}
)
find_library(COM_ERR_LIBRARY
NAMES
com_err
PATHS
${GSSAPI_ROOT_DIR}/lib
${_GSSAPI_LIBDIR}
)
if (GSSAPI_LIBRARY)
set(GSSAPI_LIBRARIES
${GSSAPI_LIBRARIES}
${GSSAPI_LIBRARY}
)
endif (GSSAPI_LIBRARY)
if (KRB5_LIBRARY)
set(GSSAPI_LIBRARIES
${GSSAPI_LIBRARIES}
${KRB5_LIBRARY}
)
endif (KRB5_LIBRARY)
if (K5CRYPTO_LIBRARY)
set(GSSAPI_LIBRARIES
${GSSAPI_LIBRARIES}
${K5CRYPTO_LIBRARY}
)
endif (K5CRYPTO_LIBRARY)
if (COM_ERR_LIBRARY)
set(GSSAPI_LIBRARIES
${GSSAPI_LIBRARIES}
${COM_ERR_LIBRARY}
)
endif (COM_ERR_LIBRARY)
endif (GSSAPI_FLAVOR_MIT)
if (GSSAPI_FLAVOR_HEIMDAL)
find_library(GSSAPI_LIBRARY
NAMES
gssapi
PATHS
${GSSAPI_ROOT_DIR}/lib
${_GSSAPI_LIBDIR}
)
find_library(KRB5_LIBRARY
NAMES
krb5
PATHS
${GSSAPI_ROOT_DIR}/lib
${_GSSAPI_LIBDIR}
)
find_library(HCRYPTO_LIBRARY
NAMES
hcrypto
PATHS
${GSSAPI_ROOT_DIR}/lib
${_GSSAPI_LIBDIR}
)
find_library(COM_ERR_LIBRARY
NAMES
com_err
PATHS
${GSSAPI_ROOT_DIR}/lib
${_GSSAPI_LIBDIR}
)
find_library(HEIMNTLM_LIBRARY
NAMES
heimntlm
PATHS
${GSSAPI_ROOT_DIR}/lib
${_GSSAPI_LIBDIR}
)
find_library(HX509_LIBRARY
NAMES
hx509
PATHS
${GSSAPI_ROOT_DIR}/lib
${_GSSAPI_LIBDIR}
)
find_library(ASN1_LIBRARY
NAMES
asn1
PATHS
${GSSAPI_ROOT_DIR}/lib
${_GSSAPI_LIBDIR}
)
find_library(WIND_LIBRARY
NAMES
wind
PATHS
${GSSAPI_ROOT_DIR}/lib
${_GSSAPI_LIBDIR}
)
find_library(ROKEN_LIBRARY
NAMES
roken
PATHS
${GSSAPI_ROOT_DIR}/lib
${_GSSAPI_LIBDIR}
)
if (GSSAPI_LIBRARY)
set(GSSAPI_LIBRARIES
${GSSAPI_LIBRARIES}
${GSSAPI_LIBRARY}
)
endif (GSSAPI_LIBRARY)
if (KRB5_LIBRARY)
set(GSSAPI_LIBRARIES
${GSSAPI_LIBRARIES}
${KRB5_LIBRARY}
)
endif (KRB5_LIBRARY)
if (HCRYPTO_LIBRARY)
set(GSSAPI_LIBRARIES
${GSSAPI_LIBRARIES}
${HCRYPTO_LIBRARY}
)
endif (HCRYPTO_LIBRARY)
if (COM_ERR_LIBRARY)
set(GSSAPI_LIBRARIES
${GSSAPI_LIBRARIES}
${COM_ERR_LIBRARY}
)
endif (COM_ERR_LIBRARY)
if (HEIMNTLM_LIBRARY)
set(GSSAPI_LIBRARIES
${GSSAPI_LIBRARIES}
${HEIMNTLM_LIBRARY}
)
endif (HEIMNTLM_LIBRARY)
if (HX509_LIBRARY)
set(GSSAPI_LIBRARIES
${GSSAPI_LIBRARIES}
${HX509_LIBRARY}
)
endif (HX509_LIBRARY)
if (ASN1_LIBRARY)
set(GSSAPI_LIBRARIES
${GSSAPI_LIBRARIES}
${ASN1_LIBRARY}
)
endif (ASN1_LIBRARY)
if (WIND_LIBRARY)
set(GSSAPI_LIBRARIES
${GSSAPI_LIBRARIES}
${WIND_LIBRARY}
)
endif (WIND_LIBRARY)
if (ROKEN_LIBRARY)
set(GSSAPI_LIBRARIES
${GSSAPI_LIBRARIES}
${WIND_LIBRARY}
)
endif (ROKEN_LIBRARY)
endif (GSSAPI_FLAVOR_HEIMDAL)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(GSSAPI DEFAULT_MSG GSSAPI_LIBRARIES GSSAPI_INCLUDE_DIR)
if(GSSAPI_FOUND)
if(_GSSAPI_FOUND) # via pkg-config
if (GSSAPI_FLAVOR_MIT)
set(GSSAPI_PC_REQUIRES ${_mit_modname})
elseif (GSSAPI_FLAVOR_HEIMDAL)
set(GSSAPI_PC_REQUIRES ${_heimdal_modname})
endif()
endif()
endif()
# show the GSSAPI_INCLUDE_DIR and GSSAPI_LIBRARIES variables only in the advanced view
mark_as_advanced(GSSAPI_INCLUDE_DIR GSSAPI_LIBRARIES)

View File

@@ -1,143 +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/ssl.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})
# mbedtls 2.8
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()
# mbedtls 3.6
if (NOT MBEDTLS_VERSION AND MBEDTLS_INCLUDE_DIR AND EXISTS "${MBEDTLS_INCLUDE_DIR}/mbedtls/build_info.h")
file(STRINGS "${MBEDTLS_INCLUDE_DIR}/mbedtls/build_info.h" _mbedtls_version_str REGEX
"^#[\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 mbedTLS 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)
if(MBEDTLS_FOUND)
if(NOT TARGET MbedTLS::mbedcrypto)
add_library(MbedTLS::mbedcrypto UNKNOWN IMPORTED)
set_target_properties(MbedTLS::mbedcrypto PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${MBEDTLS_INCLUDE_DIR}"
INTERFACE_LINK_LIBRARIES MbedTLS::mbedcrypto
IMPORTED_LINK_INTERFACE_LANGUAGES "C"
IMPORTED_LOCATION "${MBEDTLS_CRYPTO_LIBRARY}")
endif()
if(NOT TARGET MbedTLS::mbedx509)
add_library(MbedTLS::mbedx509 UNKNOWN IMPORTED)
set_target_properties(MbedTLS::mbedx509 PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${MBEDTLS_INCLUDE_DIR}"
INTERFACE_LINK_LIBRARIES MbedTLS::mbedx509
IMPORTED_LINK_INTERFACE_LANGUAGES "C"
IMPORTED_LOCATION "${MBEDTLS_X509_LIBRARY}")
endif()
if(NOT TARGET MbedTLS::mbedtls)
add_library(MbedTLS::mbedtls UNKNOWN IMPORTED)
set_target_properties(MbedTLS::mbedtls PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${MBEDTLS_INCLUDE_DIR}"
INTERFACE_LINK_LIBRARIES MbedTLS::mbedtls
IMPORTED_LINK_INTERFACE_LANGUAGES "C"
IMPORTED_LOCATION "${MBEDTLS_LIBRARY}")
endif()
endif()

View File

@@ -1,54 +0,0 @@
# - Try to find NSIS
# Once done this will define
#
# NSIS_ROOT_PATH - Set this variable to the root installation of NSIS
#
# Read-Only variables:
#
# NSIS_FOUND - system has NSIS
# NSIS_MAKE - NSIS creator executable
#
#=============================================================================
# Copyright (c) 2010-2013 Andreas Schneider <asn@cryptomilk.org>
#
# 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.
#=============================================================================
#
if (WIN32)
set(_x86 "(x86)")
set(_NSIS_ROOT_PATHS
"$ENV{ProgramFiles}/NSIS"
"$ENV{ProgramFiles${_x86}}/NSIS"
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\NSIS;Default]")
find_path(NSIS_ROOT_PATH
NAMES
Include/Library.nsh
PATHS
${_NSIS_ROOT_PATHS}
)
mark_as_advanced(NSIS_ROOT_PATH)
endif (WIN32)
find_program(NSIS_MAKE
NAMES
makensis
PATHS
${NSIS_ROOT_PATH}
)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(NSIS DEFAULT_MSG NSIS_MAKE)
if (NSIS_MAKE)
set(NSIS_FOUND TRUE)
endif (NSIS_MAKE)
mark_as_advanced(NSIS_MAKE)

View File

@@ -1,61 +0,0 @@
# - Try to find NaCl
# Once done this will define
#
# NACL_FOUND - system has NaCl
# NACL_INCLUDE_DIRS - the NaCl include directory
# NACL_LIBRARIES - Link these to use NaCl
# NACL_DEFINITIONS - Compiler switches required for using NaCl
#
# Copyright (c) 2010 Andreas Schneider <asn@cryptomilk.org>
# Copyright (c) 2013 Aris Adamantiadis <aris@badcode.be>
#
# Redistribution and use is allowed according to the terms of the New
# BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
#
if (NACL_LIBRARIES AND NACL_INCLUDE_DIRS)
# in cache already
set(NACL_FOUND TRUE)
else (NACL_LIBRARIES AND NACL_INCLUDE_DIRS)
find_path(NACL_INCLUDE_DIR
NAMES
nacl/crypto_box_curve25519xsalsa20poly1305.h
PATHS
/usr/include
/usr/local/include
/opt/local/include
/sw/include
)
find_library(NACL_LIBRARY
NAMES
nacl
PATHS
/usr/lib
/usr/local/lib
/opt/local/lib
/sw/lib
)
set(NACL_INCLUDE_DIRS
${NACL_INCLUDE_DIR}
)
if (NACL_LIBRARY)
set(NACL_LIBRARIES
${NACL_LIBRARIES}
${NACL_LIBRARY}
)
endif (NACL_LIBRARY)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(NaCl DEFAULT_MSG NACL_LIBRARIES NACL_INCLUDE_DIRS)
# show the NACL_INCLUDE_DIRS and NACL_LIBRARIES variables only in the advanced view
mark_as_advanced(NACL_INCLUDE_DIRS NACL_LIBRARIES)
endif (NACL_LIBRARIES AND NACL_INCLUDE_DIRS)

View File

@@ -0,0 +1,159 @@
# - Try to find OpenSSL
# Once done this will define
#
# OPENSSL_FOUND - system has OpenSSL
# OPENSSL_INCLUDE_DIRS - the OpenSSL include directory
# OPENSSL_LIBRARIES - Link these to use OpenSSL
# OPENSSL_DEFINITIONS - Compiler switches required for using OpenSSL
#
# Copyright (c) 2009 Andreas Schneider <mail@cynapses.org>
#
# Redistribution and use is allowed according to the terms of the New
# BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
#
if (OPENSSL_LIBRARIES AND OPENSSL_INCLUDE_DIRS)
# in cache already
set(OPENSSL_FOUND TRUE)
else (OPENSSL_LIBRARIES AND OPENSSL_INCLUDE_DIRS)
# use pkg-config to get the directories and then use these values
# in the FIND_PATH() and FIND_LIBRARY() calls
if (${CMAKE_MAJOR_VERSION} EQUAL 2 AND ${CMAKE_MINOR_VERSION} EQUAL 4)
include(UsePkgConfig)
pkgconfig(openssl _OPENSSL_INCLUDEDIR _OPENSSL_LIBDIR _OPENSSL_LDFLAGS _OPENSSL_CFLAGS)
else (${CMAKE_MAJOR_VERSION} EQUAL 2 AND ${CMAKE_MINOR_VERSION} EQUAL 4)
find_package(PkgConfig)
if (PKG_CONFIG_FOUND)
pkg_check_modules(_OPENSSL openssl)
endif (PKG_CONFIG_FOUND)
endif (${CMAKE_MAJOR_VERSION} EQUAL 2 AND ${CMAKE_MINOR_VERSION} EQUAL 4)
find_path(OPENSSL_INCLUDE_DIR
NAMES
openssl/ssl.h
PATHS
${_OPENSSL_INCLUDEDIR}
/usr/include
/usr/local/include
/opt/local/include
/sw/include
)
mark_as_advanced(OPENSSL_INCLUDE_DIR)
find_library(SSL_LIBRARY
NAMES
ssl
PATHS
${_OPENSSL_LIBDIR}
/usr/lib
/usr/local/lib
/opt/local/lib
/sw/lib
)
mark_as_advanced(SSL_LIBRARY)
find_library(SSLEAY32_LIBRARY
NAMES
ssleay32
PATHS
${_OPENSSL_LIBDIR}
/usr/lib
/usr/local/lib
/opt/local/lib
/sw/lib
)
mark_as_advanced(SSLEAY32_LIBRARY)
find_library(SSLEAY32MD_LIBRARY
NAMES
ssleay32MD
PATHS
${_OPENSSL_LIBDIR}
/usr/lib
/usr/local/lib
/opt/local/lib
/sw/lib
)
mark_as_advanced(SSLEAY32MD_LIBRARY)
find_library(CRYPTO_LIBRARY
NAMES
crypto
PATHS
${_OPENSSL_LIBDIR}
/usr/lib
/usr/local/lib
/opt/local/lib
/sw/lib
)
mark_as_advanced(CRYPTO_LIBRARY)
if (SSL_LIBRARY)
set(SSL_FOUND TRUE CACHE INTERNAL "Wether the ssl library has been found" FORCE)
endif (SSL_LIBRARY)
if (SSLEAY32_LIBRARY)
set(SSLEAY32_FOUND TRUE CACHE INTERNAL "Wether the ssleay32 library has been found" FORCE)
endif (SSLEAY32_LIBRARY)
if (SSLEAY32MD_LIBRARY)
set(SSLEAY32MD_FOUND TRUE CACHE INTERNAL "Wether the ssleay32MD library has been found" FORCE)
endif (SSLEAY32MD_LIBRARY)
if (CRYPTO_LIBRARY)
set(CRYPTO_FOUND TRUE CACHE INTERNAL "Wether the crypto library has been found" FORCE)
endif (CRYPTO_LIBRARY)
set(OPENSSL_INCLUDE_DIRS
${OPENSSL_INCLUDE_DIR}
)
if (SSL_FOUND)
set(OPENSSL_LIBRARIES
${OPENSSL_LIBRARIES}
${SSL_LIBRARY}
)
endif (SSL_FOUND)
if (SSLEAY32_FOUND)
set(OPENSSL_LIBRARIES
${OPENSSL_LIBRARIES}
${SSLEAY32_LIBRARY}
)
endif (SSLEAY32_FOUND)
if (SSLEAY32MD_FOUND)
set(OPENSSL_LIBRARIES
${OPENSSL_LIBRARIES}
${SSLEAY32MD_LIBRARY}
)
endif (SSLEAY32MD_FOUND)
if (CRYPTO_FOUND)
set(OPENSSL_LIBRARIES
${OPENSSL_LIBRARIES}
${CRYPTO_LIBRARY}
)
endif (CRYPTO_FOUND)
if (OPENSSL_INCLUDE_DIRS AND OPENSSL_LIBRARIES)
set(OPENSSL_FOUND TRUE)
endif (OPENSSL_INCLUDE_DIRS AND OPENSSL_LIBRARIES)
if (OPENSSL_FOUND)
if (NOT OpenSSL_FIND_QUIETLY)
message(STATUS "Found OpenSSL: ${OPENSSL_LIBRARIES}")
endif (NOT OpenSSL_FIND_QUIETLY)
else (OPENSSL_FOUND)
if (OpenSSL_FIND_REQUIRED)
message(FATAL_ERROR "Could not find OpenSSL")
endif (OpenSSL_FIND_REQUIRED)
endif (OPENSSL_FOUND)
# show the OPENSSL_INCLUDE_DIRS and OPENSSL_LIBRARIES variables only in the advanced view
mark_as_advanced(OPENSSL_INCLUDE_DIRS OPENSSL_LIBRARIES)
endif (OPENSSL_LIBRARIES AND OPENSSL_INCLUDE_DIRS)

View File

@@ -0,0 +1,79 @@
# - Try to find ZLIB
# Once done this will define
#
# ZLIB_FOUND - system has ZLIB
# ZLIB_INCLUDE_DIRS - the ZLIB include directory
# ZLIB_LIBRARIES - Link these to use ZLIB
# ZLIB_DEFINITIONS - Compiler switches required for using ZLIB
#
# Copyright (c) 2009 Andreas Schneider <mail@cynapses.org>
#
# Redistribution and use is allowed according to the terms of the New
# BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
#
if (ZLIB_LIBRARIES AND ZLIB_INCLUDE_DIRS)
# in cache already
set(ZLIB_FOUND TRUE)
else (ZLIB_LIBRARIES AND ZLIB_INCLUDE_DIRS)
find_path(ZLIB_INCLUDE_DIR
NAMES
zlib.h
PATHS
/usr/include
/usr/local/include
/opt/local/include
/sw/include
)
mark_as_advanced(ZLIB_INCLUDE_DIR)
find_library(Z_LIBRARY
NAMES
z
zlib
zlib1
PATHS
/usr/lib
/usr/local/lib
/opt/local/lib
/sw/lib
)
mark_as_advanced(Z_LIBRARY)
if (Z_LIBRARY)
set(Z_FOUND TRUE)
endif (Z_LIBRARY)
set(ZLIB_INCLUDE_DIRS
${ZLIB_INCLUDE_DIR}
)
if (Z_FOUND)
set(ZLIB_LIBRARIES
${ZLIB_LIBRARIES}
${Z_LIBRARY}
)
endif (Z_FOUND)
if (ZLIB_INCLUDE_DIRS AND ZLIB_LIBRARIES)
set(ZLIB_FOUND TRUE)
endif (ZLIB_INCLUDE_DIRS AND ZLIB_LIBRARIES)
if (ZLIB_FOUND)
if (NOT ZLIB_FIND_QUIETLY)
message(STATUS "Found ZLIB: ${ZLIB_LIBRARIES}")
endif (NOT ZLIB_FIND_QUIETLY)
else (ZLIB_FOUND)
if (ZLIB_FIND_REQUIRED)
message(FATAL_ERROR "Could not find ZLIB")
endif (ZLIB_FIND_REQUIRED)
endif (ZLIB_FOUND)
# show the ZLIB_INCLUDE_DIRS and ZLIB_LIBRARIES variables only in the advanced view
mark_as_advanced(ZLIB_INCLUDE_DIRS ZLIB_LIBRARIES)
endif (ZLIB_LIBRARIES AND ZLIB_INCLUDE_DIRS)

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,21 @@
# - MACRO_ADD_COMPILE_FLAGS(target_name flag1 ... flagN)
# Copyright (c) 2006, Oswald Buddenhagen, <ossi@kde.org>
# Copyright (c) 2006, Andreas Schneider, <mail@cynapses.org>
#
# Redistribution and use is allowed according to the terms of the BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
macro (MACRO_ADD_COMPILE_FLAGS _target)
get_target_property(_flags ${_target} COMPILE_FLAGS)
if (_flags)
set(_flags ${_flags} ${ARGN})
else (_flags)
set(_flags ${ARGN})
endif (_flags)
set_target_properties(${_target} PROPERTIES COMPILE_FLAGS ${_flags})
endmacro (MACRO_ADD_COMPILE_FLAGS)

View File

@@ -0,0 +1,20 @@
# - MACRO_ADD_LINK_FLAGS(target_name flag1 ... flagN)
# Copyright (c) 2006, Oswald Buddenhagen, <ossi@kde.org>
# Copyright (c) 2006, Andreas Schneider, <mail@cynapses.org>
#
# Redistribution and use is allowed according to the terms of the BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
macro (MACRO_ADD_LINK_FLAGS _target)
get_target_property(_flags ${_target} LINK_FLAGS)
if (_flags)
set(_flags "${_flags} ${ARGN}")
else (_flags)
set(_flags "${ARGN}")
endif (_flags)
set_target_properties(${_target} PROPERTIES LINK_FLAGS "${_flags}")
endmacro (MACRO_ADD_LINK_FLAGS)

View File

@@ -0,0 +1,30 @@
# - MACRO_ADD_PLUGIN(name [WITH_PREFIX] file1 .. fileN)
#
# Create a plugin from the given source files.
# If WITH_PREFIX is given, the resulting plugin will have the
# prefix "lib", otherwise it won't.
#
# Copyright (c) 2006, Alexander Neundorf, <neundorf@kde.org>
# Copyright (c) 2006, Laurent Montel, <montel@kde.org>
# Copyright (c) 2006, Andreas Schneider, <mail@cynapses.org>
#
# Redistribution and use is allowed according to the terms of the BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
macro (MACRO_ADD_PLUGIN _target_NAME _with_PREFIX)
if (${_with_PREFIX} STREQUAL "WITH_PREFIX")
set(_first_SRC)
else (${_with_PREFIX} STREQUAL "WITH_PREFIX")
set(_first_SRC ${_with_PREFIX})
endif (${_with_PREFIX} STREQUAL "WITH_PREFIX")
add_library(${_target_NAME} MODULE ${_first_SRC} ${ARGN})
if (_first_SRC)
set_target_properties(${_target_NAME} PROPERTIES PREFIX "")
endif (_first_SRC)
endmacro (MACRO_ADD_PLUGIN _name _sources)

View File

@@ -0,0 +1,33 @@
# - macro_copy_file(_src _dst)
# Copies a file to ${_dst} only if ${_src} is different (newer) than ${_dst}
#
# Example:
# macro_copy_file(${CMAKE_CURRENT_SOURCE_DIR}/icon.png ${CMAKE_CURRENT_BINARY_DIR}/.)
# Copies file icon.png to ${CMAKE_CURRENT_BINARY_DIR} directory
#
# Copyright (c) 2006-2007 Wengo
# Copyright (c) 2006-2008 Andreas Schneider <mail@cynapses.org>
#
# Redistribution and use is allowed according to the terms of the BSD license.
# For details see the accompanying COPYING file.
macro (macro_copy_file _src _dst)
# Removes all path containing .svn or CVS or CMakeLists.txt during the copy
if (NOT ${_src} MATCHES ".*\\.svn|CVS|CMakeLists\\.txt.*")
if (CMAKE_VERBOSE_MAKEFILE)
message(STATUS "Copy file from ${_src} to ${_dst}")
endif (CMAKE_VERBOSE_MAKEFILE)
# Creates directory if necessary
get_filename_component(_path ${_dst} PATH)
file(MAKE_DIRECTORY ${_path})
execute_process(
COMMAND
${CMAKE_COMMAND} -E copy_if_different ${_src} ${_dst}
OUTPUT_QUIET
)
endif (NOT ${_src} MATCHES ".*\\.svn|CVS|CMakeLists\\.txt.*")
endmacro (macro_copy_file)

View File

@@ -0,0 +1,127 @@
# -helper macro to add a "doc" target with CMake build system.
# and configure doxy.config.in to doxy.config
#
# target "doc" allows building the documentation with doxygen/dot on WIN32 and Linux
# Creates .chm windows help file if MS HTML help workshop
# (available from http://msdn.microsoft.com/workshop/author/htmlhelp)
# is installed with its DLLs in PATH.
#
#
# Please note, that the tools, e.g.:
# doxygen, dot, latex, dvips, makeindex, gswin32, etc.
# must be in path.
#
# Note about Visual Studio Projects:
# MSVS has its own path environment which may differ from the shell.
# See "Menu Tools/Options/Projects/VC++ Directories" in VS 7.1
#
# author Jan Woetzel 2004-2006
# www.mip.informatik.uni-kiel.de/~jw
FIND_PACKAGE(Doxygen)
IF (DOXYGEN_FOUND)
# click+jump in Emacs and Visual Studio (for doxy.config) (jw)
IF (CMAKE_BUILD_TOOL MATCHES "(msdev|devenv)")
SET(DOXY_WARN_FORMAT "\"$file($line) : $text \"")
ELSE (CMAKE_BUILD_TOOL MATCHES "(msdev|devenv)")
SET(DOXY_WARN_FORMAT "\"$file:$line: $text \"")
ENDIF (CMAKE_BUILD_TOOL MATCHES "(msdev|devenv)")
# we need latex for doxygen because of the formulas
FIND_PACKAGE(LATEX)
IF (NOT LATEX_COMPILER)
MESSAGE(STATUS "latex command LATEX_COMPILER not found but usually required. You will probably get warnings and user inetraction on doxy run.")
ENDIF (NOT LATEX_COMPILER)
IF (NOT MAKEINDEX_COMPILER)
MESSAGE(STATUS "makeindex command MAKEINDEX_COMPILER not found but usually required.")
ENDIF (NOT MAKEINDEX_COMPILER)
IF (NOT DVIPS_CONVERTER)
MESSAGE(STATUS "dvips command DVIPS_CONVERTER not found but usually required.")
ENDIF (NOT DVIPS_CONVERTER)
FIND_PROGRAM(DOXYGEN_DOT_EXECUTABLE_PATH NAMES dot)
IF (DOXYGEN_DOT_EXECUTABLE_PATH)
SET(DOXYGEN_DOT_FOUND "YES")
ENDIF (DOXYGEN_DOT_EXECUTABLE_PATH)
IF (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/doxy.config.in")
MESSAGE(STATUS "Generate ${CMAKE_CURRENT_BINARY_DIR}/doxy.config from doxy.config.in")
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/doxy.config.in
${CMAKE_CURRENT_BINARY_DIR}/doxy.config
@ONLY )
# use (configured) doxy.config from (out of place) BUILD tree:
SET(DOXY_CONFIG "${CMAKE_CURRENT_BINARY_DIR}/doxy.config")
ELSE (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/doxy.config.in")
# use static hand-edited doxy.config from SOURCE tree:
SET(DOXY_CONFIG "${CMAKE_CURRENT_SOURCE_DIR}/doxy.config")
IF (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/doxy.config")
MESSAGE(STATUS "WARNING: using existing ${CMAKE_CURRENT_SOURCE_DIR}/doxy.config instead of configuring from doxy.config.in file.")
ELSE (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/doxy.config")
IF (EXISTS "${CMAKE_MODULE_PATH}/doxy.config.in")
# using template doxy.config.in
MESSAGE(STATUS "Generate ${CMAKE_CURRENT_BINARY_DIR}/doxy.config from doxy.config.in")
CONFIGURE_FILE(${CMAKE_MODULE_PATH}/doxy.config.in
${CMAKE_CURRENT_BINARY_DIR}/doxy.config
@ONLY )
SET(DOXY_CONFIG "${CMAKE_CURRENT_BINARY_DIR}/doxy.config")
ELSE (EXISTS "${CMAKE_MODULE_PATH}/doxy.config.in")
# failed completely...
MESSAGE(SEND_ERROR "Please create ${CMAKE_CURRENT_SOURCE_DIR}/doxy.config.in (or doxy.config as fallback)")
ENDIF(EXISTS "${CMAKE_MODULE_PATH}/doxy.config.in")
ENDIF(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/doxy.config")
ENDIF(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/doxy.config.in")
ADD_CUSTOM_TARGET(doc ${DOXYGEN_EXECUTABLE} ${DOXY_CONFIG} DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/doxy.config)
# create a windows help .chm file using hhc.exe
# HTMLHelp DLL must be in path!
# fallback: use hhw.exe interactively
IF (WIN32)
FIND_PACKAGE(HTMLHelp)
IF (HTML_HELP_COMPILER)
SET (TMP "${CMAKE_CURRENT_BINARY_DIR}\\doc\\html\\index.hhp")
STRING(REGEX REPLACE "[/]" "\\\\" HHP_FILE ${TMP} )
# MESSAGE(SEND_ERROR "DBG HHP_FILE=${HHP_FILE}")
ADD_CUSTOM_TARGET(winhelp ${HTML_HELP_COMPILER} ${HHP_FILE})
ADD_DEPENDENCIES (winhelp doc)
IF (NOT TARGET_DOC_SKIP_INSTALL)
# install windows help?
# determine useful name for output file
# should be project and version unique to allow installing
# multiple projects into one global directory
IF (EXISTS "${PROJECT_BINARY_DIR}/doc/html/index.chm")
IF (PROJECT_NAME)
SET(OUT "${PROJECT_NAME}")
ELSE (PROJECT_NAME)
SET(OUT "Documentation") # default
ENDIF(PROJECT_NAME)
IF (${PROJECT_NAME}_VERSION_MAJOR)
SET(OUT "${OUT}-${${PROJECT_NAME}_VERSION_MAJOR}")
IF (${PROJECT_NAME}_VERSION_MINOR)
SET(OUT "${OUT}.${${PROJECT_NAME}_VERSION_MINOR}")
IF (${PROJECT_NAME}_VERSION_PATCH)
SET(OUT "${OUT}.${${PROJECT_NAME}_VERSION_PATCH}")
ENDIF(${PROJECT_NAME}_VERSION_PATCH)
ENDIF(${PROJECT_NAME}_VERSION_MINOR)
ENDIF(${PROJECT_NAME}_VERSION_MAJOR)
# keep suffix
SET(OUT "${OUT}.chm")
#MESSAGE("DBG ${PROJECT_BINARY_DIR}/doc/html/index.chm \n${OUT}")
# create target used by install and package commands
INSTALL(FILES "${PROJECT_BINARY_DIR}/doc/html/index.chm"
DESTINATION "doc"
RENAME "${OUT}"
)
ENDIF(EXISTS "${PROJECT_BINARY_DIR}/doc/html/index.chm")
ENDIF(NOT TARGET_DOC_SKIP_INSTALL)
ENDIF(HTML_HELP_COMPILER)
# MESSAGE(SEND_ERROR "HTML_HELP_COMPILER=${HTML_HELP_COMPILER}")
ENDIF (WIN32)
ENDIF(DOXYGEN_FOUND)

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,196 +1,51 @@
/* Name of package */
#cmakedefine PACKAGE "${PROJECT_NAME}"
#cmakedefine PACKAGE "${APPLICATION_NAME}"
/* 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 BINARYDIR "${BINARYDIR}"
#cmakedefine SOURCEDIR "${SOURCEDIR}"
/* Global bind configuration file path */
#cmakedefine USR_GLOBAL_BIND_CONFIG "${USR_GLOBAL_BIND_CONFIG}"
#cmakedefine GLOBAL_BIND_CONFIG "${GLOBAL_BIND_CONFIG}"
/* Global client configuration file path */
#cmakedefine USR_GLOBAL_CLIENT_CONFIG "${USR_GLOBAL_CLIENT_CONFIG}"
#cmakedefine GLOBAL_CLIENT_CONFIG "${GLOBAL_CLIENT_CONFIG}"
/************************** HEADER FILES *************************/
/* Define to 1 if you have the <argp.h> header file. */
#cmakedefine HAVE_ARGP_H 1
/* Define to 1 if you have the <aprpa/inet.h> header file. */
#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. */
#cmakedefine HAVE_PTY_H 1
/* Define to 1 if you have the <utmp.h> header file. */
#cmakedefine HAVE_UTMP_H 1
/* Define to 1 if you have the <util.h> header file. */
#cmakedefine HAVE_UTIL_H 1
/* Define to 1 if you have the <libutil.h> header file. */
#cmakedefine HAVE_LIBUTIL_H 1
/* Define to 1 if you have the <sys/time.h> header file. */
#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. */
#cmakedefine HAVE_TERMIOS_H 1
/* Define to 1 if you have the <unistd.h> header file. */
#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 <ifaddrs.h> header file. */
#cmakedefine HAVE_IFADDRS_H 1
/* Define to 1 if you have the <openssl/aes.h> header file. */
#cmakedefine HAVE_OPENSSL_AES_H 1
/* Define to 1 if you have the <wspiapi.h> header file. */
#cmakedefine HAVE_WSPIAPI_H 1
/* Define to 1 if you have the <openssl/blowfish.h> header file. */
#cmakedefine HAVE_OPENSSL_BLOWFISH_H 1
/* Define to 1 if you have the <openssl/des.h> header file. */
#cmakedefine HAVE_OPENSSL_DES_H 1
/* Define to 1 if you have the <openssl/ecdh.h> header file. */
#cmakedefine HAVE_OPENSSL_ECDH_H 1
/* Define to 1 if you have the <openssl/ec.h> header file. */
#cmakedefine HAVE_OPENSSL_EC_H 1
/* Define to 1 if you have the <openssl/ecdsa.h> header file. */
#cmakedefine HAVE_OPENSSL_ECDSA_H 1
/* Define to 1 if you have the <pthread.h> header file. */
#cmakedefine HAVE_PTHREAD_H 1
/* Define to 1 if you have elliptic curve cryptography in openssl */
#cmakedefine HAVE_OPENSSL_ECC 1
/* Define to 1 if mbedTLS supports curve25519 */
#cmakedefine HAVE_MBEDTLS_CURVE25519 1
/* Define to 1 if you have elliptic curve cryptography in gcrypt */
#cmakedefine HAVE_GCRYPT_ECC 1
/* Define to 1 if you have elliptic curve cryptography */
#cmakedefine HAVE_ECC 1
/* Define to 1 if you have gl_flags as a glob_t struct member */
#cmakedefine HAVE_GLOB_GL_FLAGS_MEMBER 1
/* Define to 1 if you have gcrypt with ChaCha20/Poly1305 support */
#cmakedefine HAVE_GCRYPT_CHACHA_POLY 1
/* Define to 1 if you have gcrypt with curve25519 support */
#cmakedefine HAVE_GCRYPT_CURVE25519
/*************************** FUNCTIONS ***************************/
/* Define to 1 if you have the `EVP_chacha20' function. */
#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 `snprintf' function. */
#cmakedefine HAVE_SNPRINTF 1
/* Define to 1 if you have the `_snprintf' function. */
#cmakedefine HAVE__SNPRINTF 1
/* Define to 1 if you have the `_snprintf_s' function. */
#cmakedefine HAVE__SNPRINTF_S 1
/* Define to 1 if you have the `vsnprintf' function. */
#cmakedefine HAVE_VSNPRINTF 1
/* Define to 1 if you have the `_vsnprintf' function. */
#cmakedefine HAVE__VSNPRINTF 1
/* Define to 1 if you have the `_vsnprintf_s' function. */
#cmakedefine HAVE__VSNPRINTF_S 1
/* Define to 1 if you have the `isblank' function. */
#cmakedefine HAVE_ISBLANK 1
/* Define to 1 if you have the `strncpy' function. */
#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. */
#cmakedefine HAVE_CFMAKERAW 1
/* Define to 1 if you have the `getaddrinfo' function. */
#cmakedefine HAVE_GETADDRINFO 1
/* Define to 1 if you have the `gethostbyname' function. */
#cmakedefine HAVE_GETHOSTBYNAME 1
/* Define to 1 if you have the `poll' function. */
#cmakedefine HAVE_POLL 1
/* Define to 1 if you have the `select' function. */
#cmakedefine HAVE_SELECT 1
/* Define to 1 if you have the `clock_gettime' function. */
#cmakedefine HAVE_CLOCK_GETTIME 1
/* Define to 1 if you have the `ntohll' function. */
#cmakedefine HAVE_NTOHLL 1
/* Define to 1 if you have the `htonll' function. */
#cmakedefine HAVE_HTONLL 1
/* Define to 1 if you have the `strtoull' function. */
#cmakedefine HAVE_STRTOULL 1
/* Define to 1 if you have the `__strtoull' function. */
#cmakedefine HAVE___STRTOULL 1
/* Define to 1 if you have the `_strtoui64' function. */
#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
/* Define to 1 if we have support for blowfish */
#cmakedefine HAVE_BLOWFISH 1
/*************************** LIBRARIES ***************************/
/* Define to 1 if you have the `crypto' library (-lcrypto). */
@@ -199,83 +54,34 @@
/* Define to 1 if you have the `gcrypt' library (-lgcrypt). */
#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). */
#cmakedefine HAVE_PTHREAD 1
/* Define to 1 if you have the `cmocka' library (-lcmocka). */
#cmakedefine HAVE_CMOCKA 1
/* Define to 1 if you have the `z' library (-lz). */
#cmakedefine HAVE_LIBZ 1
/**************************** OPTIONS ****************************/
#cmakedefine HAVE_GCC_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_COMPILER__FUNC__ 1
#cmakedefine HAVE_COMPILER__FUNCTION__ 1
#cmakedefine HAVE_GCC_BOUNDED_ATTRIBUTE 1
/* Define to 1 if you want to enable GSSAPI */
#cmakedefine WITH_GSSAPI 1
/* Define to 1 if you want to enable ZLIB */
#cmakedefine WITH_ZLIB 1
#cmakedefine WITH_LIBZ 1
/* Define to 1 if you want to enable SFTP */
/* Define to 1 if you want to enable SSH1 */
#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 */
#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 insecure none cipher and MAC */
#cmakedefine WITH_INSECURE_NONE 1
/* Define to 1 if you want to allow libssh to execute arbitrary commands from
* configuration files or options (match exec, proxy commands and OpenSSH-based
* proxy-jumps). */
#cmakedefine WITH_EXEC 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 */
#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) */
#cmakedefine WITH_PCAP 1
/* Define to 1 if you want to enable calltrace debug output */
#cmakedefine DEBUG_CALLTRACE 1
/* Define to 1 if you want to enable NaCl support */
#cmakedefine WITH_NACL 1
/* Define to 1 if you want to enable PKCS #11 URI support */
#cmakedefine WITH_PKCS11_URI 1
/* Define to 1 if we want to build a support for PKCS #11 provider. */
#cmakedefine WITH_PKCS11_PROVIDER 1
/*************************** ENDIAN *****************************/
/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
significant byte first (like Motorola and SPARC, unlike Intel). */
#cmakedefine WORDS_BIGENDIAN 1
#if defined AC_APPLE_UNIVERSAL_BUILD
# if defined __BIG_ENDIAN__
# define WORDS_BIGENDIAN 1
# endif
#else
# ifndef WORDS_BIGENDIAN
/* # undef WORDS_BIGENDIAN */
# endif
#endif

886
doc/API.html Normal file
View File

@@ -0,0 +1,886 @@
<!DOCTYPE HTML SYSTEM>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=ISO-8859-1">
<head>
<title>
Libssh's Documentation
</title>
<link href="style.css" rel="stylesheet" type="text/css">
</head>
<div id="titre">
<div align="center">
LIBSSH API GUIDE <br>
Or everything you ever wanted to know about a simple and fast ssh library.
</div>
</div>
<h2> 0 Introduction</h2>
<div class="tout">
Before inserting ssh hooks into your programs, you must know some basics about
the ssh protocol, and understand why the ssh library must implement them. <br>
Lot of the protocols specifications are hidden by the ssh library API (of
course !) but some still needs an attention from the end-user programmer.<br>
Note that libssh is still an alpha product, and the API may vary from one
version to another. The only guess I can make is that the API won't radically
change. <br>
The SSH protocol was designed for some goals which I resume here : <br>
-Privacy of data<br>
-Security<br>
-Authentication of the server<br>
-Authentication of the client.<br>
The client MUST be sure who's speaking to before entering into any
authentication way. That's where the end programmer must ensure the given
fingerprints *are* from the legitimate server. A ssh connection must follow
the following steps:<br>
<br>
1- Before connecting the socket, you can set up if you wish one or other
server public key authentication ie. DSA or RSA.
You can choose cryptographic algorithms you trust and compression algorithms
if any.<br>
2- The connection is made. A secure handshake is made, and resulting from it,
a public key from the server is gained.
You MUST verify that the public key is legitimate.<br>
3- The client must authenticate : the two implemented ways are password, and
public keys (from dsa and rsa key-pairs generated by openssh). It is
harmless to authenticate to a fake server with these keys because the
protocol ensures the data you sign can't be used twice. It just avoids
man-in-the-middle attacks.<br>
4- Now that the user has been authenticated, you must open one or several
channels. channels are different subways for information into a single ssh
connection. Each channel has a standard stream (stdout) and an error
stream (stderr). You can theoretically open an infinity of channel.<br>
5- With the channel you opened, you can do several things :<br>
-Open a shell. You may want to request a pseudo virtual terminal before <br>
-Execute a command. The virtual terminal is usable, too<br>
-Invoke the sftp subsystem. (look at chapter 6)<br>
-invoke your own subsystem. This is out the scope of this
document but it is easy to do.<br>
6- When everything is finished, just close the channels, and then the
connection.<br>
<br>
At every place, a function which returns an error code (typically -1 for int
values, NULL for pointers) also sets an error message and an error code.
I high-lined the main steps, now that's you to follow them :)
<br>
</div>
<h2> 1- Setting the options </h2>
<div class="tout">
The options mechanism will change during updates of the library, but the
functions which exists now will certainly be kept.
<br><br>
The ssh system needs to know the preferences of the user, the trust into one
or another algorithm and such. More important informations have to be given
before connecting : the host name of the server, the port (if non default),
the binding address, the default username, ... <br>
The options structure is given to a ssh_connect function, then this option
structure is used again and again by the ssh implementation. you shall not
free it manually, and you shall not share it with multiple sessions.<br>
Two ways are given for setting the options : the easy one (of course !) and
the long-but-accurate one.<br><br>
</div>
<h3>a) the easy way</h3><br>
<div class="tout">
Lot of ssh options in fact come from the command line of the program... <br>
you could parse them and then use the long way for every argument, but libssh
has a mechanism to do that for you, automatically.<br>
<br>
<div class="prot">
SSH_OPTIONS *ssh_getopt(int *argcptr, char **argv);
</div>
this function will return you a new options pointer based on the arguments
you give in parameters. <br> better, they clean the argv array from used parameters
so you can use them after in your own program<br>
<div class="ex">
int main(int argc, char **argv){<br>
SSH_OPTIONS *opt;<br>
opt=ssh_getopt(&argc, argv);<br>
if(!opt){<br>
...<br>
}<br>
</div>
the function will return NULL if some problem is appearing.<br>
As a matter of portability for you own programs, the hostname isn't always<br>
the first argument from the command line, so the single arguments (not
preceded by a -something) won't be parsed.<br>
<div class="ex">
example: <br>
user@host:~$ myssh -u aris localhost <br>
-u aris will be caught, localhost will not.<br>
</div>
cfr the options_set_user() function in the next part for more informations
about it.<br>
</div>
<h3>b) the long way</h3>
<div class="tout">
<div class="prot">
SSH_OPTIONS *options_new();
</div>
This function returns an empty but initialized option structure pointer.<br>
The structure is freed by ssh_disconnect described later, so don't use the
existing function options_free() (it's an internal function).<br>
So : use it only for <b>one</b> ssh_connect(), <b>never</b> free it.<br>
<br>
<div class="prot">
SSH_OPTIONS *options_copy(SSH_OPTIONS *opt);
</div>
If you need to replicate an option object before using it, use this function.
<br><br>
The following functions are all of the following form : <br>
<div class="prot">
int options_set_something(SSH_OPTIONS *opt, something);
</div>
the something parameters are always internaly copied, so you don't have to
strdup them.<br>
some return eather 0 or -1, in which case an error message appears in the
error functions, others never fail (return void)<br>
the error codes and descriptions for these functions are recoverable throught <i>ssh_get_error(NULL);</i>
<br>
<div class="prot">
int options_set_wanted_method(SSH_OPTIONS *opt,int method, char *list);
</div>
Passing an option structure, a ssh macro for the method, and a list of allowed
parameters indicates libssh you want to use these.<br>
The macros are :<br>
KEX_ALGO<br>
KEX_HOSTKEY Server public key type expected<br>
KEX_CRYPT_C_S 2 Cryptographic algorithm client->server<br>
KEX_CRYPT_S_C 3 Cryptographic algorithm server->client<br>
KEX_MAC_C_S 4<br>
KEX_MAC_S_C 5<br>
KEX_COMP_C_S 6 Compression method for the stream ("zlib" or "none"), client to server<br>
KEX_COMP_S_C 7 Compression method for the stream ("zlib" or "none"), server to client<br>
KEX_LANG_C_S 8<br>
KEX_LANG_S_C 9<br>
<br>
Currently, only KEX_HOSTKEY and ,KEX_CRYPT_C_S,S_C, KEX_COMP_C_S and S_C work
as expected. the list is a comma separated string of prefered
algorithms/methods, in order of preference.<br>
<br>
<div class="ex">
example : this sets the ssh stream to be compressed in client->server mode only
<br>
ret = option_set_wanted_method(options,KEX_COMP_C_S,"zlib");
</div>
<div class="ex">
example: this will set the cryptographic algorithms wanted from server to
client to aes128-cbc and then aes192-cbc if the first one isn't supported by
server:<br>
ret = option_set_wanted_method(options,KEX_CRYPT_S_C,"aes128-cbc,aes192-cbc");
</div>
<div class="ex">
if you prefer getting the Dss key from a server instead of rsa, but you still
accept rsa if dss isn't available :<br>
options_set_wanted_method(options,KEX_HOSTKEY,"ssh-dss,ssh-rsa");
</div>
return value: <br>0 if the option is valid, -1 else.<br> An error is set in that case.
<br><br>
<div class="prot">
void options_set_port(SSH_OPTIONS *opt, unsigned int port);
</div>
this function sets the server port.
<div class="prot">
void options_set_host(SSH_OPTIONS *opt, const char *hostname);
</div>
this function sets the hostname of the server. It also supports
"user@hostname" syntax in which case the user options is set too.
<div class="prot">
void options_set_fd(SSH_OPTIONS *opt, int fd);
</div>
permits you to specify an opened file descriptor you've opened yourself.
<br>
It's a good way of bypassing the internal FD opening in libssh, but there are things you should take care of : <br>
-The file descriptor should be returned to libssh without nonblocking settings<br>
-If you wish to use <i>is_server_known()</i> You should also set <i>options_set_host</i>... Otherwise libssh won't have any mean of certifying the server is known or not.<br><br>
<div class="prot">
void options_set_bindaddr(SSH_OPTIONS *opt, char *bindaddr);
</div>
this function allows you to set the binding address, in case your computer has
multiple IP or interfaces. it supports both hostnames and IP's
<br><br>
<div class="prot">
void options_set_username(SSH_OPTIONS *opt,char *username);
</div>
sets username for authenticating in this session.
<br><br>
<div class="prot">
void option_set_timeout(SSH_OPTIONS *opt,long seconds, long usec);
</div>
sets the timeout for connecting to the socket. It does not include a timeout for the name resolving or handshake.
<br>
<br>
<div class="prot">
void options_set_ssh_dir(SSH_OPTIONS *opt, char *dir);
</div>
this function sets the .ssh/ directory used by libssh. You may use a %s
which will be replaced by the home directory of the user.
NEVER accept parameters others than the user's one, they may contain
format strings which are a security hole if a malicious agent gives it.
<br><br>
<div class="prot">
void options_set_known_hosts_file(SSH_OPTIONS *opt, char *dir);
</div>
same than <i>options_set_ssh_dir()</i> for known_hosts file.
<br><br>
<div class="prot">
void options_set_identity(SSH_OPTIONS *opt, char *identity);
</div>
same than upper for the identity file (they come by pair, the one asked is the file without the .pub suffix)
<br><br>
<div class="prot">
void options_set_status_callback(SSH_OPTIONS *opt, void (*callback)(void *arg, float status), void *arg);
</div>
Because more and more developpers use libssh with GUI, I've added this function to make the ssh_connect function more
interactive. This permits to set a callback of the form
<div class="prot">void function(void *userarg, float status);</div> with status going from 0 to 1 during ssh_connect. The callback won't ever be called after the connection is made.
<br><br>
</div>
<h2>
2- Connecting the ssh server
</H2>
<div class="tout">
The API provides an abstract data type, SSH_SESSION, which describes the
connection to one particular server. You can make several connections to
different servers under the same process because of this structure.
<br>
<br>
<div class="prot">
SSH_SESSION *ssh_connect(SSH_OPTIONS *options);
</div>
This function returns a handle on the newly connection. This function expects
to have a pre-set options structure.
<br>
It returns NULL in case of error, in which case you can look at error messages
for more informations.
<br><br>
<div class="prot">
void ssh_disconnect(SSH_SESSION *session);
</div>
This function sends a polite disconnect message, and does clean the session.<br>
This is the proper way of finishing a ssh connection.<br>
<br>
<div class="prot">
int ssh_get_pubkey_hash(SSH_SESSION *session, char hash[MD5_DIGEST_LEN]);
</div>
This function places the MD5 hash of the server public key into the hash array.<br>
It's IMPORTANT to verify it matches the previous known value. One server always
have the same hash. No other server/attacker can emulate it (or it'd be caught
by the public key verification procedure automatically made by libssh).
<br>
You can skip this step if you correctly handle <i>is_server_known()</i>
<br><br>
<div class="prot">
int ssh_is_server_known(SSH_SESSION *session);
</div>
Checks the user's known host file to look for a previous connection to the specified server. Return values:<br>
SSH_SERVER_KNOWN_OK : the host is known and the key has not changed<br>
SSH_SERVER_KNOWN_CHANGED : The host's key has changed. Either you are under
an active attack or the key changed. The API doesn't give any way to modify the key in known hosts yet. I Urge end developers to WARN the user about the possibility of an attack.<br>
SSH_SERVER_FOUND_OTHER: The host gave us a public key of one type, which does
not exist yet in our known host file, but there is an other type of key which is know.<br>
IE server sent a DSA key and we had a RSA key.<br>
Be carreful it's a possible attack (coder should use option_set_wanted_method() to specify
which key to use).<br>
SSH_SERVER_NOT_KNOWN: the server is unknown in known hosts. Possible reasons :
case not matching, alias, ... In any case the user MUST confirm the Md5 hash is correct.<br>
SSH_SERVER_ERROR : Some error happened while opening known host file.<br>
<br>
<div class="prot">
int ssh_write_knownhost(SSH_SESSION *session);
</div>
write the current connected host as known in the known host file. returns a negative value if something went wrong. You generaly use it when ssh_is_server_known returned SSH_SERVER_NOT_KNOWN.
<br><br>
<div class="prot">
int pubkey_get_hash(SSH_SESSION *session,char hash[MD5_DIGEST_LEN]);
</div>
deprecated but left for binary compatibility (will be removed in newer versions).
</div>
<h2>3- Authenticating to server</h2>
<div class="tout">
The ssh library supports the two most used authentication methods from SSH.
In every function, there is a "username" argument. If null is given instead,
the server will use the default username (which is guessed from what you gave
to options_set_user or options_set_hostname or even the local user running the code).
<br>
Authentication methods :<br>
<h3>A) Public keys</h3><br>
The public key is the only method which does not compromise your key if the
remote host has been compromised (the server can't do anything more than
getting your public key). This is not the case of a password authentication
(the server can get your plaintext password).<br>
Libssh is obviously fully compatible with the openssh public and private keys.<br>
The things go this way : you scan a list of files which contain public keys.<br>
For each key, you send it to ssh server until the server acknowledges a key
(a key it knows). Then, you get the private key for this key and send a
message proving you own that private key.<br>
Here again, two ways for the public key authentication... the easy and the
complicated one.<br>
<br>
<h4> easy way:</h4>
<div class="prot">
int ssh_userauth_autopubkey(SSH_SESSION *session);
</div>
This function will try the most common places for finding the public and
private keys (your home directory) or eventualy the identity files asked by
the <i>options_set_identity()</i> function.<br>
The return values are :<br>
SSH_AUTH_ERROR : some serious error happened during authentication<br>
SSH_AUTH_DENIED : no key matched<br>
SSH_AUTH_SUCCESS : you are now authenticated<br>
SSH_AUTH_PARTIAL : some key matched but you still have to give an other mean
of authentication (like password).<br>
<br>
<h4> peanful way:</h4>
there are three steps : you get a public key, you ask the server if the key
matches a known one, if true, you get the private key and authenticate with
it.<br>
<div class="prot">
STRING *publickey_from_file(char *filename,int *_type);
</div>
will return an handle on a public key. if you give a pointer to an int,
a symbolic value will be placed there. Do it because you need it in next
step.<br><br>
<div class="prot">
int ssh_userauth_offer_pubkey(SSH_SESSION *session, char *username,
int type, STRING *publickey);
</div>
this function will offer a public key to the server. SSH_AUTH_SUCCESS is
returned if the key is accepted (in which case you'll want to get the
private key), SSH_AUTH_DENIED otherwise.<br>
Still watch for SSH_AUTH_ERROR as connection problems might happen.
<br>
in case of SSH_AUTH_SUCCESS,
<br>
<div class="prot">
PRIVATE_KEY *privatekey_from_file(SSH_SESSION *session,char *filename,
int type,char *passphrase);
</div>
will get the privatekey from the filename previously set by
publickey_from_next_file(). You can call it with a passphrase for
unlocking the key. If passphrase==NULL, the default prompt will be used.<br>
The function returns NULL if the private key wasn't opened
(ie bad passphrase or missing file).<br>
<br>
<div class="prot">
int ssh_userauth_pubkey(SSH_SESSION *session, char *username,
STRING *publickey, PRIVATE_KEY *privatekey);
</div>
Will try to authenticate using the public and private key. It shall return
SSH_AUTH_SUCCESS if you are authenticated, SSH_AUTH_ERROR, SSH_AUTH_DENIED or
SSH_AUTH_PARTIAL depending of return condition.<br>
each public key (of type STRING) must be freed with the libc "free" function.<br>
The private key must be freed with private_key_free(PRIVATE_KEY *) which
will clean the memory before (don't worry about passphrase leaking).<br>
<br>
<h3> B) Password</h3><br>
<div class="prot">
int ssh_userauth_password(SSH_SESSION *session,char *username,char *password);
</div>
Will return SSH_AUTH_SUCCESS if the password matched, one of other constants
otherwise. It's your work to ask the password and to free it in a secure
manner.<br><br>
<h3> C) Keyboard-interactive</h3><br>
<div class="prot">
int ssh_userauth_kbdint(SSH_SESSION *session, char *user, char *submethods);
</div>
This is the main keyboard-interactive function. It will return SSH_AUTH_SUCCESS,SSH_AUTH_DENIED, SSH_AUTH_PARTIAL, SSH_AUTH_ERROR depending on the result of the request.<br>
The keyboard-interactive authentication method of SSH2 is a feature which permits the server to ask a certain number of questions in an interactive manner to the client, until it decides to accept or deny the login.<br>
To begin, you call this function (you can omit user if it was set previously and omit submethods - instead you know what you do - just put them to NULL) and store the answer.
If the answer is SSH_AUTH_INFO, it means the server has sent a few questions to ask your user, which you can retrieve with the following functions. Then, set the answers and call back ssh_userauth_kbdint with same arguments. It may again ask a few other questions etc. until you get an other SSH_AUTH code than SSH_AUTH_INFO.<br>
Few remarks :<br>
-Even the first call can return SSH_AUTH_DENIED or SSH_AUTH_SUCCESS.<br>
-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.
you must still parse the answer, it might contain some message from the server saying hello or such things. Just call ssh_userauth_kbdint() once more<br>
<br>
<div class="prot">
int ssh_userauth_kbdint_getnprompts(SSH_SESSION *session);
</div>
After you called ssh_userauth_kbdint and got SSH_AUTH_INFO, the session contains a few questions (or prompts) from the server. This function returns the number of prompts and answers.<br>
It could be zero, in which case you must act as said previously.<br>
<div class="prot">
char *ssh_userauth_kbdint_getname(SSH_SESSION *session);
</div>
this functions returns the "name" of the message block. The meaning is explained later.<br>
This function returns a pointer that stays valid until the next ssh_userauth_kbdint() call and must not be freed.<br>
<div class="prot">
char *ssh_userauth_kbdint_getinstruction(SSH_SESSION *session);
</div>
this functions returns the "instruction" of the message block. The meaning is explained later.<br>
This function returns a pointer that stays valid until the next ssh_userauth_kbdint() call and must not be freed.<br>
<div class="prot">
char *ssh_userauth_kbdint_getprompt(SSH_SESSION *session,int i, char *echo);
</div>
This functions returns a pointer to the nth prompt. The character pointed by echo, if different from null, will contain a boolean value after the call, which means that the user prompt must be echoed or not.<br>
zero means that the echo is Off (like for a password prompt).<br>
any other value means the echo is on.<br>
This function returns a pointer that stays valid until the next ssh_userauth_kbdint() call and must not be freed.<br>
<div class="prot">
void ssh_userauth_kbdint_setanswer(SSH_SESSION *session, unsigned int i, char *a
nswer);
</div>
This function sets the ith answer. The string you give will be duplicated, and this copy will be discarded once it is no longer necessary.<br>
care must be taken so you discard the content of the original string after this function call.<br>
<h3> A little note about how to use the informations from keyboard-interactive authentication</h3>
<br>
The words from the original drafts explain everything
<div class="prot">
3.3 User Interface
Upon receiving a request message, the client SHOULD prompt the user
as follows:<br>
A command line interface (CLI) client SHOULD print the name and
instruction (if non-empty), adding newlines. Then for each prompt in
turn, the client SHOULD display the prompt and read the user input.<br>
<br>
A graphical user interface (GUI) client has many choices on how to
prompt the user. One possibility is to use the name field (possibly
prefixed with the application's name) as the title of a dialog window
in which the prompt(s) are presented. In that dialog window, the
instruction field would be a text message, and the prompts would be
labels for text entry fields. All fields SHOULD be presented to the
user, for example an implementation SHOULD NOT discard the name field
because its windows lack titles; it SHOULD instead find another way
to display this information. If prompts are presented in a dialog
window, then the client SHOULD NOT present each prompt in a separate
window.<br>
<br>
All clients MUST properly handle an instruction field with embedded
newlines. They SHOULD also be able to display at least 30 characters
for 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 display. If the client does truncate any fields,
there MUST be an obvious indication that such truncation has occured.<br>
The instruction field SHOULD NOT be truncated.<br>
Clients SHOULD use control character filtering as discussed in
[SSH-ARCH] to avoid attacks by including terminal control characters
in the fields to be displayed.<br>
<br>
For each prompt, the corresponding echo field indicates whether or
not the user input should be echoed as characters are typed. Clients
SHOULD correctly echo/mask user input for each prompt independently
of other prompts in the request message. If a client does not honor
the echo field for whatever reason, then the client MUST err on the
side of masking input. A GUI client might like to have a checkbox
toggling echo/mask. Clients SHOULD NOT add any additional characters
to the prompt such as ": " (colon-space); the server is responsible
for supplying all text to be displayed to the user. Clients MUST
also accept empty responses from the user and pass them on as empty
strings.<br>
</div>
<br>
<h3> D) "none"</h3><br>
In fact this mode only serve to get the list of supported authentications.<br>
however, it also serves to get the banner message from the server, if any.<br>
You should firstly try this method, at least for getting the banner, then to enter if there is no password at all.<br>
<div class="prot">
int ssh_userauth_none(SSH_SESSION *session, char *username);
</div>
if the account has no password (and the server is configured to let you
pass), the function might answer SSH_AUTH_SUCCESS. That's why
ssh_auth_autopubkey already calls it for you.
<br><br>
<div class="prot">
char *ssh_get_issue_banner(SSH_SESSION *session);
</div>
if during authentication, the server has given a banner, you can get it
this way. the function returns NULL if no banner exists, and you have to
free the returned pointer.<br><br>
</div>
<h2>4- Opening a channel</h2>
<div class="tout">
Maybe you want to use the sftp subsystem : all this is done for you, you
better read at the end of the paper how to use the sftp functions.<br>
You probably want to open one or more shells, or call one or more programs.<br>
So you need a channel.<br>
<div class="prot">
CHANNEL *channel;
</div>
This is an handler to a channel object. it describes your channel.
<br>
<div class="prot">
CHANNEL *channel_open_session(SSH_SESSION *session);
</div>
This will open a channel for use into a session (which can be used for executing
a command or a shell. Not for tcp forwarding).<br>
The function returns NULL if for a reason or another the channel can't be
opened.<br>
<i>
CHANNEL *open_session_channel(...)</i> is deprecated and should not be used in future
applications.<br><br>
<div class="prot">
CHANNEL *channel_open_forward(SSH_SESSION *session, char *remotehost,
int remoteport, char *sourcehost, int localport);
</div>
Ask the server to tunnel a TCP connection. The server will connect to
remotehost:remoteport and libssh will return an handle to the channel if it is allowed.<br>
Otherwise, NULL will be returned. sourcehost and localport are generaly
used in message debugging purpose and have no effect on the result.<br>
<br>
When you've finished with your channel, you may send an EOF message and
then close it :<br>
<div class="prot">
void channel_send_eof(CHANNEL *channel);
</div>
sends an end of file into channel. It doesn't close the channel and you can still read it.<br><br>
<div class="prot">
void channel_free(CHANNEL *channel);
</div>
closes and destroy the channel.
<br>
<div class="prot">
void channel_close(CHANNEL *channel);
</div>
sends an EOF and close the channel. (if you don't know what to do, use channel_free). It doesn't free the channel.
</div>
<h2>5- The shell</h2>
<div class="tout">
<div class="prot">
int channel_request_env(CHANNEL *channel, char *name, char *value);
</div>
Ask the server to set the "name" environment variable to "value". For security
reasons, some variables won't be accepted by the server. It returns 0 otherwise.<br><br>
<div class="prot">
int channel_request_pty(CHANNEL *channel);
</div>
ask the server to allocate a pseudo terminal for the current channel.<br>
the function returns 0 on success.<br><br>
<div class="prot">
int channel_request_pty_size(CHANNEL *channel, char *terminal, int cols, int rows);
</div>
ask the server to allocate a pty. The terminal parameter is the type of pty
(vt100,xterm,...), cols and rows are the size of the new terminal (80x24 by example).<br><br>
<div class="prot">
int channel_change_pty_size(CHANNEL *channel, int cols,int rows);
</div>
changes the window size (terminal) of the current session;<br><br>
<div class="prot">
int channel_request_shell(CHANNEL *channel);
</div>
This function requests a shell. After its success, a shell is running at the other side of the channel.<br><br>
<div class="prot">
int channel_request_exec(CHANNEL *channel, char *cmd);
</div>
run a shell command without an interactive shell, ie $SHELL -c "command".<br>
returns 0 on success.<br><br>
You might ask the server to open a subsystem for you. this is done this way :
<div class="prot">
int channel_request_subsystem(CHANNEL *channel, char *subsystem);
</div>
There are some functions used to manipulate the channels :
<br><br>
<div class="prot">
int channel_write(CHANNEL *channel,void *data,int len);
</div>
writes len bytes of data into the channel. It returns the number of bytes written. The current implementation is a blocking write
of the complete data buffer, but it may vary.<br><br>
<div class="prot">
int channel_read(CHANNEL *channel, BUFFER *buffer,int bytes,int is_stderr);
</div>
It makes a blocking read on the channel, of "bytes" bytes and returns the
result into an allocated buffer you passed in. (with <i>buffer_new()</i>).<br>
it will read on stderr, if is_stderr is set.<br>
The function might read less bytes than "bytes" variable if an End of File
happened. Otherwise, the function will always block reading until "bytes"
bytes are read.<br>
with "bytes"=0, <i>channel_read()</i> will read the current state of the read buffer, but will read at least one byte (and block if nothing is available, except EOF case).<br>
You don't need to free and allocate a new buffer each time you call this function, just pass the same object each time.<br>
look at the <i>buffer_</i> functions further for the correct way of retrieving the data.<br><br>
<div class="prot">
int channel_read_nonblocking (CHANNEL *channel, char *dest, int len, int is_stderr);
</div>
Non-blocking read on channel, at most len bytes of data are read. Returns 0 if EOF or if no data available.
<br><br>
<div class="prot">
int channel_is_open(CHANNEL *channel);
</div>
returns 0 if the channel has been closed by remote host, something else otherwise.<br><br>
<div class="prot">
int channel_poll(CHANNEL *channel, int is_stderr);
</div>
This nonblocking function returns the number of bytes immediatly available for
reading on the channel and stdin/stderr.<br><br>
More interesting, if you are going to do channel multiplexing, this function
is for you :<br><br>
<div class="prot">
int ssh_select(CHANNEL **channels,CHANNEL **outchannels, int maxfd,
fd_set *readfds, struct timeval *timeout);
</div>
channels is an array of channel pointers, finished by a NULL pointer.<br>
It can be used ever and ever, as it is never written.<br>
outchannels is an array of size at least greater or equal to "channels".<br>
It hasn't to be initialized.<br>
maxfd is the maximum file descriptor from your own filedescriptors.<br>
readfds is a pointer to a fd_set structure, like in the original
select implementation (man select).<br>
the struct timeval *timeout has the same meaning than in
select(2) (man select).<br>
There is no support for writing or special events as in <i>select(2)</i> yet.<br>
The function returns -1 if an error occured, or SSH_EINTR if select was interrupted by a syscall. This is not an error, you may restart the function.<br>
<b>note about signals:</b> libssh is not threadsafe, and most functions are not
reetrant when using the same data structures : it means you *cannot* do anything
with a channel from a ssh session passed to <i>ssh_select</i> during a signal.
<br>take a look at sample.c on how to bypass that limitation.<br>
the function works this way : it returns in the readfds the filedescriptors which have data ready for reading (the given filedescriptors have a greatest priority).<br>
Then, if no file descriptor can be read, the function looks for every
channel from the array to get a channel with data bufferized. If nothing is
available, it waits for activity on any channel/file descriptor and returns
immediatly, or waits until timeout.<br>
You will find the channels that can be read in the outchannels array (finished by NULL) and the filedescriptors in your fd_set (man FD_ISSET).<br>
this is the "heart" of your main loop.<br>
<br>
<h3>The BUFFER object.</h3>
Reading is done through the BUFFER object. here is the public interface :
<br>
<div class="prot">
BUFFER *buffer_new();
</div>
creates a buffer object.
<br><br>
<div class="prot">
void *buffer_get(BUFFER *buffer);
</div>
returns a pointer to the begining of buffer.
<br><br>
<div class="prot">
int buffer_get_len(BUFFER *buffer);
</div>
returns buffer's data size.
<br><br>
<div class="prot">
void buffer_free(BUFFER *buffer);
</div>
destoys the buffer.
<br>
<br>
How to use the buffer system when you've read something:<br>
I've seen people doing such code:<br>
<div class="prot">
char buffer[256];<br>
channel_read(channel,buf,1234,0);<br>
strcpy(buffer,buf.data);<br>
</div>
The correct way of doing this:
<div class="prot">
char buffer[256];<br>
int i;<br>
i=channel_read(channel,buf,1234,0);<br>
if(i<=0)<br>
&nbsp;&nbsp;&nbsp;&nbsp;go_out()...<br>
if(i>=256)<br>
&nbsp;&nbsp;&nbsp;&nbsp;i=255;<br>
memcpy(buffer,buffer_get(buf),i);<br>
buffer[i]=0;
</div>
Do not expect the buffer to be null-terminated. Don't access the internal structure of buffer. Check the sizes before copying.<br>
</div>
<h2>6- The SFTP subsystem</h2>
<div class="tout">
SFTP is a secure implementation of a file transfer protocol. The current
implemented version is 3. All functions aren't implemented yet but the most
important are.<br>
<br>
<h3>A) Opening the session</h3>
<div class="prot">
SFTP_SESSION *sftp_new(SSH_SESSION *session);
int sftp_init(SFTP_SESSION *sftp);
</div>
The former returns a SFTP_SESSION handle. It returns NULL if things didn't
work as expected.<br>
sftp_init makes some initialisation work. It returns 0 if things went right.
Both of them must be called.<br>
<h3>B) Opening and reading a directory</h3>
<div class="prot">
SFTP_DIR *sftp_opendir(SFTP_SESSION *session, char *path);
</div>
opens a directory for file listing. Returns NULL in error case.
<br><br>
<div class="prot">
SFTP_ATTRIBUTES *sftp_readdir(SFTP_SESSION *session, SFTP_DIR *dir);
</div>
This function reads one file attribute from an opened directory. It
returns NULL if the directory is EOF, or if something wrong happened.
<br><br>
<div class="prot">
int sftp_dir_eof(SFTP_DIR *dir);
</div>
When a <i>sftp_readdir()</i> returned NULL, you can use this function to
tell if an EOF occured. the function returns 0 if no EOF occured.
<br><br>
<div class="prot">
void sftp_attributes_free(SFTP_ATTRIBUTES *file);
</div>
You have to free any SFTP_ATTRIBUTE structure given by an other function
with it.<br><br>
<div class="prot">
int sftp_dir_close(SFTP_DIR *dir);
</div>
closes an opened directory. returns 0 when no error occured.
<br><br>
<h3>C) Opening, reading, writing files</h3>
<div class="prot">
SFTP_FILE *sftp_open(SFTP_SESSION *session, char *file, int access,
SFTP_ATTRIBUTES *attr);
</div>
Opens a file. The access flags are the same than the stdio flags.<br>
see open(2) for more details.<br>
attr are the wanted attributes for the new file. If you supply NULL,
default values will be used.<br>
rem: more work is going on parsing/making the attributes structure
<br><br>
<div class="prot">
int sftp_read(SFTP_FILE *file, void *dest, int len);
</div>
read on a file. Works as the fread() function. It is blocking by default but you can change the default behaviour with <i>sftp_file_set_nonblocking()</i>.
<br><br>
<div class="prot">
void sftp_file_set_nonblocking(SFTP_FILE *file);
</div>
sets the file non blocking. reads on this file won't ever block. You can't detect end of files this way.<br>
*** TODO more work going there for EOF ****
<br><br>
<div class="prot">
void sftp_file_set_blocking(SFTP_FILE *file);
</div>
restore the default setting of sftp_read.
<br><br>
<div class="prot">
int sftp_write(SFTP_FILE *file, void *source, int len);
</div>
works as fwrite() function. It is a blocking write.<br>
<br>
<div class="prot">
void sftp_seek(SFTP_FILE *file, int new_offset);
</div>
seek into the file for reading/writing at an other place.
<br><br>
<div class="prot">
unsigned long sftp_tell(SFTP_FILE *file);
</div>
returns the current offset (both writing and reading) into the opened file.
<br><br>
<div class="prot">
void sftp_rewind(SFTP_FILE *file);
</div>
same as sftp_seek(file,0);
<br><br>
<div class="prot">
int sftp_file_close(SFTP_FILE *file);
</div>
closes a file handle. returns 0 in no error case.
<br><br>
<div class="prot">
int sftp_rm(SFTP_SESSION *sftp, char *file);
</div>
deletes a file.
<br><br>
<div class="prot">
int sftp_rmdir(SFTP_SESSION *sftp, char *directory);
</div>
<br>
deletes a directory.
<br><br>
<div class="prot">
int sftp_mkdir(SFTP_SESSION *sftp, char *directory, SFTP_ATTRIBUTES *attr);
</div>
makes a directory, with the given attributes. You can't pass NULL for attr and hope it works.
<br><br>
<div class="prot">
int sftp_rename(SFTP_SESSION *sftp, char *original, char *newname);
</div>
changes the name of a file or directory.
<br><br>
<div class="prot">
int sftp_setstat(SFTP_SESSION *sftp, char *file, SFTP_ATTRIBUTES *attr);
</div>
changes the attributes of a file or directory.
<br><br>
<div class="prot">
char *sftp_canonicalize_path(SFTP_SESSION *sftp, char *path);
</div>
gives the canonicalized form of some path. You have to
free the pointer given in return.<br>
(returns NULL if error).
<br><br>
(a function to make proper SFTP_ATTRIBUTES structures is on the way )
<h3>D) Closing the session</h3>
<div class="prot">
void sftp_free(SFTP_SESSION *sftp);
</div>
it closes the sftp channel and subsystem.
</div>
<h2>7- Handling the errors</h2>
<div class="tout">
When some function returns an error code, it's allways possible to get an
english message describing the problem. the function ssh_get_error()
returns a pointer to the static error buffer.<br>
ssh_error_code() returns the error code number. it's declared as an enum:<br>
SSH_NO_ERROR, SSH_REQUEST_DENIED, SSH_INVALID_REQUEST, SSH_CONNECTION_LOST,
SSH_FATAL, SSH_INVALID_DATA.<br><br>
SSH_REQUEST_DENIED means the ssh server refused your request but the situation is
recoverable. the others mean something happened to the connection (some
encryption problems, server problems, library bug, ...).<br>
SSH_INVALID_REQUEST means the library got some garbage from server. (But might be
recoverable).<br>
SSH_FATAL means the connection has an important problem and isn't probably
recoverable.<br>
<br>
Most of time, the error returned are SSH_FATAL, but some functions (generaly the
<i>ssh_request_*</i> ones) may fail because of server denying request. In these cases, SSH_REQUEST_DENIED is returned.<br><br>
You'll see in the prototype SSH_SESSION *session. That's because for thread
safety, error messages that can be attached to a session aren't static
anymore. So, any error that could happen during ssh_getopt(), options_* or
ssh_connect() will be retreavable giving NULL as argument.<br>
<br>
<div class="prot">
char *ssh_get_error(SSH_SESSION *session);
</div>
returns a pointer to a static message error from the given session. No
message freeing is needed.<br><br>
<div class="prot">
enum ssh_error ssh_get_error_code(SSH_SESSION *session);
</div>
returns the error code that last happened along with the message.
<br><br>
</div>
<h2>8- Final word</h2>
<div class="tout">
I made this library because nothing in the Open source or free software community was existing yet. This project is a very personnal one as it's the first "useful" thing I ever wrote.
I hope it fits your needs, but remember the experimental state of libssh : if
something doesn't work, please mail me. If something lacks, please ask for it.
If something stinks, please write a patch and send it !
</div>
</body>
</html>

View File

@@ -1,91 +1,5 @@
#
# 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_GENERATE_TAGFILE "tags.xml")
set(DOXYGEN_PREDEFINED DOXYGEN
WITH_SERVER
WITH_SFTP
PRINTF_ATTRIBUTE\(x,y\))
set(DOXYGEN_DOT_GRAPH_MAX_NODES 100)
set(DOXYGEN_EXCLUDE ${CMAKE_CURRENT_SOURCE_DIR}/that_style)
set(DOXYGEN_HTML_HEADER ${CMAKE_CURRENT_SOURCE_DIR}/that_style/header.html)
set(DOXYGEN_HTML_EXTRA_STYLESHEET ${CMAKE_CURRENT_SOURCE_DIR}/that_style/that_style.css)
set(DOXYGEN_HTML_EXTRA_FILES ${CMAKE_CURRENT_SOURCE_DIR}/that_style/img/nav_edge_left.svg
${CMAKE_CURRENT_SOURCE_DIR}/that_style/img/nav_edge_right.svg
${CMAKE_CURRENT_SOURCE_DIR}/that_style/img/nav_edge_inter.svg
${CMAKE_CURRENT_SOURCE_DIR}/that_style/img/sync_off.png
${CMAKE_CURRENT_SOURCE_DIR}/that_style/img/sync_on.png
${CMAKE_CURRENT_SOURCE_DIR}/that_style/img/splitbar_handle.svg
${CMAKE_CURRENT_SOURCE_DIR}/that_style/img/doc.svg
${CMAKE_CURRENT_SOURCE_DIR}/that_style/img/mag_glass.svg
${CMAKE_CURRENT_SOURCE_DIR}/that_style/img/folderclosed.svg
${CMAKE_CURRENT_SOURCE_DIR}/that_style/img/folderopen.svg
${CMAKE_CURRENT_SOURCE_DIR}/that_style/js/striped_bg.js)
set(DOXYGEN_EXCLUDE_PATTERNS */src/external/* fe25519.h ge25519.h sc25519.h
blf.h)
set(DOXYGEN_EXCLUDE_SYMBOLS_STRUCTS chacha20_poly1305_keysched,dh_ctx,dh_ctx,dh_keypair,error_struct,
packet_struct,pem_get_password_struct,ssh_tokens_st,
sftp_attributes_struct,sftp_client_message_struct,
sftp_dir_struct,sftp_ext_struct,sftp_file_struct,sftp_message_struct,
sftp_packet_struct,sftp_request_queue_struct,sftp_session_struct,
sftp_status_message_struct,ssh_agent_state_struct,
ssh_agent_struct,ssh_auth_auto_state_struct,ssh_auth_request,
ssh_bind_config_keyword_table_s,ssh_bind_config_match_keyword_table_s,
ssh_bind_struct,ssh_buffer_struct,ssh_channel_callbacks_struct,
ssh_channel_read_termination_struct,ssh_channel_request,
ssh_channel_request_open,ssh_channel_struct,ssh_cipher_struct,
ssh_common_struct,ssh_config_keyword_table_s,
ssh_config_match_keyword_table_s,ssh_connector_struct,
ssh_counter_struct,ssh_crypto_struct,ssh_event_fd_wrapper,
ssh_event_struct,ssh_global_request,ssh_gssapi_struct,ssh_hmac_struct,
ssh_iterator,ssh_kbdint_struct,ssh_kex_struct,ssh_key_struct,
ssh_knownhosts_entry,ssh_list,ssh_mac_ctx_struct,ssh_message_struct,
ssh_packet_callbacks_struct,ssh_packet_header,ssh_poll_ctx_struct,
ssh_poll_handle_struct,ssh_pollfd_struct,ssh_private_key_struct,
ssh_public_key_struct,ssh_scp_struct,ssh_service_request,
ssh_session_struct,ssh_signature_struct,ssh_socket_struct,
ssh_string_struct,ssh_threads_callbacks_struct,ssh_timestamp,)
set(DOXYGEN_EXCLUDE_SYMBOLS_MACRO SSH_FXP*,SSH_SOCKET*,SERVERBANNER,SOCKOPT_TYPE_ARG4,SSH_FILEXFER*,
SSH_FXF*,SSH_S_*,SFTP_*,NSS_BUFLEN_PASSWD,CLOCK,MAX_LINE_SIZE,
PKCS11_URI,KNOWNHOSTS_MAXTYPES,)
set(DOXYGEN_EXCLUDE_SYMBOLS_TYPEDEFS sftp_attributes,sftp_client_message,sftp_dir,sftp_ext,sftp_file,
sftp_message,sftp_packet,sftp_request_queue,sftp_session,
sftp_status_message,sftp_statvfs_t,poll_fn,ssh_callback_int,
ssh_callback_data,ssh_callback_int_int,ssh_message_callback,
ssh_channel_callback_int,ssh_channel_callback_data,ssh_callbacks,
ssh_gssapi_select_oid_callback,ssh_gssapi_accept_sec_ctx_callback,
ssh_gssapi_verify_mic_callback,ssh_server_callbacks,ssh_socket_callbacks,
ssh_packet_callbacks,ssh_channel_callbacks,ssh_bind,ssh_bind_callbacks,)
set(DOXYGEN_EXCLUDE_SYMBOLS ${DOXYGEN_EXCLUDE_SYMBOLS_STRUCTS}
${DOXYGEN_EXCLUDE_SYMBOLS_MACRO}
${DOXYGEN_EXCLUDE_SYMBOLS_TYPEDEFS})
# This updates the Doxyfile if we do changes here
set(_doxyfile_template "${CMAKE_BINARY_DIR}/CMakeDoxyfile.in")
set(_target_doxyfile "${CMAKE_CURRENT_BINARY_DIR}/Doxyfile.docs")
configure_file("${_doxyfile_template}" "${_target_doxyfile}")
doxygen_add_docs(docs
${CMAKE_SOURCE_DIR}/include/libssh
${CMAKE_SOURCE_DIR}/src
${CMAKE_CURRENT_SOURCE_DIR})
add_custom_target(docs_coverage COMMAND ${CMAKE_SOURCE_DIR}/doc/doc_coverage.sh ${CMAKE_BINARY_DIR})
endif() # DOXYGEN_FOUND
endif() # CMAKE_VERSION

View File

@@ -1,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

@@ -1,378 +0,0 @@
/**
@page libssh_tutor_authentication Chapter 2: A deeper insight on authentication
@section authentication_details A deeper insight on authentication
In our guided tour, we merely mentioned that the user needed to authenticate.
We didn't explain much in detail how that was supposed to happen.
This chapter explains better the four authentication methods: with public keys,
with a password, with challenges and responses (keyboard-interactive), and with
no authentication at all.
If your software is supposed to connect to an arbitrary server, then you
might need to support all authentication methods. If your software will
connect only to a given server, then it might be enough for your software
to support only the authentication methods used by that server. If you are
the administrator of the server, it might be your call to choose those
authentication methods.
It is not the purpose of this document to review in detail the advantages
and drawbacks of each authentication method. You are therefore invited
to read the abundant documentation on this topic to fully understand the
advantages and security risks linked to each method.
@subsection pubkeys Authenticating with public keys
libssh is fully compatible with the openssh public and private keys. You
can either use the automatic public key authentication method provided by
libssh, or roll your own using the public key functions.
The process of authenticating by public key to a server is the following:
- you scan a list of files that contain public keys. each key is sent to
the SSH server, until the server acknowledges a key (a key it knows can be
used to authenticate the user).
- then, you retrieve the private key for this key and send a message
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
"~/.ssh/". The return values are the following:
- SSH_AUTH_ERROR: some serious error happened during authentication
- SSH_AUTH_DENIED: no key matched
- SSH_AUTH_SUCCESS: you are now authenticated
- SSH_AUTH_PARTIAL: some key matched but you still have to provide an other
mean of authentication (like a password).
The ssh_userauth_publickey_auto() function also tries to authenticate using the
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:
- Retrieve the public key with ssh_pki_import_pubkey_file().
- 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
authenticate using the public key and you can go to the next step.
- Retrieve the private key, using the ssh_pki_import_privkey_file() function.
If a passphrase is needed, either the passphrase specified as argument or
a callback will be used.
- Authenticate using ssh_userauth_publickey() with your private key.
- Do not forget cleaning up memory using ssh_key_free().
Here is a minimalistic example of public key authentication:
@code
int authenticate_pubkey(ssh_session session)
{
int rc;
rc = ssh_userauth_publickey_auto(session, NULL, NULL);
if (rc == SSH_AUTH_ERROR)
{
fprintf(stderr, "Authentication failed: %s\n",
ssh_get_error(session));
return SSH_AUTH_ERROR;
}
return rc;
}
@endcode
@see ssh_userauth_publickey_auto()
@see ssh_userauth_try_publickey()
@see ssh_userauth_publickey()
@see ssh_pki_import_pubkey_file()
@see ssh_pki_import_privkey_file()
@see ssh_key_free()
@subsection password Authenticating with a password
The function ssh_userauth_password() serves the purpose of authenticating
using a password. It will return SSH_AUTH_SUCCESS if the password worked,
or one of other constants otherwise. It's your work to ask the password
and to deallocate it in a secure manner.
If your server complains that the password is wrong, but you can still
authenticate using openssh's client (issuing password), it's probably
because openssh only accept keyboard-interactive. Switch to
keyboard-interactive authentication, or try to configure plain text passwords
on the SSH server.
Here is a small example of password authentication:
@code
int authenticate_password(ssh_session session)
{
char *password = NULL;
int rc;
password = getpass("Enter your password: ");
rc = ssh_userauth_password(session, NULL, password);
if (rc == SSH_AUTH_ERROR)
{
fprintf(stderr, "Authentication failed: %s\n",
ssh_get_error(session));
return SSH_AUTH_ERROR;
}
return rc;
}
@endcode
@see ssh_userauth_password
@subsection keyb_int The keyboard-interactive authentication method
The keyboard-interactive method is, as its name tells, interactive. The
server will issue one or more challenges that the user has to answer,
until the server takes an authentication decision.
ssh_userauth_kbdint() is the the main keyboard-interactive function.
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.
The keyboard-interactive authentication method of SSH2 is a feature that
permits the server to ask a certain number of questions in an interactive
manner to the client, until it decides to accept or deny the login.
To begin, you call ssh_userauth_kbdint() (just set user and submethods to
NULL) and store the answer.
If the answer is SSH_AUTH_INFO, it means that the server has sent a few
questions that you should ask the user. You can retrieve these questions
with the following functions: ssh_userauth_kbdint_getnprompts(),
ssh_userauth_kbdint_getname(), ssh_userauth_kbdint_getinstruction(), and
ssh_userauth_kbdint_getprompt().
Set the answer for each question in the challenge using
ssh_userauth_kbdint_setanswer().
Then, call again ssh_userauth_kbdint() and start the process again until
these functions returns something else than SSH_AUTH_INFO.
Here are a few remarks:
- 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
on my system) after you have sent the answers to the first questions.
You must still parse the answer, it might contain some
message from the server saying hello or such things. Just call
ssh_userauth_kbdint() until needed.
- The meaning of "name", "prompt", "instruction" may be a little
confusing. An explanation is given in the RFC section that follows.
Here is a little note about how to use the information from
keyboard-interactive authentication, coming from the RFC itself (rfc4256):
@verbatim
3.3 User Interface Upon receiving a request message, the client SHOULD
prompt the user as follows: A command line interface (CLI) client SHOULD
print the name and instruction (if non-empty), adding newlines. Then for
each prompt in turn, the client SHOULD display the prompt and read the
user input.
A graphical user interface (GUI) client has many choices on how to prompt
the user. One possibility is to use the name field (possibly prefixed
with the application's name) as the title of a dialog window in which
the prompt(s) are presented. In that dialog window, the instruction field
would be a text message, and the prompts would be labels for text entry
fields. All fields SHOULD be presented to the user, for example an
implementation SHOULD NOT discard the name field because its windows lack
titles; it SHOULD instead find another way to display this information. If
prompts are presented in a dialog window, then the client SHOULD NOT
present each prompt in a separate window.
All clients MUST properly handle an instruction field with embedded
newlines. They SHOULD also be able to display at least 30 characters for
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
display. If the client does truncate any fields, there MUST be an obvious
indication that such truncation has occurred.
The instruction field SHOULD NOT be truncated. Clients SHOULD use control
character filtering as discussed in [SSH-ARCH] to avoid attacks by
including terminal control characters in the fields to be displayed.
For each prompt, the corresponding echo field indicates whether or not
the user input should be echoed as characters are typed. Clients SHOULD
correctly echo/mask user input for each prompt independently of other
prompts in the request message. If a client does not honor the echo field
for whatever reason, then the client MUST err on the side of
masking input. A GUI client might like to have a checkbox toggling
echo/mask. Clients SHOULD NOT add any additional characters to the prompt
such as ": " (colon-space); the server is responsible for supplying all
text to be displayed to the user. Clients MUST also accept empty responses
from the user and pass them on as empty strings.
@endverbatim
The following example shows how to perform keyboard-interactive authentication:
@code
int authenticate_kbdint(ssh_session session)
{
int rc;
rc = ssh_userauth_kbdint(session, NULL, NULL);
while (rc == SSH_AUTH_INFO)
{
const char *name = NULL, *instruction = NULL;
int nprompts, iprompt;
name = ssh_userauth_kbdint_getname(session);
instruction = ssh_userauth_kbdint_getinstruction(session);
nprompts = ssh_userauth_kbdint_getnprompts(session);
if (strlen(name) > 0)
printf("%s\n", name);
if (strlen(instruction) > 0)
printf("%s\n", instruction);
for (iprompt = 0; iprompt < nprompts; iprompt++)
{
const char *prompt = NULL;
char echo;
prompt = ssh_userauth_kbdint_getprompt(session, iprompt, &echo);
if (echo)
{
char buffer[128], *ptr;
printf("%s", prompt);
if (fgets(buffer, sizeof(buffer), stdin) == NULL)
return SSH_AUTH_ERROR;
buffer[sizeof(buffer) - 1] = '\0';
if ((ptr = strchr(buffer, '\n')) != NULL)
*ptr = '\0';
if (ssh_userauth_kbdint_setanswer(session, iprompt, buffer) < 0)
return SSH_AUTH_ERROR;
memset(buffer, 0, strlen(buffer));
}
else
{
char *ptr = NULL;
ptr = getpass(prompt);
if (ssh_userauth_kbdint_setanswer(session, iprompt, ptr) < 0)
return SSH_AUTH_ERROR;
}
}
rc = ssh_userauth_kbdint(session, NULL, NULL);
}
return rc;
}
@endcode
@see ssh_userauth_kbdint()
@see ssh_userauth_kbdint_getnprompts()
@see ssh_userauth_kbdint_getname()
@see ssh_userauth_kbdint_getinstruction()
@see ssh_userauth_kbdint_getprompt()
@see ssh_userauth_kbdint_setanswer()
@subsection none Authenticating with "none" method
The primary purpose of the "none" method is to get authenticated **without**
any credential. Don't do that, use one of the other authentication methods,
unless you really want to grant anonymous access.
If the account has no password, and if the server is configured to let you
pass, ssh_userauth_none() might answer SSH_AUTH_SUCCESS.
The following example shows how to perform "none" authentication:
@code
int authenticate_none(ssh_session session)
{
int rc;
rc = ssh_userauth_none(session, NULL);
return rc;
}
@endcode
@subsection auth_list Getting the list of supported authentications
You are not meant to choose a given authentication method, you can
let the server tell you which methods are available. Once you know them,
you try them one after the other.
The following example shows how to get the list of available authentication
methods with ssh_userauth_list() and how to use the result:
@code
int test_several_auth_methods(ssh_session session)
{
int method, rc;
rc = ssh_userauth_none(session, NULL);
if (rc == SSH_AUTH_SUCCESS || rc == SSH_AUTH_ERROR) {
return rc;
}
method = ssh_userauth_list(session, NULL);
if (method & SSH_AUTH_METHOD_NONE)
{ // For the source code of function authenticate_none(),
// refer to the corresponding example
rc = authenticate_none(session);
if (rc == SSH_AUTH_SUCCESS) return rc;
}
if (method & SSH_AUTH_METHOD_PUBLICKEY)
{ // For the source code of function authenticate_pubkey(),
// refer to the corresponding example
rc = authenticate_pubkey(session);
if (rc == SSH_AUTH_SUCCESS) return rc;
}
if (method & SSH_AUTH_METHOD_INTERACTIVE)
{ // For the source code of function authenticate_kbdint(),
// refer to the corresponding example
rc = authenticate_kbdint(session);
if (rc == SSH_AUTH_SUCCESS) return rc;
}
if (method & SSH_AUTH_METHOD_PASSWORD)
{ // For the source code of function authenticate_password(),
// refer to the corresponding example
rc = authenticate_password(session);
if (rc == SSH_AUTH_SUCCESS) return rc;
}
return SSH_AUTH_ERROR;
}
@endcode
@subsection banner Getting the banner
The SSH server might send a banner, which you can retrieve with
ssh_get_issue_banner(), then display to the user.
The following example shows how to retrieve and dispose the issue banner:
@code
int display_banner(ssh_session session)
{
int rc;
char *banner = NULL;
/*
*** Does not work without calling ssh_userauth_none() first ***
*** That will be fixed ***
*/
rc = ssh_userauth_none(session, NULL);
if (rc == SSH_AUTH_ERROR)
return rc;
banner = ssh_get_issue_banner(session);
if (banner)
{
printf("%s\n", banner);
free(banner);
}
return rc;
}
@endcode
*/

View File

@@ -1,100 +0,0 @@
/**
@page libssh_tutor_command Chapter 4: Passing a remote command
@section remote_command Passing a remote command
Previous chapter has shown how to open a full shell session, with an attached
terminal or not. If you only need to execute a command on the remote end,
you don't need all that complexity.
The method described here is suited for executing only one remote command.
If you need to issue several commands in a row, you should consider using
a non-interactive remote shell, as explained in previous chapter.
@see shell
@subsection exec_remote Executing a remote command
The first steps for executing a remote command are identical to those
for opening remote shells. You first need a SSH channel, and then
a SSH session that uses this channel:
@code
int show_remote_files(ssh_session session)
{
ssh_channel channel = NULL;
int rc;
channel = ssh_channel_new(session);
if (channel == NULL) return SSH_ERROR;
rc = ssh_channel_open_session(channel);
if (rc != SSH_OK)
{
ssh_channel_free(channel);
return rc;
}
@endcode
Once a session is open, you can start the remote command with
ssh_channel_request_exec():
@code
rc = ssh_channel_request_exec(channel, "ls -l");
if (rc != SSH_OK)
{
ssh_channel_close(channel);
ssh_channel_free(channel);
return rc;
}
@endcode
If the remote command displays data, you get them with ssh_channel_read().
This function returns the number of bytes read. If there is no more
data to read on the channel, this function returns 0, and you can go to next step.
If an error has been encountered, it returns a negative value:
@code
char buffer[256];
int nbytes;
nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
while (nbytes > 0)
{
if (fwrite(buffer, 1, nbytes, stdout) != nbytes)
{
ssh_channel_close(channel);
ssh_channel_free(channel);
return SSH_ERROR;
}
nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
}
if (nbytes < 0)
{
ssh_channel_close(channel);
ssh_channel_free(channel);
return SSH_ERROR;
}
@endcode
Once you read the result of the remote command, you send an
end-of-file to the channel, close it, and free the memory
that it used:
@code
ssh_channel_send_eof(channel);
ssh_channel_close(channel);
ssh_channel_free(channel);
return SSH_OK;
}
@endcode
Warning: In a single channel, only ONE command can be executed!
If you want to executed multiple commands, allocate separate channels for
them or consider opening interactive shell.
Attempting to run multiple consecutive commands in one channel will fail.
*/

View File

@@ -1,119 +0,0 @@
curve25519-sha256@libssh.org.txt Aris Adamantiadis <aris@badcode.be>
21/9/2013
1. Introduction
This document describes the key exchange method curve25519-sha256@libssh.org
for SSH version 2 protocol. It is provided as an alternative to the existing
key exchange mechanisms based on either Diffie-Hellman or Elliptic Curve Diffie-
Hellman [RFC5656].
The reason is the following : During summer of 2013, revelations from ex-
consultant at NSA Edward Snowden gave proof that NSA willingly inserts backdoors
into software, hardware components and published standards. While it is still
believed that the mathematics behind ECC cryptography are still sound and solid,
some people (including Bruce Schneier [SCHNEIER]), showed their lack of confidence
in NIST-published curves such as nistp256, nistp384, nistp521, for which constant
parameters (including the generator point) are defined without explanation. It
is also believed that NSA had a word to say in their definition. These curves
are not the most secure or fastest possible for their key sizes [DJB], and
researchers think it is possible that NSA have ways of cracking NIST curves.
It is also interesting to note that SSH belongs to the list of protocols the NSA
claims to be able to eavesdrop. Having a secure replacement would make passive
attacks much harder if such a backdoor exists.
However an alternative exists in the form of Curve25519. This algorithm has been
proposed in 2006 by DJB [Curve25519]. Its main strengths are its speed, its
constant-time run time (and resistance against side-channel attacks), and its
lack of nebulous hard-coded constants.
The reference version being used in this document is the one described in
[Curve25519] as implemented in the library NaCl [NaCl].
This document does not attempt to provide alternatives to the ecdsa-sha1-*
authentication keys.
2. Key exchange
The key exchange procedure is very similar to the one described chapter 4 of
[RFC5656]. Public ephemeral keys are transmitted over SSH encapsulated into
standard SSH strings.
The following is an overview of the key exchange process:
Client Server
------ ------
Generate ephemeral key pair.
SSH_MSG_KEX_ECDH_INIT -------->
Verify that client public key
length is 32 bytes.
Generate ephemeral key pair.
Compute shared secret.
Generate and sign exchange hash.
<-------- SSH_MSG_KEX_ECDH_REPLY
Verify that server public key length is 32 bytes.
* Verify host keys belong to server.
Compute shared secret.
Generate exchange hash.
Verify server's signature.
* Optional but strongly recommended as this protects against MITM attacks.
This is implemented using the same messages as described in RFC5656 chapter 4
3. Method Name
The name of this key exchange method is "curve25519-sha256@libssh.org".
4. Implementation considerations
The whole method is based on the curve25519 scalar multiplication. In this
method, a private key is a scalar of 256 bits, and a public key is a point
of 256 bits.
4.1. Private key generation
A 32 bytes private key should be generated for each new connection,
using a secure PRNG. The following actions must be done on the private key:
mysecret[0] &= 248;
mysecret[31] &= 127;
mysecret[31] |= 64;
In order to keep the key valid. However, many cryptographic libraries will do
this automatically.
It should be noted that, in opposition to NIST curves, no special validation
should be done to ensure the result is a valid and secure private key.
4.2 Public key generation
The 32 bytes public key of either a client or a server must be generated using
the 32 bytes private key and a common generator base. This base is defined as 9
followed by all zeroes:
const unsigned char basepoint[32] = {9};
The public key is calculated using the cryptographic scalar multiplication:
const unsigned char privkey[32];
unsigned char pubkey[32];
crypto_scalarmult (pubkey, privkey, basepoint);
However some cryptographic libraries may provide a combined function:
crypto_scalarmult_base (pubkey, privkey);
It should be noted that, in opposition to NIST curves, no special validation
should be done to ensure the received public keys are valid curves point. The
Curve25519 algorithm ensure that every possible public key maps to a valid
ECC Point.
4.3 Shared secret generation
The shared secret, k, is defined in SSH specifications to be a big integer.
This number is calculated using the following procedure:
X is the 32 bytes point obtained by the scalar multiplication of the other
side's public key and the local private key scalar.
The whole 32 bytes of the number X are then converted into a big integer k.
This conversion follows the network byte order. This step differs from
RFC5656.
[RFC5656] https://tools.ietf.org/html/rfc5656
[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
[Curve25519] "Curve25519: new Diffie-Hellman speed records."
https://cr.yp.to/ecdh/curve25519-20060209.pdf

View File

@@ -1,52 +0,0 @@
#!/bin/bash
################################################################################
# .doc_coverage.sh #
# Script to detect overall documentation coverage of libssh. The script uses #
# doxygen to generate the documentation then parses it's output. #
# #
# maintainer: Norbert Pocs <npocs@redhat.com> #
################################################################################
BUILD_DIR="$1"
DOXYFILE_PATH="$BUILD_DIR/doc/Doxyfile.docs"
INDEX_XML_PATH="$BUILD_DIR/doc/xml/index.xml"
# filters
F_EXCLUDE_FILES=' wrapper.h legacy.h crypto.h priv.h chacha.h curve25519.h '
F_UNDOC_FUNC='(function).*is not documented'
F_FUNC='kind="function"'
F_HEADERS='libssh_8h_|group__libssh__'
F_CUT_BEFORE='.*<name>'
F_CUT_AFTER='<\/name><\/member>'
# Doxygen options
O_QUIET='QUIET=YES'
O_GEN_XML='GENERATE_XML=YES'
# check if build dir given
if [ $# -eq 0 ]; then
echo "Please provide the build directory e.g.: ./build"
exit 255
fi
# modify doxyfile to our needs:
# QUIET - less output
# GENERATE_XML - xml needed to inspect all the functions
# (note: the options are needed to be on separate lines)
# We want to exclude irrelevant files
MOD_DOXYFILE=$(cat "$DOXYFILE_PATH"; echo "$O_QUIET"; echo "$O_GEN_XML")
MOD_DOXYFILE=${MOD_DOXYFILE//EXCLUDE_PATTERNS.*=/EXCLUDE_PATTERNS=$F_EXCLUDE_FILES/g}
# call doxygen to get the warning messages
# and also generate the xml for inspection
DOXY_WARNINGS=$(echo "$MOD_DOXYFILE" | doxygen - 2>&1)
# get the number of undocumented functions
UNDOC_FUNC=$(echo "$DOXY_WARNINGS" | grep -cE "$F_UNDOC_FUNC")
# filter out the lines consisting of functions of our interest
FUNC_LINES=$(grep "$F_FUNC" "$INDEX_XML_PATH" | grep -E "$F_HEADERS")
# cut the irrelevant information and leave just the function names
ALL_FUNC=$(echo "$FUNC_LINES" | sed -e "s/$F_CUT_BEFORE//g" -e "s/$F_CUT_AFTER//")
# remove duplicates and get the number of functions
ALL_FUNC=$(echo "$ALL_FUNC" | sort - | uniq | wc -l)
# percentage of the documented functions
awk "BEGIN {printf \"Documentation coverage is %.2f%\n\", 100 - (${UNDOC_FUNC}/${ALL_FUNC}*100)}"

1540
doc/doxy.config.in Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,236 +0,0 @@
/**
@page libssh_tutor_forwarding Chapter 7: Forwarding connections (tunnel)
@section forwarding_connections Forwarding connections
Port forwarding comes in SSH protocol in two different flavours:
direct or reverse port forwarding. Direct port forwarding is also
named local port forwarding, and reverse port forwarding is also called
remote port forwarding. SSH also allows X11 tunnels.
@subsection forwarding_direct Direct port forwarding
Direct port forwarding is from client to server. The client opens a tunnel,
and forwards whatever data to the server. Then, the server connects to an
end point. The end point can reside on another machine or on the SSH
server itself.
Example of use of direct port forwarding:
@verbatim
Mail client application Google Mail
| ^
5555 (arbitrary) |
| 143 (IMAP2)
V |
SSH client =====> SSH server
Legend:
--P-->: port connections through port P
=====>: SSH tunnel
@endverbatim
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
end point). Now the local mail client can retrieve mail.
@subsection forwarding_reverse Reverse port forwarding
The reverse forwarding is slightly different. It goes from server to client,
even though the client has the initiative of establishing the tunnel.
Once the tunnel is established, the server will listen on a port. Whenever
a connection to this port is made, the server forwards the data to the client.
Example of use of reverse port forwarding:
@verbatim
Local mail server Mail client application
^ |
| 5555 (arbitrary)
143 (IMAP2) |
| V
SSH client <===== SSH server
Legend:
--P-->: port connections through port P
=====>: SSH tunnel
@endverbatim
In this example, the SSH client establishes the tunnel,
but it is used to forward the connections established at
the server to the client.
@subsection forwarding_x11 X11 tunnels
X11 tunnels allow a remote application to display locally.
Example of use of X11 tunnels:
@verbatim
Local display Graphical application
(X11 server) (X11 client)
^ |
| V
SSH client <===== SSH server
Legend:
----->: X11 connection through X11 display number
=====>: SSH tunnel
@endverbatim
The SSH tunnel is established by the client.
How to establish X11 tunnels with libssh has already been described in
this tutorial.
@see x11
@subsection libssh_direct Doing direct port forwarding with libssh
To do direct port forwarding, call function ssh_channel_open_forward():
- you need a separate channel for the tunnel as first parameter;
- second and third parameters are the remote endpoint;
- fourth and fifth parameters are sent to the remote server
so that they can be logged on that server.
If you don't plan to forward the data you will receive to any local port,
just put fake values like "localhost" and 5555 as your local host and port.
The example below shows how to open a direct channel that would be
used to retrieve google's home page from the remote SSH server.
@code
int direct_forwarding(ssh_session session)
{
ssh_channel forwarding_channel = NULL;
int rc = SSH_ERROR;
char *http_get = "GET / HTTP/1.1\nHost: www.google.com\n\n";
int nbytes, nwritten;
forwarding_channel = ssh_channel_new(session);
if (forwarding_channel == NULL) {
return rc;
}
rc = ssh_channel_open_forward(forwarding_channel,
"www.google.com", 80,
"localhost", 5555);
if (rc != SSH_OK)
{
ssh_channel_free(forwarding_channel);
return rc;
}
nbytes = strlen(http_get);
nwritten = ssh_channel_write(forwarding_channel,
http_get,
nbytes);
if (nbytes != nwritten)
{
ssh_channel_free(forwarding_channel);
return SSH_ERROR;
}
...
ssh_channel_free(forwarding_channel);
return SSH_OK;
}
@endcode
The data sent by Google can be retrieved for example with ssh_select()
and ssh_channel_read(). Goggle's home page can then be displayed on the
local SSH client, saved into a local file, made available on a local port,
or whatever use you have for it.
@subsection libssh_reverse Doing reverse port forwarding with libssh
To do reverse port forwarding, call ssh_channel_listen_forward(),
then ssh_channel_accept_forward().
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
your own privileged or non-privileged port. Beware that you should have
administrative privileges on the remote server to open a privileged port
(port number < 1024).
Below is an example of a very rough web server waiting for connections on port
8080 of remote SSH server. The incoming connections are passed to the
local libssh application, which handles them:
@code
int web_server(ssh_session session)
{
int rc;
ssh_channel channel = NULL;
char buffer[256];
int nbytes, nwritten;
int port = 0;
char *peer_address = NULL;
int peer_port = 0;
char *helloworld = ""
"HTTP/1.1 200 OK\n"
"Content-Type: text/html\n"
"Content-Length: 113\n"
"\n"
"<html>\n"
" <head>\n"
" <title>Hello, World!</title>\n"
" </head>\n"
" <body>\n"
" <h1>Hello, World!</h1>\n"
" </body>\n"
"</html>\n";
rc = ssh_channel_listen_forward(session, NULL, 8080, NULL);
if (rc != SSH_OK)
{
fprintf(stderr, "Error opening remote port: %s\n",
ssh_get_error(session));
return rc;
}
channel = ssh_channel_open_forward_port(session, 60000, &port,
&peer_address, &peer_port);
if (channel == NULL)
{
fprintf(stderr, "Error waiting for incoming connection: %s\n",
ssh_get_error(session));
return SSH_ERROR;
}
while (1)
{
nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
if (nbytes < 0)
{
fprintf(stderr, "Error reading incoming data: %s\n",
ssh_get_error(session));
ssh_channel_send_eof(channel);
ssh_channel_free(channel);
ssh_string_free_char(peer_address);
return SSH_ERROR;
}
if (strncmp(buffer, "GET /", 5)) continue;
nbytes = strlen(helloworld);
nwritten = ssh_channel_write(channel, helloworld, nbytes);
if (nwritten != nbytes)
{
fprintf(stderr, "Error sending answer: %s\n",
ssh_get_error(session));
ssh_channel_send_eof(channel);
ssh_channel_free(channel);
ssh_string_free_char(peer_address);
return SSH_ERROR;
}
printf("Sent answer to %s:%d\n", peer_address, peer_port);
}
ssh_channel_send_eof(channel);
ssh_channel_free(channel);
ssh_string_free_char(peer_address);
return SSH_OK;
}
@endcode
*/

View File

@@ -1,473 +0,0 @@
/**
@page libssh_tutor_guided_tour Chapter 1: A typical SSH session
@section ssh_session A typical SSH session
A SSH session goes through the following steps:
- Before connecting to the server, you can set up if you wish one or other
server public key authentication, i.e. RSA, ED25519 or ECDSA. You can choose
cryptographic algorithms you trust and compression algorithms if any. You
must of course set up the hostname.
- The connection is established. A secure handshake is made, and resulting from
it, a public key from the server is gained. You MUST verify that the public
key is legitimate, using for instance the MD5 fingerprint or the known hosts
file.
- The client must authenticate: the classical ways are password, or
public keys (from ecdsa, ed25519 and rsa key-pairs generated by openssh).
If a SSH agent is running, it is possible to use it.
- Now that the user has been authenticated, you must open one or several
channels. Channels are different subways for information into a single ssh
connection. Each channel has a standard stream (stdout) and an error stream
(stderr). You can theoretically open an infinity of channels.
- With the channel you opened, you can do several things:
- Execute a single command.
- Open a shell. You may want to request a pseudo-terminal before.
- Invoke the sftp subsystem to transfer files.
- Invoke the scp subsystem to transfer files.
- Invoke your own subsystem. This is outside the scope of this document,
but can be done.
- 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 programmer. If you want to use those subsystems, instead of a channel,
you'll usually open a "sftp session" or a "scp session".
@subsection setup Creating the session and setting options
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
always verify that the allocation succeeded.
@code
#include <libssh/libssh.h>
#include <stdlib.h>
int main()
{
ssh_session my_ssh_session = ssh_new();
if (my_ssh_session == NULL)
exit(-1);
...
ssh_free(my_ssh_session);
}
@endcode
libssh follows the allocate-it-deallocate-it pattern. Each object that you allocate
using xxxxx_new() must be deallocated using xxxxx_free(). In this case, ssh_new()
does the allocation and ssh_free() does the contrary.
The ssh_options_set() function sets the options of the session. The most important options are:
- SSH_OPTIONS_HOST: the name of the host you want to connect to
- SSH_OPTIONS_PORT: the used port (default is port 22)
- SSH_OPTIONS_USER: the system user under which you want to connect
- SSH_OPTIONS_LOG_VERBOSITY: the quantity of messages that are printed
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 local username of your account will be used.
Here is a small example of how to use it:
@code
#include <libssh/libssh.h>
#include <stdlib.h>
int main()
{
ssh_session my_ssh_session = NULL;
int verbosity = SSH_LOG_PROTOCOL;
int port = 22;
my_ssh_session = ssh_new();
if (my_ssh_session == NULL)
exit(-1);
ssh_options_set(my_ssh_session, SSH_OPTIONS_HOST, "localhost");
ssh_options_set(my_ssh_session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity);
ssh_options_set(my_ssh_session, SSH_OPTIONS_PORT, &port);
...
ssh_free(my_ssh_session);
}
@endcode
Please notice that all parameters are passed to ssh_options_set() as pointers,
even if you need to set an integer value.
@see ssh_new
@see ssh_free
@see ssh_options_set
@see ssh_options_parse_config
@see ssh_options_copy
@see ssh_options_getopt
@subsection connect Connecting to the server
Once all settings have been made, you can connect using ssh_connect(). That
function will return SSH_OK if the connection worked, SSH_ERROR otherwise.
You can get the English error string with ssh_get_error() in order to show the
user what went wrong. Then, use ssh_disconnect() when you want to stop
the session.
Here's an example:
@code
#include <libssh/libssh.h>
#include <stdlib.h>
#include <stdio.h>
int main()
{
ssh_session my_ssh_session = NULL;
int rc;
my_ssh_session = ssh_new();
if (my_ssh_session == NULL)
exit(-1);
ssh_options_set(my_ssh_session, SSH_OPTIONS_HOST, "localhost");
rc = ssh_connect(my_ssh_session);
if (rc != SSH_OK)
{
fprintf(stderr, "Error connecting to localhost: %s\n",
ssh_get_error(my_ssh_session));
exit(-1);
}
...
ssh_disconnect(my_ssh_session);
ssh_free(my_ssh_session);
}
@endcode
@subsection serverauth Authenticating the server
Once you're connected, the following step is mandatory: you must check that the server
you just connected to is known and safe to use (remember, SSH is about security and
authentication).
There are two ways of doing this:
- The first way (recommended) is to use the ssh_session_is_known_server()
function. This function will look into the known host file
(~/.ssh/known_hosts on UNIX), look for the server hostname's pattern,
and determine whether this host is present or not in the list.
- The second way is to use ssh_get_pubkey_hash() to get a binary version
of the public key hash value. You can then use your own database to check
if this public key is known and secure.
You can also use the ssh_get_pubkey_hash() to show the public key hash
value to the user, in case he knows what the public key hash value is
(some paranoid people write their public key hash values on paper before
going abroad, just in case ...).
If the remote host is being used to for the first time, you can ask the user whether
he/she trusts it. Once he/she concluded that the host is valid and worth being
added in the known hosts file, you use ssh_write_knownhost() to register it in
the known hosts file, or any other way if you use your own database.
The following example is part of the examples suite available in the
examples/ directory:
@code
#include <errno.h>
#include <string.h>
int verify_knownhost(ssh_session session)
{
enum ssh_known_hosts_e state;
unsigned char *hash = NULL;
ssh_key srv_pubkey = NULL;
size_t hlen;
char buf[10];
char *hexa = NULL;
char *p = NULL;
int cmp;
int rc;
rc = ssh_get_server_publickey(session, &srv_pubkey);
if (rc < 0) {
return -1;
}
rc = ssh_get_publickey_hash(srv_pubkey,
SSH_PUBLICKEY_HASH_SHA1,
&hash,
&hlen);
ssh_key_free(srv_pubkey);
if (rc < 0) {
return -1;
}
state = ssh_session_is_known_server(session);
switch (state) {
case SSH_KNOWN_HOSTS_OK:
/* OK */
break;
case SSH_KNOWN_HOSTS_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");
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
@see ssh_connect
@see ssh_disconnect
@see ssh_get_error
@see ssh_get_error_code
@see ssh_get_server_publickey
@see ssh_get_publickey_hash
@see ssh_session_is_known_server
@see ssh_session_update_known_hosts
@subsection auth Authenticating the user
The authentication process is the way a service provider can identify a
user and verify his/her identity. The authorization process is about enabling
the authenticated user the access to resources. In SSH, the two concepts
are linked. After authentication, the server can grant the user access to
several resources such as port forwarding, shell, sftp subsystem, and so on.
libssh supports several methods of authentication:
- "none" method. This method allows to get the available authentications
methods. It also gives the server a chance to authenticate the user with
just his/her login. Some very old hardware uses this feature to fallback
the user on a "telnet over SSH" style of login.
- password method. A password is sent to the server, which accepts it or not.
- keyboard-interactive method. The server sends several challenges to the
user, who must answer correctly. This makes possible the authentication
via a codebook for instance ("give code at 23:R on page 3").
- public key method. The host knows the public key of the user, and the
user must prove he knows the associated private key. This can be done
manually, or delegated to the SSH agent as we'll see later.
All these methods can be combined. You can for instance force the user to
authenticate with at least two of the authentication methods. In that case,
one speaks of "Partial authentication". A partial authentication is a
response from authentication functions stating that your credential was
accepted, but yet another one is required to get in.
The example below shows an authentication with password:
@code
#include <libssh/libssh.h>
#include <stdlib.h>
#include <stdio.h>
int main()
{
ssh_session my_ssh_session = NULL;
int rc;
char *password = NULL;
// Open session and set options
my_ssh_session = ssh_new();
if (my_ssh_session == NULL)
exit(-1);
ssh_options_set(my_ssh_session, SSH_OPTIONS_HOST, "localhost");
// Connect to server
rc = ssh_connect(my_ssh_session);
if (rc != SSH_OK)
{
fprintf(stderr, "Error connecting to localhost: %s\n",
ssh_get_error(my_ssh_session));
ssh_free(my_ssh_session);
exit(-1);
}
// Verify the server's identity
// For the source code of verify_knownhost(), check previous example
if (verify_knownhost(my_ssh_session) < 0)
{
ssh_disconnect(my_ssh_session);
ssh_free(my_ssh_session);
exit(-1);
}
// Authenticate ourselves
password = getpass("Password: ");
rc = ssh_userauth_password(my_ssh_session, NULL, password);
if (rc != SSH_AUTH_SUCCESS)
{
fprintf(stderr, "Error authenticating with password: %s\n",
ssh_get_error(my_ssh_session));
ssh_disconnect(my_ssh_session);
ssh_free(my_ssh_session);
exit(-1);
}
...
ssh_disconnect(my_ssh_session);
ssh_free(my_ssh_session);
}
@endcode
@see @ref authentication_details
@subsection using_ssh Doing something
At this point, the authenticity of both server and client is established.
Time has come to take advantage of the many possibilities offered by the SSH
protocol: execute a remote command, open remote shells, transfer files,
forward ports, etc.
The example below shows how to execute a remote command:
@code
int show_remote_processes(ssh_session session)
{
ssh_channel channel = NULL;
int rc;
char buffer[256];
int nbytes;
channel = ssh_channel_new(session);
if (channel == NULL)
return SSH_ERROR;
rc = ssh_channel_open_session(channel);
if (rc != SSH_OK)
{
ssh_channel_free(channel);
return rc;
}
rc = ssh_channel_request_exec(channel, "ps aux");
if (rc != SSH_OK)
{
ssh_channel_close(channel);
ssh_channel_free(channel);
return rc;
}
nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
while (nbytes > 0)
{
if (write(1, buffer, nbytes) != (unsigned int) nbytes)
{
ssh_channel_close(channel);
ssh_channel_free(channel);
return SSH_ERROR;
}
nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
}
if (nbytes < 0)
{
ssh_channel_close(channel);
ssh_channel_free(channel);
return SSH_ERROR;
}
ssh_channel_send_eof(channel);
ssh_channel_close(channel);
ssh_channel_free(channel);
return SSH_OK;
}
@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 remote_command
@see @ref sftp_subsystem
@see @ref scp_subsystem
@subsection errors Handling the errors
All the libssh functions which return an error value also set an English error message
describing the problem.
Error values are typically SSH_ERROR for integer values, or NULL for pointers.
The function ssh_get_error() returns a pointer to the static error message.
ssh_error_code() returns the error code number : SSH_NO_ERROR,
SSH_REQUEST_DENIED, SSH_INVALID_REQUEST, SSH_CONNECTION_LOST, SSH_FATAL,
or SSH_INVALID_DATA. SSH_REQUEST_DENIED means the ssh server refused your
request, but the situation is recoverable. The others mean something happened
to the connection (some encryption problems, server problems, ...).
SSH_INVALID_REQUEST means the library got some garbage from server, but
might be recoverable. SSH_FATAL means the connection has an important
problem and isn't probably recoverable.
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.
In these cases, SSH_REQUEST_DENIED is returned.
For thread safety, errors are bound to ssh_session objects.
As long as your ssh_session object is not NULL, you can retrieve the last error
message and error code from the ssh_session using ssh_get_error() and
ssh_get_error_code() respectively.
The SFTP subsystem has its own error codes, in addition to libssh ones.
*/

View File

@@ -1,53 +0,0 @@
/**
@page libssh_tutorial The Tutorial
@section introduction Introduction
libssh is a C library that enables you to write a program that uses the
SSH protocol. With it, you can remotely execute programs, transfer
files, or use a secure and transparent tunnel for your remote programs.
The SSH protocol is encrypted, ensures data integrity, and provides strong
means of authenticating both the server of the client. The library hides
a lot of technical details from the SSH protocol, but this does not
mean that you should not try to know about and understand these details.
libssh is a Free Software / Open Source project. The libssh library
is distributed under LGPL license. The libssh project has nothing to do with
"libssh2", which is a completely different and independent project.
libssh can run on top of either libcrypto, mbedtls or libgcrypt (deprecated)
general-purpose cryptographic libraries.
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),
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
from the 0.4.X series. However, the examples should work with
little changes on versions like 0.4.2 and later.
Table of contents:
@subpage libssh_tutor_guided_tour
@subpage libssh_tutor_authentication
@subpage libssh_tutor_shell
@subpage libssh_tutor_command
@subpage libssh_tutor_sftp
@subpage libssh_tutor_scp
@subpage libssh_tutor_forwarding
@subpage libssh_tutor_threads
@subpage libssh_tutor_pkcs11
@subpage libssh_tutor_sftp_aio
@subpage libssh_tutor_todo
*/

385
doc/libssh-0.2-api-1.txt Normal file
View File

@@ -0,0 +1,385 @@
The new libssh 0.2 API
----------------------
Version 1
A. Introduction
---------------
With the time from the first release of libssh, I have received lots of
comments about the current API. Myself, I found it quite limiting when doing
my first libssh-server drafts. Thus, I am moving to a stronger API.
This API must still be simple. I am not introducing complex changes. An API
well designed must hide the implementation details. Implementation can change
easily within bugfixes - but API cannot change each release.
To the people already using libssh 0.11 : sorry. Once I have the complete API
redesigned, I will write a migration paper. It won't be too hard normally.
Here are the things that were lacking in the previous API and *must* change:
* A non-blocking mode connection type
* Functions to relegate File descriptor listening to Calling functions and to
the programmer. (I'll explain later).
* Along with that, good buffering system (well, it's not an API but).
* Leave the "functions returns a pointer when it works and NULL when it does
not work". It gives serious problems to implement bindings (A C++
constructor should not fail and should not depend on a network thing
* Make the Session structure an abstract structure that can work with both
client and *servers*. That mean we should have a Server object which listen
to clients on a bound port, does the different handshakes and return a
session.
Since C is not per se an Object language, I won't use inheritance between
objects.
* This same server thing must provide the reverse capabilities than the
client. That is, accept the handshake, in a nonblocking way. Accept channel
requests, or send them to the controller program.
* Support for program forking : Imagine you have a Ssh server object. You
accept a connection and receive a session, then you receive a channel. You
may want to keep the good old days fork() tricks. Libssh will give a way to
destroy handlers from sessions which belong to an other process without
disturbing the session.
* So often I received the comment back saying that it was not clear why a
session or a channel was terminated. This is over.
* And of course I received lot of mails about the fact I'm doing namespace
polution. this will be resolved this time.
So, please read this draft not as a formal documentation but like a roadmap of
things that each kind of object must do.
B. Description of objects and functions
Initialization and finalization
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Initialization is for now called automatically, so you don't have to take care
of that.
As for finalization, we need to finalize the underlying cryptographic library
(either OpenSSL or libgcrypt). Be sure that you call ssh_finalize when this
library won't be used anymore, even by other libraries (i.e. if you use libssh
and another library that uses OpenSSL, call ssh_finalize when any function of
both these libraries won't be called).
If you trust your operating system to clean up the mess after a process
terminates, you can skip this call.
Options structure
~~~~~~~~~~~~~~~~~
struct ssh_options *ssh_options_new()
ssh_options_getopt(options, *argc, argv)
ssh_options_copy(options)
char ** ssh_options_get_supported_algos(options,type)
returns a list of the algos supported by libssh, type being one of
SSH_HOSTKEYS, SSH_KEX, SSH_CRYPT, SSH_MAC, SSH_COMP, SSH_LANG
ssh_options_set_wanted_algos(options,type, char *list)
list being comma-separated list of algos, and type being the upper constants
but with _C_S or _S_V added to them.
ssh_options_set_port(options, port)
ssh_options_set_host(options, host)
ssh_options_set_fd(options, fd)
ssh_options_set_bind(options, bindaddr, port)
this options sets the address to bind for a client *or* a server. a port of
zero means whatever port is free (what most clients want).
ssh_options_set_username(options, username)
ssh_options_set_connect_timeout(options, seconds, usec)
ssh_options_set_ssh_dir(options, dir)
ssh_options_set_known_hosts_file(options, file)
ssh_options_set_identity(options, file)
ssh_options_set_banner(options, banner)
ssh_options_allow_ssh1(options, bool allow)
ssh_options_allow_ssh2(options, bool allow)
options_set_status_callback has moved into ssh_* functions.
ssh_session Structure
~~~~~~~~~~~~~~~~~~~~~
This session structure represents a ssh socket to a server *or* a client.
ssh_session *ssh_new()
ssh_set_options(ssh_session,ssh_options)
ssh_connect(session);
it will return some status describing at which point of the connection it is,
or an error code. If the connection method is non-blocking, the function
will be called more than once, though the return value SSH_AGAIN.
ssh_set_blocking(session, bool blocking)
set blocking mode or non blocking mode.
ssh_get_fd(session)
get the currently used connection file descriptor or equivalent (windows)
ssh_set_fd_toread(session)
ssh_set_fd_towrite(session)
ssh_set_fd_except(session)
Serve to notify the library that data is actualy available to be read on the
file descriptor socket. why ? because on most platforms select can't be done
twice on the same socket when the first reported data to read or to write
ssh_get_status(session)
Returns the current status bitmask : connection Open or closed, data
pending to read or not (even if connection closed), connection closed on
error or on an exit message
ssh_get_disconnect_message(session)
Returns the connection disconnect error/exit message
ssh_get_pubkey_hash(session, hash)
get the public key hash from the server.
ssh_is_server_known(session)
ssh_write_knownhost(session)
these 2 functions will be kept
ssh_disconnect(session)
standard disconnect
ssh_disconnect_error(session,error code, message)
disconnect with a message
ssh_set_username(session)
set the user name to log in
ssh_userauth_* functions will be kept as they are now, excepted the fact that
the username field will disapear.
the public key mechanism may get some more functions, like retrieving a public
key from a private key and authenticating without a public key.
ssh_get_issue_banner(session)
get the issue banner from the server, that is the welcome message.
ssh_silent_free(session)
This function silently free all data structures used by the session and
closes the socket. It may be used for instance when the process forked and
doesn't want to keep track of this session. This is obviously not possible to
do with separate channels.
The channel_struct structure
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The channels will change a bit. the constructor thing will change, and the way
to multiplex different connections will change too. channel functions will be
prefixed with "ssh_"
struct channel_struct *ssh_channel_new()
ssh_channel_open_session(channel)
will return if the channel allocation failed or not.
ssh_channel_open_forward(channel, ...) won't change. it will report an error if
the channel allocation failed.
ssh_channel_send_eof(channel)
send EOF
ssh_channel_close(channel)
closes a channel but doesn't destroy it. you may read unread data still in
the buffer. Once you closed the buffer, the other party can't send you data,
while it could still do it if you only sent an EOF.
ssh_channel_is_closed(channel)
returns true if the channel was closed at one of both sides. a closed chan
may still have data to read, if you closed yourself the connection. otherwise
(you didn't close it) the closed notification only comes when you read the
last buffer byte, or when trying to write into the channel (the SIGPIPE-like
behaviour).
ssh_channel_is_eof(channel)
reports if the other side has sent an EOF. This functions returns FALSE if
there is still data to read. A closed channel is always EOF.
ssh_channel_free(channel)
completely free the channel. closes it before if it was not done.
ssh_channel_request_env(channel, name, value)
set an environment variable.
ssh_channel_request_pty(channel)
ssh_channel_request_pty_size()
ssh_channel_change_pty_size()
ssh_channel_request_shell()
ssh_channel_request_exec()
ssh_channel_request_subsystem()
These functions won't change.
int ssh_channel_write(channel,data, len,stderr)
Depending on the blocking/non blocking mode of the channel, the behaviour may
change.
stderr is the extended buffer. It's generaly only a server->client stream.
ssh_channel_set_blocking(bool blocking)
int ssh_channel_read(channel, buffer, maxlen, is_stderr)
the behaviour will be this one:
-if the chan is in non blocking mode, it will poll what's available to read
and return this. otherwise (nothing to read) it will return 0.
-if the chan is blocking, it will block until at least one byte is
available.
ssh_channel_nonblocking disapears for the later reason.
int channel_poll(channel, is_stderr)
polls the network and reports the number of bytes ready to be read in the
chan.
ssh_session ssh_channel_get_session(channel)
returns the session pointer associated to the channel, for simplicity
reasons.
int ssh_channel_select(CHANNELS *readchans, CHANNELS *writechans, CHANNELS
*exceptchans, struct timeval *timeout)
This function won't work the same way ssh_select did.
I removed the custom file descriptor thing for 2 reasons:
1- it's not windows compliant. D'ouh !
2- most programmers won't want to depend on libssh for socket multiplexing.
that's why i let the programmer poll the fds himself and then use
ssh_set_fd_toread, towrite or except. Then, he may use ssh_channel_select
with a NULL timeout to poll which channels have something to read, write or
error report.
Here is how it's going to work. The coder sets 3 different arrays with the
channels he wants to select(), the last entry being a NULL pointer. The
function will first poll them and return the chans that must be
read/write/excepted. If nothing has this state, the function will select()
using the timeout.
The function will return 0 if everything is ok, SSH_TIMEOUT or SSH_EINTR if
the select was interrupted by a signal. It is dangerous to execute any
channel-related functions into signal handlers. they should set a flag that
you read into your loop. this "trap" (SSH_EINTR) will permit you to catch
them faster and make your program responsive and look fast.
the function will return -1 if a serious problem happens.
Error handling
~~~~~~~~~~~~~~
when an error happens, the programmer can get the error code and description
with ssh_get_error(session). the creation of a failess constructor for
ssh_session was needed for this reason.
ssh_get_error_code(session) will return an error code into this subset:
SSH_NO_ERROR : no error :)
SSH_REQUEST_DENIED : you request for a functionality or a service that is not
allowed. The session can continue.
SSH_FATAL : Unrecoverable error. The session can't continue and you should
disconnect the session. It includes the connection being cut without a
disconnect() message.
If a disconnect() message or the channel was closed, a read on such a channel
won't produce an error. otherwise it will return -1 with a SSH_FATAL error
code.
Server socket binding
~~~~~~~~~~~~~~~~~~~~~
It is not possible to bind a socket for ssh with a SSH_SESSION type, because a
single bound port may lead to multiple ssh connections. That's why the
SSH_BIND structure must be created. It uses options from the SSH_OPTIONS
structure.
SSH_BIND *ssh_bind_new()
creates a structure
ssh_bind_set_options(bind, options)
set the option structure
int ssh_bind_listen(bind)
bind and listen to the port. This call is not blocking. if some error
happens, it returns -1 and the error code can be found with perror().
ssh_bind_set_blocking(bind, bool blocking)
should ssh_bind_accept() block or not.
int ssh_bind_get_fd(bind)
return the bound file descriptor, that is the listener socket. you may put it
into a select() in your code to detect a connection attempt.
ssh_bind_set_fd_toaccept(bind)
say that the listener socket has a connection to accept (to avoid
ssh_bind_accept() to do a select on it).
SSH_SESSION *ssh_bind_accept(bind)
return a server handle to a ssh session. if the mode is blocking, the
function will always return a pointer to a session. if the mode is not
blocking, the function can return NULL if there is no connection to accept.
This SSH_SESSION handle must then pass through the functions explained above.
*server functions *
int ssh_accept(session)
when a new connection is accepted, the handshake must be done. this function
will do the banner handshake and the key exchange.
it will return SSH_AGAIN if the session mode is non blocking, and the
function must be called again until an error occurs or the kex is done.
Here, I had a few choises about *how* to implement the message parsing as a
server. There are multiple ways to do it, one being callbacks and one being
"Message" reading, parsing and then choice going to the user to use it and
answer. I've choosen the latter because i believe it's the stronger method.
A ssh server can receive 30 different kind of messages having to be dealt by
the high level routines, like channel request_shell or authentication. Having
a callback for all of them would produce a huge kludge of callbacks, with
no relations on when there were called etc.
A message based parsing allows the user to filtrate the messages he's
interested into and to use a default answer for the others. Then, the callback
thing is still possible to handle through a simple message code/callback
function array.
I did not define yet what it would look like, but i'm sure there will be a
SSH_MESSAGE (they won't have a 1/1 correspondance with ssh packets) which will
be read through
SSH_MESSAGE *ssh_server_read_message(session).
with all of the non-blocking stuff in head like returning NULL if the message
is not full.
Then, the message can be parsed, ie
int ssh_message_get_code(message)
which will return SSH_MESSAGE_AUTH
then
int ssh_message_get_subcode(message)
which then will returh SSH_MESSAGE_AUTH_PASSWORD or _NONE or _PUBKEY etc.
Then, once the message was parsed, the message will have to be answered, ie
with the generic functions like
ssh_message_accept(message) which says 'Ok your request is accepted' or
ssh_message_deny(message) which says 'Your request is refused'.
There would be specific message answer functions for some kind of messages
like the authentication one. you may want to reply that the authentication is
Partial rather than denied, and that you still accept some kind of auths, like
ssh_message_auth_reply(message,SSH_AUTH_PARTIAL,SSH_AUTH_PASSWORD |
SSH_AUTH_PUBKEY | SSH_AUTH_KEYBINT);
I won't let the user have to deal with the channels himself. When a channel is
going to be created by the remote size, a message will come asking to open a
channel. the programmer can either deny or accept, in which case a CHANNEL
object will be created and returned to the programmer. then, all standard
channel functions will run.
C. Change log of this document
3. Add paragraph about initalization and finalization.
2. ssh_options_set_username finaly is kept into the options, because it can be
set by ssh_options_getopt()
1. first release
D. End notes
I think libssh must have a very simple to use, powerful and exhaustive API. It
must have no design flaw either.
While I got some good experience at the SSH protocol, I've never writen
more-than-100 lines programs than use libssh and I don't really know the
problems of the library. I'd like people who don't understand some detail into
the API I describe here, who have comments or opinions about it to write me
the soonest possible to limit the damages if I made something the completely
wrong way.
Thanks for your patience.

View File

@@ -1,33 +0,0 @@
/**
@page libssh_linking The Linking HowTo
@section dynamic Dynamic Linking
On UNIX and Windows systems its the same, you need at least the libssh.h
header file and the libssh shared library.
@section static Static Linking
@warning <b>The libssh library is licensed under the LGPL! Make sure you
understand what this means to your codebase if you want to distribute
binaries and link statically against LGPL code!</b>
On UNIX systems linking against the static version of the library is the
same as linking against the shared library. Both have the same name. Some
build system require to use the full path to the static library.
To be able to compile the application you're developing you need to either pass
LIBSSH_STATIC as a define in the compiler command line or define it before you
include libssh.h. This is required cause the dynamic library needs to specify
the dllimport attribute.
@code
#define LIBSSH_STATIC 1
#include <libssh/libssh.h>
@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

@@ -1,254 +0,0 @@
/**
@mainpage
This is the online reference for developing with the libssh library. It
documents the libssh C API and the C++ wrapper.
@section main-linking Linking
We created a small howto how to link libssh against your application, read
@subpage libssh_linking.
@section main-tutorial Tutorial
You should start by reading @subpage libssh_tutorial, then reading the documentation of
the interesting functions as you go.
@section main-features Features
The libssh library provides:
- <strong>Key Exchange Methods</strong>: <i>sntrup761x25519-sha512@openssh.com, curve25519-sha256, curve25519-sha256@libssh.org, ecdh-sha2-nistp256, ecdh-sha2-nistp384, ecdh-sha2-nistp521</i>, diffie-hellman-group1-sha1, diffie-hellman-group14-sha1
- <strong>Public Key Algorithms</strong>: ssh-ed25519, ecdsa-sha2-nistp256, ecdsa-sha2-nistp384, ecdsa-sha2-nistp521, ssh-rsa, rsa-sha2-512, rsa-sha2-256
- <strong>Ciphers</strong>: <i>aes256-ctr, aes192-ctr, aes128-ctr</i>, aes256-cbc (rijndael-cbc@lysator.liu.se), aes192-cbc, aes128-cbc, 3des-cbc, blowfish-cbc
- <strong>Compression Schemes</strong>: zlib, <i>zlib@openssh.com</i>, none
- <strong>MAC hashes</strong>: hmac-sha1, hmac-sha2-256, hmac-sha2-512, hmac-md5
- <strong>Authentication</strong>: none, password, public-key, 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>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>Subsystems</strong>: sftp(version 3), <i>OpenSSH Extensions</i>
- <strong>SFTP</strong>: <i>statvfs@openssh.com, fstatvfs@openssh.com</i>
- <strong>Thread-safe</strong>: Just don't share sessions
- <strong>Non-blocking</strong>: it can be used both blocking and non-blocking
- <strong>Your sockets</strong>: the app hands over the socket, or uses libssh sockets
- <b>OpenSSL</b>, <b>MBedTLS</b> or <b>gcrypt</b> (deprecated): builds with either
@section main-additional-features Additional Features
- Client <b>and</b> server support
- SSHv2 protocol support
- Supports <a href="https://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>
- Event model based on poll(2), or a poll(2)-emulation.
@section main-copyright 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
@verbatim
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
@endverbatim
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:
@verbatim
Signed-off-by: Random J Developer <random@developer.example.org>
@endverbatim
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:
@verbatim
(c) Example Corporation.
@endverbatim
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!
The libssh Team
@section main-rfc Internet standard
@subsection main-rfc-secsh Secure Shell (SSH)
The following RFC documents described SSH-2 protocol as an Internet standard.
- <a href="https://tools.ietf.org/html/rfc4250" target="_blank">RFC 4250</a>,
The Secure Shell (SSH) Protocol Assigned Numbers
- <a href="https://tools.ietf.org/html/rfc4251" target="_blank">RFC 4251</a>,
The Secure Shell (SSH) Protocol Architecture
- <a href="https://tools.ietf.org/html/rfc4252" target="_blank">RFC 4252</a>,
The Secure Shell (SSH) Authentication Protocol
- <a href="https://tools.ietf.org/html/rfc4253" target="_blank">RFC 4253</a>,
The Secure Shell (SSH) Transport Layer Protocol
- <a href="https://tools.ietf.org/html/rfc4254" target="_blank">RFC 4254</a>,
The Secure Shell (SSH) Connection Protocol
- <a href="https://tools.ietf.org/html/rfc4255" target="_blank">RFC 4255</a>,
Using DNS to Securely Publish Secure Shell (SSH) Key Fingerprints
(not implemented in libssh)
- <a href="https://tools.ietf.org/html/rfc4256" target="_blank">RFC 4256</a>,
Generic Message Exchange Authentication for the Secure Shell Protocol (SSH)
- <a href="https://tools.ietf.org/html/rfc4335" target="_blank">RFC 4335</a>,
The Secure Shell (SSH) Session Channel Break Extension
- <a href="https://tools.ietf.org/html/rfc4344" target="_blank">RFC 4344</a>,
The Secure Shell (SSH) Transport Layer Encryption Modes
- <a href="https://tools.ietf.org/html/rfc4345" target="_blank">RFC 4345</a>,
Improved Arcfour Modes for the Secure Shell (SSH) Transport Layer Protocol
It was later modified and expanded by the following RFCs.
- <a href="https://tools.ietf.org/html/rfc4419" target="_blank">RFC 4419</a>,
Diffie-Hellman Group Exchange for the Secure Shell (SSH) Transport Layer
Protocol
- <a href="https://tools.ietf.org/html/rfc4432" target="_blank">RFC 4432</a>,
RSA Key Exchange for the Secure Shell (SSH) Transport Layer Protocol
(not implemented in libssh)
- <a href="https://tools.ietf.org/html/rfc4462" target="_blank">RFC 4462</a>,
Generic Security Service Application Program Interface (GSS-API)
Authentication and Key Exchange for the Secure Shell (SSH) Protocol
(only the authentication implemented in libssh)
- <a href="https://tools.ietf.org/html/rfc4716" target="_blank">RFC 4716</a>,
The Secure Shell (SSH) Public Key File Format
(not implemented in libssh)
- <a href="https://tools.ietf.org/html/rfc5647" target="_blank">RFC 5647</a>,
AES Galois Counter Mode for the Secure Shell Transport Layer Protocol
(the algorithm negotiation implemented according to openssh.com)
- <a href="https://tools.ietf.org/html/rfc5656" target="_blank">RFC 5656</a>,
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
- <a href="https://tools.ietf.org/html/rfc8709" target="_blank">RFC 8731</a>,
Secure Shell (SSH) Key Exchange Method Using Curve25519 and Curve448
- <a href="https://tools.ietf.org/html/rfc9142" target="_blank">RFC 9142</a>,
Key Exchange (KEX) Method Updates and Recommendations for Secure Shell (SSH)
There are also drafts that are being currently developed and followed.
- <a href="https://tools.ietf.org/html/draft-miller-ssh-agent-03" target="_blank">draft-miller-ssh-agent-08</a>
SSH Agent Protocol
Interesting cryptography documents:
- <a href="https://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)
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
do the same in libssh.
- <a href="https://tools.ietf.org/html/draft-ietf-secsh-filexfer-02" target="_blank">
draft-ietf-secsh-filexfer-02.txt</a>,
SSH File Transfer Protocol
@subsection main-rfc-extensions Secure Shell Extensions
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.
- <a href="https://api.libssh.org/rfc/PROTOCOL" target="_blank">
OpenSSH's deviations and extensions</a>
- <a href="https://api.libssh.org/rfc/PROTOCOL.certkeys" target="_blank">
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,86 +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 < 3.0):
OpenSSL 1.x 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 application.
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).
@warning The support for Engines was deprecated in OpenSSL 3.0 so this approach
is deprecated in libssh 0.11.x.
# Pre-requisites (OpenSSL 3.0.8+)
The OpenSSL 3.0 is deprecating usage of low-level engines in favor of high-level
"providers" to provide alternative implementation of cryptographic operations
or acceleration.
To build and use libssh with PKCS #11 support using OpenSSL providers:
1. Install and configure pkcs11 provider (https://github.com/latchset/pkcs11-provider).
2. Enable the cmake options: $ cmake -DWITH_PKCS11_URI=ON -DWITH_PKCS11_PROVIDER=ON
3. Build with OpenSSL.
4. Plug in a working smart card or configure softhsm (https://www.opendnssec.org/softhsm).
# New API functions
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.
For testing, the SoftHSM PKCS#11 library is used.
*/

View File

@@ -1,268 +0,0 @@
/**
@page libssh_tutor_scp Chapter 6: The SCP subsystem
@section scp_subsystem The SCP subsystem
The SCP subsystem has far less functionality than the SFTP subsystem.
However, if you only need to copy files from and to the remote system,
it does its job.
@subsection scp_session Opening and closing a SCP session
Like in the SFTP subsystem, you don't handle the SSH channels directly.
Instead, you open a "SCP session".
When you open your SCP session, you have to choose between read or write mode.
You can't do both in the same session. So you specify either SSH_SCP_READ or
SSH_SCP_WRITE as the second parameter of function ssh_scp_new().
Another important mode flag for opening your SCP session is SSH_SCP_RECURSIVE.
When you use SSH_SCP_RECURSIVE, you declare that you are willing to emulate
the behaviour of "scp -r" command in your program, no matter it is for
reading or for writing.
Once your session is created, you initialize it with ssh_scp_init(). When
you have finished transferring files, you terminate the SCP connection with
ssh_scp_close(). Finally, you can dispose the SCP connection with
ssh_scp_free().
The example below does the maintenance work to open a SCP connection for writing in
recursive mode:
@code
int scp_write(ssh_session session)
{
ssh_scp scp;
int rc;
scp = ssh_scp_new
(session, SSH_SCP_WRITE | SSH_SCP_RECURSIVE, ".");
if (scp == NULL)
{
fprintf(stderr, "Error allocating scp session: %s\n",
ssh_get_error(session));
return SSH_ERROR;
}
rc = ssh_scp_init(scp);
if (rc != SSH_OK)
{
fprintf(stderr, "Error initializing scp session: %s\n",
ssh_get_error(session));
ssh_scp_free(scp);
return rc;
}
...
ssh_scp_close(scp);
ssh_scp_free(scp);
return SSH_OK;
}
@endcode
The example below shows how to open a connection to read a single file:
@code
int scp_read(ssh_session session)
{
ssh_scp scp;
int rc;
scp = ssh_scp_new
(session, SSH_SCP_READ, "helloworld/helloworld.txt");
if (scp == NULL)
{
fprintf(stderr, "Error allocating scp session: %s\n",
ssh_get_error(session));
return SSH_ERROR;
}
rc = ssh_scp_init(scp);
if (rc != SSH_OK)
{
fprintf(stderr, "Error initializing scp session: %s\n",
ssh_get_error(session));
ssh_scp_free(scp);
return rc;
}
...
ssh_scp_close(scp);
ssh_scp_free(scp);
return SSH_OK;
}
@endcode
@subsection scp_write Creating files and directories
You create directories with ssh_scp_push_directory(). In recursive mode,
you are placed in this directory once it is created. If the directory
already exists and if you are in recursive mode, you simply enter that
directory.
Creating files is done in two steps. First, you prepare the writing with
ssh_scp_push_file(). Then, you write the data with ssh_scp_write().
The length of the data to write must be identical between both function calls.
There's no need to "open" nor "close" the file, this is done automatically
on the remote end. If the file already exists, it is overwritten and truncated.
The following example creates a new directory named "helloworld/", then creates
a file named "helloworld.txt" in that directory:
@code
int scp_helloworld(ssh_session session, ssh_scp scp)
{
int rc;
const char *helloworld = "Hello, world!\n";
int length = strlen(helloworld);
rc = ssh_scp_push_directory(scp, "helloworld", S_IRWXU);
if (rc != SSH_OK)
{
fprintf(stderr, "Can't create remote directory: %s\n",
ssh_get_error(session));
return rc;
}
rc = ssh_scp_push_file
(scp, "helloworld.txt", length, S_IRUSR | S_IWUSR);
if (rc != SSH_OK)
{
fprintf(stderr, "Can't open remote file: %s\n",
ssh_get_error(session));
return rc;
}
rc = ssh_scp_write(scp, helloworld, length);
if (rc != SSH_OK)
{
fprintf(stderr, "Can't write to remote file: %s\n",
ssh_get_error(session));
return rc;
}
return SSH_OK;
}
@endcode
@subsection scp_recursive_write Copying full directory trees to the remote server
Let's say you want to copy the following tree of files to the remote site:
@verbatim
+-- file1
+-- B --+
| +-- file2
-- A --+
| +-- file3
+-- C --+
+-- file4
@endverbatim
You would do it that way:
- open the session in recursive mode
- enter directory A
- enter its subdirectory B
- create file1 in B
- create file2 in B
- leave directory B
- enter subdirectory C
- create file3 in C
- create file4 in C
- leave directory C
- leave directory A
To leave a directory, call ssh_scp_leave_directory().
@subsection scp_read Reading files and directories
To receive files, you pull requests from the other side with ssh_scp_pull_request().
If this function returns SSH_SCP_REQUEST_NEWFILE, then you must get ready for
the reception. You can get the size of the data to receive with ssh_scp_request_get_size()
and allocate a buffer accordingly. When you are ready, you accept the request with
ssh_scp_accept_request(), then read the data with ssh_scp_read().
The following example receives a single file. The name of the file to
receive has been given earlier, when the scp session was opened:
@code
int scp_receive(ssh_session session, ssh_scp scp)
{
int rc;
int size, mode;
char *filename, *buffer;
rc = ssh_scp_pull_request(scp);
if (rc != SSH_SCP_REQUEST_NEWFILE)
{
fprintf(stderr, "Error receiving information about file: %s\n",
ssh_get_error(session));
return SSH_ERROR;
}
size = ssh_scp_request_get_size(scp);
filename = strdup(ssh_scp_request_get_filename(scp));
mode = ssh_scp_request_get_permissions(scp);
printf("Receiving file %s, size %d, permissions 0%o\n",
filename, size, mode);
free(filename);
buffer = malloc(size);
if (buffer == NULL)
{
fprintf(stderr, "Memory allocation error\n");
return SSH_ERROR;
}
ssh_scp_accept_request(scp);
rc = ssh_scp_read(scp, buffer, size);
if (rc == SSH_ERROR)
{
fprintf(stderr, "Error receiving file data: %s\n",
ssh_get_error(session));
free(buffer);
return rc;
}
printf("Done\n");
write(1, buffer, size);
free(buffer);
rc = ssh_scp_pull_request(scp);
if (rc != SSH_SCP_REQUEST_EOF)
{
fprintf(stderr, "Unexpected request: %s\n",
ssh_get_error(session));
return SSH_ERROR;
}
return SSH_OK;
}
@endcode
In this example, since we just requested a single file, we expect ssh_scp_request()
to return SSH_SCP_REQUEST_NEWFILE first, then SSH_SCP_REQUEST_EOF. That's quite a
naive approach; for example, the remote server might send a warning as well
(return code SSH_SCP_REQUEST_WARNING) and the example would fail. A more comprehensive
reception program would receive the requests in a loop and analyze them carefully
until SSH_SCP_REQUEST_EOF has been received.
@subsection scp_recursive_read Receiving full directory trees from the remote server
If you opened the SCP session in recursive mode, the remote end will be
telling you when to change directory.
In that case, when ssh_scp_pull_request() answers
SSH_SCP_REQUEST_NEWDIRECTORY, you should make that local directory (if
it does not exist yet) and enter it. When ssh_scp_pull_request() answers
SSH_SCP_REQUEST_ENDDIRECTORY, you should leave the current directory.
*/

View File

@@ -1,381 +0,0 @@
/**
@page libssh_tutor_sftp Chapter 5: The SFTP subsystem
@section sftp_subsystem The SFTP subsystem
SFTP stands for "Secure File Transfer Protocol". It enables you to safely
transfer files between the local and the remote computer. It reminds a lot
of the old FTP protocol.
SFTP is a rich protocol. It lets you do over the network almost everything
that you can do with local files:
- send files
- modify only a portion of a file
- receive files
- receive only a portion of a file
- get file owner and group
- get file permissions
- set file owner and group
- set file permissions
- remove files
- rename files
- create a directory
- remove a directory
- retrieve the list of files in a directory
- get the target of a symbolic link
- create symbolic links
- get information about mounted filesystems.
The current implemented version of the SFTP protocol is version 3. All functions
aren't implemented yet, but the most important are.
@subsection sftp_session Opening and closing a SFTP session
Unlike with remote shells and remote commands, when you use the SFTP subsystem,
you don't handle directly the SSH channels. Instead, you open a "SFTP session".
The function sftp_new() creates a new SFTP session. The function sftp_init()
initializes it. The function sftp_free() deletes it.
As you see, all the SFTP-related functions start with the "sftp_" prefix
instead of the usual "ssh_" prefix.
The example below shows how to use these functions:
@code
#include <libssh/sftp.h>
int sftp_helloworld(ssh_session session)
{
sftp_session sftp;
int rc;
sftp = sftp_new(session);
if (sftp == NULL)
{
fprintf(stderr, "Error allocating SFTP session: %s\n",
ssh_get_error(session));
return SSH_ERROR;
}
rc = sftp_init(sftp);
if (rc != SSH_OK)
{
fprintf(stderr, "Error initializing SFTP session: code %d.\n",
sftp_get_error(sftp));
sftp_free(sftp);
return rc;
}
...
sftp_free(sftp);
return SSH_OK;
}
@endcode
@subsection sftp_errors Analyzing SFTP errors
In case of a problem, the function sftp_get_error() returns a SFTP-specific
error number, in addition to the regular SSH error number returned by
ssh_get_error_number().
Possible errors are:
- SSH_FX_OK: no error
- SSH_FX_EOF: end-of-file encountered
- SSH_FX_NO_SUCH_FILE: file does not exist
- SSH_FX_PERMISSION_DENIED: permission denied
- SSH_FX_FAILURE: generic failure
- SSH_FX_BAD_MESSAGE: garbage received from server
- SSH_FX_NO_CONNECTION: no connection has been set up
- SSH_FX_CONNECTION_LOST: there was a connection, but we lost it
- SSH_FX_OP_UNSUPPORTED: operation not supported by libssh yet
- SSH_FX_INVALID_HANDLE: invalid file handle
- SSH_FX_NO_SUCH_PATH: no such file or directory path exists
- SSH_FX_FILE_ALREADY_EXISTS: an attempt to create an already existing file or directory has been made
- SSH_FX_WRITE_PROTECT: write-protected filesystem
- SSH_FX_NO_MEDIA: no media was in remote drive
@subsection sftp_mkdir Creating a directory
The function sftp_mkdir() takes the "SFTP session" we just created as
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()
function. To get a comprehensive list of the available permissions, use the
"man 2 stat" command. The desired permissions are combined with the remote
user's mask to determine the effective permissions.
The code below creates a directory named "helloworld" in the current directory that
can be read and written only by its owner:
@code
#include <libssh/sftp.h>
#include <sys/stat.h>
int sftp_helloworld(ssh_session session, sftp_session sftp)
{
int rc;
rc = sftp_mkdir(sftp, "helloworld", S_IRWXU);
if (rc != SSH_OK)
{
if (sftp_get_error(sftp) != SSH_FX_FILE_ALREADY_EXISTS)
{
fprintf(stderr, "Can't create directory: %s\n",
ssh_get_error(session));
return rc;
}
}
...
return SSH_OK;
}
@endcode
Unlike its equivalent in the SCP subsystem, this function does NOT change the
current directory to the newly created subdirectory.
@subsection sftp_write Writing to a file on the remote computer
You handle the contents of a remote file just like you would do with a
local file: you open the file in a given mode, move the file pointer in it,
read or write data, and close the file.
The sftp_open() function is very similar to the regular open() function,
excepted that it returns a file handle of type sftp_file. This file handle
is then used by the other file manipulation functions and remains valid
until you close the remote file with sftp_close().
The example below creates a new file named "helloworld.txt" in the
newly created "helloworld" directory. If the file already exists, it will
be truncated. It then writes the famous "Hello, World!" sentence to the
file, followed by a new line character. Finally, the file is closed:
@code
#include <libssh/sftp.h>
#include <sys/stat.h>
#include <fcntl.h>
int sftp_helloworld(ssh_session session, sftp_session sftp)
{
int access_type = O_WRONLY | O_CREAT | O_TRUNC;
sftp_file file;
const char *helloworld = "Hello, World!\n";
int length = strlen(helloworld);
int rc, nwritten;
...
file = sftp_open(sftp, "helloworld/helloworld.txt",
access_type, S_IRWXU);
if (file == NULL)
{
fprintf(stderr, "Can't open file for writing: %s\n",
ssh_get_error(session));
return SSH_ERROR;
}
nwritten = sftp_write(file, helloworld, length);
if (nwritten != length)
{
fprintf(stderr, "Can't write data to file: %s\n",
ssh_get_error(session));
sftp_close(file);
return SSH_ERROR;
}
rc = sftp_close(file);
if (rc != SSH_OK)
{
fprintf(stderr, "Can't close the written file: %s\n",
ssh_get_error(session));
return rc;
}
return SSH_OK;
}
@endcode
@subsection sftp_read Reading a file from the remote computer
A synchronous read from a remote file is done using sftp_read(). This
section describes how to download a remote file using sftp_read(). The
next section will discuss more about synchronous/asynchronous read/write
operations using libssh sftp API.
Files are normally transferred in chunks. A good chunk size is 16 KB. The following
example transfers the remote file "/etc/profile" in 16 KB chunks. For each chunk we
request, sftp_read() blocks till the data has been received:
@code
// Good chunk size
#define MAX_XFER_BUF_SIZE 16384
int sftp_read_sync(ssh_session session, sftp_session sftp)
{
int access_type;
sftp_file file;
char buffer[MAX_XFER_BUF_SIZE];
int nbytes, nwritten, rc;
int fd;
access_type = O_RDONLY;
file = sftp_open(sftp, "/etc/profile",
access_type, 0);
if (file == NULL) {
fprintf(stderr, "Can't open file for reading: %s\n",
ssh_get_error(session));
return SSH_ERROR;
}
fd = open("/path/to/profile", O_CREAT);
if (fd < 0) {
fprintf(stderr, "Can't open file for writing: %s\n",
strerror(errno));
return SSH_ERROR;
}
for (;;) {
nbytes = sftp_read(file, buffer, sizeof(buffer));
if (nbytes == 0) {
break; // EOF
} else if (nbytes < 0) {
fprintf(stderr, "Error while reading file: %s\n",
ssh_get_error(session));
sftp_close(file);
return SSH_ERROR;
}
nwritten = write(fd, buffer, nbytes);
if (nwritten != nbytes) {
fprintf(stderr, "Error writing: %s\n",
strerror(errno));
sftp_close(file);
return SSH_ERROR;
}
}
rc = sftp_close(file);
if (rc != SSH_OK) {
fprintf(stderr, "Can't close the read file: %s\n",
ssh_get_error(session));
return rc;
}
return SSH_OK;
}
@endcode
@subsection sftp_aio Performing an asynchronous read/write on a file on the remote computer
sftp_read() performs a "synchronous" read operation on a remote file.
This means that sftp_read() will first request the server to read some
data from the remote file and then would wait until the server response
containing data to read (or an error) arrives at the client side.
sftp_write() performs a "synchronous" write operation on a remote file.
This means that sftp_write() will first request the server to write some
data to the remote file and then would wait until the server response
containing information about the status of the write operation arrives at the
client side.
If your client program wants to do something other than waiting for the
response after requesting a read/write, the synchronous sftp_read() and
sftp_write() can't be used. In such a case the "asynchronous" sftp aio API
should be used.
Please go through @ref libssh_tutor_sftp_aio for a detailed description
of the sftp aio API.
The sftp aio API provides two categories of functions :
- sftp_aio_begin_*() : For requesting a read/write from the server.
- sftp_aio_wait_*() : For waiting for the response of a previously
issued read/write request from the server.
Hence, the client program can call sftp_aio_begin_*() to request a read/write
and then can perform any number of operations (other than waiting) before
calling sftp_aio_wait_*() for waiting for the response of the previously
issued request.
We call read/write operations performed in the manner described above as
"asynchronous" read/write operations on a remote file.
@subsection sftp_ls Listing the contents of a directory
The functions sftp_opendir(), sftp_readdir(), sftp_dir_eof(),
and sftp_closedir() enable to list the contents of a directory.
They use a new handle_type, "sftp_dir", which gives access to the
directory being read.
In addition, sftp_readdir() returns a "sftp_attributes" which is a pointer
to a structure with information about a directory entry:
- name: the name of the file or directory
- size: its size in bytes
- etc.
sftp_readdir() might return NULL under two conditions:
- when the end of the directory has been met
- when an error occurred
To tell the difference, call sftp_dir_eof().
The attributes must be freed with sftp_attributes_free() when no longer
needed.
The following example reads the contents of some remote directory:
@code
int sftp_list_dir(ssh_session session, sftp_session sftp)
{
sftp_dir dir;
sftp_attributes attributes;
int rc;
dir = sftp_opendir(sftp, "/var/log");
if (!dir)
{
fprintf(stderr, "Directory not opened: %s\n",
ssh_get_error(session));
return SSH_ERROR;
}
printf("Name Size Perms Owner\tGroup\n");
while ((attributes = sftp_readdir(sftp, dir)) != NULL)
{
printf("%-20s %10llu %.8o %s(%d)\t%s(%d)\n",
attributes->name,
(long long unsigned int) attributes->size,
attributes->permissions,
attributes->owner,
attributes->uid,
attributes->group,
attributes->gid);
sftp_attributes_free(attributes);
}
if (!sftp_dir_eof(dir))
{
fprintf(stderr, "Can't list directory: %s\n",
ssh_get_error(session));
sftp_closedir(dir);
return SSH_ERROR;
}
rc = sftp_closedir(dir);
if (rc != SSH_OK)
{
fprintf(stderr, "Can't close directory: %s\n",
ssh_get_error(session));
return rc;
}
}
@endcode
*/

View File

@@ -1,705 +0,0 @@
/**
@page libssh_tutor_sftp_aio Chapter 10: The SFTP asynchronous I/O
@section sftp_aio_api The SFTP asynchronous I/O
NOTE : Please read @ref libssh_tutor_sftp before reading this page. The
synchronous sftp_read() and sftp_write() have been described there.
SFTP AIO stands for "SFTP Asynchronous Input/Output". This API contains
functions which perform async read/write operations on remote files.
File transfers performed using the asynchronous sftp aio API can be
significantly faster than the file transfers performed using the synchronous
sftp read/write API (see sftp_read() and sftp_write()).
The sftp aio API functions are divided into two categories :
- sftp_aio_begin_*() [see sftp_aio_begin_read(), sftp_aio_begin_write()]:
These functions send a request for an i/o operation to the server and
provide the caller an sftp aio handle corresponding to the sent request.
- sftp_aio_wait_*() [see sftp_aio_wait_read(), sftp_aio_wait_write()]:
These functions wait for the server response corresponding to a previously
issued request. Which request ? the request corresponding to the sftp aio
handle supplied by the caller to these functions.
Conceptually, you can think of the sftp aio handle as a request identifier.
Technically, the sftp_aio_begin_*() functions dynamically allocate memory to
store information about the i/o request they send and provide the caller a
handle to this memory, we call this handle an sftp aio handle.
sftp_aio_wait_*() functions use the information stored in that memory (handled
by the caller supplied sftp aio handle) to identify a request, and then they
wait for that request's response. These functions also release the memory
handled by the caller supplied sftp aio handle (except when they return
SSH_AGAIN).
sftp_aio_free() can also be used to release the memory handled by an sftp aio
handle but unlike the sftp_aio_wait_*() functions, it doesn't wait for a
response. This should be used to release the memory corresponding to an sftp
aio handle when some failure occurs. An example has been provided at the
end of this page to show the usage of sftp_aio_free().
To begin with, this tutorial will provide basic examples that describe the
usage of sftp aio API to perform a single read/write operation.
The later sections describe the usage of the sftp aio API to obtain faster file
transfers as compared to the transfers performed using the synchronous sftp
read/write API.
On encountering an error, the sftp aio API functions set the sftp and ssh
errors just like any other libssh sftp API function. These errors can be
obtained using sftp_get_error(), ssh_get_error() and ssh_get_error_code().
The code examples provided on this page ignore error handling for the sake of
brevity.
@subsection sftp_aio_read Using the sftp aio API for reading (a basic example)
For performing an async read operation on a sftp file (see sftp_open()),
the first step is to call sftp_aio_begin_read() to send a read request to the
server. The caller is provided an sftp aio handle corresponding to the sent
read request.
The second step is to pass a pointer to this aio handle to
sftp_aio_wait_read(), this function waits for the server response which
indicates the success/failure of the read request. On success, the response
indicates EOF or contains the data read from the sftp file.
The following code example shows how a read operation can be performed
on an sftp file using the sftp aio API.
@code
ssize_t read_chunk(sftp_file file, void *buf, size_t to_read)
{
ssize_t bytes_requested, bytes_read;
// Variable to store an sftp aio handle
sftp_aio aio = NULL;
// Send a read request to the sftp server
bytes_requested = sftp_aio_begin_read(file, to_read, &aio);
if (bytes_requested == SSH_ERROR) {
// handle error
}
// Here its possible that (bytes_requested < to_read) as specified in
// the function documentation of sftp_aio_begin_read()
// Wait for the response of the read request corresponding to the
// sftp aio handle stored in the aio variable.
bytes_read = sftp_aio_wait_read(&aio, buf, to_read);
if (bytes_read == SSH_ERROR) {
// handle error
}
return bytes_read;
}
@endcode
@subsection sftp_aio_write Using the sftp aio API for writing (a basic example)
For performing an async write operation on a sftp file (see sftp_open()),
the first step is to call sftp_aio_begin_write() to send a write request to
the server. The caller is provided an sftp aio handle corresponding to the
sent write request.
The second step is to pass a pointer to this aio handle to
sftp_aio_wait_write(), this function waits for the server response which
indicates the success/failure of the write request.
The following code example shows how a write operation can be performed on an
sftp file using the sftp aio API.
@code
ssize_t write_chunk(sftp_file file, void *buf, size_t to_write)
{
ssize_t bytes_requested, bytes_written;
// Variable to store an sftp aio handle
sftp_aio aio = NULL;
// Send a write request to the sftp server
bytes_requested = sftp_aio_begin_write(file, buf, to_write, &aio);
if (bytes_requested == SSH_ERROR) {
// handle error
}
// Here its possible that (bytes_requested < to_write) as specified in
// the function documentation of sftp_aio_begin_write()
// Wait for the response of the write request corresponding to
// the sftp aio handle stored in the aio variable.
bytes_written = sftp_aio_wait_write(&aio);
if (bytes_written == SSH_ERROR) {
// handle error
}
return bytes_written;
}
@endcode
@subsection sftp_aio_actual_use Using the sftp aio API to speed up a transfer
The above examples were provided to introduce the sftp aio API.
This is not how the sftp aio API is intended to be used, because the
above usage offers no advantage over the synchronous sftp read/write API
which does the same thing i.e issue a request and then immediately wait for
its response.
The facility that the sftp aio API provides is that the user can do
anything between issuing a request and getting the corresponding response.
Any number of operations can be performed after calling sftp_aio_begin_*()
[which issues a request] and before calling sftp_aio_wait_*() [which waits
for a response]
The code can leverage this feature by calling sftp_aio_begin_*() multiple times
to issue multiple requests before calling sftp_aio_wait_*() to wait for the
response of an earlier issued request. This approach will keep a certain number
of requests outstanding at the client side.
After issuing those requests, while the client code does something else (for
example waiting for an outstanding request's response, processing an obtained
response, issuing another request or any other operation the client wants
to perform), at the same time :
- Some of those outstanding requests may be travelling over the
network towards the server.
- Some of the outstanding requests may have reached the server and may
be queued for processing at the server side.
- Some of the outstanding requests may have been processed and the
corresponding responses may be travelling over the network towards the
client.
- Some of the responses corresponding to the outstanding requests may
have already reached the client side.
Clearly in this case, operations that the client performs and operations
involved in transfer/processing of a outstanding request can occur in
parallel. Also, operations involved in transfer/processing of two or more
outstanding requests may also occur in parallel (for example when one request
travels to the server, another request's response may be incoming towards the
client). Such kind of parallelism makes the overall transfer faster as compared
to a transfer performed using the synchronous sftp read/write API.
When the synchronous sftp read/write API is used to perform a transfer,
a strict sequence is followed:
- The client issues a single read/write request.
- Then waits for its response.
- On obtaining the response, the client processes it.
- After the processing ends, the client issues the next read/write request.
A file transfer performed in this manner would be slower than the case where
multiple read/write requests are kept outstanding at the client side. Because
here at any given time, operations related to transfer/processing of only one
request/response pair occurs. This is in contrast to the multiple outstanding
requests scenario where operations related to transfer/processing of multiple
request/response pairs may occur at the same time.
Although it's true that keeping multiple requests outstanding can speed up a
transfer, those outstanding requests come at a cost of increased memory
consumption both at the client side and the server side. Hence care must be
taken to use a reasonable limit for the number of requests kept outstanding.
The further sections provide code examples to show how uploads/downloads
can be performed using the sftp aio API and the concept of outstanding requests
discussed in this section. In those code examples, error handling has been
ignored and at some places pseudo code has been used for the sake of brevity.
The complete code for performing uploads/downloads using the sftp aio API,
can be found at https://gitlab.com/libssh/libssh-mirror/-/tree/master.
- libssh benchmarks for uploads performed using the sftp aio API [See
tests/benchmarks/bench_sftp.c]
- libssh benchmarks for downloads performed using the sftp aio API. [See
tests/benchmarks/bench_sftp.c]
- libssh sftp ft API code for performing a local to remote transfer (upload).
[See src/sftp_ft.c]
- libssh sftp ft API code for performing a remote to local transfer
(download). [See src/sftp_ft.c]
@subsection sftp_aio_cap Capping applied by the sftp aio API
Before the code examples for uploads and downloads, its important
to know about the capping applied by the sftp aio API.
sftp_aio_begin_read() caps the number of bytes the caller can request
to read from the remote file. That cap is the value of the max_read_length
field of the sftp_limits_t returned by sftp_limits(). Say that cap is LIM
and the caller passes x as the number of bytes to read to
sftp_aio_begin_read(), then (assuming no error occurs) :
- if x <= LIM, then sftp_aio_begin_read() will request the server
to read x bytes from the remote file, and will return x.
- if x > LIM, then sftp_aio_begin_read() will request the server
to read LIM bytes from the remote file and will return LIM.
Hence to request server to read x bytes (> LIM), the caller would have
to call sftp_aio_begin_read() multiple times, typically in a loop and
break out of the loop when the summation of return values of the multiple
sftp_aio_begin_read() calls becomes equal to x.
For the sake of simplicity, the code example for download in the upcoming
section would always ask sftp_aio_begin_read() to read x <= LIM bytes,
so that its return value is guaranteed to be x, unless an error occurs.
Similarly, sftp_aio_begin_write() caps the number of bytes the caller
can request to write to the remote file. That cap is the value of
max_write_length field of the sftp_limits_t returned by sftp_limits().
Say that cap is LIM and the caller passes x as the number of bytes to
write to sftp_aio_begin_write(), then (assuming no error occurs) :
- if x <= LIM, then sftp_aio_begin_write() will request the server
to write x bytes to the remote file, and will return x.
- if x > LIM, then sftp_aio_begin_write() will request the server
to write LIM bytes to the remote file and will return LIM.
Hence to request server to write x bytes (> LIM), the caller would have
to call sftp_aio_begin_write() multiple times, typically in a loop and
break out of the loop when the summation of return values of the multiple
sftp_aio_begin_write() calls becomes equal to x.
For the sake of simplicity, the code example for upload in the upcoming
section would always ask sftp_aio_begin_write() to write x <= LIM bytes,
so that its return value is guaranteed to be x, unless an error occurs.
@subsection sftp_aio_download_example Performing a download using the sftp aio API
Terminologies used in the following code snippets :
- sftp : The sftp_session opened using sftp_new() and initialised using
sftp_init()
- file : The sftp file handle of the remote file to download data
from. (See sftp_open())
- file_size : the size of the sftp file to download. This size can be obtained
by statting the remote file to download (e.g by using sftp_stat())
- We will need to maintain a queue which will be used to store the sftp aio
handles corresponding to the outstanding requests.
First, we issue the read requests while ensuring that their count
doesn't exceed a particular limit decided by us, and the number of bytes
requested don't exceed the size of the file to download.
@code
sftp_aio aio = NULL;
// Chunk size to use for the transfer
size_t chunk_size;
// For the limits structure that would be used
// by the code to set the chunk size
sftp_limits_t lim = NULL;
// Max number of requests to keep outstanding at a time
size_t in_flight_requests = 5;
// Number of bytes for which requests have been sent
size_t total_bytes_requested = 0;
// Number of bytes which have been downloaded
size_t bytes_downloaded = 0;
// Buffer to use for the download
char *buffer = NULL;
// Helper variables
size_t to_read;
ssize_t bytes_requested;
// Get the sftp limits
lim = sftp_limits(sftp);
if (lim == NULL) {
// handle error
}
// Set the chunk size for download = the max limit for reading
// The reason for this has been given in the "Capping applied by
// the sftp aio API" section (Its to make the code simpler)
//
// Assigning a size_t type variable a uint64_t type value here,
// theoretically could cause an overflow, but practically
// max_read_length would never exceed SIZE_MAX so its okay.
chunk_size = lim->max_read_length;
buffer = malloc(chunk_size);
if (buffer == NULL) {
// handle error
}
... // Code to open the remote file (to download) using sftp_open().
... // Code to stat the remote file's file size.
... // Code to open the local file in which downloaded data is to be stored.
... // Code to initialize the queue which will be used to store sftp aio
// handles.
for (i = 0;
i < in_flight_requests && total_bytes_requested < file_size;
++i) {
to_read = file_size - total_bytes_requested;
if (to_read > chunk_size) {
to_read = chunk_size;
}
// Issue a read request
bytes_requested = sftp_aio_begin_read(file, to_read, &aio);
if (bytes_requested == SSH_ERROR) {
// handle error
}
if ((size_t)bytes_requested < to_read) {
// Should not happen for this code, as the to_read is <=
// max limit for reading (chunk size), so there is no reason
// for sftp_aio_begin_read() to return a lesser value.
}
total_bytes_requested += (size_t)bytes_requested;
// Pseudo code
ENQUEUE aio in the queue;
}
@endcode
At this point, at max in_flight_requests number of requests may be
outstanding. Now we wait for the response corresponding to the earliest
issued outstanding request.
On getting that response, we issue another read request if there are
still some bytes in the sftp file (to download) for which we haven't sent the
read request. (This happens when total_bytes_requested < file_size)
This issuing of another read request (under a condition) is done to
keep the number of outstanding requests equal to the value of the
in_flight_requests variable.
This process has to be repeated for every remaining outstanding request.
@code
while (the queue is not empty) {
// Pseudo code
aio = DEQUEUE an sftp aio handle from the queue of sftp aio handles;
// Wait for the response of the request corresponding to the aio
bytes_read = sftp_aio_wait_read(&aio, buffer, chunk_size);
if (bytes_read == SSH_ERROR) {
//handle error
}
bytes_downloaded += bytes_read;
if (bytes_read != chunk_size && bytes_downloaded != file_size) {
// A short read encountered on the remote file before reaching EOF,
// short read before reaching EOF should never happen for the sftp aio
// API which respects the max limit for reading. This probably
// indicates a bad server.
}
// Pseudo code
WRITE bytes_read bytes from the buffer into the local file
in which downloaded data is to be stored ;
if (total_bytes_requested == file_size) {
// no need to issue more read requests
continue;
}
// else issue a read request
to_read = file_size - total_bytes_requested;
if (to_read > chunk_size) {
to_read = chunk_size;
}
bytes_requested = sftp_aio_begin_read(file, to_read, &aio);
if (bytes_requested == SSH_ERROR) {
// handle error
}
if ((size_t)bytes_requested < to_read) {
// Should not happen for this code, as the to_read is <=
// max limit for reading (chunk size), so there is no reason
// for sftp_aio_begin_read() to return a lesser value.
}
total_bytes_requested += bytes_requested;
// Pseudo code
ENQUEUE aio in the queue;
}
free(buffer);
sftp_limits_free(lim);
... // Code to destroy the queue which was used to store the sftp aio
// handles.
@endcode
After exiting the while (the queue is not empty) loop, the download
would've been complete (assuming no error occurs).
@subsection sftp_aio_upload_example Performing an upload using the sftp aio API
Terminologies used in the following code snippets :
- sftp : The sftp_session opened using sftp_new() and initialised using
sftp_init()
- file : The sftp file handle of the remote file in which uploaded data
is to be stored. (See sftp_open())
- file_size : The size of the local file to upload. This size can be
obtained by statting the local file to upload (e.g by using stat())
- We will need maintain a queue which will be used to store the sftp aio
handles corresponding to the outstanding requests.
First, we issue the write requests while ensuring that their count
doesn't exceed a particular limit decided by us, and the number of bytes
requested to write don't exceed the size of the file to upload.
@code
sftp_aio aio = NULL;
// The chunk size to use for the transfer
size_t chunk_size;
// For the limits structure that would be used by
// the code to set the chunk size
sftp_limits_t lim = NULL;
// Max number of requests to keep outstanding at a time
size_t in_flight_requests = 5;
// Total number of bytes for which write requests have been sent
size_t total_bytes_requested = 0;
// Buffer to use for the upload
char *buffer = NULL;
// Helper variables
size_t to_write;
ssize_t bytes_requested;
// Get the sftp limits
lim = sftp_limits(sftp);
if (lim == NULL) {
// handle error
}
// Set the chunk size for upload = the max limit for writing.
// The reason for this has been given in the "Capping applied by
// the sftp aio API" section (Its to make the code simpler)
//
// Assigning a size_t type variable a uint64_t type value here,
// theoretically could cause an overflow, but practically
// max_write_length would never exceed SIZE_MAX so its okay.
chunk_size = lim->max_write_length;
buffer = malloc(chunk_size);
if (buffer == NULL) {
// handle error
}
... // Code to open the local file (to upload) [e.g using open(), fopen()].
... // Code to stat the local file's file size [e.g using stat()].
... // Code to open the remote file in which uploaded data will be stored [see
// sftp_open()].
... // Code to initialize the queue which will be used to store sftp aio
// handles.
for (i = 0;
i < in_flight_requests && total_bytes_requested < file_size;
++i) {
to_write = file_size - total_bytes_requested;
if (to_write > chunk_size) {
to_write = chunk_size;
}
// Pseudo code
READ to_write bytes from the local file (to upload) into the buffer;
bytes_requested = sftp_aio_begin_write(file, buffer, to_write, &aio);
if (bytes_requested == SSH_ERROR) {
// handle error
}
if ((size_t)bytes_requested < to_write) {
// Should not happen for this code, as the to_write is <=
// max limit for writing (chunk size), so there is no reason
// for sftp_aio_begin_write() to return a lesser value.
}
total_bytes_requested += (size_t)bytes_requested;
// Pseudo code
ENQUEUE aio in the queue;
}
@endcode
At this point, at max in_flight_requests number of requests may be
outstanding. Now we wait for the response corresponding to the earliest
issued outstanding request.
On getting that response, we issue another write request if there are
still some bytes in the local file (to upload) for which we haven't sent
the write request. (This happens when total_bytes_requested < file_size)
This issuing of another write request (under a condition) is done to
keep the number of outstanding requests equal to the value of the
in_flight_requests variable.
This process has to be repeated for every remaining outstanding request.
@code
while (the queue is not empty) {
// Pseudo code
aio = DEQUEUE an sftp aio handle from the queue of sftp aio handles;
// Wait for the response of the request corresponding to the aio
bytes_written = sftp_aio_wait_write(&aio);
if (bytes_written == SSH_ERROR) {
// handle error
}
// sftp_aio_wait_write() won't report a short write, so no need
// to check for a short write here.
if (total_bytes_requested == file_size) {
// no need to issue more write requests
continue;
}
// else issue a write request
to_write = file_size - total_bytes_requested;
if (to_write > chunk_size) {
to_write = chunk_size;
}
// Pseudo code
READ to_write bytes from the local file (to upload) into a buffer;
bytes_requested = sftp_aio_begin_write(file, buffer, to_write, &aio);
if (bytes_requested == SSH_ERROR) {
// handle error
}
if ((size_t)bytes_requested < to_write) {
// Should not happen for this code, as the to_write is <=
// max limit for writing (chunk size), so there is no reason
// for sftp_aio_begin_write() to return a lesser value.
}
total_bytes_requested += (size_t)bytes_requested;
// Pseudo code
ENQUEUE aio in the queue;
}
free(buffer);
... // Code to destroy the queue which was used to store the sftp aio
// handles.
@endcode
After exiting the while (the queue is not empty) loop, the upload
would've been complete (assuming no error occurs).
@subsection sftp_aio_free Example showing the usage of sftp_aio_free()
The purpose of sftp_aio_free() was discussed at the beginning of this page,
the following code example shows how it can be used during cleanup.
@code
void print_sftp_error(sftp_session sftp)
{
if (sftp == NULL) {
return;
}
fprintf(stderr, "sftp error : %d\n", sftp_get_error(sftp));
fprintf(stderr, "ssh error : %s\n", ssh_get_error(sftp->session));
}
// Returns 0 on success, -1 on error
int write_strings(sftp_file file)
{
const char * strings[] = {
"This is the first string",
"This is the second string",
"This is the third string",
"This is the fourth string"
};
size_t string_count = sizeof(strings) / sizeof(strings[0]);
size_t i;
sftp_session sftp = NULL;
sftp_aio aio = NULL;
int rc;
if (file == NULL) {
return -1;
}
... // Code to initialize the queue which will be used to store sftp aio
// handles
sftp = file->sftp;
for (i = 0; i < string_count; ++i) {
rc = sftp_aio_begin_write(file,
strings[i],
strlen(strings[i]),
&aio);
if (rc == SSH_ERROR) {
print_sftp_error(sftp);
goto err;
}
// Pseudo code
ENQUEUE aio in the queue of sftp aio handles
}
for (i = 0; i < string_count; ++i) {
// Pseudo code
aio = DEQUEUE an sftp aio handle from the queue of sftp aio handles;
rc = sftp_aio_wait_write(&aio);
if (rc == SSH_ERROR) {
print_sftp_error(sftp);
goto err;
}
}
... // Code to destroy the queue in which sftp aio handles were
// stored
return 0;
err:
while (queue is not empty) {
// Pseudo code
aio = DEQUEUE an sftp aio handle from the queue of sftp aio handles;
sftp_aio_free(aio);
}
... // Code to destroy the queue in which sftp aio handles were
// stored.
return -1;
}
@endcode
*/

View File

@@ -1,391 +0,0 @@
/**
@page libssh_tutor_shell Chapter 3: Opening a remote shell
@section opening_shell Opening a remote shell
We already mentioned that a single SSH connection can be shared
between several "channels". Channels can be used for different purposes.
This chapter shows how to open one of these channels, and how to use it to
start a command interpreter on a remote computer.
@subsection open_channel Opening and closing a channel
The ssh_channel_new() function creates a channel. It returns the channel as
a variable of type ssh_channel.
Once you have this channel, you open a SSH session that uses it with
ssh_channel_open_session().
Once you don't need the channel anymore, you can send an end-of-file
to it with ssh_channel_close(). At this point, you can destroy the channel
with ssh_channel_free().
The code sample below achieves these tasks:
@code
int shell_session(ssh_session session)
{
ssh_channel channel = NULL;
int rc;
channel = ssh_channel_new(session);
if (channel == NULL)
return SSH_ERROR;
rc = ssh_channel_open_session(channel);
if (rc != SSH_OK)
{
ssh_channel_free(channel);
return rc;
}
...
ssh_channel_close(channel);
ssh_channel_send_eof(channel);
ssh_channel_free(channel);
return SSH_OK;
}
@endcode
@subsection interactive Interactive and non-interactive sessions
A "shell" is a command interpreter. It is said to be "interactive"
if there is a human user typing the commands, one after the
other. The contrary, a non-interactive shell, is similar to
the execution of commands in the background: there is no attached
terminal.
If you plan using an interactive shell, you need to create a
pseud-terminal on the remote side. A remote terminal is usually referred
to as a "pty", for "pseudo-teletype". The remote processes won't see the
difference with a real text-oriented terminal.
If needed, you request the pty with the function ssh_channel_request_pty().
If you want define its dimensions (number of rows and columns),
call ssh_channel_request_pty_size() instead. It's also possible to change
the dimensions after creating the pty with ssh_channel_change_pty_size().
These two functions configure the pty using the same terminal modes that
stdin has. If stdin isn't a TTY, they use default modes that configure
the pty with in canonical mode and e.g. preserving CR and LF characters.
If you want to change the terminal modes used by the pty (e.g. to change
CRLF handling), use ssh_channel_request_pty_size_modes(). This function
accepts an additional "modes" buffer that is expected to contain encoded
terminal modes according to RFC 4254 section 8.
Be your session interactive or not, the next step is to request a
shell with ssh_channel_request_shell().
@code
int interactive_shell_session(ssh_channel channel)
{
int rc;
rc = ssh_channel_request_pty(channel);
if (rc != SSH_OK) return rc;
rc = ssh_channel_change_pty_size(channel, 80, 24);
if (rc != SSH_OK) return rc;
rc = ssh_channel_request_shell(channel);
if (rc != SSH_OK) return rc;
...
return rc;
}
@endcode
@subsection read_data Displaying the data sent by the remote computer
In your program, you will usually need to receive all the data "displayed"
into the remote pty. You will usually analyse, log, or display this data.
ssh_channel_read() and ssh_channel_read_nonblocking() are the simplest
way to read data from a channel. If you only need to read from a single
channel, they should be enough.
The example below shows how to wait for remote data using ssh_channel_read():
@code
int interactive_shell_session(ssh_channel channel)
{
int rc;
char buffer[256];
int nbytes;
rc = ssh_channel_request_pty(channel);
if (rc != SSH_OK) return rc;
rc = ssh_channel_change_pty_size(channel, 80, 24);
if (rc != SSH_OK) return rc;
rc = ssh_channel_request_shell(channel);
if (rc != SSH_OK) return rc;
while (ssh_channel_is_open(channel) &&
!ssh_channel_is_eof(channel))
{
nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
if (nbytes < 0)
return SSH_ERROR;
if (nbytes > 0)
write(1, buffer, nbytes);
}
return rc;
}
@endcode
Unlike ssh_channel_read(), ssh_channel_read_nonblocking() never waits for
remote data to be ready. It returns immediately.
If you plan to use ssh_channel_read_nonblocking() repeatedly in a loop,
you should use a "passive wait" function like usleep(3) in the same
loop. Otherwise, your program will consume all the CPU time, and your
computer might become unresponsive.
@subsection write_data Sending user input to the remote computer
User's input is sent to the remote site with ssh_channel_write().
The following example shows how to combine a nonblocking read from a SSH
channel with a nonblocking read from the keyboard. The local input is then
sent to the remote computer:
@code
/* Under Linux, this function determines whether a key has been pressed.
Under Windows, it is a standard function, so you need not redefine it.
*/
int kbhit()
{
struct timeval tv = { 0L, 0L };
fd_set fds;
FD_ZERO(&fds);
FD_SET(0, &fds);
return select(1, &fds, NULL, NULL, &tv);
}
/* A very simple terminal emulator:
- print data received from the remote computer
- send keyboard input to the remote computer
*/
int interactive_shell_session(ssh_channel channel)
{
/* Session and terminal initialization skipped */
...
char buffer[256];
int nbytes, nwritten;
while (ssh_channel_is_open(channel) &&
!ssh_channel_is_eof(channel))
{
nbytes = ssh_channel_read_nonblocking(channel, buffer, sizeof(buffer), 0);
if (nbytes < 0) return SSH_ERROR;
if (nbytes > 0)
{
nwritten = write(1, buffer, nbytes);
if (nwritten != nbytes) return SSH_ERROR;
if (!kbhit())
{
usleep(50000L); // 0.05 second
continue;
}
nbytes = read(0, buffer, sizeof(buffer));
if (nbytes < 0) return SSH_ERROR;
if (nbytes > 0)
{
nwritten = ssh_channel_write(channel, buffer, nbytes);
if (nwritten != nbytes) return SSH_ERROR;
}
}
return rc;
}
@endcode
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.
Also, user's input should not be sent once "Enter" key is pressed, but
immediately after each key is pressed. This can be accomplished
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
recode it with:
@code
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;
}
@endcode
If you are not using a local terminal, but some kind of graphical
environment, the solution to this kind of "echo" problems will be different.
@subsection select_loop A more elaborate way to get the remote data
*** Warning: ssh_select() and ssh_channel_select() are not relevant anymore,
since libssh is about to provide an easier system for asynchronous
communications. This subsection should be removed then. ***
ssh_channel_read() and ssh_channel_read_nonblocking() functions are simple,
but they are not adapted when you expect data from more than one SSH channel,
or from other file descriptors. Last example showed how getting data from
the standard input (the keyboard) at the same time as data from the SSH
channel was complicated. The functions ssh_select() and ssh_channel_select()
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
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
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
and make your computer unresponsive. It is quite common to use these
functions in your application's main loop.
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_select() is more complete and enables watching regular file descriptors
as well, in the same function call.
Below is an example of a function that waits both for remote SSH data to come,
as well as standard input from the keyboard:
@code
int interactive_shell_session(ssh_session session, ssh_channel channel)
{
/* Session and terminal initialization skipped */
...
char buffer[256];
int nbytes, nwritten;
while (ssh_channel_is_open(channel) &&
!ssh_channel_is_eof(channel))
{
struct timeval timeout;
ssh_channel in_channels[2], out_channels[2];
fd_set fds;
int maxfd;
timeout.tv_sec = 30;
timeout.tv_usec = 0;
in_channels[0] = channel;
in_channels[1] = NULL;
FD_ZERO(&fds);
FD_SET(0, &fds);
FD_SET(ssh_get_fd(session), &fds);
maxfd = ssh_get_fd(session) + 1;
ssh_select(in_channels, out_channels, maxfd, &fds, &timeout);
if (out_channels[0] != NULL)
{
nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
if (nbytes < 0) return SSH_ERROR;
if (nbytes > 0)
{
nwritten = write(1, buffer, nbytes);
if (nwritten != nbytes) return SSH_ERROR;
}
}
if (FD_ISSET(0, &fds))
{
nbytes = read(0, buffer, sizeof(buffer));
if (nbytes < 0) return SSH_ERROR;
if (nbytes > 0)
{
nwritten = ssh_channel_write(channel, buffer, nbytes);
if (nbytes != nwritten) return SSH_ERROR;
}
}
}
return rc;
}
@endcode
@subsection x11 Using graphical applications on the remote side
If your remote application is graphical, you can forward the X11 protocol to
your local computer.
To do that, you first declare a callback to manage channel_open_request_x11_function.
Then you create the forwarding tunnel for the X11 protocol with ssh_channel_request_x11().
The following code performs channel initialization and shell session
opening, and handles a parallel X11 connection:
@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 rc;
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);
if (rc != SSH_OK) return rc;
rc = ssh_channel_change_pty_size(channel, 80, 24);
if (rc != SSH_OK) return rc;
rc = ssh_channel_request_x11(channel, 0, NULL, NULL, 0);
if (rc != SSH_OK) return rc;
rc = ssh_channel_request_shell(channel);
if (rc != SSH_OK) return rc;
/* Read the data sent by the remote computer here */
...
}
@endcode
Don't forget to check the $DISPLAY environment variable on the remote
side, or the remote applications won't try using the X11 tunnel:
@code
$ echo $DISPLAY
localhost:10.0
$ xclock &
@endcode
See an implementation example at https://gitlab.com/libssh/libssh-mirror/-/tree/master/examples/ssh_X11_client.c for details.
*/

184
doc/style.css Normal file
View File

@@ -0,0 +1,184 @@
body {
background-color:#ddf;
/*background-image:url(../back6.jpg);*/
margin:10px 10px 10px 10px;
}
h1 {
font-family:verdana, sans-serif;
font-size:80%;
color:black;
background-color:transparent;
text-align:left;
}
h2 {
font-family:verdana, sans-serif;
font-size:100%;
color:black;
background-color:transparent;
text-align:left;
}
h3 {
font-family:verdana, sans-serif;
font-size:80%;
color:black;
background-color:transparent;
text-align:left;
}
p {
font-family:verdana, sans-serif;
font-size:80%;
color:black;
background-color:transparent;
text-align:left;
margin-left:0px;
margin-right:0px;
}
li {
font-family:verdana, sans-serif;
font-size:80%;
color:black;
background-color:transparent;
text-align:left;
margin-left:0px;
margin-right:0px;
}
a:link {
font-family:verdana, sans-serif;
font-size:100%;
color:black;
background-color:transparent;
text-decoration:underline;
}
a:visited {
font-family:verdana, sans-serif;
font-size:100%;
color:black;
background-color:transparent;
text-decoration:underline;
}
a:hover {
font-family:verdana, sans-serif;
font-size:100%;
color:black;
background-color:transparent;
text-decoration:underline;
}
table {
border-color:transparent;
border-style:solid;
border-width:1px;
}
td {
font-family:verdana, sans-serif;
font-size:80%;
color:black;
text-align:left;
background-color:transparent;
border-color:transparent;
border-style:solid;
border-width:1px;
}
.tout {
margin: 5px;
padding: 0px;
border: 2px solid #aac;
background: #eef;
}
.prot {
border-style:solid;
border-width:2px;
border-color:#88F;
padding: 4px;
background-color:#cce;
margin: 5px 5px 5px 5px;
}
.ex {
border-style:solid;
border-width:2px;
border-color:#aaF;
padding: 4px;
background-color:#dde;
margin: 5px 5px 5px 5px;
}
.desc {
border-style:solid;
border-width:3px;
border-color:#66F;
padding: 4px;
background-color:#aac;
margin: 15px 5px 20px 5px;
}
#titre {
margin: 5px;
padding: 0px;
border: 5px solid #aac;
background: #eef;
}
#gauche {
float:left;
margin: 5px;
padding: 4px;
border: 5px solid #aac;
background: #bbf;
width: 130px;
}
#droite {
position: relative;
top:5px;
left:165px;
margin: 5px 170px 5px 5px;
padding: 10px;
border: 5px solid #aac;
background: #bbf;
}
/* boutons */
a.bouton:link{
width:128px;
height:34px;
text-decoration:none;
color:#aaa;
text-align:center;
font-weight:bold;
/*background-color:#444;*/
background-image:url(noclicked.png);
}
a.bouton:visited{
width:128px;
height:34px;
text-decoration:none;
color:#aaa;
text-align:center;
font-weight:bold;
/*background-color:#444;*/
background-image:url(noclicked.png);
}
a.bouton:hover{
width:128px;
height:34px;
text-decoration:none;
color:white;
text-align:center;
font-weight:bold;
/*background-color:#888;*/
background-image:url(clicked.png);
}
.bouton{
text-align:center;
display:block;
}

View File

@@ -1,14 +0,0 @@
/**
@page libssh_tutor_todo To be done
*** To be written ***
@section sshd Writing a libssh-based server
*** To be written ***
@section cpp The libssh C++ wrapper
*** To be written ***
*/

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

@@ -1,52 +0,0 @@
/**
@page libssh_tutor_threads Chapter 8: Threads with libssh
@section threads_with_libssh How to use libssh with threads
libssh may be used in multithreaded applications, but under several conditions :
- Your system must support libpthread or, in Windows environment,
CriticalSection based mutex control.
- Since version 0.8.0, threads initialization is called automatically in the
library constructor if libssh is dynamically linked. This means it is no
longer necessary to call ssh_init()/ssh_finalize().
- If libssh is statically linked, threading must be initialized by calling
ssh_init() before using any of libssh provided functions. This initialization
must be done outside of any threading context. Don't forget to call
ssh_finalize() to avoid memory leak
- 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
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
being worked out and will maybe disappear later.
@subsection threads_init Initialization of threads
Since version 0.8.0, it is no longer necessary to call ssh_init()/ssh_finalize()
if libssh is dynamically linked.
If libssh is statically linked, call ssh_init() before using any of libssh
provided functions.
@subsection threads_pthread Using libpthread with libssh
Since version 0.8.0, libpthread is the default threads library used by libssh.
To use libpthread, simply link it to you application.
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
Since version 0.8.0, libssh does not support custom threading libraries.
The change makes sense since the newer versions for libcrypto (OpenSSL) and
libgcrypt don't support custom threading libraries.
The default used threading library is libpthread.
Alternatively, in Windows environment, CriticalSection based mutex control can
be used.
If your system does not support libpthread nor CriticalSection based mutex
control, unfortunately, you cannot use libssh in multithreaded scenarios.
Good luck !
*/

View File

@@ -1,105 +0,0 @@
project(libssh-examples C CXX)
set(examples_SRCS
authentication.c
knownhosts.c
connect_ssh.c
)
include_directories(${libssh_BINARY_DIR}/include ${libssh_BINARY_DIR})
if (ARGP_INCLUDE_DIR)
include_directories(${ARGP_INCLUDE_DIR})
endif()
if (UNIX AND NOT WIN32)
add_executable(libssh_scp libssh_scp.c ${examples_SRCS})
target_compile_options(libssh_scp PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
target_link_libraries(libssh_scp ssh::ssh)
add_executable(scp_download scp_download.c ${examples_SRCS})
target_compile_options(scp_download PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
target_link_libraries(scp_download ssh::ssh)
add_executable(sshnetcat sshnetcat.c ${examples_SRCS})
target_compile_options(sshnetcat PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
target_link_libraries(sshnetcat ssh::ssh)
if (WITH_SFTP)
add_executable(samplesftp samplesftp.c ${examples_SRCS})
target_compile_options(samplesftp PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
target_link_libraries(samplesftp ssh::ssh)
if (WITH_SERVER)
add_executable(sample_sftpserver sample_sftpserver.c ${examples_SRCS})
target_compile_options(sample_sftpserver PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
target_link_libraries(sample_sftpserver ssh::ssh ${ARGP_LIBRARIES})
endif (WITH_SERVER)
endif (WITH_SFTP)
add_executable(ssh-client ssh_client.c ${examples_SRCS})
target_compile_options(ssh-client PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
target_link_libraries(ssh-client ssh::ssh)
add_executable(ssh-X11-client ssh_X11_client.c ${examples_SRCS})
target_compile_options(ssh-X11-client PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
target_link_libraries(ssh-X11-client ssh::ssh)
if (WITH_SERVER AND (ARGP_LIBRARIES OR HAVE_ARGP_H))
if (HAVE_LIBUTIL)
add_executable(ssh_server_fork ssh_server.c)
target_compile_options(ssh_server_fork PRIVATE ${DEFAULT_C_COMPILE_FLAGS} -DWITH_FORK)
target_link_libraries(ssh_server_fork ssh::ssh ${ARGP_LIBRARIES} 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_LIBRARIES} pthread util)
endif (HAVE_LIBUTIL)
if (WITH_GSSAPI AND GSSAPI_FOUND)
add_executable(proxy proxy.c)
target_compile_options(proxy PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
target_link_libraries(proxy ssh::ssh ${ARGP_LIBRARIES})
add_executable(sshd_direct-tcpip sshd_direct-tcpip.c)
target_compile_options(sshd_direct-tcpip PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
target_link_libraries(sshd_direct-tcpip ssh::ssh ${ARGP_LIBRARIES})
endif (WITH_GSSAPI AND GSSAPI_FOUND)
add_executable(samplesshd-kbdint samplesshd-kbdint.c)
target_compile_options(samplesshd-kbdint PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
target_link_libraries(samplesshd-kbdint ssh::ssh ${ARGP_LIBRARIES})
add_executable(keygen2 keygen2.c ${examples_SRCS})
target_compile_options(keygen2 PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
target_link_libraries(keygen2 ssh::ssh ${ARGP_LIBRARIES})
endif()
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_LIBRARIES OR HAVE_ARGP_H)
target_link_libraries(samplesshd-cb ${ARGP_LIBRARIES})
endif(ARGP_LIBRARIES OR HAVE_ARGP_H)
endif()
add_executable(exec exec.c ${examples_SRCS})
target_compile_options(exec PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
target_link_libraries(exec ssh::ssh)
add_executable(senddata senddata.c ${examples_SRCS})
target_compile_options(senddata PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
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)
target_link_libraries(libsshpp ssh::ssh)
add_executable(libsshpp_noexcept libsshpp_noexcept.cpp)
target_link_libraries(libsshpp_noexcept ssh::ssh)

View File

@@ -1,240 +0,0 @@
/*
* authentication.c
* This file contains an example of how to do an authentication to a
* SSH server using libssh
*/
/*
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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <libssh/libssh.h>
#include "examples_common.h"
int authenticate_kbdint(ssh_session session, const char *password)
{
int err;
err = ssh_userauth_kbdint(session, NULL, NULL);
while (err == SSH_AUTH_INFO) {
const char *instruction = NULL;
const char *name = NULL;
char buffer[128];
int i, n;
name = ssh_userauth_kbdint_getname(session);
instruction = ssh_userauth_kbdint_getinstruction(session);
n = ssh_userauth_kbdint_getnprompts(session);
if (name && strlen(name) > 0) {
printf("%s\n", name);
}
if (instruction && strlen(instruction) > 0) {
printf("%s\n", instruction);
}
for (i = 0; i < n; i++) {
const char *answer = NULL;
const char *prompt = NULL;
char echo;
prompt = ssh_userauth_kbdint_getprompt(session, i, &echo);
if (prompt == NULL) {
break;
}
if (echo) {
char *p = NULL;
printf("%s", prompt);
if (fgets(buffer, sizeof(buffer), stdin) == NULL) {
return SSH_AUTH_ERROR;
}
if ((p = strchr(buffer, '\n'))) {
*p = '\0';
}
if (ssh_userauth_kbdint_setanswer(session, i, buffer) < 0) {
return SSH_AUTH_ERROR;
}
memset(buffer, 0, sizeof(buffer));
} else {
if (password && strstr(prompt, "Password:")) {
answer = password;
} else {
buffer[0] = '\0';
if (ssh_getpass(prompt, buffer, sizeof(buffer), 0, 0) < 0) {
return SSH_AUTH_ERROR;
}
answer = buffer;
}
err = ssh_userauth_kbdint_setanswer(session, i, answer);
memset(buffer, 0, sizeof(buffer));
if (err < 0) {
return SSH_AUTH_ERROR;
}
}
}
err=ssh_userauth_kbdint(session,NULL,NULL);
}
return err;
}
static int auth_keyfile(ssh_session session, char* keyfile)
{
ssh_key key = NULL;
char pubkey[132] = {0}; // +".pub"
int rc;
snprintf(pubkey, sizeof(pubkey), "%s.pub", keyfile);
rc = ssh_pki_import_pubkey_file( pubkey, &key);
if (rc != SSH_OK)
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);
return rc;
}
static void error(ssh_session session)
{
fprintf(stderr,"Authentication failed: %s\n",ssh_get_error(session));
}
int authenticate_console(ssh_session session)
{
int rc;
int method;
char password[128] = {0};
char *banner = NULL;
// Try to authenticate
rc = ssh_userauth_none(session, NULL);
if (rc == SSH_AUTH_ERROR || !ssh_is_connected(session)) {
error(session);
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 || !ssh_is_connected(session)) {
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 || !ssh_is_connected(session)) {
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 || !ssh_is_connected(session)) {
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 || !ssh_is_connected(session)) {
error(session);
return rc;
} else if (rc == SSH_AUTH_SUCCESS) {
break;
}
}
memset(password, 0, sizeof(password));
}
banner = ssh_get_issue_banner(session);
if (banner) {
printf("%s\n",banner);
SSH_STRING_FREE_CHAR(banner);
}
return rc;
}

View File

@@ -1,70 +0,0 @@
/*
* connect_ssh.c
* This file contains an example of how to connect to a
* SSH server using libssh
*/
/*
Copyright 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 <libssh/libssh.h>
#include "examples_common.h"
#include <stdio.h>
ssh_session connect_ssh(const char *host, const char *user, int verbosity)
{
ssh_session session = NULL;
int auth = 0;
session = ssh_new();
if (session == NULL) {
return NULL;
}
if (user != NULL) {
if (ssh_options_set(session, SSH_OPTIONS_USER, user) < 0) {
ssh_free(session);
return NULL;
}
}
if (ssh_options_set(session, SSH_OPTIONS_HOST, host) < 0) {
ssh_free(session);
return NULL;
}
ssh_options_set(session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity);
if (ssh_connect(session)) {
fprintf(stderr, "Connection failed : %s\n", ssh_get_error(session));
ssh_disconnect(session);
ssh_free(session);
return NULL;
}
if (verify_knownhost(session) < 0) {
ssh_disconnect(session);
ssh_free(session);
return NULL;
}
auth = authenticate_console(session);
if (auth == SSH_AUTH_SUCCESS) {
return session;
} else if (auth == SSH_AUTH_DENIED) {
fprintf(stderr, "Authentication failed\n");
} else {
fprintf(stderr,
"Error while authenticating : %s\n",
ssh_get_error(session));
}
ssh_disconnect(session);
ssh_free(session);
return NULL;
}

View File

@@ -1,26 +0,0 @@
/*
Copyright 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.
*/
#ifndef EXAMPLES_COMMON_H_
#define EXAMPLES_COMMON_H_
#include <libssh/libssh.h>
/** Zero a structure */
#define ZERO_STRUCT(x) memset(&(x), 0, sizeof(x))
int authenticate_console(ssh_session session);
int authenticate_kbdint(ssh_session session, const char *password);
int verify_knownhost(ssh_session session);
ssh_session connect_ssh(const char *hostname, const char *user, int verbosity);
#endif /* EXAMPLES_COMMON_H_ */

View File

@@ -1,81 +0,0 @@
/* simple exec example */
#include <stdio.h>
#include <libssh/libssh.h>
#include "examples_common.h"
int main(void) {
ssh_session session = NULL;
ssh_channel channel = NULL;
char buffer[256];
int rbytes, wbytes, total = 0;
int rc;
session = connect_ssh("localhost", NULL, 0);
if (session == NULL) {
ssh_finalize();
return 1;
}
channel = ssh_channel_new(session);
if (channel == NULL) {
ssh_disconnect(session);
ssh_free(session);
ssh_finalize();
return 1;
}
rc = ssh_channel_open_session(channel);
if (rc < 0) {
goto failed;
}
rc = ssh_channel_request_exec(channel, "lsof");
if (rc < 0) {
goto failed;
}
rbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
if (rbytes <= 0) {
goto failed;
}
do {
wbytes = fwrite(buffer + total, 1, rbytes, stdout);
if (wbytes <= 0) {
goto failed;
}
total += wbytes;
/* 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;
}
ssh_channel_send_eof(channel);
ssh_channel_close(channel);
ssh_channel_free(channel);
ssh_disconnect(session);
ssh_free(session);
ssh_finalize();
return 0;
failed:
ssh_channel_close(channel);
ssh_channel_free(channel);
ssh_disconnect(session);
ssh_free(session);
ssh_finalize();
return 1;
}

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