Compare commits
159 Commits
libssh-0.1
...
libssh-0.5
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6da817aa47 | ||
|
|
05ed61848f | ||
|
|
d63f19c300 | ||
|
|
455da60846 | ||
|
|
46b2eb3c14 | ||
|
|
6236001ff4 | ||
|
|
1471f2c67a | ||
|
|
b485463197 | ||
|
|
64fca8a7ed | ||
|
|
e3d9501b31 | ||
|
|
1699adfa03 | ||
|
|
db81310d71 | ||
|
|
8489521c0d | ||
|
|
2ee6282fdd | ||
|
|
ae218d0d15 | ||
|
|
26579b2231 | ||
|
|
04f1d950b9 | ||
|
|
191c0ae2bb | ||
|
|
5b32f31a31 | ||
|
|
3eac8e1c18 | ||
|
|
dc8f0cddee | ||
|
|
97b263aee9 | ||
|
|
cb53c4f0e1 | ||
|
|
0d029e7038 | ||
|
|
aae725a44c | ||
|
|
0e833d75e6 | ||
|
|
ae83f77511 | ||
|
|
4d8420f328 | ||
|
|
d8f2a793d3 | ||
|
|
558b53a856 | ||
|
|
0764adc82f | ||
|
|
87fd7d617e | ||
|
|
3e83af5f5e | ||
|
|
0dc57fdcf1 | ||
|
|
3799670d01 | ||
|
|
d6390d50bf | ||
|
|
e27b31c9c4 | ||
|
|
684b7f6a57 | ||
|
|
b0b2fd768c | ||
|
|
9180bfffcd | ||
|
|
058bb0f4ea | ||
|
|
64b125700e | ||
|
|
6f650a61ca | ||
|
|
d4e95f4653 | ||
|
|
26be91fb8e | ||
|
|
43a3becf08 | ||
|
|
d127d68b9f | ||
|
|
730da3e3c2 | ||
|
|
661722753b | ||
|
|
ac445a1e18 | ||
|
|
b7a3d41baf | ||
|
|
096475b356 | ||
|
|
d08554dabd | ||
|
|
cbe8f8b760 | ||
|
|
8987bc53e0 | ||
|
|
39802b31fe | ||
|
|
e5a2aef1bf | ||
|
|
edb03bd224 | ||
|
|
1204f43ea9 | ||
|
|
b542bc9e4e | ||
|
|
61a97ccede | ||
|
|
a1ef27c0b8 | ||
|
|
fb8f2cd11b | ||
|
|
1d8a9ddf84 | ||
|
|
bea66b6476 | ||
|
|
a8111934d5 | ||
|
|
f201e983b0 | ||
|
|
81332e1e27 | ||
|
|
ea84f50603 | ||
|
|
ccc94e7ab6 | ||
|
|
4c05be0c1b | ||
|
|
a493a90c59 | ||
|
|
4a18df8574 | ||
|
|
cfa74c1dc6 | ||
|
|
de706de8c3 | ||
|
|
71fa0dc6bb | ||
|
|
914a2d8e41 | ||
|
|
956b64d348 | ||
|
|
91489cd378 | ||
|
|
615bc3b8f7 | ||
|
|
5b645419fd | ||
|
|
c436e07022 | ||
|
|
188fb37801 | ||
|
|
44fed3eb9b | ||
|
|
36abd82a7e | ||
|
|
fd6d0b6897 | ||
|
|
09b0018b93 | ||
|
|
2624e603d4 | ||
|
|
fd61eda16d | ||
|
|
a6dda5fefd | ||
|
|
da8356b477 | ||
|
|
e5fb20c17b | ||
|
|
c472bd7437 | ||
|
|
8796756ae5 | ||
|
|
9c8f285a98 | ||
|
|
8154e24027 | ||
|
|
629cfbccc4 | ||
|
|
c5990791db | ||
|
|
16241938af | ||
|
|
6a8cb38dd3 | ||
|
|
bac2227ee2 | ||
|
|
dcb50cc0c8 | ||
|
|
f503c4a3e1 | ||
|
|
a56c925da9 | ||
|
|
833cc00014 | ||
|
|
09e8cf33d7 | ||
|
|
a03bb2fbf7 | ||
|
|
bb784ec6be | ||
|
|
996c00c81c | ||
|
|
30bdca07e9 | ||
|
|
b4b49cf3f6 | ||
|
|
189796e94f | ||
|
|
2431c7d925 | ||
|
|
fc9c61714f | ||
|
|
e096658df3 | ||
|
|
b1d58c5454 | ||
|
|
ced66eb11f | ||
|
|
1b44daddf6 | ||
|
|
a309c1b38e | ||
|
|
e56aaf5f44 | ||
|
|
632cee4426 | ||
|
|
af25fc35d1 | ||
|
|
db49b84a44 | ||
|
|
c5f4b8c1c7 | ||
|
|
6a0daddd8f | ||
|
|
af997b221d | ||
|
|
9d6855702e | ||
|
|
daf256e15f | ||
|
|
0eddcb4424 | ||
|
|
b7f6794e03 | ||
|
|
cd9fc88151 | ||
|
|
fbe0f37e1b | ||
|
|
c496194614 | ||
|
|
ca639ceb63 | ||
|
|
e85537aac4 | ||
|
|
e839c9cae6 | ||
|
|
100e94c18e | ||
|
|
e7f7b4e499 | ||
|
|
eca8b53868 | ||
|
|
b8767be373 | ||
|
|
9658eade0b | ||
|
|
689536ec92 | ||
|
|
3ff2999228 | ||
|
|
4f65104ecc | ||
|
|
242e1c342c | ||
|
|
935e3b70ae | ||
|
|
8d1bfb5a85 | ||
|
|
2ac664968d | ||
|
|
1199ad8f47 | ||
|
|
c12559f8f6 | ||
|
|
840e1abcdc | ||
|
|
e3594ba0ec | ||
|
|
0d07dc5355 | ||
|
|
4170258595 | ||
|
|
dacfc41d21 | ||
|
|
5158877b72 | ||
|
|
a785ba3c4d | ||
|
|
92dbd4eca2 | ||
|
|
a7144c5b6b |
@@ -1,4 +0,0 @@
|
||||
{
|
||||
"phabricator.uri" : "https://bugs.libssh.org/",
|
||||
"history.immutable": true
|
||||
}
|
||||
1
.clang_complete
Normal file
@@ -0,0 +1 @@
|
||||
-Iinclude -Ibuild
|
||||
@@ -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
|
||||
8
.gitignore
vendored
@@ -1,12 +1,6 @@
|
||||
*.a
|
||||
*.o
|
||||
.*
|
||||
*.swp
|
||||
*~$
|
||||
build
|
||||
cscope.*
|
||||
compile_commands.json
|
||||
/.cache
|
||||
/.clangd
|
||||
tags
|
||||
/build
|
||||
/obj*
|
||||
|
||||
528
.gitlab-ci.yml
@@ -1,528 +0,0 @@
|
||||
---
|
||||
variables:
|
||||
BUILD_IMAGES_PROJECT: libssh/build-images
|
||||
CENTOS7_BUILD: buildenv-centos7
|
||||
CENTOS9_BUILD: buildenv-c9s
|
||||
COVERITY_BUILD: buildenv-coverity
|
||||
FEDORA_BUILD: buildenv-fedora
|
||||
MINGW_BUILD: buildenv-mingw
|
||||
TUMBLEWEED_BUILD: buildenv-tumbleweed
|
||||
UBUNTU_BUILD: buildenv-ubuntu
|
||||
ALPINE_BUILD: buildenv-alpine
|
||||
|
||||
stages:
|
||||
- build
|
||||
- test
|
||||
- analysis
|
||||
|
||||
.build:
|
||||
stage: build
|
||||
variables:
|
||||
CMAKE_DEFAULT_OPTIONS: "-DCMAKE_BUILD_TYPE=RelWithDebInfo -DPICKY_DEVELOPER=ON"
|
||||
CMAKE_BUILD_OPTIONS: "-DWITH_BLOWFISH_CIPHER=ON -DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON -DWITH_DEBUG_CRYPTO=ON -DWITH_DEBUG_PACKET=ON -DWITH_DEBUG_CALLTRACE=ON -DWITH_DSA=ON"
|
||||
CMAKE_TEST_OPTIONS: "-DUNIT_TESTING=ON -DCLIENT_TESTING=ON -DSERVER_TESTING=ON -DWITH_BENCHMARKS=ON"
|
||||
CMAKE_OPTIONS: $CMAKE_DEFAULT_OPTIONS $CMAKE_BUILD_OPTIONS $CMAKE_TEST_OPTIONS
|
||||
before_script: &build
|
||||
- uname -a
|
||||
- cat /etc/os-release
|
||||
- mount
|
||||
- df -h
|
||||
- cat /proc/swaps
|
||||
- free -h
|
||||
- mkdir -p obj && cd obj
|
||||
script:
|
||||
- cmake $CMAKE_OPTIONS $CMAKE_ADDITIONAL_OPTIONS .. &&
|
||||
make -j$(nproc) &&
|
||||
make -j$(nproc) install
|
||||
# Do not use after_script as it does not make the targets fail
|
||||
tags:
|
||||
- shared
|
||||
except:
|
||||
- tags
|
||||
artifacts:
|
||||
expire_in: 1 week
|
||||
when: on_failure
|
||||
paths:
|
||||
- obj/
|
||||
|
||||
.tests:
|
||||
extends: .build
|
||||
stage: test
|
||||
# This is needed to prevent passing artifacts from previous stages
|
||||
dependencies: []
|
||||
script:
|
||||
- cmake $CMAKE_OPTIONS $CMAKE_ADDITIONAL_OPTIONS .. &&
|
||||
make -j$(nproc) &&
|
||||
ctest --output-on-failure
|
||||
# Do not use after_script as it does not make the targets fail
|
||||
|
||||
.fedora:
|
||||
extends: .tests
|
||||
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD
|
||||
variables:
|
||||
CMAKE_ADDITIONAL_OPTIONS: -DWITH_PKCS11_URI=ON
|
||||
|
||||
.tumbleweed:
|
||||
extends: .tests
|
||||
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$TUMBLEWEED_BUILD
|
||||
|
||||
|
||||
###############################################################################
|
||||
# CentOS builds #
|
||||
###############################################################################
|
||||
# pkd tests fail on CentOS7 docker images, so we don't use -DSERVER_TESTING=ON
|
||||
centos7/openssl_1.0.x/x86_64:
|
||||
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$CENTOS7_BUILD
|
||||
extends: .tests
|
||||
script:
|
||||
- cmake3 $CMAKE_OPTIONS .. &&
|
||||
make -j$(nproc) &&
|
||||
ctest --output-on-failure
|
||||
|
||||
centos9s/openssl_3.0.x/x86_64:
|
||||
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$CENTOS9_BUILD
|
||||
extends: .tests
|
||||
script:
|
||||
- export OPENSSL_ENABLE_SHA1_SIGNATURES=1
|
||||
- cmake3 $CMAKE_OPTIONS .. &&
|
||||
make -j$(nproc) &&
|
||||
ctest --output-on-failure
|
||||
|
||||
|
||||
###############################################################################
|
||||
# Fedora builds #
|
||||
###############################################################################
|
||||
fedora/build:
|
||||
extends: .build
|
||||
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD
|
||||
|
||||
fedora/docs:
|
||||
extends: .build
|
||||
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD
|
||||
script:
|
||||
- cmake .. && make docs
|
||||
|
||||
fedora/ninja:
|
||||
extends: .fedora
|
||||
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD
|
||||
script:
|
||||
- cmake -G Ninja $CMAKE_OPTIONS ../ && ninja && ninja test
|
||||
|
||||
fedora/openssl_3.0.x/x86_64:
|
||||
extends: .fedora
|
||||
|
||||
fedora/openssl_3.0.x/x86_64/fips:
|
||||
extends: .fedora
|
||||
before_script:
|
||||
- echo "# userspace fips" > /etc/system-fips
|
||||
# We do not need the kernel part, but in case we ever do:
|
||||
# mkdir -p /var/tmp/userspace-fips
|
||||
# echo 1 > /var/tmp/userspace-fips/fips_enabled
|
||||
# mount --bind /var/tmp/userspace-fips/fips_enabled \
|
||||
# /proc/sys/crypto/fips_enabled
|
||||
- update-crypto-policies --show
|
||||
- update-crypto-policies --set FIPS
|
||||
- update-crypto-policies --show
|
||||
- mkdir -p obj && cd obj && cmake
|
||||
-DCMAKE_BUILD_TYPE=RelWithDebInfo
|
||||
-DPICKY_DEVELOPER=ON
|
||||
-DWITH_BLOWFISH_CIPHER=ON
|
||||
-DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON
|
||||
-DWITH_DEBUG_CRYPTO=ON -DWITH_DEBUG_PACKET=ON -DWITH_DEBUG_CALLTRACE=ON
|
||||
-DWITH_DSA=ON
|
||||
-DUNIT_TESTING=ON -DCLIENT_TESTING=ON -DSERVER_TESTING=ON ..
|
||||
script:
|
||||
- cmake $CMAKE_OPTIONS .. &&
|
||||
make -j$(nproc) &&
|
||||
OPENSSL_FORCE_FIPS_MODE=1 ctest --output-on-failure
|
||||
|
||||
fedora/openssl_3.0.x/x86_64/minimal:
|
||||
extends: .fedora
|
||||
variables:
|
||||
script:
|
||||
- cmake $CMAKE_DEFAULT_OPTIONS
|
||||
-DWITH_SFTP=OFF
|
||||
-DWITH_SERVER=OFF
|
||||
-DWITH_ZLIB=OFF
|
||||
-DWITH_PCAP=OFF
|
||||
-DWITH_DSA=OFF
|
||||
-DUNIT_TESTING=ON
|
||||
-DCLIENT_TESTING=ON
|
||||
-DWITH_GEX=OFF .. &&
|
||||
make -j$(nproc)
|
||||
|
||||
# Address sanitizer doesn't mix well with LD_PRELOAD used in the testsuite
|
||||
# so, this is only enabled for unit tests right now.
|
||||
# TODO: add -DCLIENT_TESTING=ON -DSERVER_TESTING=ON
|
||||
fedora/address-sanitizer:
|
||||
extends: .fedora
|
||||
stage: analysis
|
||||
script:
|
||||
- cmake
|
||||
-DCMAKE_BUILD_TYPE=AddressSanitizer
|
||||
-DCMAKE_C_COMPILER=clang
|
||||
-DCMAKE_CXX_COMPILER=clang++
|
||||
-DPICKY_DEVELOPER=ON
|
||||
$CMAKE_BUILD_OPTIONS
|
||||
-DUNIT_TESTING=ON
|
||||
-DFUZZ_TESTING=ON .. &&
|
||||
make -j$(nproc) &&
|
||||
ctest --output-on-failure
|
||||
|
||||
# This is disabled as it report OpenSSL issues
|
||||
# It also has the same issues with cwrap as AddressSanitizer
|
||||
.fedora/memory-sanitizer:
|
||||
extends: .fedora
|
||||
stage: analysis
|
||||
script:
|
||||
- cmake
|
||||
-DCMAKE_BUILD_TYPE=MemorySanitizer
|
||||
-DCMAKE_C_COMPILER=clang
|
||||
-DCMAKE_CXX_COMPILER=clang++
|
||||
-DPICKY_DEVELOPER=ON
|
||||
$CMAKE_BUILD_OPTIONS
|
||||
-DUNIT_TESTING=ON
|
||||
-DFUZZ_TESTING=ON .. &&
|
||||
make -j$(nproc) &&
|
||||
ctest --output-on-failure
|
||||
|
||||
fedora/undefined-sanitizer:
|
||||
extends: .fedora
|
||||
stage: analysis
|
||||
script:
|
||||
- cmake
|
||||
-DCMAKE_BUILD_TYPE=UndefinedSanitizer
|
||||
-DCMAKE_C_COMPILER=clang
|
||||
-DCMAKE_CXX_COMPILER=clang++
|
||||
-DPICKY_DEVELOPER=ON
|
||||
$CMAKE_BUILD_OPTIONS
|
||||
-DUNIT_TESTING=ON
|
||||
-DFUZZ_TESTING=ON .. &&
|
||||
make -j$(nproc) &&
|
||||
ctest --output-on-failure
|
||||
|
||||
fedora/libgcrypt/x86_64:
|
||||
extends: .fedora
|
||||
variables:
|
||||
CMAKE_ADDITIONAL_OPTIONS: "-DWITH_GCRYPT=ON -DWITH_DEBUG_CRYPTO=ON"
|
||||
|
||||
fedora/mbedtls/x86_64:
|
||||
extends: .fedora
|
||||
variables:
|
||||
CMAKE_ADDITIONAL_OPTIONS: "-DWITH_MBEDTLS=ON -DWITH_DEBUG_CRYPTO=ON -DWITH_DSA=OFF"
|
||||
|
||||
# Unit testing only, no client and pkd testing, because cwrap is not available
|
||||
# for MinGW
|
||||
fedora/mingw64:
|
||||
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$MINGW_BUILD
|
||||
extends: .tests
|
||||
script:
|
||||
- export WINEPATH=/usr/x86_64-w64-mingw32/sys-root/mingw/bin
|
||||
- export WINEDEBUG=-all
|
||||
- mingw64-cmake $CMAKE_DEFAULT_OPTIONS
|
||||
-DWITH_SFTP=ON
|
||||
-DWITH_SERVER=ON
|
||||
-DWITH_ZLIB=ON
|
||||
-DWITH_PCAP=ON
|
||||
-DUNIT_TESTING=ON .. &&
|
||||
make -j$(nproc) &&
|
||||
ctest --output-on-failure
|
||||
|
||||
# Unit testing only, no client and pkd testing, because cwrap is not available
|
||||
# for MinGW
|
||||
fedora/mingw32:
|
||||
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$MINGW_BUILD
|
||||
extends: .tests
|
||||
script:
|
||||
- export WINEPATH=/usr/i686-w64-mingw32/sys-root/mingw/bin
|
||||
- export WINEDEBUG=-all
|
||||
- mingw32-cmake $CMAKE_DEFAULT_OPTIONS
|
||||
-DWITH_SFTP=ON
|
||||
-DWITH_SERVER=ON
|
||||
-DWITH_ZLIB=ON
|
||||
-DWITH_PCAP=ON
|
||||
-DUNIT_TESTING=ON .. &&
|
||||
make -j$(nproc) &&
|
||||
ctest --output-on-failure
|
||||
|
||||
|
||||
###############################################################################
|
||||
# Fedora csbuild #
|
||||
###############################################################################
|
||||
.csbuild:
|
||||
stage: analysis
|
||||
variables:
|
||||
GIT_DEPTH: "100"
|
||||
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD
|
||||
before_script:
|
||||
- |
|
||||
if [[ -z "$CI_COMMIT_BEFORE_SHA" ]]; then
|
||||
export CI_COMMIT_BEFORE_SHA=$(git rev-parse "${CI_COMMIT_SHA}~20")
|
||||
fi
|
||||
|
||||
# Check if the commit exists in this branch
|
||||
# This is not the case for a force push
|
||||
git branch --contains $CI_COMMIT_BEFORE_SHA 2>/dev/null || export CI_COMMIT_BEFORE_SHA=$(git rev-parse "${CI_COMMIT_SHA}~20")
|
||||
|
||||
export CI_COMMIT_RANGE="$CI_COMMIT_BEFORE_SHA..$CI_COMMIT_SHA"
|
||||
tags:
|
||||
- shared
|
||||
except:
|
||||
- tags
|
||||
artifacts:
|
||||
expire_in: 1 week
|
||||
when: on_failure
|
||||
paths:
|
||||
- obj-csbuild/
|
||||
|
||||
fedora/csbuild/openssl_3.0.x:
|
||||
extends: .csbuild
|
||||
script:
|
||||
- csbuild
|
||||
--build-dir=obj-csbuild
|
||||
--build-cmd "rm -rf CMakeFiles CMakeCache.txt && cmake -DCMAKE_BUILD_TYPE=Debug -DPICKY_DEVELOPER=ON -DUNIT_TESTING=ON -DCLIENT_TESTING=ON -DSERVER_TESTING=ON -DFUZZ_TESTING=ON -DWITH_DSA=ON @SRCDIR@ && make clean && make -j$(nproc)"
|
||||
--git-commit-range $CI_COMMIT_RANGE
|
||||
--color
|
||||
--print-current --print-fixed
|
||||
|
||||
fedora/csbuild/libgcrypt:
|
||||
extends: .csbuild
|
||||
script:
|
||||
- csbuild
|
||||
--build-dir=obj-csbuild
|
||||
--build-cmd "rm -rf CMakeFiles CMakeCache.txt && cmake -DCMAKE_BUILD_TYPE=Debug -DPICKY_DEVELOPER=ON -DUNIT_TESTING=ON -DCLIENT_TESTING=ON -DSERVER_TESTING=ON -DFUZZ_TESTING=ON -DWITH_GCRYPT=ON -DWITH_DSA=ON @SRCDIR@ && make clean && make -j$(nproc)"
|
||||
--git-commit-range $CI_COMMIT_RANGE
|
||||
--color
|
||||
--print-current --print-fixed
|
||||
|
||||
fedora/csbuild/mbedtls:
|
||||
extends: .csbuild
|
||||
script:
|
||||
- csbuild
|
||||
--build-dir=obj-csbuild
|
||||
--build-cmd "rm -rf CMakeFiles CMakeCache.txt && cmake -DCMAKE_BUILD_TYPE=Debug -DPICKY_DEVELOPER=ON -DUNIT_TESTING=ON -DCLIENT_TESTING=ON -DSERVER_TESTING=ON -DFUZZ_TESTING=ON -DWITH_MBEDTLS=ON @SRCDIR@ && make clean && make -j$(nproc)"
|
||||
--git-commit-range $CI_COMMIT_RANGE
|
||||
--color
|
||||
--print-current --print-fixed
|
||||
|
||||
|
||||
###############################################################################
|
||||
# Ubuntu builds #
|
||||
###############################################################################
|
||||
ubuntu/openssl_1.1.x/x86_64:
|
||||
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$UBUNTU_BUILD
|
||||
extends: .tests
|
||||
|
||||
|
||||
###############################################################################
|
||||
# Alpine builds #
|
||||
###############################################################################
|
||||
alpine/musl:
|
||||
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$ALPINE_BUILD
|
||||
extends: .tests
|
||||
script:
|
||||
- cmake $CMAKE_DEFAULT_OPTIONS
|
||||
-DWITH_SFTP=ON
|
||||
-DWITH_SERVER=ON
|
||||
-DWITH_ZLIB=ON
|
||||
-DWITH_PCAP=ON
|
||||
-DUNIT_TESTING=ON .. &&
|
||||
make -j$(nproc) &&
|
||||
ctest --output-on-failure
|
||||
|
||||
|
||||
###############################################################################
|
||||
# Tumbleweed builds #
|
||||
###############################################################################
|
||||
tumbleweed/openssl_1.1.x/x86_64/gcc:
|
||||
extends: .tumbleweed
|
||||
variables:
|
||||
CMAKE_ADDITIONAL_OPTIONS: "-DKRB5_CONFIG=/usr/lib/mit/bin/krb5-config"
|
||||
|
||||
tumbleweed/openssl_1.1.x/x86/gcc:
|
||||
extends: .tumbleweed
|
||||
script:
|
||||
- cmake
|
||||
-DCMAKE_TOOLCHAIN_FILE=../cmake/Toolchain-cross-m32.cmake
|
||||
$CMAKE_DEFAULT_OPTIONS
|
||||
-DWITH_SFTP=ON
|
||||
-DWITH_SERVER=ON
|
||||
-DWITH_ZLIB=ON
|
||||
-DWITH_PCAP=ON
|
||||
-DWITH_DSA=ON
|
||||
-DUNIT_TESTING=ON ..
|
||||
|
||||
tumbleweed/openssl_1.1.x/x86_64/gcc7:
|
||||
extends: .tumbleweed
|
||||
variables:
|
||||
CMAKE_ADDITIONAL_OPTIONS: "-DCMAKE_C_COMPILER=gcc-7 -DCMAKE_CXX_COMPILER=g++-7 -DKRB5_CONFIG=/usr/lib/mit/bin/krb5-config"
|
||||
|
||||
tumbleweed/openssl_1.1.x/x86/gcc7:
|
||||
extends: .tumbleweed
|
||||
script:
|
||||
- cmake
|
||||
-DCMAKE_TOOLCHAIN_FILE=../cmake/Toolchain-cross-m32.cmake
|
||||
-DCMAKE_C_COMPILER=gcc-7 -DCMAKE_CXX_COMPILER=g++-7
|
||||
$CMAKE_DEFAULT_OPTIONS
|
||||
-DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON
|
||||
-DWITH_DSA=ON
|
||||
-DUNIT_TESTING=ON .. &&
|
||||
make -j$(nproc) &&
|
||||
ctest --output-on-failure
|
||||
|
||||
tumbleweed/openssl_1.1.x/x86_64/clang:
|
||||
extends: .tumbleweed
|
||||
variables:
|
||||
CMAKE_ADDITIONAL_OPTIONS: "-DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DKRB5_CONFIG=/usr/lib/mit/bin/krb5-config"
|
||||
|
||||
tumbleweed/static-analysis:
|
||||
extends: .tests
|
||||
stage: analysis
|
||||
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$TUMBLEWEED_BUILD
|
||||
script:
|
||||
- export CCC_CC=clang
|
||||
- export CCC_CXX=clang++
|
||||
- scan-build cmake
|
||||
-DCMAKE_BUILD_TYPE=Debug
|
||||
-DCMAKE_C_COMPILER=clang
|
||||
-DCMAKE_CXX_COMPILER=clang++
|
||||
-DPICKY_DEVELOPER=ON
|
||||
$CMAKE_BUILD_OPTIONS
|
||||
$CMAKE_TEST_OPTIONS .. &&
|
||||
scan-build --status-bugs -o scan make -j$(nproc)
|
||||
artifacts:
|
||||
expire_in: 1 week
|
||||
when: on_failure
|
||||
paths:
|
||||
- obj/scan
|
||||
|
||||
|
||||
###############################################################################
|
||||
# FreeBSD builds #
|
||||
###############################################################################
|
||||
# That is a specific runner that we cannot enable universally.
|
||||
# We restrict it to builds under the $BUILD_IMAGES_PROJECT project.
|
||||
freebsd/x86_64:
|
||||
image:
|
||||
extends: .tests
|
||||
before_script:
|
||||
- mkdir -p obj && cd obj && cmake
|
||||
-DCMAKE_BUILD_TYPE=RelWithDebInfo
|
||||
-DPICKY_DEVELOPER=ON
|
||||
-DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON
|
||||
-DUNIT_TESTING=ON ..
|
||||
script:
|
||||
- cmake $CMAKE_DEFAULT_OPTIONS
|
||||
-DWITH_SFTP=ON
|
||||
-DWITH_SERVER=ON
|
||||
-DWITH_ZLIB=ON
|
||||
-DWITH_PCAP=ON
|
||||
-DUNIT_TESTING=ON .. &&
|
||||
make &&
|
||||
ctest --output-on-failure
|
||||
tags:
|
||||
- private
|
||||
- freebsd
|
||||
only:
|
||||
- branches@libssh/libssh-mirror
|
||||
- branches@cryptomilk/libssh-mirror
|
||||
- branches@jjelen/libssh-mirror
|
||||
- branches@marco.fortina/libssh-mirror
|
||||
|
||||
|
||||
###############################################################################
|
||||
# Visual Studio builds #
|
||||
###############################################################################
|
||||
.vs:
|
||||
stage: test
|
||||
cache:
|
||||
key: vcpkg.${CI_JOB_NAME}
|
||||
paths:
|
||||
- .vcpkg
|
||||
variables:
|
||||
ErrorActionPreference: STOP
|
||||
script:
|
||||
- cmake --build .
|
||||
- ctest --output-on-failure
|
||||
tags:
|
||||
- windows
|
||||
- shared-windows
|
||||
except:
|
||||
- tags
|
||||
artifacts:
|
||||
expire_in: 1 week
|
||||
when: on_failure
|
||||
paths:
|
||||
- obj/
|
||||
before_script:
|
||||
- choco install --no-progress -y cmake
|
||||
- $env:Path += ';C:\Program Files\CMake\bin'
|
||||
- If (!(test-path .vcpkg\archives)) { mkdir -p .vcpkg\archives }
|
||||
- $env:VCPKG_DEFAULT_BINARY_CACHE="$PWD\.vcpkg\archives"
|
||||
- echo $env:VCPKG_DEFAULT_BINARY_CACHE
|
||||
- $env:VCPKG_DEFAULT_TRIPLET="$TRIPLET-windows"
|
||||
- vcpkg install cmocka
|
||||
- vcpkg install openssl
|
||||
- vcpkg install zlib
|
||||
- vcpkg integrate install
|
||||
- mkdir -p obj; if ($?) {cd obj}; if (! $?) {exit 1}
|
||||
- cmake
|
||||
-A $PLATFORM
|
||||
-DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake
|
||||
-DPICKY_DEVELOPER=ON
|
||||
-DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON
|
||||
-DUNIT_TESTING=ON ..
|
||||
|
||||
visualstudio/x86_64:
|
||||
extends: .vs
|
||||
variables:
|
||||
PLATFORM: "x64"
|
||||
TRIPLET: "x64"
|
||||
|
||||
visualstudio/x86:
|
||||
extends: .vs
|
||||
variables:
|
||||
PLATFORM: "win32"
|
||||
TRIPLET: "x86"
|
||||
|
||||
###############################################################################
|
||||
# Coverity #
|
||||
###############################################################################
|
||||
#
|
||||
# git push -o ci.variable="COVERITY_SCAN_TOKEN=XXXXXX" \
|
||||
# -o ci.variable="COVERITY_SCAN_PROJECT_NAME=XXXXXX" \
|
||||
# -o ci.variable="COVERITY_SCAN_EMAIL=XXXXXX" \
|
||||
# -f gitlab
|
||||
|
||||
coverity:
|
||||
stage: analysis
|
||||
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$COVERITY_BUILD
|
||||
script:
|
||||
- mkdir obj && cd obj
|
||||
- wget https://scan.coverity.com/download/linux64 --post-data "token=$COVERITY_SCAN_TOKEN&project=$COVERITY_SCAN_PROJECT_NAME" -O /tmp/coverity_tool.tgz
|
||||
- tar xf /tmp/coverity_tool.tgz
|
||||
- cmake -DCMAKE_BUILD_TYPE=Debug $CMAKE_BUILD_OPTIONS $CMAKE_TEST_OPTIONS ..
|
||||
- cov-analysis-linux64-*/bin/cov-build --dir cov-int make -j$(nproc)
|
||||
- tar czf cov-int.tar.gz cov-int
|
||||
- curl
|
||||
--form token=$COVERITY_SCAN_TOKEN
|
||||
--form email=$COVERITY_SCAN_EMAIL
|
||||
--form file=@cov-int.tar.gz
|
||||
--form version="`git describe --tags`"
|
||||
--form description="CI build"
|
||||
https://scan.coverity.com/builds?project=$COVERITY_SCAN_PROJECT_NAME
|
||||
tags:
|
||||
- shared
|
||||
only:
|
||||
refs:
|
||||
- master
|
||||
- schedules
|
||||
variables:
|
||||
- $COVERITY_SCAN_TOKEN != null
|
||||
- $COVERITY_SCAN_PROJECT_NAME != null
|
||||
- $COVERITY_SCAN_EMAIL != null
|
||||
artifacts:
|
||||
expire_in: 1 week
|
||||
when: on_failure
|
||||
paths:
|
||||
- obj/cov-int/*.txt
|
||||
2
AUTHORS
@@ -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)
|
||||
|
||||
|
||||
225
CMakeLists.txt
@@ -1,20 +1,17 @@
|
||||
cmake_minimum_required(VERSION 3.3.0)
|
||||
cmake_policy(SET CMP0048 NEW)
|
||||
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.10.4 LANGUAGES C)
|
||||
|
||||
# global needed variable
|
||||
# global needed variables
|
||||
set(APPLICATION_NAME ${PROJECT_NAME})
|
||||
|
||||
set(APPLICATION_VERSION_MAJOR "0")
|
||||
set(APPLICATION_VERSION_MINOR "5")
|
||||
set(APPLICATION_VERSION_PATCH "3")
|
||||
|
||||
set(APPLICATION_VERSION "${APPLICATION_VERSION_MAJOR}.${APPLICATION_VERSION_MINOR}.${APPLICATION_VERSION_PATCH}")
|
||||
|
||||
# SOVERSION scheme: CURRENT.AGE.REVISION
|
||||
# If there was an incompatible interface change:
|
||||
# Increment CURRENT. Set AGE and REVISION to 0
|
||||
@@ -22,98 +19,54 @@ set(APPLICATION_NAME ${PROJECT_NAME})
|
||||
# Increment AGE. Set REVISION to 0
|
||||
# If the source code was changed, but there were no interface changes:
|
||||
# Increment REVISION.
|
||||
set(LIBRARY_VERSION "4.9.4")
|
||||
set(LIBRARY_VERSION "4.2.3")
|
||||
set(LIBRARY_SOVERSION "4")
|
||||
|
||||
# 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(DefineCMakeDefaults)
|
||||
include(DefinePlatformDefaults)
|
||||
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")
|
||||
# add macros
|
||||
include(MacroAddPlugin)
|
||||
include(MacroCopyFile)
|
||||
|
||||
# search for libraries
|
||||
if (WITH_ZLIB)
|
||||
if (WITH_LIBZ)
|
||||
find_package(ZLIB REQUIRED)
|
||||
endif (WITH_ZLIB)
|
||||
endif (WITH_LIBZ)
|
||||
|
||||
if (WITH_GCRYPT)
|
||||
find_package(GCrypt 1.5.0 REQUIRED)
|
||||
find_package(GCrypt REQUIRED)
|
||||
if (NOT GCRYPT_FOUND)
|
||||
message(FATAL_ERROR "Could not find GCrypt")
|
||||
endif (NOT GCRYPT_FOUND)
|
||||
elseif(WITH_MBEDTLS)
|
||||
find_package(MbedTLS REQUIRED)
|
||||
if (NOT MBEDTLS_FOUND)
|
||||
message(FATAL_ERROR "Could not find mbedTLS")
|
||||
endif (NOT MBEDTLS_FOUND)
|
||||
else (WITH_GCRYPT)
|
||||
find_package(OpenSSL 1.0.1)
|
||||
if (OPENSSL_FOUND)
|
||||
# On CMake < 3.16, OPENSSL_CRYPTO_LIBRARIES is usually a synonym for OPENSSL_CRYPTO_LIBRARY, but is not defined
|
||||
# when building on Windows outside of Cygwin. We provide the synonym here, if FindOpenSSL didn't define it already.
|
||||
if (NOT DEFINED OPENSSL_CRYPTO_LIBRARIES)
|
||||
set(OPENSSL_CRYPTO_LIBRARIES ${OPENSSL_CRYPTO_LIBRARY})
|
||||
endif (NOT DEFINED OPENSSL_CRYPTO_LIBRARIES)
|
||||
else (OPENSSL_FOUND)
|
||||
find_package(OpenSSL)
|
||||
if (NOT OPENSSL_FOUND)
|
||||
find_package(GCrypt)
|
||||
if (NOT GCRYPT_FOUND)
|
||||
find_package(MbedTLS)
|
||||
if (NOT MBEDTLS_FOUND)
|
||||
message(FATAL_ERROR "Could not find OpenSSL, GCrypt or mbedTLS")
|
||||
endif (NOT MBEDTLS_FOUND)
|
||||
message(FATAL_ERROR "Could not find OpenSSL or GCrypt")
|
||||
endif (NOT GCRYPT_FOUND)
|
||||
endif (OPENSSL_FOUND)
|
||||
endif (NOT OPENSSL_FOUND)
|
||||
endif(WITH_GCRYPT)
|
||||
|
||||
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)
|
||||
endif (WITH_GSSAPI)
|
||||
|
||||
if (WITH_PKCS11_URI)
|
||||
find_package(softhsm)
|
||||
if (NOT SOFTHSM_FOUND)
|
||||
message(SEND_ERROR "Could not find softhsm module!")
|
||||
endif (NOT SOFTHSM_FOUND)
|
||||
endif (WITH_PKCS11_URI)
|
||||
|
||||
if (WITH_NACL)
|
||||
find_package(NaCl)
|
||||
if (NOT NACL_FOUND)
|
||||
set(WITH_NACL OFF)
|
||||
endif (NOT NACL_FOUND)
|
||||
endif (WITH_NACL)
|
||||
|
||||
if (BSD OR SOLARIS OR OSX OR CYGWIN)
|
||||
find_package(Argp)
|
||||
endif (BSD OR SOLARIS OR OSX OR CYGWIN)
|
||||
|
||||
# Disable symbol versioning in non UNIX platforms
|
||||
if (UNIX)
|
||||
find_package(ABIMap 0.3.1)
|
||||
else (UNIX)
|
||||
set(WITH_SYMBOL_VERSIONING OFF)
|
||||
endif (UNIX)
|
||||
|
||||
# config.h checks
|
||||
include(ConfigureChecks.cmake)
|
||||
configure_file(config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config.h)
|
||||
@@ -124,141 +77,43 @@ add_subdirectory(include)
|
||||
add_subdirectory(src)
|
||||
|
||||
# pkg-config file
|
||||
if (UNIX OR MINGW)
|
||||
configure_file(libssh.pc.cmake ${CMAKE_CURRENT_BINARY_DIR}/libssh.pc)
|
||||
configure_file(libssh_threads.pc.cmake ${CMAKE_CURRENT_BINARY_DIR}/libssh_threads.pc)
|
||||
install(
|
||||
FILES
|
||||
${CMAKE_CURRENT_BINARY_DIR}/libssh.pc
|
||||
${CMAKE_CURRENT_BINARY_DIR}/libssh_threads.pc
|
||||
DESTINATION
|
||||
${CMAKE_INSTALL_LIBDIR}/pkgconfig
|
||||
${LIB_INSTALL_DIR}/pkgconfig
|
||||
COMPONENT
|
||||
pkgconfig
|
||||
)
|
||||
endif (UNIX OR MINGW)
|
||||
|
||||
# CMake config files
|
||||
include(CMakePackageConfigHelpers)
|
||||
add_subdirectory(examples)
|
||||
|
||||
set(LIBSSH_LIBRARY_NAME ${CMAKE_SHARED_LIBRARY_PREFIX}ssh${CMAKE_SHARED_LIBRARY_SUFFIX})
|
||||
if (WITH_TESTING)
|
||||
find_package(CMockery REQUIRED)
|
||||
include(AddCMockeryTest)
|
||||
add_subdirectory(tests)
|
||||
endif (WITH_TESTING)
|
||||
|
||||
# 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)
|
||||
|
||||
add_custom_target(dist COMMAND ${CMAKE_MAKE_PROGRAM} package_source DEPENDS ${_SYMBOL_TARGET} VERBATIM)
|
||||
|
||||
# Link compile database for clangd
|
||||
execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink
|
||||
"${CMAKE_BINARY_DIR}/compile_commands.json"
|
||||
"${CMAKE_SOURCE_DIR}/compile_commands.json")
|
||||
|
||||
message(STATUS "********************************************")
|
||||
message(STATUS "********** ${PROJECT_NAME} build options : **********")
|
||||
|
||||
message(STATUS "zlib support: ${WITH_ZLIB}")
|
||||
message(STATUS "zlib support: ${WITH_LIBZ}")
|
||||
message(STATUS "libgcrypt support: ${WITH_GCRYPT}")
|
||||
message(STATUS "libmbedTLS support: ${WITH_MBEDTLS}")
|
||||
message(STATUS "libnacl support: ${WITH_NACL}")
|
||||
message(STATUS "SSH-1 support: ${WITH_SSH1}")
|
||||
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 "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: ${WITH_BLOWFISH_CIPHER}")
|
||||
message(STATUS "PKCS #11 URI support: ${WITH_PKCS11_URI}")
|
||||
message(STATUS "DSA support: ${WITH_DSA}")
|
||||
set(_SERVER_TESTING OFF)
|
||||
if (WITH_SERVER)
|
||||
set(_SERVER_TESTING ${SERVER_TESTING})
|
||||
endif()
|
||||
message(STATUS "Server code testing: ${_SERVER_TESTING}")
|
||||
message(STATUS "Unit testing: ${WITH_TESTING}")
|
||||
message(STATUS "Client code Unit testing: ${WITH_CLIENT_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}")
|
||||
message(STATUS "Global client config: ${GLOBAL_CLIENT_CONFIG}")
|
||||
if (WITH_SERVER)
|
||||
message(STATUS "Global bind config: ${GLOBAL_BIND_CONFIG}")
|
||||
endif()
|
||||
message(STATUS "********************************************")
|
||||
|
||||
|
||||
484
CONTRIBUTING.md
@@ -1,484 +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.
|
||||
|
||||
|
||||
# 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...*/
|
||||
|
||||
### Indention & 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.
|
||||
|
||||
|
||||
Have fun and happy libssh hacking!
|
||||
|
||||
The libssh Team
|
||||
13
COPYING
@@ -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
|
||||
|
||||
@@ -1,19 +1,27 @@
|
||||
### 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")
|
||||
# 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$;/[.]git/;/[.]clangd/;/[.]cache/;.gitignore;/build*;/obj*;tags;cscope.*;compile_commands.json;.*\.patch")
|
||||
### versions
|
||||
set(CPACK_PACKAGE_VERSION_MAJOR "0")
|
||||
set(CPACK_PACKAGE_VERSION_MINOR "5")
|
||||
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")
|
||||
|
||||
@@ -23,7 +31,7 @@ if (WIN32)
|
||||
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")
|
||||
set(CPACK_NSIS_MENU_LINKS "http://www.libssh.org/" "libssh homepage")
|
||||
endif (NSIS_MAKE)
|
||||
endif (WIN32)
|
||||
|
||||
@@ -38,6 +46,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")
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
set(UPDATE_TYPE "true")
|
||||
|
||||
set(CTEST_PROJECT_NAME "libssh")
|
||||
set(CTEST_NIGHTLY_START_TIME "01:00:00 UTC")
|
||||
set(CTEST_NIGHTLY_START_TIME "01:00:00 CET")
|
||||
|
||||
set(CTEST_DROP_METHOD "https")
|
||||
set(CTEST_DROP_METHOD "http")
|
||||
set(CTEST_DROP_SITE "test.libssh.org")
|
||||
set(CTEST_DROP_LOCATION "/submit.php?project=libssh")
|
||||
set(CTEST_DROP_SITE_CDASH TRUE)
|
||||
|
||||
@@ -1,264 +1,5 @@
|
||||
CHANGELOG
|
||||
=========
|
||||
|
||||
version 0.10.4 (released 2022-09-07)
|
||||
* Fixed issues with KDF on big endian
|
||||
|
||||
version 0.10.3 (released 2022-09-05)
|
||||
* Fixed possible infinite loop in known hosts checking
|
||||
|
||||
version 0.10.2 (released 2022-09-02)
|
||||
* Fixed tilde expansion when handling include directives
|
||||
* Fixed building the shared torture library
|
||||
* Made rekey test more robust (fixes running on i586 build systems e.g koji)
|
||||
|
||||
version 0.10.1 (released 2022-08-30)
|
||||
* Fixed proxycommand support
|
||||
* Fixed musl libc support
|
||||
|
||||
version 0.10.0 (released 2022-08-26)
|
||||
* Added support for OpenSSL 3.0
|
||||
* Added support for mbedTLS 3
|
||||
* Added support for Smart Cards (through openssl pkcs11 engine)
|
||||
* Added support for chacha20-poly1305@openssh.com with libgcrypt
|
||||
* Added support ed25519 keys in PEM files
|
||||
* Added support for sk-ecdsa and sk-ed25519 (server side)
|
||||
* Added support for limiting RSA key sizes and not accepting small one by
|
||||
default
|
||||
* Added support for ssh-agent on Windows
|
||||
* Added ssh_userauth_publickey_auto_get_current_identity() API
|
||||
* Added ssh_vlog() API
|
||||
* Added ssh_send_issue_banner() API
|
||||
* Added ssh_session_set_disconnect_message() API
|
||||
* Added new configuration options:
|
||||
+ IdentityAgent
|
||||
+ ModuliFile
|
||||
* Provided X11 client example
|
||||
* Disabled DSA support at build time by default (will be removed in the next
|
||||
release)
|
||||
* Deprecated the SCP API!
|
||||
* Deprecated old pubkey, privatekey API
|
||||
* Avoided some needless large stack buffers to minimize memory footprint
|
||||
* Removed support for OpenSSL < 1.0.1
|
||||
* Fixed parsing username@host in login name
|
||||
* Free global init mutex in the destructor on Windows
|
||||
* Fixed PEM parsing in mbedtls to support both legacy and new PKCS8 formats
|
||||
|
||||
version 0.9.6 (released 2021-08-26)
|
||||
* CVE-2021-3634: Fix possible heap-buffer overflow when rekeying with
|
||||
different key exchange mechanism
|
||||
* Fix several memory leaks on error paths
|
||||
* Reset pending_call_state on disconnect
|
||||
* Fix handshake bug with AEAD ciphers and no HMAC overlap
|
||||
* Use OPENSSL_CRYPTO_LIBRARIES in CMake
|
||||
* Ignore request success and failure message if they are not expected
|
||||
* Support more identity files in configuration
|
||||
* Avoid setting compiler flags directly in CMake
|
||||
* Support build directories with special characters
|
||||
* Include stdlib.h to avoid crash in Windows
|
||||
* Fix sftp_new_channel constructs an invalid object
|
||||
* Fix Ninja multiple rules error
|
||||
* Several tests fixes
|
||||
|
||||
version 0.9.5 (released 2020-09-10)
|
||||
* CVE-2020-16135: Avoid null pointer dereference in sftpserver (T232)
|
||||
* Improve handling of library initialization (T222)
|
||||
* Fix parsing of subsecond times in SFTP (T219)
|
||||
* Make the documentation reproducible
|
||||
* Remove deprecated API usage in OpenSSL
|
||||
* Fix regression of ssh_channel_poll_timeout() returning SSH_AGAIN
|
||||
* Define version in one place (T226)
|
||||
* Prevent invalid free when using different C runtimes than OpenSSL (T229)
|
||||
* Compatibility improvements to testsuite
|
||||
|
||||
version 0.9.4 (released 2020-04-09)
|
||||
* Fixed CVE-2020-1730 - Possible DoS in client and server when handling
|
||||
AES-CTR keys with OpenSSL
|
||||
* Added diffie-hellman-group14-sha256
|
||||
* Fixed serveral possible memory leaks
|
||||
|
||||
version 0.9.3 (released 2019-12-10)
|
||||
* Fixed CVE-2019-14889 - SCP: Unsanitized location leads to command execution
|
||||
* SSH-01-003 Client: Missing NULL check leads to crash in erroneous state
|
||||
* SSH-01-006 General: Various unchecked Null-derefs cause DOS
|
||||
* SSH-01-007 PKI Gcrypt: Potential UAF/double free with RSA pubkeys
|
||||
* SSH-01-010 SSH: Deprecated hash function in fingerprinting
|
||||
* SSH-01-013 Conf-Parsing: Recursive wildcards in hostnames lead to DOS
|
||||
* SSH-01-014 Conf-Parsing: Integer underflow leads to OOB array access
|
||||
* SSH-01-001 State Machine: Initial machine states should be set explicitly
|
||||
* SSH-01-002 Kex: Differently bound macros used to iterate same array
|
||||
* SSH-01-005 Code-Quality: Integer sign confusion during assignments
|
||||
* SSH-01-008 SCP: Protocol Injection via unescaped File Names
|
||||
* SSH-01-009 SSH: Update documentation which RFCs are implemented
|
||||
* SSH-01-012 PKI: Information leak via uninitialized stack buffer
|
||||
|
||||
version 0.9.2 (released 2019-11-07)
|
||||
* Fixed libssh-config.cmake
|
||||
* Fixed issues with rsa algorithm negotiation (T191)
|
||||
* Fixed detection of OpenSSL ed25519 support (T197)
|
||||
|
||||
version 0.9.1 (released 2019-10-25)
|
||||
* Added support for Ed25519 via OpenSSL
|
||||
* Added support for X25519 via OpenSSL
|
||||
* Added support for localuser in Match keyword
|
||||
* Fixed Match keyword to be case sensitive
|
||||
* Fixed compilation with LibreSSL
|
||||
* Fixed error report of channel open (T75)
|
||||
* Fixed sftp documentation (T137)
|
||||
* Fixed known_hosts parsing (T156)
|
||||
* Fixed build issue with MinGW (T157)
|
||||
* Fixed build with gcc 9 (T164)
|
||||
* Fixed deprecation issues (T165)
|
||||
* Fixed known_hosts directory creation (T166)
|
||||
|
||||
version 0.9.0 (released 2019-02-xx)
|
||||
* Added support for AES-GCM
|
||||
* Added improved rekeying support
|
||||
* Added performance improvements
|
||||
* Disabled blowfish support by default
|
||||
* Fixed several ssh config parsing issues
|
||||
* Added support for DH Group Exchange KEX
|
||||
* Added support for Encrypt-then-MAC mode
|
||||
* Added support for parsing server side configuration file
|
||||
* Added support for ECDSA/Ed25519 certificates
|
||||
* Added FIPS 140-2 compatibility
|
||||
* Improved known_hosts parsing
|
||||
* Improved documentation
|
||||
* Improved OpenSSL API usage for KEX, DH, and signatures
|
||||
|
||||
version 0.8.0 (released 2018-08-10)
|
||||
* Removed support for deprecated SSHv1 protocol
|
||||
* Added new connector API for clients
|
||||
* Added new known_hosts parsing API
|
||||
* Added support for OpenSSL 1.1
|
||||
* Added support for chacha20-poly1305 cipher
|
||||
* Added crypto backend for mbedtls crypto library
|
||||
* Added ECDSA support with gcrypt backend
|
||||
* Added advanced client and server testing using cwrap.org
|
||||
* Added support for curve25519-sha256 alias
|
||||
* Added support for global known_hosts file
|
||||
* Added support for symbol versioning
|
||||
* Improved ssh_config parsing
|
||||
* Improved threading support
|
||||
|
||||
version 0.7.5 (released 2017-04-13)
|
||||
* Fixed a memory allocation issue with buffers
|
||||
* Fixed PKI on Windows
|
||||
* Fixed some SSHv1 functions
|
||||
* Fixed config hostname expansion
|
||||
|
||||
version 0.7.4 (released 2017-02-03)
|
||||
* Added id_ed25519 to the default identity list
|
||||
* Fixed sftp EOF packet handling
|
||||
* Fixed ssh_send_banner() to confirm with RFC 4253
|
||||
* Fixed some memory leaks
|
||||
|
||||
version 0.7.3 (released 2016-01-23)
|
||||
* Fixed CVE-2016-0739
|
||||
* Fixed ssh-agent on big endian
|
||||
* Fixed some documentation issues
|
||||
|
||||
version 0.7.2 (released 2015-09-15)
|
||||
* Fixed OpenSSL detection on Windows
|
||||
* Fixed return status for ssh_userauth_agent()
|
||||
* Fixed KEX to prefer hmac-sha2-256
|
||||
* Fixed sftp packet handling
|
||||
* Fixed return values of ssh_key_is_(public|private)
|
||||
* Fixed bug in global success reply
|
||||
|
||||
version 0.7.1 (released 2015-06-30)
|
||||
* Fixed SSH_AUTH_PARTIAL auth with auto public key
|
||||
* Fixed memory leak in session options
|
||||
* Fixed allocation of ed25519 public keys
|
||||
* Fixed channel exit-status and exit-signal
|
||||
* Reintroduce ssh_forward_listen()
|
||||
|
||||
version 0.7.0 (released 2015-05-11)
|
||||
* 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 dectection.
|
||||
|
||||
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 emtpy.
|
||||
* 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.
|
||||
ChangeLog
|
||||
==========
|
||||
|
||||
version 0.5.3 (released 2012-11-20)
|
||||
* CVE-2012-4559 Fixed multiple double free() flaws.
|
||||
@@ -460,6 +201,14 @@ version 0.3.2 (released 2009-08-05)
|
||||
* 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.1 (released 2009-07-14)
|
||||
* Added return code SSH_SERVER_FILE_NOT_FOUND.
|
||||
* Fixed compilation of SSHv1.
|
||||
@@ -509,7 +258,7 @@ version 0.2 (released 2007-11-29)
|
||||
version 0.11-dev
|
||||
* Server implementation development.
|
||||
* Small bug corrected when connecting to sun ssh servers.
|
||||
* Channel weirdness corrected (writing huge data packets)
|
||||
* Channel wierdness corrected (writing huge data packets)
|
||||
* Channel_read_nonblocking added
|
||||
* Channel bug where stderr wasn't correctly read fixed.
|
||||
* Added sftp_file_set_nonblocking(), which is nonblocking SFTP IO
|
||||
@@ -1,124 +0,0 @@
|
||||
include(AddCCompilerFlag)
|
||||
include(CheckCCompilerFlagSSP)
|
||||
|
||||
if (UNIX)
|
||||
#
|
||||
# Check for -Werror turned on if possible
|
||||
#
|
||||
# This will prevent that compiler flags are detected incorrectly.
|
||||
#
|
||||
check_c_compiler_flag("-Werror" REQUIRED_FLAGS_WERROR)
|
||||
if (REQUIRED_FLAGS_WERROR)
|
||||
set(CMAKE_REQUIRED_FLAGS "-Werror")
|
||||
|
||||
if (PICKY_DEVELOPER)
|
||||
list(APPEND SUPPORTED_COMPILER_FLAGS "-Werror")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
add_c_compiler_flag("-std=gnu99" SUPPORTED_COMPILER_FLAGS)
|
||||
add_c_compiler_flag("-Wpedantic" SUPPORTED_COMPILER_FLAGS)
|
||||
add_c_compiler_flag("-Wall" SUPPORTED_COMPILER_FLAGS)
|
||||
add_c_compiler_flag("-Wshadow" SUPPORTED_COMPILER_FLAGS)
|
||||
add_c_compiler_flag("-Wmissing-prototypes" SUPPORTED_COMPILER_FLAGS)
|
||||
add_c_compiler_flag("-Wcast-align" SUPPORTED_COMPILER_FLAGS)
|
||||
#add_c_compiler_flag("-Wcast-qual" SUPPORTED_COMPILER_FLAGS)
|
||||
add_c_compiler_flag("-Werror=address" SUPPORTED_COMPILER_FLAGS)
|
||||
add_c_compiler_flag("-Wstrict-prototypes" SUPPORTED_COMPILER_FLAGS)
|
||||
add_c_compiler_flag("-Werror=strict-prototypes" SUPPORTED_COMPILER_FLAGS)
|
||||
add_c_compiler_flag("-Wwrite-strings" SUPPORTED_COMPILER_FLAGS)
|
||||
add_c_compiler_flag("-Werror=write-strings" SUPPORTED_COMPILER_FLAGS)
|
||||
add_c_compiler_flag("-Werror-implicit-function-declaration" SUPPORTED_COMPILER_FLAGS)
|
||||
add_c_compiler_flag("-Wpointer-arith" SUPPORTED_COMPILER_FLAGS)
|
||||
add_c_compiler_flag("-Werror=pointer-arith" SUPPORTED_COMPILER_FLAGS)
|
||||
add_c_compiler_flag("-Wdeclaration-after-statement" SUPPORTED_COMPILER_FLAGS)
|
||||
add_c_compiler_flag("-Werror=declaration-after-statement" SUPPORTED_COMPILER_FLAGS)
|
||||
add_c_compiler_flag("-Wreturn-type" SUPPORTED_COMPILER_FLAGS)
|
||||
add_c_compiler_flag("-Werror=return-type" SUPPORTED_COMPILER_FLAGS)
|
||||
add_c_compiler_flag("-Wuninitialized" SUPPORTED_COMPILER_FLAGS)
|
||||
add_c_compiler_flag("-Werror=uninitialized" SUPPORTED_COMPILER_FLAGS)
|
||||
add_c_compiler_flag("-Wimplicit-fallthrough" SUPPORTED_COMPILER_FLAGS)
|
||||
add_c_compiler_flag("-Werror=strict-overflow" SUPPORTED_COMPILER_FLAGS)
|
||||
add_c_compiler_flag("-Wstrict-overflow=2" SUPPORTED_COMPILER_FLAGS)
|
||||
add_c_compiler_flag("-Wno-format-zero-length" SUPPORTED_COMPILER_FLAGS)
|
||||
add_c_compiler_flag("-Wmissing-field-initializers" SUPPORTED_COMPILER_FLAGS)
|
||||
add_c_compiler_flag("-Wsign-compare" SUPPORTED_COMPILER_FLAGS)
|
||||
|
||||
check_c_compiler_flag("-Wformat" REQUIRED_FLAGS_WFORMAT)
|
||||
if (REQUIRED_FLAGS_WFORMAT)
|
||||
list(APPEND SUPPORTED_COMPILER_FLAGS "-Wformat")
|
||||
set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -Wformat")
|
||||
endif()
|
||||
add_c_compiler_flag("-Wformat-security" SUPPORTED_COMPILER_FLAGS)
|
||||
add_c_compiler_flag("-Werror=format-security" SUPPORTED_COMPILER_FLAGS)
|
||||
|
||||
# Allow zero for a variadic macro argument
|
||||
string(TOLOWER "${CMAKE_C_COMPILER_ID}" _C_COMPILER_ID)
|
||||
if ("${_C_COMPILER_ID}" STREQUAL "clang")
|
||||
add_c_compiler_flag("-Wno-gnu-zero-variadic-macro-arguments" SUPPORTED_COMPILER_FLAGS)
|
||||
endif()
|
||||
|
||||
add_c_compiler_flag("-fno-common" SUPPORTED_COMPILER_FLAGS)
|
||||
|
||||
if (CMAKE_BUILD_TYPE)
|
||||
string(TOLOWER "${CMAKE_BUILD_TYPE}" CMAKE_BUILD_TYPE_LOWER)
|
||||
if (CMAKE_BUILD_TYPE_LOWER MATCHES (release|relwithdebinfo|minsizerel))
|
||||
add_c_compiler_flag("-Wp,-D_FORTIFY_SOURCE=2" SUPPORTED_COMPILER_FLAGS)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
check_c_compiler_flag_ssp("-fstack-protector-strong" WITH_STACK_PROTECTOR_STRONG)
|
||||
if (WITH_STACK_PROTECTOR_STRONG)
|
||||
list(APPEND SUPPORTED_COMPILER_FLAGS "-fstack-protector-strong")
|
||||
# This is needed as Solaris has a seperate libssp
|
||||
if (SOLARIS)
|
||||
list(APPEND SUPPORTED_LINKER_FLAGS "-fstack-protector-strong")
|
||||
endif()
|
||||
else (WITH_STACK_PROTECTOR_STRONG)
|
||||
check_c_compiler_flag_ssp("-fstack-protector" WITH_STACK_PROTECTOR)
|
||||
if (WITH_STACK_PROTECTOR)
|
||||
list(APPEND SUPPORTED_COMPILER_FLAGS "-fstack-protector")
|
||||
# This is needed as Solaris has a seperate libssp
|
||||
if (SOLARIS)
|
||||
list(APPEND SUPPORTED_LINKER_FLAGS "-fstack-protector")
|
||||
endif()
|
||||
endif()
|
||||
endif (WITH_STACK_PROTECTOR_STRONG)
|
||||
|
||||
if (NOT WINDOWS AND NOT CYGWIN)
|
||||
check_c_compiler_flag_ssp("-fstack-clash-protection" WITH_STACK_CLASH_PROTECTION)
|
||||
if (WITH_STACK_CLASH_PROTECTION)
|
||||
list(APPEND SUPPORTED_COMPILER_FLAGS "-fstack-clash-protection")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (PICKY_DEVELOPER)
|
||||
add_c_compiler_flag("-Wno-error=deprecated-declarations" SUPPORTED_COMPILER_FLAGS)
|
||||
add_c_compiler_flag("-Wno-error=tautological-compare" SUPPORTED_COMPILER_FLAGS)
|
||||
endif()
|
||||
|
||||
add_c_compiler_flag("-Wno-deprecated-declarations" DEPRECATION_COMPILER_FLAGS)
|
||||
|
||||
# Unset CMAKE_REQUIRED_FLAGS
|
||||
unset(CMAKE_REQUIRED_FLAGS)
|
||||
endif()
|
||||
|
||||
if (MSVC)
|
||||
add_c_compiler_flag("/D _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES=1" SUPPORTED_COMPILER_FLAGS)
|
||||
add_c_compiler_flag("/D _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT=1" SUPPORTED_COMPILER_FLAGS)
|
||||
add_c_compiler_flag("/D _CRT_NONSTDC_NO_WARNINGS=1" SUPPORTED_COMPILER_FLAGS)
|
||||
add_c_compiler_flag("/D _CRT_SECURE_NO_WARNINGS=1" SUPPORTED_COMPILER_FLAGS)
|
||||
endif()
|
||||
|
||||
# This removes this annoying warning
|
||||
# "warning: 'BN_CTX_free' is deprecated: first deprecated in OS X 10.7 [-Wdeprecated-declarations]"
|
||||
if (OSX)
|
||||
add_c_compiler_flag("-Wno-deprecated-declarations" SUPPORTED_COMPILER_FLAGS)
|
||||
endif()
|
||||
|
||||
set(DEFAULT_C_COMPILE_FLAGS ${SUPPORTED_COMPILER_FLAGS} CACHE INTERNAL "Default C Compiler Flags" FORCE)
|
||||
set(DEFAULT_LINK_FLAGS ${SUPPORTED_LINKER_FLAGS} CACHE INTERNAL "Default C Linker Flags" FORCE)
|
||||
|
||||
if (DEPRECATION_COMPILER_FLAGS)
|
||||
set(DEFAULT_C_NO_DEPRECATION_FLAGS ${DEPRECATION_COMPILER_FLAGS} CACHE INTERNAL "Default no deprecation flags" FORCE)
|
||||
endif()
|
||||
@@ -1,15 +1,17 @@
|
||||
include(CheckIncludeFile)
|
||||
include(CheckIncludeFiles)
|
||||
include(CheckSymbolExists)
|
||||
include(CheckFunctionExists)
|
||||
include(CheckLibraryExists)
|
||||
include(CheckTypeSize)
|
||||
include(CheckStructHasMember)
|
||||
include(CheckCXXSourceCompiles)
|
||||
include(TestBigEndian)
|
||||
|
||||
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})
|
||||
@@ -34,216 +36,73 @@ 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)
|
||||
check_c_compiler_flag("-fvisibility=hidden" WITH_VISIBILITY_HIDDEN)
|
||||
endif (NOT GNUCC_VERSION EQUAL 34)
|
||||
endif(CMAKE_COMPILER_IS_GNUCC AND NOT MINGW AND NOT OS2)
|
||||
|
||||
# HEADER FILES
|
||||
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)
|
||||
|
||||
if (WIN32)
|
||||
check_include_file(io.h HAVE_IO_H)
|
||||
|
||||
check_include_files("winsock2.h;ws2tcpip.h;wspiapi.h" HAVE_WSPIAPI_H)
|
||||
check_include_file(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)
|
||||
check_include_file(ws2tcpip.h HAVE_WS2TCPIP_H)
|
||||
if (HAVE_WSPIAPI_H OR HAVE_WS2TCPIP_H)
|
||||
set(HAVE_GETADDRINFO TRUE)
|
||||
set(HAVE_GETHOSTBYNAME TRUE)
|
||||
endif (HAVE_WSPIAPI_H OR HAVE_WS2TCPIP_H)
|
||||
|
||||
set(HAVE_SELECT TRUE)
|
||||
endif (WIN32)
|
||||
|
||||
if (OPENSSL_FOUND)
|
||||
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
|
||||
check_include_file(openssl/des.h HAVE_OPENSSL_DES_H)
|
||||
if (NOT HAVE_OPENSSL_DES_H)
|
||||
message(FATAL_ERROR "Could not detect openssl/des.h")
|
||||
endif()
|
||||
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIRS})
|
||||
check_include_file(openssl/aes.h HAVE_OPENSSL_AES_H)
|
||||
|
||||
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
|
||||
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()
|
||||
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIRS})
|
||||
check_include_file(openssl/blowfish.h HAVE_OPENSSL_BLOWFISH_H)
|
||||
|
||||
if (WITH_BLOWFISH_CIPHER)
|
||||
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
|
||||
check_include_file(openssl/blowfish.h HAVE_OPENSSL_BLOWFISH_H)
|
||||
endif()
|
||||
|
||||
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
|
||||
check_include_file(openssl/ecdh.h HAVE_OPENSSL_ECDH_H)
|
||||
|
||||
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
|
||||
check_include_file(openssl/ec.h HAVE_OPENSSL_EC_H)
|
||||
|
||||
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
|
||||
check_include_file(openssl/ecdsa.h HAVE_OPENSSL_ECDSA_H)
|
||||
|
||||
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARIES})
|
||||
check_function_exists(EVP_KDF_CTX_new_id HAVE_OPENSSL_EVP_KDF_CTX_NEW_ID)
|
||||
|
||||
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARIES})
|
||||
check_function_exists(EVP_KDF_CTX_new HAVE_OPENSSL_EVP_KDF_CTX_NEW)
|
||||
|
||||
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARIES})
|
||||
check_function_exists(FIPS_mode HAVE_OPENSSL_FIPS_MODE)
|
||||
|
||||
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARIES})
|
||||
check_function_exists(RAND_priv_bytes HAVE_OPENSSL_RAND_PRIV_BYTES)
|
||||
|
||||
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARIES})
|
||||
check_function_exists(EVP_DigestSign HAVE_OPENSSL_EVP_DIGESTSIGN)
|
||||
|
||||
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARIES})
|
||||
check_function_exists(EVP_DigestVerify HAVE_OPENSSL_EVP_DIGESTVERIFY)
|
||||
|
||||
check_function_exists(OPENSSL_ia32cap_loc HAVE_OPENSSL_IA32CAP_LOC)
|
||||
|
||||
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARIES})
|
||||
check_symbol_exists(EVP_PKEY_ED25519 "openssl/evp.h" FOUND_OPENSSL_ED25519)
|
||||
|
||||
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARIES})
|
||||
check_function_exists(EVP_chacha20 HAVE_OPENSSL_EVP_CHACHA20)
|
||||
|
||||
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARIES})
|
||||
check_symbol_exists(EVP_PKEY_POLY1305 "openssl/evp.h" HAVE_OPENSSL_EVP_POLY1305)
|
||||
|
||||
if (HAVE_OPENSSL_EVP_DIGESTSIGN AND HAVE_OPENSSL_EVP_DIGESTVERIFY AND
|
||||
FOUND_OPENSSL_ED25519)
|
||||
set(HAVE_OPENSSL_ED25519 1)
|
||||
endif()
|
||||
|
||||
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARIES})
|
||||
check_symbol_exists(EVP_PKEY_X25519 "openssl/evp.h" HAVE_OPENSSL_X25519)
|
||||
|
||||
unset(CMAKE_REQUIRED_INCLUDES)
|
||||
unset(CMAKE_REQUIRED_LIBRARIES)
|
||||
endif()
|
||||
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIRS})
|
||||
check_include_file(openssl/des.h HAVE_OPENSSL_DES_H)
|
||||
|
||||
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 ()
|
||||
|
||||
if (WITH_DSA)
|
||||
if (NOT WITH_MBEDTLS)
|
||||
set(HAVE_DSA 1)
|
||||
endif (NOT WITH_MBEDTLS)
|
||||
endif()
|
||||
|
||||
# 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(vsnprintf HAVE_VSNPRINTF)
|
||||
check_function_exists(snprintf HAVE_SNPRINTF)
|
||||
|
||||
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)
|
||||
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(_vsnprintf_s HAVE__VSNPRINTF_S)
|
||||
check_function_exists(_vsnprintf HAVE__VSNPRINTF)
|
||||
check_function_exists(_snprintf HAVE__SNPRINTF)
|
||||
check_function_exists(_snprintf_s HAVE__SNPRINTF_S)
|
||||
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)
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} socket)
|
||||
endif (HAVE_LIBSOCKET)
|
||||
|
||||
# libresolv
|
||||
check_library_exists(resolv hstrerror "" HAVE_LIBRESOLV)
|
||||
if (HAVE_LIBRESOLV)
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} resolv)
|
||||
endif (HAVE_LIBRESOLV)
|
||||
|
||||
# libnsl/inet_pton (Solaris)
|
||||
check_library_exists(nsl inet_pton "" HAVE_LIBNSL)
|
||||
if (HAVE_LIBNSL)
|
||||
set(_REQUIRED_LIBRARIES ${_REQUIRED_LIBRARIES} nsl)
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} nsl)
|
||||
endif (HAVE_LIBNSL)
|
||||
|
||||
# librt
|
||||
@@ -252,15 +111,18 @@ if (UNIX)
|
||||
|
||||
check_library_exists(rt clock_gettime "" HAVE_CLOCK_GETTIME)
|
||||
if (HAVE_LIBRT OR HAVE_CLOCK_GETTIME)
|
||||
set(_REQUIRED_LIBRARIES ${_REQUIRED_LIBRARIES} rt)
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} rt)
|
||||
endif (HAVE_LIBRT OR HAVE_CLOCK_GETTIME)
|
||||
|
||||
check_library_exists(util forkpty "" HAVE_LIBUTIL)
|
||||
check_function_exists(getaddrinfo HAVE_GETADDRINFO)
|
||||
check_function_exists(poll HAVE_POLL)
|
||||
check_function_exists(select HAVE_SELECT)
|
||||
check_function_exists(cfmakeraw HAVE_CFMAKERAW)
|
||||
check_function_exists(__strtoull HAVE___STRTOULL)
|
||||
check_function_exists(regcomp HAVE_REGCOMP)
|
||||
check_function_exists(ntohll HAVE_NTOHLL)
|
||||
endif (UNIX)
|
||||
|
||||
set(LIBSSH_REQUIRED_LIBRARIES ${_REQUIRED_LIBRARIES} CACHE INTERNAL "libssh required system libraries")
|
||||
set(LIBSSH_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} CACHE INTERNAL "libssh required system libraries")
|
||||
|
||||
# LIBRARIES
|
||||
if (OPENSSL_FOUND)
|
||||
@@ -268,245 +130,28 @@ if (OPENSSL_FOUND)
|
||||
endif (OPENSSL_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)
|
||||
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)
|
||||
if (ZLIB_LIBRARY)
|
||||
set(HAVE_LIBZ 1)
|
||||
endif (ZLIB_LIBRARY)
|
||||
|
||||
set(CMAKE_REQUIRED_INCLUDES "${MBEDTLS_INCLUDE_DIR}/mbedtls")
|
||||
check_include_file(chacha20.h HAVE_MBEDTLS_CHACHA20_H)
|
||||
check_include_file(poly1305.h HAVE_MBEDTLS_POLY1305_H)
|
||||
unset(CMAKE_REQUIRED_INCLUDES)
|
||||
|
||||
endif (MBEDTLS_FOUND)
|
||||
|
||||
if (CMAKE_USE_PTHREADS_INIT)
|
||||
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 (CMAKE_HAVE_THREADS_LIBRARY)
|
||||
if (CMAKE_USE_PTHREADS_INIT)
|
||||
set(HAVE_PTHREAD 1)
|
||||
endif (CMAKE_USE_PTHREADS_INIT)
|
||||
endif (CMAKE_HAVE_THREADS_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 attributs
|
||||
check_c_compiler_flag("-Wattributes" REQUIRED_FLAGS_WERROR)
|
||||
if (REQUIRED_FLAGS_WERROR)
|
||||
string(APPEND CMAKE_REQUIRED_FLAGS "-Wattributes ")
|
||||
endif()
|
||||
|
||||
# Turn warnings into errors
|
||||
check_c_compiler_flag("-Werror" REQUIRED_FLAGS_WERROR)
|
||||
if (REQUIRED_FLAGS_WERROR)
|
||||
string(APPEND CMAKE_REQUIRED_FLAGS "-Werror ")
|
||||
endif()
|
||||
endif ()
|
||||
|
||||
check_c_source_compiles("
|
||||
void test_constructor_attribute(void) __attribute__ ((constructor));
|
||||
|
||||
void test_constructor_attribute(void)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
return 0;
|
||||
}" HAVE_CONSTRUCTOR_ATTRIBUTE)
|
||||
|
||||
check_c_source_compiles("
|
||||
void test_destructor_attribute(void) __attribute__ ((destructor));
|
||||
|
||||
void test_destructor_attribute(void)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
return 0;
|
||||
}" HAVE_DESTRUCTOR_ATTRIBUTE)
|
||||
|
||||
check_c_source_compiles("
|
||||
#define FALL_THROUGH __attribute__((fallthrough))
|
||||
|
||||
int main(void) {
|
||||
int i = 2;
|
||||
|
||||
switch (i) {
|
||||
case 0:
|
||||
FALL_THROUGH;
|
||||
case 1:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}" HAVE_FALLTHROUGH_ATTRIBUTE)
|
||||
|
||||
check_c_source_compiles("
|
||||
#define WEAK __attribute__((weak))
|
||||
|
||||
WEAK int sum(int a, int b)
|
||||
{
|
||||
return a + b;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int i = sum(2, 2);
|
||||
|
||||
(void)i;
|
||||
|
||||
return 0;
|
||||
}" HAVE_WEAK_ATTRIBUTE)
|
||||
|
||||
if (NOT WIN32)
|
||||
check_c_source_compiles("
|
||||
#define __unused __attribute__((unused))
|
||||
|
||||
static int do_nothing(int i __unused)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
i = do_nothing(5);
|
||||
if (i > 5) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}" HAVE_UNUSED_ATTRIBUTE)
|
||||
endif()
|
||||
|
||||
check_c_source_compiles("
|
||||
#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)
|
||||
endif()
|
||||
if (WITH_MBEDTLS)
|
||||
message(FATAL_ERROR "PKCS #11 is not supported for mbedcrypto")
|
||||
set(WITH_PKCS11_URI 0)
|
||||
endif()
|
||||
if (HAVE_OPENSSL AND NOT OPENSSL_VERSION VERSION_GREATER_EQUAL "1.1.1")
|
||||
message(FATAL_ERROR "PKCS #11 requires at least OpenSSL 1.1.1")
|
||||
set(WITH_PKCS11_URI 0)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (WITH_MBEDTLS)
|
||||
if (WITH_DSA)
|
||||
message(FATAL_ERROR "DSA is not supported with mbedTLS crypto")
|
||||
set(HAVE_DSA 0)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# ENDIAN
|
||||
if (NOT WIN32)
|
||||
test_big_endian(WORDS_BIGENDIAN)
|
||||
|
||||
@@ -1,62 +1,21 @@
|
||||
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_STATIC_LIB "Build with a static library" OFF)
|
||||
option(WITH_DEBUG_CRYPTO "Build with cryto debug output" OFF)
|
||||
option(WITH_DEBUG_PACKET "Build with packet debug output" OFF)
|
||||
option(WITH_DEBUG_CALLTRACE "Build with calltrace debug output" ON)
|
||||
option(WITH_DSA "Build with DSA" OFF)
|
||||
option(WITH_GCRYPT "Compile against libgcrypt" OFF)
|
||||
option(WITH_MBEDTLS "Compile against libmbedtls" OFF)
|
||||
option(WITH_BLOWFISH_CIPHER "Compile with blowfish support" OFF)
|
||||
option(WITH_PCAP "Compile with Pcap generation support" ON)
|
||||
option(WITH_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(UNIT_TESTING "Build with unit tests" OFF)
|
||||
option(CLIENT_TESTING "Build with client tests; requires openssh" OFF)
|
||||
option(SERVER_TESTING "Build with server tests; requires openssh and dropbear" OFF)
|
||||
option(WITH_TESTING "Build with unit tests" OFF)
|
||||
option(WITH_CLIENT_TESTING "Build with client tests; requires a running sshd" OFF)
|
||||
option(WITH_BENCHMARKS "Build benchmarks tools" 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(FUZZ_TESTING "Build with fuzzer for the server and client (automatically enables none cipher!)" OFF)
|
||||
option(PICKY_DEVELOPER "Build with picky developer flags" OFF)
|
||||
|
||||
if (WITH_ZLIB)
|
||||
set(WITH_LIBZ ON)
|
||||
else (WITH_ZLIB)
|
||||
set(WITH_LIBZ OFF)
|
||||
endif (WITH_ZLIB)
|
||||
if(WITH_BENCHMARKS)
|
||||
set(WITH_TESTING ON)
|
||||
endif(WITH_BENCHMARKS)
|
||||
|
||||
if (WITH_BENCHMARKS)
|
||||
set(UNIT_TESTING ON)
|
||||
set(CLIENT_TESTING ON)
|
||||
endif()
|
||||
|
||||
if (UNIT_TESTING OR CLIENT_TESTING OR SERVER_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 (FUZZ_TESTING)
|
||||
set(WITH_INSECURE_NONE ON)
|
||||
endif (FUZZ_TESTING)
|
||||
if (WITH_TESTING)
|
||||
set(WITH_STATIC_LIB ON)
|
||||
endif (WITH_TESTING)
|
||||
|
||||
58
INSTALL
@@ -7,56 +7,27 @@
|
||||
In order to build libssh, you need to install several components:
|
||||
|
||||
- A C compiler
|
||||
- [CMake](https://www.cmake.org) >= 3.3.0
|
||||
- [openssl](https://www.openssl.org) >= 1.0.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.4
|
||||
- [libz](https://www.zlib.net) >= 1.2
|
||||
- [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
|
||||
- [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 -DUNIT_TESTING=ON -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Debug ..
|
||||
cmake -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Debug ..
|
||||
make
|
||||
|
||||
On Windows you should choose a makefile gernerator with -G or use
|
||||
|
||||
cmake-gui.exe ..
|
||||
|
||||
To enable additional client tests against a local OpenSSH server, add the
|
||||
compile option -DCLIENT_TESTING=ON. These tests require an OpenSSH
|
||||
server package and some wrapper libraries (see optional requirements) to
|
||||
be installed.
|
||||
|
||||
If you're interested in server testing, then a OpenSSH client should be
|
||||
installed on the system and if possible also dropbear. Once that is done
|
||||
enable server support with -DWITH_SERVER=ON and enable testing of it with
|
||||
-DSERVER_TESTING=ON.
|
||||
|
||||
## Testing build
|
||||
|
||||
make test
|
||||
|
||||
### CMake standard options
|
||||
Here is a list of the most interesting options provided out of the box by
|
||||
CMake.
|
||||
@@ -76,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
|
||||
|
||||
@@ -88,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:
|
||||
@@ -107,7 +67,7 @@ If you want to install libssh after compilation run:
|
||||
|
||||
## Running
|
||||
|
||||
The libssh binary can be found in the `build/src` directory.
|
||||
The libssh binary can be found in the `build/libssh` directory.
|
||||
You can use `build/examples/samplessh` which is a sample client to
|
||||
test libssh on UNIX.
|
||||
|
||||
@@ -117,4 +77,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
|
||||
|
||||
138
README
@@ -1,12 +1,5 @@
|
||||
_ _ _ _
|
||||
(_) (_) (_) (_)
|
||||
(_) _ (_) _ _ _ _ _ (_) _
|
||||
(_) (_) (_)(_) _ (_)(_) (_)(_) (_)(_) _
|
||||
(_) (_) (_) (_) _ (_) _ (_) (_) (_)
|
||||
(_) (_) (_)(_)(_) (_)(_) (_)(_) (_) (_).org
|
||||
|
||||
The SSH library
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
libssh: the SSH library
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
1* Why ?
|
||||
-_-_-_-_-_
|
||||
@@ -31,13 +24,132 @@ If you ask yourself how to compile libssh, please read INSTALL before anything.
|
||||
3* Where ?
|
||||
-_-_-_-_-_-_
|
||||
|
||||
https://www.libssh.org
|
||||
http://www.libssh.org
|
||||
|
||||
4* Contributing
|
||||
4* API Changes !
|
||||
-_-_-_-_-_-_-_-_-_
|
||||
|
||||
Please read the file 'CONTRIBUTING.md' next to this README file. It explains
|
||||
our copyright policy and how you should send patches for upstream inclusion.
|
||||
Changes between 0.4 and 0.5
|
||||
---------------------------
|
||||
|
||||
We use the ssh_ prefix as namespace for every function now. There is a legacy.h
|
||||
which could be used to get the old function names.
|
||||
|
||||
Changes between 0.3 and 0.4
|
||||
---------------------------
|
||||
|
||||
We changed libssh to be typesafe now:
|
||||
|
||||
SSH_SESSION *session -> ssh_session session
|
||||
SFTP_SESSION *sftp -> sftp_session sftp
|
||||
CHANNEL *channel -> ssh_channel channel
|
||||
STRING *string -> ssh_string string
|
||||
...
|
||||
|
||||
The options structure has been removed and there is a new function. This
|
||||
function can set all available options now. You can find the enum in the
|
||||
header file and it is documented. Example:
|
||||
|
||||
ssh_options_set(session, SSH_OPTIONS_HOST, "localhost");
|
||||
|
||||
5* Copyright policy
|
||||
-_-_-_-_-_-_-_-_-_-_
|
||||
|
||||
libssh is a project with distributed copyright ownership, which means we prefer
|
||||
the copyright on parts of libssh to be held by individuals rather than
|
||||
corporations if possible. There are historical legal reasons for this, but one
|
||||
of the best ways to explain it is that 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 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 you’re doing libssh changes on behalf of a company who
|
||||
normally owns all the work you do please get them to assign personal copyright
|
||||
ownership of your changes to you as an individual, that makes things very easy
|
||||
for us to work with and avoids bringing corporate legal departments into the
|
||||
picture.
|
||||
|
||||
If you can’t do this we can still accept patches from you owned by your
|
||||
employer under a standard employment contract with corporate copyright
|
||||
ownership. It just requires a simple set-up process first.
|
||||
|
||||
We use a process very similar to the way things are done in the Linux Kernel
|
||||
community, so it should be very easy to get a sign off from your corporate
|
||||
legal department. The only changes we’ve made are to accommodate the license we
|
||||
use, which is LGPLv2 (or later) whereas the Linux kernel uses GPLv2.
|
||||
|
||||
The process is called signing.
|
||||
|
||||
How to sign your work
|
||||
----------------------
|
||||
|
||||
Once you have permission to contribute to libssh from your employer, simply
|
||||
email a copy of the following text from your corporate email address to:
|
||||
|
||||
contributing@libssh.org
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
libssh Developer's Certificate of Origin. Version 1.0
|
||||
|
||||
By making a contribution to this project, I certify that:
|
||||
|
||||
(a) The contribution was created in whole or in part by me and I
|
||||
have the right to submit it under the appropriate
|
||||
version of the GNU General Public License; or
|
||||
|
||||
(b) The contribution is based upon previous work that, to the best of
|
||||
my knowledge, is covered under an appropriate open source license
|
||||
and I have the right under that license to submit that work with
|
||||
modifications, whether created in whole or in part by me, under
|
||||
the GNU General Public License, in the appropriate version; or
|
||||
|
||||
(c) The contribution was provided directly to me by some other
|
||||
person who certified (a) or (b) and I have not modified it.
|
||||
|
||||
(d) I understand and agree that this project and the contribution are
|
||||
public and that a record of the contribution (including all
|
||||
metadata and personal information I submit with it, including my
|
||||
sign-off) is maintained indefinitely and may be redistributed
|
||||
consistent with the libssh Team's policies and the requirements of
|
||||
the GNU GPL where they are relevant.
|
||||
|
||||
(e) I am granting this work to this project under the terms of the
|
||||
GNU Lesser General Public License as published by the
|
||||
Free Software Foundation; either version 2.1 of
|
||||
the License, or (at the option of the project) any later version.
|
||||
|
||||
http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
We will maintain a copy of that email as a record that you have the rights to
|
||||
contribute code to libssh under the required licenses whilst working for the
|
||||
company where the email came from.
|
||||
|
||||
Then when sending in a patch via the normal mechanisms described above, add a
|
||||
line that states:
|
||||
|
||||
|
||||
Signed-off-by: Random J Developer <random@developer.example.org>
|
||||
|
||||
|
||||
using your real name and the email address you sent the original email you used
|
||||
to send the libssh Developer’s Certificate of Origin to us (sorry, no
|
||||
pseudonyms or anonymous contributions.)
|
||||
|
||||
That’s it! Such code can then quite happily contain changes that have copyright
|
||||
messages such as:
|
||||
|
||||
|
||||
(c) Example Corporation.
|
||||
|
||||
|
||||
and can be merged into the libssh codebase in the same way as patches from any
|
||||
other individual. You don’t need to send in a copy of the libssh Developer’s
|
||||
Certificate of Origin for each patch, or inside each patch. Just the sign-off
|
||||
message is all that is required once we’ve received the initial email.
|
||||
|
||||
Have fun and happy libssh hacking!
|
||||
|
||||
|
||||
@@ -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.
|
||||
45
README.md
@@ -1,45 +0,0 @@
|
||||
[](https://gitlab.com/libssh/libssh-mirror/commits/master)
|
||||
[](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
|
||||
197
build/build_make.sh
Executable file
@@ -0,0 +1,197 @@
|
||||
#!/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() {
|
||||
if [ -n "${CMAKEDIR}" ]; then
|
||||
${CMAKEDIR}/bin/cmake "$@" ${SOURCE_DIR} || cleanup_and_exit $?
|
||||
else
|
||||
cmake "$@" ${SOURCE_DIR} || cleanup_and_exit $?
|
||||
fi
|
||||
}
|
||||
|
||||
function compile() {
|
||||
if [ -f /proc/cpuinfo ]; then
|
||||
CPUCOUNT=$(grep -c processor /proc/cpuinfo)
|
||||
elif test `uname` = "SunOS" ; then
|
||||
CPUCOUNT=$(psrinfo -p)
|
||||
else
|
||||
CPUCOUNT="1"
|
||||
fi
|
||||
|
||||
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|--clang|--cmakedir /directory|--make
|
||||
(gmake|make)|--ccompiler (gcc|cc)|--withstaticlib|--unittesting|--clientunittesting|--withssh1|--withserver]"
|
||||
cleanup_and_exit
|
||||
}
|
||||
|
||||
cd ${BUILDDIR}
|
||||
|
||||
# the default CMake options:
|
||||
OPTIONS="--graphviz=${BUILDDIR}/libssh.dot"
|
||||
|
||||
# the default 'make' utility:
|
||||
MAKE="make"
|
||||
|
||||
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
|
||||
;;
|
||||
*-clang)
|
||||
OPTIONS="${OPTIONS} -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++"
|
||||
;;
|
||||
*-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
|
||||
;;
|
||||
*-cmakedir)
|
||||
CMAKEDIR="${ARG}"
|
||||
shift
|
||||
;;
|
||||
*-make)
|
||||
MAKE="${ARG}"
|
||||
shift
|
||||
;;
|
||||
*-ccompiler)
|
||||
OPTIONS="${OPTIONS} -DCMAKE_C_COMPILER=${ARG}"
|
||||
shift
|
||||
;;
|
||||
*-withstaticlib)
|
||||
OPTIONS="${OPTIONS} -DWITH_STATIC_LIB=ON"
|
||||
;;
|
||||
*-unittesting)
|
||||
OPTIONS="${OPTIONS} -DWITH_TESTING=ON"
|
||||
;;
|
||||
*-clientunittesting)
|
||||
OPTIONS="${OPTIONS} -DWITH_CLIENT_TESTING=ON"
|
||||
;;
|
||||
*-withssh1)
|
||||
OPTIONS="${OPTIONS} -DWITH_SSH1=ON"
|
||||
;;
|
||||
*-withserver)
|
||||
OPTIONS="${OPTIONS} -DWITH_SERVER=ON"
|
||||
;;
|
||||
----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}" == "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
|
||||
@@ -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()
|
||||
@@ -1,120 +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}
|
||||
)
|
||||
|
||||
endfunction (ADD_CMOCKA_TEST)
|
||||
23
cmake/Modules/AddCMockeryTest.cmake
Normal file
@@ -0,0 +1,23 @@
|
||||
# - ADD_CHECK_TEST(test_name test_source linklib1 ... linklibN)
|
||||
|
||||
# Copyright (c) 2007 Daniel Gollub <dgollub@suse.de>
|
||||
# Copyright (c) 2007-2010 Andreas Schneider <asn@cynapses.org>
|
||||
#
|
||||
# Redistribution and use is allowed according to the terms of the BSD license.
|
||||
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
|
||||
|
||||
enable_testing()
|
||||
include(CTest)
|
||||
|
||||
if(CMAKE_COMPILER_IS_GNUCC AND NOT MINGW)
|
||||
set(CMAKE_C_FLAGS_PROFILING "-g -O0 -Wall -W -Wshadow -Wunused-variable -Wunused-parameter -Wunused-function -Wunused -Wno-system-headers -Wwrite-strings -fprofile-arcs -ftest-coverage" CACHE STRING "Profiling Compiler Flags")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS_PROFILING " -fprofile-arcs -ftest-coverage" CACHE STRING "Profiling Linker Flags")
|
||||
set(CMAKE_MODULE_LINKER_FLAGS_PROFILING " -fprofile-arcs -ftest-coverage" CACHE STRING "Profiling Linker Flags")
|
||||
set(CMAKE_EXEC_LINKER_FLAGS_PROFILING " -fprofile-arcs -ftest-coverage" CACHE STRING "Profiling Linker Flags")
|
||||
endif(CMAKE_COMPILER_IS_GNUCC AND NOT MINGW)
|
||||
|
||||
function (ADD_CMOCKERY_TEST _testName _testSource)
|
||||
add_executable(${_testName} ${_testSource})
|
||||
target_link_libraries(${_testName} ${ARGN})
|
||||
add_test(${_testName} ${CMAKE_CURRENT_BINARY_DIR}/${_testName})
|
||||
endfunction (ADD_CMOCKERY_TEST)
|
||||
@@ -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)
|
||||
|
||||
@@ -1,49 +1,71 @@
|
||||
# define system dependent compiler flags
|
||||
|
||||
include(CheckCCompilerFlag)
|
||||
include(MacroCheckCCompilerFlagSSP)
|
||||
|
||||
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.")
|
||||
#
|
||||
# Define GNUCC compiler flags
|
||||
#
|
||||
if (${CMAKE_C_COMPILER_ID} MATCHES GNU)
|
||||
# add -Wconversion ?
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99 -pedantic -pedantic-errors")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wshadow -Wmissing-prototypes -Wdeclaration-after-statement")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wunused -Wfloat-equal -Wpointer-arith -Wwrite-strings -Wformat-security")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wmissing-format-attribute")
|
||||
|
||||
# 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)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -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.")
|
||||
check_c_compiler_flag_ssp("-fstack-protector" WITH_STACK_PROTECTOR)
|
||||
if (WITH_STACK_PROTECTOR)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fstack-protector")
|
||||
endif (WITH_STACK_PROTECTOR)
|
||||
|
||||
# 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()
|
||||
check_c_compiler_flag("-D_FORTIFY_SOURCE=2" WITH_FORTIFY_SOURCE)
|
||||
if (WITH_FORTIFY_SOURCE)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_FORTIFY_SOURCE=2")
|
||||
endif (WITH_FORTIFY_SOURCE)
|
||||
endif (${CMAKE_C_COMPILER_ID} MATCHES GNU)
|
||||
|
||||
#
|
||||
# Check for large filesystem support
|
||||
#
|
||||
if (CMAKE_SIZEOF_VOID_P MATCHES "8")
|
||||
# with large file support
|
||||
execute_process(
|
||||
COMMAND
|
||||
getconf LFS64_CFLAGS
|
||||
OUTPUT_VARIABLE
|
||||
_lfs_CFLAGS
|
||||
ERROR_QUIET
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
else (CMAKE_SIZEOF_VOID_P MATCHES "8")
|
||||
# with large file support
|
||||
execute_process(
|
||||
COMMAND
|
||||
getconf LFS_CFLAGS
|
||||
OUTPUT_VARIABLE
|
||||
_lfs_CFLAGS
|
||||
ERROR_QUIET
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
endif (CMAKE_SIZEOF_VOID_P MATCHES "8")
|
||||
if (_lfs_CFLAGS)
|
||||
string(REGEX REPLACE "[\r\n]" " " "${_lfs_CFLAGS}" "${${_lfs_CFLAGS}}")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${_lfs_CFLAGS}")
|
||||
endif (_lfs_CFLAGS)
|
||||
|
||||
endif (UNIX AND NOT WIN32)
|
||||
|
||||
if (MSVC)
|
||||
# Use secure functions by defaualt and suppress warnings about
|
||||
#"deprecated" functions
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /D _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES=1")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /D _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT=1")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /D _CRT_NONSTDC_NO_WARNINGS=1 /D _CRT_SECURE_NO_WARNINGS=1")
|
||||
endif (MSVC)
|
||||
|
||||
104
cmake/Modules/DefineInstallationPaths.cmake
Normal file
@@ -0,0 +1,104 @@
|
||||
if (WIN32)
|
||||
# Same same
|
||||
set(BIN_INSTALL_DIR "bin" 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 "-")
|
||||
elseif (UNIX OR OS2)
|
||||
IF (NOT APPLICATION_NAME)
|
||||
MESSAGE(STATUS "${PROJECT_NAME} is used as APPLICATION_NAME")
|
||||
SET(APPLICATION_NAME ${PROJECT_NAME})
|
||||
ENDIF (NOT APPLICATION_NAME)
|
||||
|
||||
# Suffix for Linux
|
||||
SET(LIB_SUFFIX
|
||||
CACHE STRING "Define suffix of directory name (32/64)"
|
||||
)
|
||||
|
||||
SET(EXEC_INSTALL_PREFIX
|
||||
"${CMAKE_INSTALL_PREFIX}"
|
||||
CACHE PATH "Base directory for executables and libraries"
|
||||
)
|
||||
SET(SHARE_INSTALL_PREFIX
|
||||
"${CMAKE_INSTALL_PREFIX}/share"
|
||||
CACHE PATH "Base directory for files which go to share/"
|
||||
)
|
||||
SET(DATA_INSTALL_PREFIX
|
||||
"${SHARE_INSTALL_PREFIX}/${APPLICATION_NAME}"
|
||||
CACHE PATH "The parent directory where applications can install their data")
|
||||
|
||||
# The following are directories where stuff will be installed to
|
||||
SET(BIN_INSTALL_DIR
|
||||
"${EXEC_INSTALL_PREFIX}/bin"
|
||||
CACHE PATH "The ${APPLICATION_NAME} binary install dir (default prefix/bin)"
|
||||
)
|
||||
SET(SBIN_INSTALL_DIR
|
||||
"${EXEC_INSTALL_PREFIX}/sbin"
|
||||
CACHE PATH "The ${APPLICATION_NAME} sbin install dir (default prefix/sbin)"
|
||||
)
|
||||
SET(LIB_INSTALL_DIR
|
||||
"${EXEC_INSTALL_PREFIX}/lib${LIB_SUFFIX}"
|
||||
CACHE PATH "The subdirectory relative to the install prefix where libraries will be installed (default is prefix/lib)"
|
||||
)
|
||||
SET(LIBEXEC_INSTALL_DIR
|
||||
"${EXEC_INSTALL_PREFIX}/libexec"
|
||||
CACHE PATH "The subdirectory relative to the install prefix where libraries will be installed (default is prefix/libexec)"
|
||||
)
|
||||
SET(PLUGIN_INSTALL_DIR
|
||||
"${LIB_INSTALL_DIR}/${APPLICATION_NAME}"
|
||||
CACHE PATH "The subdirectory relative to the install prefix where plugins will be installed (default is prefix/lib/${APPLICATION_NAME})"
|
||||
)
|
||||
SET(INCLUDE_INSTALL_DIR
|
||||
"${CMAKE_INSTALL_PREFIX}/include"
|
||||
CACHE PATH "The subdirectory to the header prefix (default prefix/include)"
|
||||
)
|
||||
|
||||
SET(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 ()
|
||||
@@ -26,7 +26,3 @@ 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")
|
||||
|
||||
@@ -1,92 +0,0 @@
|
||||
#
|
||||
# Copyright (c) 2018 Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
|
||||
#
|
||||
# Redistribution and use is allowed according to the terms of the New
|
||||
# BSD license.
|
||||
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
|
||||
#
|
||||
|
||||
#.rst:
|
||||
# ExtractSymbols
|
||||
# --------------
|
||||
#
|
||||
# This is a helper script for FindABImap.cmake.
|
||||
#
|
||||
# Extract symbols from header files and output a list to a file.
|
||||
# This script is run in build time to extract symbols from the provided header
|
||||
# files. This way, symbols added or removed can be checked and used to update
|
||||
# the symbol version script.
|
||||
#
|
||||
# All symbols followed by the character ``'('`` are extracted. If a
|
||||
# ``FILTER_PATTERN`` is provided, only the lines containing the given string are
|
||||
# considered.
|
||||
#
|
||||
# Expected defined variables
|
||||
# --------------------------
|
||||
#
|
||||
# ``HEADERS_LIST_FILE``:
|
||||
# Required, expects a file containing the list of header files to be parsed.
|
||||
#
|
||||
# ``OUTPUT_PATH``:
|
||||
# Required, expects the output file path.
|
||||
#
|
||||
# Optionally defined variables
|
||||
# ----------------------------
|
||||
#
|
||||
# ``FILTER_PATTERN``:
|
||||
# Expects a string. Only lines containing the given string will be considered
|
||||
# when extracting symbols.
|
||||
#
|
||||
|
||||
if (NOT DEFINED OUTPUT_PATH)
|
||||
message(SEND_ERROR "OUTPUT_PATH not defined")
|
||||
endif()
|
||||
|
||||
if (NOT DEFINED HEADERS_LIST_FILE)
|
||||
message(SEND_ERROR "HEADERS not defined")
|
||||
endif()
|
||||
|
||||
file(READ ${HEADERS_LIST_FILE} HEADERS_LIST)
|
||||
|
||||
set(symbols)
|
||||
foreach(header ${HEADERS_LIST})
|
||||
|
||||
# Filter only lines containing the FILTER_PATTERN
|
||||
file(STRINGS ${header} contain_filter
|
||||
REGEX "^.*${FILTER_PATTERN}.*[(]"
|
||||
)
|
||||
|
||||
# Remove function-like macros
|
||||
foreach(line ${contain_filter})
|
||||
if (NOT ${line} MATCHES ".*#[ ]*define")
|
||||
list(APPEND not_macro ${line})
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
set(functions)
|
||||
|
||||
# Get only the function names followed by '('
|
||||
foreach(line ${not_macro})
|
||||
string(REGEX MATCHALL "[a-zA-Z0-9_]+[ ]*[(]" func ${line})
|
||||
list(APPEND functions ${func})
|
||||
endforeach()
|
||||
|
||||
set(extracted_symbols)
|
||||
|
||||
# Remove '('
|
||||
foreach(line ${functions})
|
||||
string(REGEX REPLACE "[(]" "" symbol ${line})
|
||||
string(STRIP "${symbol}" symbol)
|
||||
list(APPEND extracted_symbols ${symbol})
|
||||
endforeach()
|
||||
|
||||
list(APPEND symbols ${extracted_symbols})
|
||||
endforeach()
|
||||
|
||||
list(REMOVE_DUPLICATES symbols)
|
||||
|
||||
list(SORT symbols)
|
||||
|
||||
string(REPLACE ";" "\n" symbols_list "${symbols}")
|
||||
|
||||
file(WRITE ${OUTPUT_PATH} "${symbols_list}")
|
||||
@@ -1,492 +0,0 @@
|
||||
#
|
||||
# Copyright (c) 2018 Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
|
||||
#
|
||||
# Redistribution and use is allowed according to the terms of the New
|
||||
# BSD license.
|
||||
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
|
||||
#
|
||||
|
||||
#.rst:
|
||||
# FindABIMap
|
||||
# ----------
|
||||
#
|
||||
# This file provides functions to generate the symbol version script. It uses
|
||||
# the ``abimap`` tool to generate and update the linker script file. It can be
|
||||
# installed by calling::
|
||||
#
|
||||
# $ pip install abimap
|
||||
#
|
||||
# The ``function generate_map_file`` generates a symbol version script
|
||||
# containing the provided symbols. It defines a custom command which sets
|
||||
# ``target_name`` as its ``OUTPUT``.
|
||||
#
|
||||
# The experimental function ``extract_symbols()`` is provided as a simple
|
||||
# parser to extract the symbols from C header files. It simply extracts symbols
|
||||
# followed by an opening '``(``'. It is recommended to use a filter pattern to
|
||||
# select the lines to be considered. It defines a custom command which sets
|
||||
# ``target_name`` as its output.
|
||||
#
|
||||
# The helper function ``get_files_list()`` is provided to find files given a
|
||||
# name pattern. It defines a custom command which sets ``target_name`` as its
|
||||
# output.
|
||||
#
|
||||
# Functions provided
|
||||
# ------------------
|
||||
#
|
||||
# ::
|
||||
#
|
||||
# generate_map_file(target_name
|
||||
# RELEASE_NAME_VERSION release_name
|
||||
# SYMBOLS symbols_target
|
||||
# [CURRENT_MAP cur_map]
|
||||
# [FINAL]
|
||||
# [BREAK_ABI]
|
||||
# [COPY_TO output]
|
||||
# )
|
||||
#
|
||||
# ``target_name``:
|
||||
# Required, expects the name of the file to receive the generated symbol
|
||||
# version script. It should be added as a dependency for the library. Use the
|
||||
# linker option ``--version-script filename`` to add the version information
|
||||
# to the symbols when building the library.
|
||||
#
|
||||
# ``RELEASE_NAME_VERSION``:
|
||||
# Required, expects a string containing the name and version information to be
|
||||
# added to the symbols in the format ``lib_name_1_2_3``.
|
||||
#
|
||||
# ``SYMBOLS``:
|
||||
# Required, expects a target with the property ``LIST_FILE`` containing a path
|
||||
# to a file containing the list of symbols to be added to the symbol version
|
||||
# script.
|
||||
#
|
||||
# ``CURRENT_MAP``:
|
||||
# Optional. If given, the new set of symbols will be checked against the
|
||||
# ones contained in the ``cur_map`` file and updated properly. If an
|
||||
# incompatible change is detected and ``BREAK_ABI`` is not defined, the build
|
||||
# will fail.
|
||||
#
|
||||
# ``FINAL``:
|
||||
# Optional. If given, will provide the ``--final`` option to ``abimap`` tool,
|
||||
# which will mark the modified release in the symbol version script with a
|
||||
# special comment, preventing later changes. This option should be set when
|
||||
# creating a library release and the resulting map file should be stored with
|
||||
# the source code.
|
||||
#
|
||||
# ``BREAK_ABI``:
|
||||
# Optional. If provided, will use ``abimap`` ``--allow-abi-break`` option, which
|
||||
# accepts incompatible changes to the set of symbols. This is necessary if any
|
||||
# previously existing symbol were removed.
|
||||
#
|
||||
# ``COPY_TO``:
|
||||
# Optional, expects a string containing the path to where the generated
|
||||
# map file will be copied.
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# .. code-block:: cmake
|
||||
#
|
||||
# find_package(ABIMap)
|
||||
# generate_map_file("lib.map"
|
||||
# RELEASE_NAME_VERSION "lib_1_0_0"
|
||||
# SYMBOLS symbols
|
||||
# )
|
||||
#
|
||||
# Where the target ``symbols`` has its property ``LIST_FILE`` set to the path to
|
||||
# a file containing::
|
||||
#
|
||||
# ``symbol1``
|
||||
# ``symbol2``
|
||||
#
|
||||
# This example would result in the symbol version script to be created in
|
||||
# ``${CMAKE_CURRENT_BINARY_DIR}/lib.map`` containing the provided symbols.
|
||||
#
|
||||
# ::
|
||||
#
|
||||
# get_files_list(target_name
|
||||
# DIRECTORIES dir1 [dir2 ...]
|
||||
# FILES_PATTERNS exp1 [exp2 ...]
|
||||
# [COPY_TO output]
|
||||
# )
|
||||
#
|
||||
# ``target_name``:
|
||||
# Required, expects the name of the target to be created. A file named as
|
||||
# ``${target_name}.list`` will be created in
|
||||
# ``${CMAKE_CURRENT_BINARY_DIR}`` to receive the list of files found.
|
||||
#
|
||||
# ``DIRECTORIES``:
|
||||
# Required, expects a list of directories paths. Only absolute paths are
|
||||
# supported.
|
||||
#
|
||||
# ``FILES_PATTERN``:
|
||||
# Required, expects a list of matching expressions to find the files to be
|
||||
# considered in the directories.
|
||||
#
|
||||
# ``COPY_TO``:
|
||||
# Optional, expects a string containing the path to where the file containing
|
||||
# the list of files will be copied.
|
||||
#
|
||||
# This command searches the directories provided in ``DIRECTORIES`` for files
|
||||
# matching any of the patterns provided in ``FILES_PATTERNS``. The obtained list
|
||||
# is written to the path specified by ``output``. A target named ``target_name``
|
||||
# will be created and its property ``LIST_FILE`` will be set to contain
|
||||
# ``${CMAKE_CURRENT_BINARY_DIR}/${target_name}.list``
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# .. code-block:: cmake
|
||||
#
|
||||
# find_package(ABIMap)
|
||||
# get_files_list(target
|
||||
# DIRECTORIES "/include/mylib"
|
||||
# FILES_PATTERNS "*.h"
|
||||
# COPY_TO "my_list.txt"
|
||||
# )
|
||||
#
|
||||
# Consider that ``/include/mylib`` contains 3 files, ``h1.h``, ``h2.h``, and
|
||||
# ``h3.hpp``
|
||||
#
|
||||
# Will result in a file ``my_list.txt`` containing::
|
||||
#
|
||||
# ``h1.h;h2.h``
|
||||
#
|
||||
# And the target ``target`` will have its property ``LIST_FILE`` set to contain
|
||||
# ``${CMAKE_CURRENT_BINARY_DIR}/target.list``
|
||||
#
|
||||
# ::
|
||||
#
|
||||
# extract_symbols(target_name
|
||||
# HEADERS_LIST headers_list_target
|
||||
# [FILTER_PATTERN pattern]
|
||||
# [COPY_TO output]
|
||||
# )
|
||||
#
|
||||
# ``target_name``:
|
||||
# Required, expects the name of the target to be created. A file named after
|
||||
# the string given in ``target_name`` will be created in
|
||||
# ``${CMAKE_CURRENT_BINARY_DIR}`` to receive the list of symbols.
|
||||
#
|
||||
# ``HEADERS_LIST``:
|
||||
# Required, expects a target with the property ``LIST_FILE`` set, containing a
|
||||
# file path. Such file must contain a list of files paths.
|
||||
#
|
||||
# ``FILTER_PATTERN``:
|
||||
# Optional, expects a string. Only the lines containing the filter pattern
|
||||
# will be considered.
|
||||
#
|
||||
# ``COPY_TO``:
|
||||
# Optional, expects a string containing the path to where the file containing
|
||||
# the found symbols will be copied.
|
||||
#
|
||||
# This command extracts the symbols from the files listed in
|
||||
# ``headers_list`` and write them on the ``output`` file. If ``pattern``
|
||||
# is provided, then only the lines containing the string given in ``pattern``
|
||||
# will be considered. It is recommended to provide a ``FILTER_PATTERN`` to mark
|
||||
# the lines containing exported function declaration, since this function is
|
||||
# experimental and can return wrong symbols when parsing the header files. A
|
||||
# target named ``target_name`` will be created with the property ``LIST_FILE``
|
||||
# set to contain ``${CMAKE_CURRENT_BINARY_DIR}/${target_name}.list``.
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# .. code-block:: cmake
|
||||
#
|
||||
# find_package(ABIMap)
|
||||
# extract_symbols("lib.symbols"
|
||||
# HEADERS_LIST "headers_target"
|
||||
# FILTER_PATTERN "API_FUNCTION"
|
||||
# )
|
||||
#
|
||||
# Where ``LIST_FILE`` property in ``headers_target`` points to a file
|
||||
# containing::
|
||||
#
|
||||
# header1.h;header2.h
|
||||
#
|
||||
# Where ``header1.h`` contains::
|
||||
#
|
||||
# API_FUNCTION int exported_func1(int a, int b);
|
||||
#
|
||||
# ``header2.h`` contains::
|
||||
#
|
||||
# API_FUNCTION int exported_func2(int a);
|
||||
#
|
||||
# int private_func2(int b);
|
||||
#
|
||||
# Will result in a file ``lib.symbols.list`` in ``${CMAKE_CURRENT_BINARY_DIR}``
|
||||
# containing::
|
||||
#
|
||||
# ``exported_func1``
|
||||
# ``exported_func2``
|
||||
#
|
||||
|
||||
# Search for python which is required
|
||||
if (ABIMap_FIND_REQURIED)
|
||||
find_package(PythonInterp REQUIRED)
|
||||
else()
|
||||
find_package(PythonInterp)
|
||||
endif()
|
||||
|
||||
|
||||
if (PYTHONINTERP_FOUND)
|
||||
# Search for abimap tool used to generate the map files
|
||||
find_program(ABIMAP_EXECUTABLE NAMES abimap DOC "path to the abimap executable")
|
||||
mark_as_advanced(ABIMAP_EXECUTABLE)
|
||||
|
||||
if (NOT ABIMAP_EXECUTABLE AND UNIX)
|
||||
message(STATUS "Could not find `abimap` in PATH."
|
||||
" It can be found in PyPI as `abimap`"
|
||||
" (try `pip install abimap`)")
|
||||
endif ()
|
||||
|
||||
if (ABIMAP_EXECUTABLE)
|
||||
# Get the abimap version
|
||||
execute_process(COMMAND ${ABIMAP_EXECUTABLE} version
|
||||
OUTPUT_VARIABLE ABIMAP_VERSION_STRING
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
|
||||
# If the version string starts with abimap-, strip it
|
||||
if ("abimap" STRLESS_EQUAL ${ABIMAP_VERSION_STRING})
|
||||
string(REGEX REPLACE "abimap-" "" ABIMAP_VERSION_STRING "${ABIMAP_VERSION_STRING}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(ABIMap
|
||||
REQUIRED_VARS ABIMAP_EXECUTABLE
|
||||
VERSION_VAR ABIMAP_VERSION_STRING)
|
||||
endif()
|
||||
|
||||
|
||||
if (ABIMAP_FOUND)
|
||||
|
||||
# Define helper scripts
|
||||
set(_EXTRACT_SYMBOLS_SCRIPT ${CMAKE_CURRENT_LIST_DIR}/ExtractSymbols.cmake)
|
||||
set(_GENERATE_MAP_SCRIPT ${CMAKE_CURRENT_LIST_DIR}/GenerateMap.cmake)
|
||||
set(_GET_FILES_LIST_SCRIPT ${CMAKE_CURRENT_LIST_DIR}/GetFilesList.cmake)
|
||||
|
||||
function(get_file_list _TARGET_NAME)
|
||||
|
||||
set(one_value_arguments
|
||||
COPY_TO
|
||||
)
|
||||
|
||||
set(multi_value_arguments
|
||||
DIRECTORIES
|
||||
FILES_PATTERNS
|
||||
)
|
||||
|
||||
cmake_parse_arguments(_get_files_list
|
||||
""
|
||||
"${one_value_arguments}"
|
||||
"${multi_value_arguments}"
|
||||
${ARGN}
|
||||
)
|
||||
|
||||
# The DIRS argument is required
|
||||
if (NOT DEFINED _get_files_list_DIRECTORIES)
|
||||
message(FATAL_ERROR "No directories paths provided. Provide a list of"
|
||||
" directories paths containing header files.")
|
||||
endif()
|
||||
|
||||
# The FILES_PATTERNS argument is required
|
||||
if (NOT DEFINED _get_files_list_FILES_PATTERNS)
|
||||
message(FATAL_ERROR "No matching expressions provided. Provide a list"
|
||||
" of matching patterns for the header files.")
|
||||
endif()
|
||||
|
||||
set(_FILES_LIST_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR}/${_TARGET_NAME}.list)
|
||||
|
||||
get_filename_component(_get_files_list_OUTPUT_PATH
|
||||
"${_FILES_LIST_OUTPUT_PATH}"
|
||||
ABSOLUTE)
|
||||
|
||||
add_custom_target(
|
||||
${_TARGET_NAME}_int ALL
|
||||
COMMAND ${CMAKE_COMMAND}
|
||||
-DOUTPUT_PATH=${_get_files_list_OUTPUT_PATH}
|
||||
-DDIRECTORIES=${_get_files_list_DIRECTORIES}
|
||||
-DFILES_PATTERNS=${_get_files_list_FILES_PATTERNS}
|
||||
-P ${_GET_FILES_LIST_SCRIPT}
|
||||
COMMENT
|
||||
"Searching for files"
|
||||
VERBATIM
|
||||
)
|
||||
|
||||
if (DEFINED _get_files_list_COPY_TO)
|
||||
# Copy the generated file back to the COPY_TO
|
||||
add_custom_target(${_TARGET_NAME} ALL
|
||||
COMMAND
|
||||
${CMAKE_COMMAND} -E copy_if_different
|
||||
${_FILES_LIST_OUTPUT_PATH} ${_get_files_list_COPY_TO}
|
||||
DEPENDS ${_TARGET_NAME}_int
|
||||
COMMENT "Copying ${_TARGET_NAME} to ${_get_files_list_COPY_TO}"
|
||||
VERBATIM
|
||||
)
|
||||
else()
|
||||
add_custom_target(${_TARGET_NAME} ALL
|
||||
DEPENDS ${_TARGET_NAME}_int
|
||||
)
|
||||
endif()
|
||||
|
||||
set_target_properties(${_TARGET_NAME}
|
||||
PROPERTIES LIST_FILE ${_FILES_LIST_OUTPUT_PATH}
|
||||
)
|
||||
|
||||
endfunction()
|
||||
|
||||
function(extract_symbols _TARGET_NAME)
|
||||
|
||||
set(one_value_arguments
|
||||
FILTER_PATTERN
|
||||
HEADERS_LIST
|
||||
COPY_TO
|
||||
)
|
||||
|
||||
set(multi_value_arguments
|
||||
)
|
||||
|
||||
cmake_parse_arguments(_extract_symbols
|
||||
""
|
||||
"${one_value_arguments}"
|
||||
"${multi_value_arguments}"
|
||||
${ARGN}
|
||||
)
|
||||
|
||||
# The HEADERS_LIST_FILE argument is required
|
||||
if (NOT DEFINED _extract_symbols_HEADERS_LIST)
|
||||
message(FATAL_ERROR "No target provided in HEADERS_LIST. Provide a"
|
||||
" target with the property LIST_FILE set as the"
|
||||
" path to the file containing the list of headers.")
|
||||
endif()
|
||||
|
||||
get_filename_component(_SYMBOLS_OUTPUT_PATH
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/${_TARGET_NAME}.list"
|
||||
ABSOLUTE
|
||||
)
|
||||
|
||||
get_target_property(_HEADERS_LIST_FILE
|
||||
${_extract_symbols_HEADERS_LIST}
|
||||
LIST_FILE
|
||||
)
|
||||
|
||||
add_custom_target(
|
||||
${_TARGET_NAME}_int ALL
|
||||
COMMAND ${CMAKE_COMMAND}
|
||||
-DOUTPUT_PATH=${_SYMBOLS_OUTPUT_PATH}
|
||||
-DHEADERS_LIST_FILE=${_HEADERS_LIST_FILE}
|
||||
-DFILTER_PATTERN=${_extract_symbols_FILTER_PATTERN}
|
||||
-P ${_EXTRACT_SYMBOLS_SCRIPT}
|
||||
DEPENDS ${_extract_symbols_HEADERS_LIST}
|
||||
COMMENT "Extracting symbols from headers"
|
||||
VERBATIM
|
||||
)
|
||||
|
||||
if (DEFINED _extract_symbols_COPY_TO)
|
||||
# Copy the generated file back to the COPY_TO
|
||||
add_custom_target(${_TARGET_NAME} ALL
|
||||
COMMAND
|
||||
${CMAKE_COMMAND} -E copy_if_different
|
||||
${_SYMBOLS_OUTPUT_PATH} ${_extract_symbols_COPY_TO}
|
||||
DEPENDS ${_TARGET_NAME}_int
|
||||
COMMENT "Copying ${_TARGET_NAME} to ${_extract_symbols_COPY_TO}"
|
||||
VERBATIM
|
||||
)
|
||||
else()
|
||||
add_custom_target(${_TARGET_NAME} ALL
|
||||
DEPENDS ${_TARGET_NAME}_int
|
||||
)
|
||||
endif()
|
||||
|
||||
set_target_properties(${_TARGET_NAME}
|
||||
PROPERTIES LIST_FILE ${_SYMBOLS_OUTPUT_PATH}
|
||||
)
|
||||
|
||||
endfunction()
|
||||
|
||||
function(generate_map_file _TARGET_NAME)
|
||||
|
||||
set(options
|
||||
FINAL
|
||||
BREAK_ABI
|
||||
)
|
||||
|
||||
set(one_value_arguments
|
||||
RELEASE_NAME_VERSION
|
||||
SYMBOLS
|
||||
CURRENT_MAP
|
||||
COPY_TO
|
||||
)
|
||||
|
||||
set(multi_value_arguments
|
||||
)
|
||||
|
||||
cmake_parse_arguments(_generate_map_file
|
||||
"${options}"
|
||||
"${one_value_arguments}"
|
||||
"${multi_value_arguments}"
|
||||
${ARGN}
|
||||
)
|
||||
|
||||
if (NOT DEFINED _generate_map_file_SYMBOLS)
|
||||
message(FATAL_ERROR "No target provided in SYMBOLS. Provide a target"
|
||||
" with the property LIST_FILE set as the path to"
|
||||
" the file containing the list of symbols.")
|
||||
endif()
|
||||
|
||||
if (NOT DEFINED _generate_map_file_RELEASE_NAME_VERSION)
|
||||
message(FATAL_ERROR "Release name and version not provided."
|
||||
" (e.g. libname_1_0_0)")
|
||||
endif()
|
||||
|
||||
|
||||
get_target_property(_SYMBOLS_FILE
|
||||
${_generate_map_file_SYMBOLS}
|
||||
LIST_FILE
|
||||
)
|
||||
|
||||
# Set generated map file path
|
||||
get_filename_component(_MAP_OUTPUT_PATH
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/${_TARGET_NAME}"
|
||||
ABSOLUTE
|
||||
)
|
||||
|
||||
add_custom_target(
|
||||
${_TARGET_NAME}_int ALL
|
||||
COMMAND ${CMAKE_COMMAND}
|
||||
-DABIMAP_EXECUTABLE=${ABIMAP_EXECUTABLE}
|
||||
-DSYMBOLS=${_SYMBOLS_FILE}
|
||||
-DCURRENT_MAP=${_generate_map_file_CURRENT_MAP}
|
||||
-DOUTPUT_PATH=${_MAP_OUTPUT_PATH}
|
||||
-DFINAL=${_generate_map_file_FINAL}
|
||||
-DBREAK_ABI=${_generate_map_file_BREAK_ABI}
|
||||
-DRELEASE_NAME_VERSION=${_generate_map_file_RELEASE_NAME_VERSION}
|
||||
-P ${_GENERATE_MAP_SCRIPT}
|
||||
DEPENDS ${_generate_map_file_SYMBOLS}
|
||||
COMMENT "Generating the map ${_TARGET_NAME}"
|
||||
VERBATIM
|
||||
)
|
||||
|
||||
# Add a custom command setting the map as OUTPUT to allow it to be added as
|
||||
# a generated source
|
||||
add_custom_command(
|
||||
OUTPUT ${_MAP_OUTPUT_PATH}
|
||||
DEPENDS ${_TARGET_NAME}_copy
|
||||
)
|
||||
|
||||
if (DEFINED _generate_map_file_COPY_TO)
|
||||
# Copy the generated map back to the COPY_TO
|
||||
add_custom_target(${_TARGET_NAME}_copy ALL
|
||||
COMMAND
|
||||
${CMAKE_COMMAND} -E copy_if_different ${_MAP_OUTPUT_PATH}
|
||||
${_generate_map_file_COPY_TO}
|
||||
DEPENDS ${_TARGET_NAME}_int
|
||||
COMMENT "Copying ${_MAP_OUTPUT_PATH} to ${_generate_map_file_COPY_TO}"
|
||||
VERBATIM
|
||||
)
|
||||
else()
|
||||
add_custom_target(${_TARGET_NAME}_copy ALL
|
||||
DEPENDS ${_TARGET_NAME}_int
|
||||
)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
endif (ABIMAP_FOUND)
|
||||
@@ -1,66 +1,60 @@
|
||||
# - Try to find ARGP
|
||||
# - Try to find Argp
|
||||
# Once done this will define
|
||||
#
|
||||
# ARGP_ROOT_DIR - Set this variable to the root installation of ARGP
|
||||
# ARGP_FOUND - system has Argp
|
||||
# ARGP_INCLUDE_DIRS - the Argp include directory
|
||||
# ARGP_LIBRARIES - Link these to use Argp
|
||||
# ARGP_DEFINITIONS - Compiler switches required for using Argp
|
||||
#
|
||||
# Read-Only variables:
|
||||
# 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) 2010 Andreas Schneider <asn@cynapses.org>
|
||||
#
|
||||
#=============================================================================
|
||||
# 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.
|
||||
#=============================================================================
|
||||
# Redistribution and use is allowed according to the terms of the New
|
||||
# BSD license.
|
||||
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
|
||||
#
|
||||
|
||||
set(_ARGP_ROOT_HINTS
|
||||
)
|
||||
|
||||
set(_ARGP_ROOT_PATHS
|
||||
"$ENV{PROGRAMFILES}/argp"
|
||||
)
|
||||
if (ARGP_LIBRARIES AND ARGP_INCLUDE_DIRS)
|
||||
# in cache already
|
||||
set(ARGP_FOUND TRUE)
|
||||
else (ARGP_LIBRARIES AND ARGP_INCLUDE_DIRS)
|
||||
|
||||
find_path(ARGP_ROOT_DIR
|
||||
find_path(ARGP_INCLUDE_DIR
|
||||
NAMES
|
||||
include/argp.h
|
||||
HINTS
|
||||
${_ARGP_ROOT_HINTS}
|
||||
argp.h
|
||||
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}
|
||||
/usr/include
|
||||
/usr/local/include
|
||||
/opt/local/include
|
||||
/sw/include
|
||||
)
|
||||
endif (ARGP_LIBRARY)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(ARGP DEFAULT_MSG ARGP_LIBRARIES ARGP_INCLUDE_DIR)
|
||||
find_library(ARGP_LIBRARY
|
||||
NAMES
|
||||
argp
|
||||
PATHS
|
||||
/usr/lib
|
||||
/usr/local/lib
|
||||
/opt/local/lib
|
||||
/sw/lib
|
||||
)
|
||||
|
||||
set(ARGP_INCLUDE_DIRS
|
||||
${ARGP_INCLUDE_DIR}
|
||||
)
|
||||
|
||||
if (ARGP_LIBRARY)
|
||||
set(ARGP_LIBRARIES
|
||||
${ARGP_LIBRARIES}
|
||||
${ARGP_LIBRARY}
|
||||
)
|
||||
endif (ARGP_LIBRARY)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(Argp DEFAULT_MSG ARGP_LIBRARIES ARGP_INCLUDE_DIRS)
|
||||
|
||||
# show the ARGP_INCLUDE_DIRS and ARGP_LIBRARIES variables only in the advanced view
|
||||
mark_as_advanced(ARGP_INCLUDE_DIRS ARGP_LIBRARIES)
|
||||
|
||||
endif (ARGP_LIBRARIES AND ARGP_INCLUDE_DIRS)
|
||||
|
||||
# show the ARGP_INCLUDE_DIR and ARGP_LIBRARIES variables only in the advanced view
|
||||
mark_as_advanced(ARGP_INCLUDE_DIR ARGP_LIBRARIES)
|
||||
|
||||
@@ -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)
|
||||
63
cmake/Modules/FindCMockery.cmake
Normal file
@@ -0,0 +1,63 @@
|
||||
# - Try to find CMockery
|
||||
# Once done this will define
|
||||
#
|
||||
# CMOCKERY_FOUND - system has CMockery
|
||||
# CMOCKERY_INCLUDE_DIRS - the CMockery include directory
|
||||
# CMOCKERY_LIBRARIES - Link these to use CMockery
|
||||
# CMOCKERY_DEFINITIONS - Compiler switches required for using CMockery
|
||||
#
|
||||
# Copyright (c) 2010 Andreas Schneider <asn@cryptomilk.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 (CMOCKERY_LIBRARIES AND CMOCKERY_INCLUDE_DIRS)
|
||||
# in cache already
|
||||
set(CMOCKERY_FOUND TRUE)
|
||||
else (CMOCKERY_LIBRARIES AND CMOCKERY_INCLUDE_DIRS)
|
||||
|
||||
find_path(CMOCKERY_INCLUDE_DIR
|
||||
NAMES
|
||||
google/cmockery.h
|
||||
PATHS
|
||||
${_CMOCKERY_DIR}/include
|
||||
/usr/include
|
||||
/usr/local/include
|
||||
/opt/local/include
|
||||
/sw/include
|
||||
$ENV{PROGRAMFILES}/cmockery/include
|
||||
)
|
||||
|
||||
find_library(CMOCKERY_LIBRARY
|
||||
NAMES
|
||||
cmockery
|
||||
PATHS
|
||||
${_CMOCKERY_DIR}/lib
|
||||
/usr/lib
|
||||
/usr/local/lib
|
||||
/opt/local/lib
|
||||
/sw/lib
|
||||
$ENV{PROGRAMFILES}/cmockery/lib
|
||||
)
|
||||
|
||||
set(CMOCKERY_INCLUDE_DIRS
|
||||
${CMOCKERY_INCLUDE_DIR}
|
||||
)
|
||||
|
||||
if (CMOCKERY_LIBRARY)
|
||||
set(CMOCKERY_LIBRARIES
|
||||
${CMOCKERY_LIBRARIES}
|
||||
${CMOCKERY_LIBRARY}
|
||||
)
|
||||
endif (CMOCKERY_LIBRARY)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(CMockery DEFAULT_MSG CMOCKERY_LIBRARIES CMOCKERY_INCLUDE_DIRS)
|
||||
|
||||
# show the CMOCKERY_INCLUDE_DIRS and CMOCKERY_LIBRARIES variables only in the advanced view
|
||||
mark_as_advanced(CMOCKERY_INCLUDE_DIRS CMOCKERY_LIBRARIES)
|
||||
|
||||
endif (CMOCKERY_LIBRARIES AND CMOCKERY_INCLUDE_DIRS)
|
||||
@@ -7,7 +7,7 @@
|
||||
# GCRYPT_DEFINITIONS - Compiler switches required for using GCrypt
|
||||
#
|
||||
#=============================================================================
|
||||
# Copyright (c) 2009-2012 Andreas Schneider <asn@cryptomilk.org>
|
||||
# Copyright (c) 2009-2011 Andreas Schneider <asn@cryptomilk.org>
|
||||
#
|
||||
# Distributed under the OSI-approved BSD License (the "License");
|
||||
# see accompanying file Copyright.txt for details.
|
||||
@@ -18,70 +18,53 @@
|
||||
#=============================================================================
|
||||
#
|
||||
|
||||
set(_GCRYPT_ROOT_HINTS
|
||||
$ENV{GCRYTPT_ROOT_DIR}
|
||||
${GCRYPT_ROOT_DIR})
|
||||
if (GCRYPT_LIBRARIES AND GCRYPT_INCLUDE_DIRS)
|
||||
# in cache already
|
||||
# set(GCRYPT_FOUND TRUE)
|
||||
else (GCRYPT_LIBRARIES AND GCRYPT_INCLUDE_DIRS)
|
||||
|
||||
set(_GCRYPT_ROOT_PATHS
|
||||
"$ENV{PROGRAMFILES}/libgcrypt")
|
||||
|
||||
set(_GCRYPT_ROOT_HINTS_AND_PATHS
|
||||
HINTS ${_GCRYPT_ROOT_HINTS}
|
||||
PATHS ${_GCRYPT_ROOT_PATHS})
|
||||
|
||||
|
||||
find_path(GCRYPT_INCLUDE_DIR
|
||||
NAMES
|
||||
gcrypt.h
|
||||
HINTS
|
||||
${_GCRYPT_ROOT_HINTS_AND_PATHS}
|
||||
PATH_SUFFIXES
|
||||
include
|
||||
)
|
||||
|
||||
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}
|
||||
)
|
||||
set(GCRYPT_LIBRARIES ${GCRYPT_LIBRARY} ${GCRYPT_ERROR_LIBRARY})
|
||||
|
||||
if (GCRYPT_INCLUDE_DIR)
|
||||
file(STRINGS "${GCRYPT_INCLUDE_DIR}/gcrypt.h" _gcrypt_version_str REGEX "^#define GCRYPT_VERSION \"[0-9]+\\.[0-9]+\\.[0-9]")
|
||||
|
||||
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"
|
||||
set(_GCRYPT_ROOT_PATHS
|
||||
"$ENV{PROGRAMFILES}/libgcrypt"
|
||||
)
|
||||
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)
|
||||
|
||||
# show the GCRYPT_INCLUDE_DIRS and GCRYPT_LIBRARIES variables only in the advanced view
|
||||
mark_as_advanced(GCRYPT_INCLUDE_DIR GCRYPT_LIBRARIES)
|
||||
find_path(GCRYPT_ROOT_DIR
|
||||
NAMES
|
||||
include/gcrypt.h
|
||||
PATHS
|
||||
${_GCRYPT_ROOT_PATHS}
|
||||
)
|
||||
mark_as_advanced(ZLIB_ROOT_DIR)
|
||||
|
||||
find_path(GCRYPT_INCLUDE_DIR
|
||||
NAMES
|
||||
gcrypt.h
|
||||
PATHS
|
||||
/usr/local/include
|
||||
/opt/local/include
|
||||
/sw/include
|
||||
/usr/lib/sfw/include
|
||||
${GCRYPT_ROOT_DIR}/include
|
||||
)
|
||||
set(GCRYPT_INCLUDE_DIRS ${GCRYPT_INCLUDE_DIR})
|
||||
|
||||
find_library(GCRYPT_LIBRARY
|
||||
NAMES
|
||||
gcrypt
|
||||
gcrypt11
|
||||
libgcrypt-11
|
||||
PATHS
|
||||
/opt/local/lib
|
||||
/sw/lib
|
||||
/usr/sfw/lib/64
|
||||
/usr/sfw/lib
|
||||
${GCRYPT_ROOT_DIR}/lib
|
||||
)
|
||||
set(GCRYPT_LIBRARIES ${GCRYPT_LIBRARY})
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(GCrypt DEFAULT_MSG GCRYPT_LIBRARIES GCRYPT_INCLUDE_DIRS)
|
||||
|
||||
# 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)
|
||||
|
||||
@@ -1,325 +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 TURE 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
|
||||
#
|
||||
#=============================================================================
|
||||
# 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.
|
||||
#=============================================================================
|
||||
#
|
||||
|
||||
find_path(GSSAPI_ROOT_DIR
|
||||
NAMES
|
||||
include/gssapi.h
|
||||
include/gssapi/gssapi.h
|
||||
HINTS
|
||||
${_GSSAPI_ROOT_HINTS}
|
||||
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_INCLUDE_DIRS AND GSSAPI_LIBRARIES)
|
||||
set(GSSAPI_FOUND TRUE)
|
||||
endif (GSSAPI_INCLUDE_DIRS AND GSSAPI_LIBRARIES)
|
||||
|
||||
# show the GSSAPI_INCLUDE_DIRS and GSSAPI_LIBRARIES variables only in the advanced view
|
||||
mark_as_advanced(GSSAPI_INCLUDE_DIRS GSSAPI_LIBRARIES)
|
||||
@@ -1,104 +0,0 @@
|
||||
# - Try to find mbedTLS
|
||||
# Once done this will define
|
||||
#
|
||||
# MBEDTLS_FOUND - system has mbedTLS
|
||||
# MBEDTLS_INCLUDE_DIRS - the mbedTLS include directory
|
||||
# MBEDTLS_LIBRARIES - Link these to use mbedTLS
|
||||
# MBEDTLS_DEFINITIONS - Compiler switches required for using mbedTLS
|
||||
#=============================================================================
|
||||
# Copyright (c) 2017 Sartura d.o.o.
|
||||
#
|
||||
# Author: Juraj Vijtiuk <juraj.vijtiuk@sartura.hr>
|
||||
#
|
||||
# Distributed under the OSI-approved BSD License (the "License");
|
||||
# see accompanying file Copyright.txt for details.
|
||||
#
|
||||
# This software is distributed WITHOUT ANY WARRANTY; without even the
|
||||
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
# See the License for more information.
|
||||
#=============================================================================
|
||||
#
|
||||
|
||||
|
||||
set(_MBEDTLS_ROOT_HINTS
|
||||
$ENV{MBEDTLS_ROOT_DIR}
|
||||
${MBEDTLS_ROOT_DIR})
|
||||
|
||||
set(_MBEDTLS_ROOT_PATHS
|
||||
"$ENV{PROGRAMFILES}/libmbedtls")
|
||||
|
||||
set(_MBEDTLS_ROOT_HINTS_AND_PATHS
|
||||
HINTS ${_MBEDTLS_ROOT_HINTS}
|
||||
PATHS ${_MBEDTLS_ROOT_PATHS})
|
||||
|
||||
|
||||
find_path(MBEDTLS_INCLUDE_DIR
|
||||
NAMES
|
||||
mbedtls/config.h
|
||||
HINTS
|
||||
${_MBEDTLS_ROOT_HINTS_AND_PATHS}
|
||||
PATH_SUFFIXES
|
||||
include
|
||||
)
|
||||
|
||||
find_library(MBEDTLS_SSL_LIBRARY
|
||||
NAMES
|
||||
mbedtls
|
||||
HINTS
|
||||
${_MBEDTLS_ROOT_HINTS_AND_PATHS}
|
||||
PATH_SUFFIXES
|
||||
lib
|
||||
|
||||
)
|
||||
|
||||
find_library(MBEDTLS_CRYPTO_LIBRARY
|
||||
NAMES
|
||||
mbedcrypto
|
||||
HINTS
|
||||
${_MBEDTLS_ROOT_HINTS_AND_PATHS}
|
||||
PATH_SUFFIXES
|
||||
lib
|
||||
)
|
||||
|
||||
find_library(MBEDTLS_X509_LIBRARY
|
||||
NAMES
|
||||
mbedx509
|
||||
HINTS
|
||||
${_MBEDTLS_ROOT_HINTS_AND_PATHS}
|
||||
PATH_SUFFIXES
|
||||
lib
|
||||
)
|
||||
|
||||
set(MBEDTLS_LIBRARIES ${MBEDTLS_SSL_LIBRARY} ${MBEDTLS_CRYPTO_LIBRARY}
|
||||
${MBEDTLS_X509_LIBRARY})
|
||||
|
||||
if (MBEDTLS_INCLUDE_DIR AND EXISTS "${MBEDTLS_INCLUDE_DIR}/mbedtls/version.h")
|
||||
file(STRINGS "${MBEDTLS_INCLUDE_DIR}/mbedtls/version.h" _mbedtls_version_str REGEX
|
||||
"^#[\t ]*define[\t ]+MBEDTLS_VERSION_STRING[\t ]+\"[0-9]+.[0-9]+.[0-9]+\"")
|
||||
|
||||
string(REGEX REPLACE "^.*MBEDTLS_VERSION_STRING.*([0-9]+.[0-9]+.[0-9]+).*"
|
||||
"\\1" MBEDTLS_VERSION "${_mbedtls_version_str}")
|
||||
endif ()
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
if (MBEDTLS_VERSION)
|
||||
find_package_handle_standard_args(MbedTLS
|
||||
REQUIRED_VARS
|
||||
MBEDTLS_INCLUDE_DIR
|
||||
MBEDTLS_LIBRARIES
|
||||
VERSION_VAR
|
||||
MBEDTLS_VERSION
|
||||
FAIL_MESSAGE
|
||||
"Could NOT find mbedTLS, try to set the path to mbedTLS root folder
|
||||
in the system variable MBEDTLS_ROOT_DIR"
|
||||
)
|
||||
else (MBEDTLS_VERSION)
|
||||
find_package_handle_standard_args(MBedTLS
|
||||
"Could NOT find mbedTLS, try to set the path to mbedLS root folder in
|
||||
the system variable MBEDTLS_ROOT_DIR"
|
||||
MBEDTLS_INCLUDE_DIR
|
||||
MBEDTLS_LIBRARIES)
|
||||
endif (MBEDTLS_VERSION)
|
||||
|
||||
# show the MBEDTLS_INCLUDE_DIRS and MBEDTLS_LIBRARIES variables only in the advanced view
|
||||
mark_as_advanced(MBEDTLS_INCLUDE_DIR MBEDTLS_LIBRARIES)
|
||||
@@ -1,15 +1,14 @@
|
||||
# - Try to find NSIS
|
||||
# Once done this will define
|
||||
#
|
||||
# NSIS_ROOT_PATH - Set this variable to the root installation of NSIS
|
||||
# NSIS_ROOT_DIR - Set this variable to the root installation of ZLIB
|
||||
#
|
||||
# Read-Only variables:
|
||||
#
|
||||
# NSIS_FOUND - system has NSIS
|
||||
# NSIS_MAKE - NSIS creator executable
|
||||
#
|
||||
#=============================================================================
|
||||
# Copyright (c) 2010-2013 Andreas Schneider <asn@cryptomilk.org>
|
||||
# Copyright (c) 2010-2011 Andreas Schneider <asn@cryptomilk.org>
|
||||
#
|
||||
# Distributed under the OSI-approved BSD License (the "License");
|
||||
# see accompanying file Copyright.txt for details.
|
||||
@@ -20,35 +19,21 @@
|
||||
#=============================================================================
|
||||
#
|
||||
|
||||
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)
|
||||
set(_NSIS_ROOT_PATHS
|
||||
C:/NSIS/Bin
|
||||
"$ENV{PROGRAMFILES}/NSIS"
|
||||
)
|
||||
|
||||
find_program(NSIS_MAKE
|
||||
NAMES
|
||||
makensis
|
||||
PATHS
|
||||
${NSIS_ROOT_PATH}
|
||||
${NSIS_ROOT_PATH}/Bin
|
||||
${_NSIS_ROOT_PATHS}
|
||||
)
|
||||
|
||||
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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
208
cmake/Modules/FindOpenSSL.cmake
Normal file
@@ -0,0 +1,208 @@
|
||||
# - Try to find OpenSSL
|
||||
# Once done this will define
|
||||
#
|
||||
# OPENSSL_ROOT_DIR - Set this variable to the root installation of OpenSSL
|
||||
#
|
||||
# Read-Only variables:
|
||||
# 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) 2006-2009 Kitware, Inc.
|
||||
# Copyright (c) 2006 Alexander Neundorf <neundorf@kde.org>
|
||||
# Copyright (c) 2009-2010 Mathieu Malaterre <mathieu.malaterre@gmail.com>
|
||||
# Copyright (c) 2011 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 (OPENSSL_LIBRARIES AND OPENSSL_INCLUDE_DIRS)
|
||||
# in cache already
|
||||
set(OPENSSL_FOUND TRUE)
|
||||
else (OPENSSL_LIBRARIES AND OPENSSL_INCLUDE_DIRS)
|
||||
|
||||
if (UNIX)
|
||||
find_package(PkgConfig)
|
||||
if (PKG_CONFIG_FOUND)
|
||||
pkg_check_modules(_OPENSSL openssl)
|
||||
endif (PKG_CONFIG_FOUND)
|
||||
endif (UNIX)
|
||||
|
||||
# http://www.slproweb.com/products/Win32OpenSSL.html
|
||||
set(_OPENSSL_ROOT_HINTS
|
||||
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\OpenSSL (32-bit)_is1;Inno Setup: App Path]"
|
||||
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\OpenSSL (64-bit)_is1;Inno Setup: App Path]"
|
||||
)
|
||||
|
||||
set(_OPENSSL_ROOT_PATHS
|
||||
"C:/OpenSSL/"
|
||||
"C:/OpenSSL-Win32/"
|
||||
"C:/OpenSSL-Win64/"
|
||||
"$ENV{PROGRAMFILES}/OpenSSL"
|
||||
"$ENV{PROGRAMFILES}/OpenSSL-Win32"
|
||||
"$ENV{PROGRAMFILES}/OpenSSL-Win64"
|
||||
)
|
||||
|
||||
find_path(OPENSSL_ROOT_DIR
|
||||
NAMES
|
||||
include/openssl/ssl.h
|
||||
HINTS
|
||||
${_OPENSSL_ROOT_HINTS}
|
||||
PATHS
|
||||
${_OPENSSL_ROOT_PATHS}
|
||||
)
|
||||
mark_as_advanced(OPENSSL_ROOT_DIR)
|
||||
|
||||
find_path(OPENSSL_INCLUDE_DIR
|
||||
NAMES
|
||||
openssl/ssl.h
|
||||
PATHS
|
||||
/usr/local/include
|
||||
/opt/local/include
|
||||
/sw/include
|
||||
/usr/lib/sfw/include
|
||||
${OPENSSL_ROOT_DIR}/include
|
||||
)
|
||||
|
||||
set(OPENSSL_INCLUDE_DIRS ${OPENSSL_INCLUDE_DIR})
|
||||
mark_as_advanced(OPENSSL_INCLUDE_DIRS)
|
||||
|
||||
if (WIN32 AND NOT CYGWIN)
|
||||
# MINGW should go here too
|
||||
if (MSVC)
|
||||
# /MD and /MDd are the standard values - if someone wants to use
|
||||
# others, the libnames have to change here too
|
||||
# use also ssl and ssleay32 in debug as fallback for openssl < 0.9.8b
|
||||
# TODO: handle /MT and static lib
|
||||
# In Visual C++ naming convention each of these four kinds of Windows libraries has it's standard suffix:
|
||||
# * MD for dynamic-release
|
||||
# * MDd for dynamic-debug
|
||||
# * MT for static-release
|
||||
# * MTd for static-debug
|
||||
|
||||
# Implementation details:
|
||||
# We are using the libraries located in the VC subdir instead of the parent directory eventhough :
|
||||
# libeay32MD.lib is identical to ../libeay32.lib, and
|
||||
# ssleay32MD.lib is identical to ../ssleay32.lib
|
||||
find_library(LIB_EAY_DEBUG
|
||||
NAMES
|
||||
libeay32MDd
|
||||
libeay32
|
||||
PATHS
|
||||
${OPENSSL_ROOT_DIR}/lib/VC
|
||||
)
|
||||
|
||||
find_library(LIB_EAY_RELEASE
|
||||
NAMES
|
||||
libeay32MD
|
||||
libeay32
|
||||
PATHS
|
||||
${OPENSSL_ROOT_DIR}/lib/VC
|
||||
)
|
||||
|
||||
find_library(SSL_EAY_DEBUG
|
||||
NAMES
|
||||
ssleay32MDd
|
||||
ssleay32
|
||||
ssl
|
||||
PATHS ${OPENSSL_ROOT_DIR}/lib/VC
|
||||
)
|
||||
|
||||
find_library(SSL_EAY_RELEASE
|
||||
NAMES
|
||||
ssleay32MD
|
||||
ssleay32
|
||||
ssl
|
||||
PATHS
|
||||
${OPENSSL_ROOT_DIR}/lib/VC
|
||||
)
|
||||
|
||||
if (CMAKE_CONFIGURATION_TYPES OR CMAKE_BUILD_TYPE)
|
||||
set(OPENSSL_LIBRARIES
|
||||
optimized ${SSL_EAY_RELEASE} debug ${SSL_EAY_DEBUG}
|
||||
optimized ${LIB_EAY_RELEASE} debug ${LIB_EAY_DEBUG}
|
||||
)
|
||||
else (CMAKE_CONFIGURATION_TYPES OR CMAKE_BUILD_TYPE)
|
||||
set( OPENSSL_LIBRARIES ${SSL_EAY_RELEASE} ${LIB_EAY_RELEASE} )
|
||||
endif (CMAKE_CONFIGURATION_TYPES OR CMAKE_BUILD_TYPE)
|
||||
|
||||
mark_as_advanced(SSL_EAY_DEBUG SSL_EAY_RELEASE)
|
||||
mark_as_advanced(LIB_EAY_DEBUG LIB_EAY_RELEASE)
|
||||
elseif (MINGW)
|
||||
# same player, for MingW
|
||||
find_library(LIB_EAY
|
||||
NAMES
|
||||
libeay32
|
||||
PATHS
|
||||
${OPENSSL_ROOT_DIR}/lib/MinGW
|
||||
)
|
||||
|
||||
find_library(SSL_EAY
|
||||
NAMES
|
||||
ssleay32
|
||||
PATHS
|
||||
${OPENSSL_ROOT_DIR}/lib/MinGW
|
||||
)
|
||||
|
||||
mark_as_advanced(SSL_EAY LIB_EAY)
|
||||
set(OPENSSL_LIBRARIES ${SSL_EAY} ${LIB_EAY})
|
||||
else(MSVC)
|
||||
# Not sure what to pick for -say- intel, let's use the toplevel ones and hope someone report issues:
|
||||
find_library(LIB_EAY
|
||||
NAMES
|
||||
libeay32
|
||||
PATHS
|
||||
${OPENSSL_ROOT_DIR}/lib
|
||||
)
|
||||
|
||||
find_library(SSL_EAY
|
||||
NAMES
|
||||
ssleay32
|
||||
PATHS
|
||||
${OPENSSL_ROOT_DIR}/lib
|
||||
)
|
||||
|
||||
mark_as_advanced(SSL_EAY LIB_EAY)
|
||||
set(OPENSSL_LIBRARIES ${SSL_EAY} ${LIB_EAY})
|
||||
endif(MSVC)
|
||||
else (WIN32 AND NOT CYGWIN)
|
||||
find_library(OPENSSL_SSL_LIBRARIES
|
||||
NAMES
|
||||
ssl
|
||||
ssleay32
|
||||
ssleay32MD
|
||||
PATHS
|
||||
${_OPENSSL_LIBDIR}
|
||||
/opt/local/lib
|
||||
/sw/lib
|
||||
/usr/sfw/lib/64
|
||||
/usr/sfw/lib
|
||||
)
|
||||
|
||||
find_library(OPENSSL_CRYPTO_LIBRARIES
|
||||
NAMES
|
||||
crypto
|
||||
PATHS
|
||||
${_OPENSSL_LIBDIR}
|
||||
/opt/local/lib
|
||||
/sw/lib
|
||||
/usr/sfw/lib/64
|
||||
/usr/sfw/lib
|
||||
)
|
||||
|
||||
mark_as_advanced(OPENSSL_CRYPTO_LIBRARIES OPENSSL_SSL_LIBRARIES)
|
||||
set(OPENSSL_LIBRARIES ${OPENSSL_SSL_LIBRARIES} ${OPENSSL_CRYPTO_LIBRARIES})
|
||||
endif (WIN32 AND NOT CYGWIN)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(OpenSSL DEFAULT_MSG OPENSSL_LIBRARIES OPENSSL_INCLUDE_DIRS)
|
||||
|
||||
endif (OPENSSL_LIBRARIES AND OPENSSL_INCLUDE_DIRS)
|
||||
119
cmake/Modules/FindZLIB.cmake
Normal file
@@ -0,0 +1,119 @@
|
||||
# - Try to find ZLIB
|
||||
# Once done this will define
|
||||
#
|
||||
# ZLIB_ROOT_DIR - Set this variable to the root installation of ZLIB
|
||||
#
|
||||
# Read-Only variables:
|
||||
# ZLIB_FOUND - system has ZLIB
|
||||
# ZLIB_INCLUDE_DIRS - the ZLIB include directory
|
||||
# ZLIB_LIBRARIES - Link these to use ZLIB
|
||||
#
|
||||
# ZLIB_VERSION_STRING - The version of zlib found (x.y.z)
|
||||
# ZLIB_VERSION_MAJOR - The major version of zlib
|
||||
# ZLIB_VERSION_MINOR - The minor version of zlib
|
||||
# ZLIB_VERSION_PATCH - The patch version of zlib
|
||||
# ZLIB_VERSION_TWEAK - The tweak version of zlib
|
||||
#
|
||||
# The following variable are provided for backward compatibility
|
||||
#
|
||||
# ZLIB_MAJOR_VERSION - The major version of zlib
|
||||
# ZLIB_MINOR_VERSION - The minor version of zlib
|
||||
# ZLIB_PATCH_VERSION - The patch version of zlib
|
||||
#
|
||||
#=============================================================================
|
||||
# Copyright (c) 2001-2009 Kitware, Inc.
|
||||
# Copyright (c) 2011 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 (ZLIB_LIBRARIES AND ZLIB_INCLUDE_DIRS)
|
||||
# in cache already
|
||||
set(ZLIB_FOUND TRUE)
|
||||
else (ZLIB_LIBRARIES AND ZLIB_INCLUDE_DIRS)
|
||||
|
||||
set(_ZLIB_ROOT_HINTS
|
||||
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\GnuWin32\\Zlib;InstallPath]/include"
|
||||
)
|
||||
|
||||
set(_ZLIB_ROOT_PATHS
|
||||
"$ENV{PROGRAMFILES}/zlib"
|
||||
)
|
||||
|
||||
find_path(ZLIB_ROOT_DIR
|
||||
NAMES
|
||||
include/zlib.h
|
||||
HINTS
|
||||
${_ZLIB_ROOT_HINTS}
|
||||
PATHS
|
||||
${_ZLIB_ROOT_PATHS}
|
||||
)
|
||||
mark_as_advanced(ZLIB_ROOT_DIR)
|
||||
|
||||
# check for header file
|
||||
find_path(ZLIB_INCLUDE_DIR
|
||||
NAMES
|
||||
zlib.h
|
||||
PATHS
|
||||
/usr/local/include
|
||||
/opt/local/include
|
||||
/sw/include
|
||||
/usr/lib/sfw/include
|
||||
${ZLIB_ROOT_DIR}/include
|
||||
)
|
||||
mark_as_advanced(ZLIB_INCLUDE_DIR)
|
||||
|
||||
# check version number
|
||||
if (ZLIB_INCLUDE_DIR AND EXISTS "${ZLIB_INCLUDE_DIR}/zlib.h")
|
||||
file(STRINGS "${ZLIB_INCLUDE_DIR}/zlib.h" ZLIB_H REGEX "^#define ZLIB_VERSION \"[^\"]*\"$")
|
||||
|
||||
string(REGEX REPLACE "^.*ZLIB_VERSION \"([0-9]+).*$" "\\1" ZLIB_VERSION_MAJOR "${ZLIB_H}")
|
||||
string(REGEX REPLACE "^.*ZLIB_VERSION \"[0-9]+\\.([0-9]+).*$" "\\1" ZLIB_VERSION_MINOR "${ZLIB_H}")
|
||||
string(REGEX REPLACE "^.*ZLIB_VERSION \"[0-9]+\\.[0-9]+\\.([0-9]+).*$" "\\1" ZLIB_VERSION_PATCH "${ZLIB_H}")
|
||||
|
||||
set(ZLIB_VERSION_STRING "${ZLIB_VERSION_MAJOR}.${ZLIB_VERSION_MINOR}.${ZLIB_VERSION_PATCH}")
|
||||
|
||||
# only append a TWEAK version if it exists:
|
||||
set(ZLIB_VERSION_TWEAK "")
|
||||
if ("${ZLIB_H}" MATCHES "^.*ZLIB_VERSION \"[0-9]+\\.[0-9]+\\.[0-9]+\\.([0-9]+).*$")
|
||||
set(ZLIB_VERSION_TWEAK "${CMAKE_MATCH_1}")
|
||||
set(ZLIB_VERSION_STRING "${ZLIB_VERSION_STRING}.${ZLIB_VERSION_TWEAK}")
|
||||
endif ("${ZLIB_H}" MATCHES "^.*ZLIB_VERSION \"[0-9]+\\.[0-9]+\\.[0-9]+\\.([0-9]+).*$")
|
||||
|
||||
set(ZLIB_MAJOR_VERSION "${ZLIB_VERSION_MAJOR}")
|
||||
set(ZLIB_MINOR_VERSION "${ZLIB_VERSION_MINOR}")
|
||||
set(ZLIB_PATCH_VERSION "${ZLIB_VERSION_PATCH}")
|
||||
endif (ZLIB_INCLUDE_DIR AND EXISTS "${ZLIB_INCLUDE_DIR}/zlib.h")
|
||||
|
||||
find_library(ZLIB_LIBRARY
|
||||
NAMES
|
||||
z
|
||||
zdll
|
||||
zlib
|
||||
zlib1
|
||||
PATHS
|
||||
/usr/local/lib
|
||||
/opt/local/lib
|
||||
/sw/lib
|
||||
/usr/sfw/lib/64
|
||||
/usr/sfw/lib
|
||||
${ZLIB_ROOT_DIR}/lib
|
||||
)
|
||||
mark_as_advanced(ZLIB_LIBRARY)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(ZLIB DEFAULT_MSG ZLIB_INCLUDE_DIR ZLIB_LIBRARY)
|
||||
#find_package_handle_standard_args(ZLIB REQUIRED_VARS ZLIB_INCLUDE_DIR ZLIB_LIBRARY
|
||||
# VERSION_VAR ZLIB_VERSION_STRING)
|
||||
|
||||
if (ZLIB_FOUND)
|
||||
set(ZLIB_INCLUDE_DIRS ${ZLIB_INCLUDE_DIR})
|
||||
set(ZLIB_LIBRARIES ${ZLIB_LIBRARY})
|
||||
endif (ZLIB_FOUND)
|
||||
endif (ZLIB_LIBRARIES AND ZLIB_INCLUDE_DIRS)
|
||||
@@ -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)
|
||||
@@ -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()
|
||||
@@ -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}")
|
||||
21
cmake/Modules/MacroAddCompileFlags.cmake
Normal 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)
|
||||
20
cmake/Modules/MacroAddLinkFlags.cmake
Normal 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)
|
||||
30
cmake/Modules/MacroAddPlugin.cmake
Normal 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)
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
# - 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.
|
||||
#
|
||||
# This actually calls the check_c_source_compiles macro.
|
||||
# See help for CheckCSourceCompiles for a listing of variables
|
||||
# that can modify the build.
|
||||
|
||||
@@ -15,15 +14,13 @@
|
||||
# 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}")
|
||||
INCLUDE(CheckCSourceCompiles)
|
||||
|
||||
check_c_source_compiles("int main(int argc, char **argv) { char buffer[256]; return buffer[argc]=0;}" ${_RESULT})
|
||||
MACRO (CHECK_C_COMPILER_FLAG_SSP _FLAG _RESULT)
|
||||
SET(SAFE_CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS}")
|
||||
SET(CMAKE_REQUIRED_DEFINITIONS "${_FLAG}")
|
||||
CHECK_C_SOURCE_COMPILES("int main(int argc, char **argv) { char buffer[256]; return buffer[argc]=0;}" ${_RESULT})
|
||||
SET (CMAKE_REQUIRED_DEFINITIONS "${SAFE_CMAKE_REQUIRED_DEFINITIONS}")
|
||||
ENDMACRO (CHECK_C_COMPILER_FLAG_SSP)
|
||||
|
||||
set(CMAKE_REQUIRED_FLAGS "${SAFE_CMAKE_REQUIRED_FLAGS}")
|
||||
endmacro(CHECK_C_COMPILER_FLAG_SSP)
|
||||
33
cmake/Modules/MacroCopyFile.cmake
Normal 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)
|
||||
100
cmake/Modules/UseDoxygen.cmake
Normal file
@@ -0,0 +1,100 @@
|
||||
# - Run Doxygen
|
||||
#
|
||||
# Adds a doxygen target that runs doxygen to generate the html
|
||||
# and optionally the LaTeX API documentation.
|
||||
# The doxygen target is added to the doc target as dependency.
|
||||
# i.e.: the API documentation is built with:
|
||||
# make doc
|
||||
#
|
||||
# USAGE: INCLUDE IN PROJECT
|
||||
#
|
||||
# set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
# include(UseDoxygen)
|
||||
# Add the Doxyfile.in and UseDoxygen.cmake files to the projects source directory.
|
||||
#
|
||||
#
|
||||
# Variables you may define are:
|
||||
# DOXYFILE_OUTPUT_DIR - Path where the Doxygen output is stored. Defaults to "doc".
|
||||
#
|
||||
# DOXYFILE_LATEX_DIR - Directory where the Doxygen LaTeX output is stored. Defaults to "latex".
|
||||
#
|
||||
# DOXYFILE_HTML_DIR - Directory where the Doxygen html output is stored. Defaults to "html".
|
||||
#
|
||||
|
||||
#
|
||||
# Copyright (c) 2009-2010 Tobias Rautenkranz <tobias@rautenkranz.ch>
|
||||
# Copyright (c) 2010 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.
|
||||
#
|
||||
|
||||
macro(usedoxygen_set_default name value)
|
||||
if(NOT DEFINED "${name}")
|
||||
set("${name}" "${value}")
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
find_package(Doxygen)
|
||||
|
||||
if(DOXYGEN_FOUND)
|
||||
find_file(DOXYFILE_IN
|
||||
NAMES
|
||||
doxy.config.in
|
||||
PATHS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${CMAKE_ROOT}/Modules/
|
||||
NO_DEFAULT_PATH)
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(DOXYFILE_IN DEFAULT_MSG "DOXYFILE_IN")
|
||||
endif()
|
||||
|
||||
if(DOXYGEN_FOUND AND DOXYFILE_IN_FOUND)
|
||||
add_custom_target(doxygen ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/doxy.config)
|
||||
|
||||
usedoxygen_set_default(DOXYFILE_OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}")
|
||||
usedoxygen_set_default(DOXYFILE_HTML_DIR "html")
|
||||
|
||||
set_property(DIRECTORY APPEND PROPERTY
|
||||
ADDITIONAL_MAKE_CLEAN_FILES "${DOXYFILE_OUTPUT_DIR}/${DOXYFILE_HTML_DIR}")
|
||||
|
||||
set(DOXYFILE_LATEX FALSE)
|
||||
set(DOXYFILE_PDFLATEX FALSE)
|
||||
set(DOXYFILE_DOT FALSE)
|
||||
|
||||
find_package(LATEX)
|
||||
if(LATEX_COMPILER AND MAKEINDEX_COMPILER)
|
||||
set(DOXYFILE_LATEX TRUE)
|
||||
usedoxygen_set_default(DOXYFILE_LATEX_DIR "latex")
|
||||
|
||||
set_property(DIRECTORY APPEND PROPERTY
|
||||
ADDITIONAL_MAKE_CLEAN_FILES
|
||||
"${DOXYFILE_OUTPUT_DIR}/${DOXYFILE_LATEX_DIR}")
|
||||
|
||||
if(PDFLATEX_COMPILER)
|
||||
set(DOXYFILE_PDFLATEX TRUE)
|
||||
endif()
|
||||
if(DOXYGEN_DOT_EXECUTABLE)
|
||||
set(DOXYFILE_DOT TRUE)
|
||||
endif()
|
||||
|
||||
add_custom_command(TARGET doxygen
|
||||
POST_BUILD
|
||||
COMMAND ${CMAKE_MAKE_PROGRAM}
|
||||
WORKING_DIRECTORY "${DOXYFILE_OUTPUT_DIR}/${DOXYFILE_LATEX_DIR}")
|
||||
endif()
|
||||
|
||||
configure_file(${DOXYFILE_IN} ${CMAKE_CURRENT_BINARY_DIR}/doxy.config ESCAPE_QUOTES IMMEDIATE @ONLY)
|
||||
if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/doxy.trac.in)
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/doxy.trac.in ${CMAKE_CURRENT_BINARY_DIR}/doxy.trac ESCAPE_QUOTES IMMEDIATE @ONLY)
|
||||
add_custom_target(doxygen-trac ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/doxy.trac)
|
||||
endif()
|
||||
|
||||
get_target_property(DOC_TARGET doc TYPE)
|
||||
if(NOT DOC_TARGET)
|
||||
add_custom_target(doc)
|
||||
endif()
|
||||
|
||||
add_dependencies(doc doxygen)
|
||||
endif()
|
||||
@@ -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()
|
||||
185
config.h.cmake
@@ -1,63 +1,28 @@
|
||||
/* 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 GLOBAL_BIND_CONFIG "${GLOBAL_BIND_CONFIG}"
|
||||
|
||||
/* Global client configuration file path */
|
||||
#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 <openssl/aes.h> header file. */
|
||||
#cmakedefine HAVE_OPENSSL_AES_H 1
|
||||
|
||||
@@ -70,65 +35,12 @@
|
||||
/* 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 eliptic curve cryptography in openssl */
|
||||
#cmakedefine HAVE_OPENSSL_ECC 1
|
||||
|
||||
/* Define to 1 if you have eliptic curve cryptography in gcrypt */
|
||||
#cmakedefine HAVE_GCRYPT_ECC 1
|
||||
|
||||
/* Define to 1 if you have eliptic curve cryptography */
|
||||
#cmakedefine HAVE_ECC 1
|
||||
|
||||
/* Define to 1 if you have DSA */
|
||||
#cmakedefine HAVE_DSA 1
|
||||
|
||||
/* Define to 1 if you have gl_flags as a glob_t sturct member */
|
||||
#cmakedefine HAVE_GLOB_GL_FLAGS_MEMBER 1
|
||||
|
||||
/* Define to 1 if you have OpenSSL with Ed25519 support */
|
||||
#cmakedefine HAVE_OPENSSL_ED25519 1
|
||||
|
||||
/* Define to 1 if you have OpenSSL with X25519 support */
|
||||
#cmakedefine HAVE_OPENSSL_X25519 1
|
||||
|
||||
/* Define to 1 if you have OpenSSL with Poly1305 support */
|
||||
#cmakedefine HAVE_OPENSSL_EVP_POLY1305 1
|
||||
|
||||
/* Define to 1 if you have gcrypt with ChaCha20/Poly1305 support */
|
||||
#cmakedefine HAVE_GCRYPT_CHACHA_POLY 1
|
||||
|
||||
/*************************** FUNCTIONS ***************************/
|
||||
|
||||
/* Define to 1 if you have the `EVP_chacha20' function. */
|
||||
#cmakedefine HAVE_OPENSSL_EVP_CHACHA20 1
|
||||
|
||||
/* Define to 1 if you have the `EVP_KDF_CTX_new_id' or `EVP_KDF_CTX_new` function. */
|
||||
#cmakedefine HAVE_OPENSSL_EVP_KDF_CTX 1
|
||||
|
||||
/* Define to 1 if you have the `FIPS_mode' function. */
|
||||
#cmakedefine HAVE_OPENSSL_FIPS_MODE 1
|
||||
|
||||
/* Define to 1 if you have the `EVP_DigestSign' function. */
|
||||
#cmakedefine HAVE_OPENSSL_EVP_DIGESTSIGN 1
|
||||
|
||||
/* Define to 1 if you have the `EVP_DigestVerify' function. */
|
||||
#cmakedefine HAVE_OPENSSL_EVP_DIGESTVERIFY 1
|
||||
|
||||
/* Define to 1 if you have the `OPENSSL_ia32cap_loc' function. */
|
||||
#cmakedefine HAVE_OPENSSL_IA32CAP_LOC 1
|
||||
|
||||
/* Define to 1 if you have the `snprintf' function. */
|
||||
#cmakedefine HAVE_SNPRINTF 1
|
||||
|
||||
@@ -147,15 +59,9 @@
|
||||
/* 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
|
||||
|
||||
@@ -168,39 +74,15 @@
|
||||
/* Define to 1 if you have the `select' function. */
|
||||
#cmakedefine HAVE_SELECT 1
|
||||
|
||||
/* Define to 1 if you have the `regcomp' function. */
|
||||
#cmakedefine HAVE_REGCOMP 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
|
||||
|
||||
/*************************** LIBRARIES ***************************/
|
||||
|
||||
/* Define to 1 if you have the `crypto' library (-lcrypto). */
|
||||
@@ -209,73 +91,36 @@
|
||||
/* 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 `z' library (-lz). */
|
||||
#cmakedefine HAVE_LIBZ 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
|
||||
|
||||
/**************************** 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 */
|
||||
#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 none cipher and MAC */
|
||||
#cmakedefine WITH_INSECURE_NONE 1
|
||||
|
||||
/* Define to 1 if you want to enable blowfish cipher support */
|
||||
#cmakedefine WITH_BLOWFISH_CIPHER 1
|
||||
|
||||
/* Define to 1 if you want to enable debug output for crypto functions */
|
||||
#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
|
||||
|
||||
/*************************** ENDIAN *****************************/
|
||||
|
||||
/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
|
||||
|
||||
@@ -1,49 +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_PREDEFINED DOXYGEN
|
||||
WITH_SERVER
|
||||
WITH_SFTP
|
||||
PRINTF_ATTRIBUTE(x,y))
|
||||
|
||||
set(DOXYGEN_EXCLUDE ${CMAKE_CURRENT_SOURCE_DIR}/that_style)
|
||||
set(DOXYGEN_HTML_HEADER ${CMAKE_CURRENT_SOURCE_DIR}/that_style/header.html)
|
||||
set(DOXYGEN_HTML_EXTRA_STYLESHEET ${CMAKE_CURRENT_SOURCE_DIR}/that_style/that_style.css)
|
||||
set(DOXYGEN_HTML_EXTRA_FILES ${CMAKE_CURRENT_SOURCE_DIR}/that_style/img/nav_edge_left.svg
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/that_style/img/nav_edge_right.svg
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/that_style/img/nav_edge_inter.svg
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/that_style/img/sync_off.png
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/that_style/img/sync_on.png
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/that_style/img/splitbar_handle.svg
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/that_style/img/doc.svg
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/that_style/img/mag_glass.svg
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/that_style/img/folderclosed.svg
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/that_style/img/folderopen.svg
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/that_style/js/striped_bg.js)
|
||||
|
||||
# This updates the Doxyfile if we do changes here
|
||||
set(_doxyfile_template "${CMAKE_BINARY_DIR}/CMakeDoxyfile.in")
|
||||
set(_target_doxyfile "${CMAKE_CURRENT_BINARY_DIR}/Doxyfile.docs")
|
||||
configure_file("${_doxyfile_template}" "${_target_doxyfile}")
|
||||
|
||||
doxygen_add_docs(docs
|
||||
${CMAKE_SOURCE_DIR}/include/libssh
|
||||
${CMAKE_SOURCE_DIR}/src
|
||||
${CMAKE_CURRENT_SOURCE_DIR})
|
||||
endif() # DOXYGEN_FOUND
|
||||
|
||||
endif() # CMAKE_VERSION
|
||||
|
||||
@@ -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
|
||||
```
|
||||
1
doc/TracFooter.html
Normal file
@@ -0,0 +1 @@
|
||||
<!-- Doxygen TracFooter -->
|
||||
4
doc/TracHeader.html
Normal file
@@ -0,0 +1,4 @@
|
||||
<!-- Doxygen TracHeader -->
|
||||
<style>@import url(/chrome/site/doxygen.css);</style>
|
||||
<style>@import url(/chrome/site/tabs.css);</style>
|
||||
<!-- /Doxygen TracHeader -->
|
||||
@@ -21,7 +21,7 @@ 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
|
||||
@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
|
||||
@@ -33,9 +33,6 @@ The process of authenticating by public key to a server is the following:
|
||||
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:
|
||||
@@ -43,21 +40,22 @@ The function ssh_userauth_autopubkey() does this using the available keys in
|
||||
- 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).
|
||||
mean of authentication (like a password).
|
||||
|
||||
The ssh_userauth_publickey_auto() function also tries to authenticate using the
|
||||
The ssh_userauth_autopubkey() 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().
|
||||
- Retrieve the public key in a ssh_string using publickey_from_file().
|
||||
- Offer the public key to the SSH server using ssh_userauth_offer_pubkey().
|
||||
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().
|
||||
- Retrieve the private key, using the privatekey_from_file() function. If
|
||||
a passphrase is needed, either the passphrase specified as argument or
|
||||
a callback (see callbacks section) will be used.
|
||||
- Authenticate using ssh_userauth_pubkey() with your public key string
|
||||
and private key.
|
||||
- Do not forget cleaning up memory using string_free() and privatekey_free().
|
||||
|
||||
Here is a minimalistic example of public key authentication:
|
||||
|
||||
@@ -66,7 +64,7 @@ int authenticate_pubkey(ssh_session session)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = ssh_userauth_publickey_auto(session, NULL, NULL);
|
||||
rc = ssh_userauth_autopubkey(session, NULL);
|
||||
|
||||
if (rc == SSH_AUTH_ERROR)
|
||||
{
|
||||
@@ -79,12 +77,14 @@ int authenticate_pubkey(ssh_session session)
|
||||
}
|
||||
@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()
|
||||
@see ssh_userauth_autopubkey
|
||||
@see ssh_userauth_offer_pubkey
|
||||
@see ssh_userauth_pubkey
|
||||
@see publickey_from_file
|
||||
@see publickey_from_privatekey
|
||||
@see string_free
|
||||
@see privatekey_from_file
|
||||
@see privatekey_free
|
||||
|
||||
|
||||
@subsection password Authenticating with a password
|
||||
@@ -130,7 +130,7 @@ The keyboard-interactive method is, as its name tells, interactive. The
|
||||
server will issue one or more challenges that the user has to answer,
|
||||
until the server takes an authentication decision.
|
||||
|
||||
ssh_userauth_kbdint() is the the main keyboard-interactive function.
|
||||
ssh_userauth_kbdint() is the the main keyboard-interactive function.
|
||||
It will return SSH_AUTH_SUCCESS,SSH_AUTH_DENIED, SSH_AUTH_PARTIAL,
|
||||
SSH_AUTH_ERROR, or SSH_AUTH_INFO, depending on the result of the request.
|
||||
|
||||
@@ -157,9 +157,9 @@ 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
|
||||
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.
|
||||
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.
|
||||
|
||||
@@ -167,13 +167,13 @@ 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
|
||||
@@ -184,18 +184,18 @@ keyboard-interactive authentication, coming from the RFC itself (rfc4256):
|
||||
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.
|
||||
|
||||
indication that such truncation has occured.
|
||||
|
||||
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
|
||||
@@ -265,10 +265,10 @@ int authenticate_kbdint(ssh_session session)
|
||||
@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_getnprompts
|
||||
@see ssh_userauth_kbdint_getname
|
||||
@see ssh_userauth_kbdint_getinstruction
|
||||
@see ssh_userauth_kbdint_getprompt
|
||||
@see ssh_userauth_kbdint_setanswer()
|
||||
|
||||
|
||||
@@ -284,11 +284,11 @@ 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 authenticate_kbdint(ssh_session session)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = ssh_userauth_none(session, NULL);
|
||||
rc = ssh_userauth_none(session, NULL, NULL);
|
||||
return rc;
|
||||
}
|
||||
@endcode
|
||||
@@ -307,11 +307,6 @@ 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)
|
||||
|
||||
@@ -56,7 +56,7 @@ If an error has been encountered, it returns a negative value:
|
||||
|
||||
@code
|
||||
char buffer[256];
|
||||
int nbytes;
|
||||
unsigned int nbytes;
|
||||
|
||||
nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
|
||||
while (nbytes > 0)
|
||||
|
||||
@@ -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 methode 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 softwares, 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 recommanded 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
|
||||
1546
doc/doxy.config.in
Normal file
1546
doc/doxy.trac.in
Normal file
@@ -4,7 +4,7 @@
|
||||
|
||||
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
|
||||
named local port forwardind, and reverse port forwarding is also called
|
||||
remote port forwarding. SSH also allows X11 tunnels.
|
||||
|
||||
|
||||
@@ -23,15 +23,15 @@ Mail client application Google Mail
|
||||
5555 (arbitrary) |
|
||||
| 143 (IMAP2)
|
||||
V |
|
||||
SSH client =====> SSH server
|
||||
SSH client =====> SSH server
|
||||
|
||||
Legend:
|
||||
--P-->: port connections through port P
|
||||
--P-->: port connexion 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.
|
||||
end point). Now the local mail client can retreive mail.
|
||||
|
||||
|
||||
@subsection forwarding_reverse Reverse port forwarding
|
||||
@@ -51,7 +51,7 @@ Example of use of reverse port forwarding:
|
||||
SSH client <===== SSH server
|
||||
|
||||
Legend:
|
||||
--P-->: port connections through port P
|
||||
--P-->: port connexion through port P
|
||||
=====>: SSH tunnel
|
||||
@endverbatim
|
||||
In this example, the SSH client establishes the tunnel,
|
||||
@@ -85,7 +85,7 @@ this tutorial.
|
||||
|
||||
@subsection libssh_direct Doing direct port forwarding with libssh
|
||||
|
||||
To do direct port forwarding, call function ssh_channel_open_forward():
|
||||
To do direct port forwarding, call function 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
|
||||
@@ -101,18 +101,16 @@ used to retrieve google's home page from the remote SSH server.
|
||||
int direct_forwarding(ssh_session session)
|
||||
{
|
||||
ssh_channel forwarding_channel;
|
||||
int rc = SSH_ERROR;
|
||||
int rc;
|
||||
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;
|
||||
}
|
||||
if (rc != SSH_OK) return rc;
|
||||
|
||||
rc = ssh_channel_open_forward(forwarding_channel,
|
||||
"www.google.com", 80,
|
||||
"localhost", 5555);
|
||||
rc = channel_open_forward(forwarding_channel,
|
||||
"www.google.com", 80,
|
||||
"localhost", 5555);
|
||||
if (rc != SSH_OK)
|
||||
{
|
||||
ssh_channel_free(forwarding_channel);
|
||||
@@ -120,9 +118,7 @@ int direct_forwarding(ssh_session session)
|
||||
}
|
||||
|
||||
nbytes = strlen(http_get);
|
||||
nwritten = ssh_channel_write(forwarding_channel,
|
||||
http_get,
|
||||
nbytes);
|
||||
nwritten = channel_write(forwarding_channel, http_get, nbytes);
|
||||
if (nbytes != nwritten)
|
||||
{
|
||||
ssh_channel_free(forwarding_channel);
|
||||
@@ -144,13 +140,13 @@ 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().
|
||||
To do reverse port forwarding, call ssh_channel_forward_listen(),
|
||||
then ssh_channel_forward_accept().
|
||||
|
||||
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
|
||||
When you call ssh_channel_forward_listen(), you can let the remote server
|
||||
chose the non-priviledged port it should listen to. Otherwise, you can chose
|
||||
your own priviledged or non-priviledged port. Beware that you should have
|
||||
administrative priviledges on the remote server to open a priviledged port
|
||||
(port number < 1024).
|
||||
|
||||
Below is an example of a very rough web server waiting for connections on port
|
||||
@@ -164,9 +160,6 @@ int web_server(ssh_session session)
|
||||
ssh_channel channel;
|
||||
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"
|
||||
@@ -181,20 +174,17 @@ int web_server(ssh_session session)
|
||||
" </body>\n"
|
||||
"</html>\n";
|
||||
|
||||
rc = ssh_channel_listen_forward(session, NULL, 8080, NULL);
|
||||
rc = ssh_channel_forward_listen(session, NULL, 8080, NULL);
|
||||
if (rc != SSH_OK)
|
||||
{
|
||||
fprintf(stderr, "Error opening remote port: %s\n",
|
||||
ssh_get_error(session));
|
||||
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);
|
||||
channel = ssh_channel_forward_accept(session, 60000);
|
||||
if (channel == NULL)
|
||||
{
|
||||
fprintf(stderr, "Error waiting for incoming connection: %s\n",
|
||||
ssh_get_error(session));
|
||||
fprintf(stderr, "Error waiting for incoming connection: %s\n", ssh_get_error(session));
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
@@ -203,11 +193,9 @@ int web_server(ssh_session session)
|
||||
nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
|
||||
if (nbytes < 0)
|
||||
{
|
||||
fprintf(stderr, "Error reading incoming data: %s\n",
|
||||
ssh_get_error(session));
|
||||
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;
|
||||
@@ -216,19 +204,16 @@ int web_server(ssh_session session)
|
||||
nwritten = ssh_channel_write(channel, helloworld, nbytes);
|
||||
if (nwritten != nbytes)
|
||||
{
|
||||
fprintf(stderr, "Error sending answer: %s\n",
|
||||
ssh_get_error(session));
|
||||
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);
|
||||
printf("Sent answer\n");
|
||||
}
|
||||
|
||||
ssh_channel_send_eof(channel);
|
||||
ssh_channel_free(channel);
|
||||
ssh_string_free_char(peer_address);
|
||||
return SSH_OK;
|
||||
}
|
||||
@endcode
|
||||
|
||||
@@ -31,20 +31,20 @@ A SSH session goes through the following steps:
|
||||
- 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.
|
||||
- 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.
|
||||
always verify that the allocation successed.
|
||||
@code
|
||||
#include <libssh/libssh.h>
|
||||
#include <libssh/libssh.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int main()
|
||||
@@ -69,12 +69,12 @@ The ssh_options_set() function sets the options of the session. The most importa
|
||||
|
||||
The complete list of options can be found in the documentation of ssh_options_set().
|
||||
The only mandatory option is SSH_OPTIONS_HOST. If you don't use SSH_OPTIONS_USER,
|
||||
the local username of your account will be used.
|
||||
the local username of your account will be used.
|
||||
|
||||
Here is a small example of how to use it:
|
||||
|
||||
@code
|
||||
#include <libssh/libssh.h>
|
||||
#include <libssh/libssh.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int main()
|
||||
@@ -122,7 +122,7 @@ Here's an example:
|
||||
@code
|
||||
#include <libssh/libssh.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
@@ -158,7 +158,7 @@ you just connected to is known and safe to use (remember, SSH is about security
|
||||
authentication).
|
||||
|
||||
There are two ways of doing this:
|
||||
- The first way (recommended) is to use the ssh_session_is_known_server()
|
||||
- The first way (recommended) is to use the ssh_is_server_known()
|
||||
function. This function will look into the known host file
|
||||
(~/.ssh/known_hosts on UNIX), look for the server hostname's pattern,
|
||||
and determine whether this host is present or not in the list.
|
||||
@@ -185,89 +185,74 @@ examples/ directory:
|
||||
|
||||
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;
|
||||
char *p;
|
||||
int cmp;
|
||||
int rc;
|
||||
int state, hlen;
|
||||
unsigned char *hash = NULL;
|
||||
char *hexa;
|
||||
char buf[10];
|
||||
|
||||
rc = ssh_get_server_publickey(session, &srv_pubkey);
|
||||
if (rc < 0) {
|
||||
state = ssh_is_server_known(session);
|
||||
|
||||
hlen = ssh_get_pubkey_hash(session, &hash);
|
||||
if (hlen < 0)
|
||||
return -1;
|
||||
|
||||
switch (state)
|
||||
{
|
||||
case SSH_SERVER_KNOWN_OK:
|
||||
break; /* ok */
|
||||
|
||||
case SSH_SERVER_KNOWN_CHANGED:
|
||||
fprintf(stderr, "Host key for server changed: it is now:\n");
|
||||
ssh_print_hexa("Public key hash", hash, hlen);
|
||||
fprintf(stderr, "For security reasons, connection will be stopped\n");
|
||||
free(hash);
|
||||
return -1;
|
||||
|
||||
case SSH_SERVER_FOUND_OTHER:
|
||||
fprintf(stderr, "The host key for this server was not found but an other"
|
||||
"type of key exists.\n");
|
||||
fprintf(stderr, "An attacker might change the default server key to"
|
||||
"confuse your client into thinking the key does not exist\n");
|
||||
free(hash);
|
||||
return -1;
|
||||
|
||||
case SSH_SERVER_FILE_NOT_FOUND:
|
||||
fprintf(stderr, "Could not find known host file.\n");
|
||||
fprintf(stderr, "If you accept the host key here, the file will be"
|
||||
"automatically created.\n");
|
||||
/* fallback to SSH_SERVER_NOT_KNOWN behavior */
|
||||
|
||||
case SSH_SERVER_NOT_KNOWN:
|
||||
hexa = ssh_get_hexa(hash, hlen);
|
||||
fprintf(stderr,"The server is unknown. Do you trust the host key?\n");
|
||||
fprintf(stderr, "Public key hash: %s\n", hexa);
|
||||
free(hexa);
|
||||
if (fgets(buf, sizeof(buf), stdin) == NULL)
|
||||
{
|
||||
free(hash);
|
||||
return -1;
|
||||
}
|
||||
|
||||
rc = ssh_get_publickey_hash(srv_pubkey,
|
||||
SSH_PUBLICKEY_HASH_SHA1,
|
||||
&hash,
|
||||
&hlen);
|
||||
ssh_key_free(srv_pubkey);
|
||||
if (rc < 0) {
|
||||
}
|
||||
if (strncasecmp(buf, "yes", 3) != 0)
|
||||
{
|
||||
free(hash);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (ssh_write_knownhost(session) < 0)
|
||||
{
|
||||
fprintf(stderr, "Error %s\n", strerror(errno));
|
||||
free(hash);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
state = ssh_session_is_known_server(session);
|
||||
switch (state) {
|
||||
case SSH_KNOWN_HOSTS_OK:
|
||||
/* OK */
|
||||
case SSH_SERVER_ERROR:
|
||||
fprintf(stderr, "Error %s", ssh_get_error(session));
|
||||
free(hash);
|
||||
return -1;
|
||||
}
|
||||
|
||||
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;
|
||||
free(hash);
|
||||
return 0;
|
||||
}
|
||||
@endcode
|
||||
|
||||
@@ -275,19 +260,18 @@ int verify_knownhost(ssh_session session)
|
||||
@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
|
||||
@see ssh_get_pubkey_hash
|
||||
@see ssh_is_server_known
|
||||
@see ssh_write_knownhost
|
||||
|
||||
|
||||
@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
|
||||
the authenticated user the access to ressources. 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.
|
||||
several ressources 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
|
||||
@@ -313,7 +297,7 @@ The example below shows an authentication with password:
|
||||
@code
|
||||
#include <libssh/libssh.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
@@ -338,7 +322,7 @@ int main()
|
||||
}
|
||||
|
||||
// Verify the server's identity
|
||||
// For the source code of verify_knownhost(), check previous example
|
||||
// For the source code of verify_knowhost(), check previous example
|
||||
if (verify_knownhost(my_ssh_session) < 0)
|
||||
{
|
||||
ssh_disconnect(my_ssh_session);
|
||||
@@ -383,7 +367,7 @@ int show_remote_processes(ssh_session session)
|
||||
ssh_channel channel;
|
||||
int rc;
|
||||
char buffer[256];
|
||||
int nbytes;
|
||||
unsigned int nbytes;
|
||||
|
||||
channel = ssh_channel_new(session);
|
||||
if (channel == NULL)
|
||||
@@ -407,7 +391,7 @@ int show_remote_processes(ssh_session session)
|
||||
nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
|
||||
while (nbytes > 0)
|
||||
{
|
||||
if (write(1, buffer, nbytes) != (unsigned int) nbytes)
|
||||
if (write(1, buffer, nbytes) != nbytes)
|
||||
{
|
||||
ssh_channel_close(channel);
|
||||
ssh_channel_free(channel);
|
||||
@@ -415,7 +399,7 @@ int show_remote_processes(ssh_session session)
|
||||
}
|
||||
nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
|
||||
}
|
||||
|
||||
|
||||
if (nbytes < 0)
|
||||
{
|
||||
ssh_channel_close(channel);
|
||||
@@ -431,9 +415,6 @@ int show_remote_processes(ssh_session session)
|
||||
}
|
||||
@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
|
||||
@@ -459,13 +440,14 @@ 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.
|
||||
(generaly 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.
|
||||
ssh_get_error() and ssh_get_error_code() take a ssh_session as a parameter.
|
||||
That's for thread safety, error messages that can be attached to a session
|
||||
aren't static anymore. Any error that happens during ssh_options_xxx()
|
||||
or ssh_connect() (i.e., outside of any session) can be retrieved by
|
||||
giving NULL as argument.
|
||||
|
||||
The SFTP subsystem has its own error codes, in addition to libssh ones.
|
||||
|
||||
|
||||
@@ -12,13 +12,14 @@ 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.
|
||||
"libssh2", which is a completly different and independant project.
|
||||
|
||||
libssh can run on top of either libgcrypt or libcrypto,
|
||||
two general-purpose cryptographic libraries.
|
||||
libssh can run on top of either libgcrypt (http://directory.fsf.org/project/libgcrypt/)
|
||||
or libcrypto (http://www.openssl.org/docs/crypto/crypto.html), two 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),
|
||||
To learn how to accept incoming SSH connexions (how to write a SSH server),
|
||||
you'll have to jump to the end of this document.
|
||||
|
||||
This tutorial describes libssh version 0.5.0. This version is a little different
|
||||
|
||||
@@ -17,17 +17,8 @@ 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!
|
||||
On Windows you need to define LIBSSH_STATIC in the compiler command
|
||||
line. This is required cause the dynamic library needs to specify the
|
||||
dllimport attribute.
|
||||
|
||||
*/
|
||||
|
||||
123
doc/mainpage.dox
@@ -19,29 +19,24 @@ the interesting functions as you go.
|
||||
|
||||
The libssh library provides:
|
||||
|
||||
- <strong>Key Exchange Methods</strong>: <i>curve25519-sha256, curve25519-sha256@libssh.org, ecdh-sha2-nistp256, ecdh-sha2-nistp384, ecdh-sha2-nistp521</i>, diffie-hellman-group1-sha1, diffie-hellman-group14-sha1
|
||||
- <strong>Public Key Algorithms</strong>: ssh-ed25519, ecdsa-sha2-nistp256, ecdsa-sha2-nistp384, ecdsa-sha2-nistp521, ssh-rsa, rsa-sha2-512, rsa-sha2-256,ssh-dss
|
||||
- <strong>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> or <b>gcrypt</b>: 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.
|
||||
- Full C library functions for manipulating a client-side SSH connection
|
||||
- SSH2 and SSH1 protocol compliant
|
||||
- Fully configurable sessions
|
||||
- Server support
|
||||
- SSH agent authentication support
|
||||
- Support for AES-128, AES-192, AES-256, Blowfish, 3DES in CBC mode, and AES in CTR mode
|
||||
- Supports OpenSSL and GCrypt
|
||||
- Use multiple SSH connections in a same process, at same time
|
||||
- Use multiple channels in the same connection
|
||||
- Thread safety when using different sessions at same time
|
||||
- POSIX-like SFTP (Secure File Transfer) implementation with openssh extension support
|
||||
- SCP implementation
|
||||
- Large file system support (files bigger than 4GB)
|
||||
- RSA and DSS server public key supported
|
||||
- Compression support (with zlib)
|
||||
- Public key (RSA and DSS), password and keyboard-interactive authentication
|
||||
- Full poll()/WSAPoll() support and a poll-emulation for Win32.
|
||||
- Runs and tested under x86_64, x86, ARM, Sparc32, PPC under Linux, BSD, MacOSX, Solaris and Windows
|
||||
|
||||
@section main-copyright Copyright Policy
|
||||
|
||||
@@ -111,7 +106,7 @@ By making a contribution to this project, I certify that:
|
||||
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
|
||||
http://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
|
||||
@@ -151,81 +146,45 @@ The libssh Team
|
||||
|
||||
The following RFC documents described SSH-2 protcol as an Internet standard.
|
||||
|
||||
- <a href="https://tools.ietf.org/html/rfc4250" target="_blank">RFC 4250</a>,
|
||||
- <a href="http://tools.ietf.org/html/rfc4250" target="_blank">RFC 4250</a>,
|
||||
The Secure Shell (SSH) Protocol Assigned Numbers
|
||||
- <a href="https://tools.ietf.org/html/rfc4251" target="_blank">RFC 4251</a>,
|
||||
- <a href="http://tools.ietf.org/html/rfc4251" target="_blank">RFC 4251</a>,
|
||||
The Secure Shell (SSH) Protocol Architecture
|
||||
- <a href="https://tools.ietf.org/html/rfc4252" target="_blank">RFC 4252</a>,
|
||||
- <a href="http://tools.ietf.org/html/rfc4252" target="_blank">RFC 4252</a>,
|
||||
The Secure Shell (SSH) Authentication Protocol
|
||||
- <a href="https://tools.ietf.org/html/rfc4253" target="_blank">RFC 4253</a>,
|
||||
- <a href="http://tools.ietf.org/html/rfc4253" target="_blank">RFC 4253</a>,
|
||||
The Secure Shell (SSH) Transport Layer Protocol
|
||||
- <a href="https://tools.ietf.org/html/rfc4254" target="_blank">RFC 4254</a>,
|
||||
- <a href="http://tools.ietf.org/html/rfc4254" target="_blank">RFC 4254</a>,
|
||||
The Secure Shell (SSH) Connection Protocol
|
||||
- <a href="https://tools.ietf.org/html/rfc4255" target="_blank">RFC 4255</a>,
|
||||
- <a href="http://tools.ietf.org/html/rfc4255" target="_blank">RFC 4255</a>,
|
||||
Using DNS to Securely Publish Secure Shell (SSH) Key Fingerprints
|
||||
(not implemented in libssh)
|
||||
- <a href="https://tools.ietf.org/html/rfc4256" target="_blank">RFC 4256</a>,
|
||||
- <a href="http://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>,
|
||||
- <a href="http://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>,
|
||||
- <a href="http://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>,
|
||||
- <a href="http://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>,
|
||||
- <a href="http://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>,
|
||||
- <a href="http://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>,
|
||||
- <a href="http://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>,
|
||||
- <a href="http://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>,
|
||||
- <a href="http://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
|
||||
|
||||
There are also drafts that are being currently developed and followed.
|
||||
|
||||
- <a href="https://tools.ietf.org/html/draft-ietf-curdle-ssh-kex-sha2-10" target="_blank">draft-ietf-curdle-ssh-kex-sha2-10</a>
|
||||
Key Exchange (KEX) Method Updates and Recommendations for Secure Shell (SSH)
|
||||
- <a href="https://tools.ietf.org/html/draft-miller-ssh-agent-03" target="_blank">draft-miller-ssh-agent-03</a>
|
||||
SSH Agent Protocol
|
||||
- <a href="https://tools.ietf.org/html/draft-ietf-curdle-ssh-curves-12" target="_blank">draft-ietf-curdle-ssh-curves-12</a>
|
||||
Secure Shell (SSH) Key Exchange Method using Curve25519 and Curve448
|
||||
|
||||
Interesting cryptography documents:
|
||||
|
||||
- <a href="https://www.cryptsoft.com/pkcs11doc/" target="_blank">PKCS #11</a>, PKCS #11 reference documents, describing interface with smartcards.
|
||||
- <a href="http://www.cryptsoft.com/pkcs11doc/" target="_blank">PKCS #11</a>, PKCS #11 reference documents, describing interface with smartcards.
|
||||
|
||||
@subsection main-rfc-sftp Secure Shell File Transfer Protocol (SFTP)
|
||||
|
||||
@@ -233,7 +192,7 @@ 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">
|
||||
- <a href="http://tools.ietf.org/html/draft-ietf-secsh-filexfer-02" target="_blank">
|
||||
draft-ietf-secsh-filexfer-02.txt</a>,
|
||||
SSH File Transfer Protocol
|
||||
|
||||
@@ -242,13 +201,9 @@ do the same in libssh.
|
||||
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">
|
||||
- <a href="http://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>
|
||||
- <a href="http://api.libssh.org/rfc/PROTOCOL.agent" target="_blank">
|
||||
OpenSSH's ssh-agent</a>
|
||||
|
||||
*/
|
||||
|
||||
@@ -1,67 +0,0 @@
|
||||
/**
|
||||
@page libssh_tutor_pkcs11 Chapter 9: Authentication using PKCS #11 URIs
|
||||
@section how_to How to use PKCS #11 URIs in libssh?
|
||||
|
||||
PKCS #11 is a Cryptographic Token Interface Standard that provides an API
|
||||
to devices like smart cards that store cryptographic private information.
|
||||
Such cryptographic devices are referenced as tokens. A mechanism through which
|
||||
objects stored on the tokens can be uniquely identified is called PKCS #11 URI
|
||||
(Uniform Resource Identifier) and is defined in RFC 7512
|
||||
(https://tools.ietf.org/html/rfc7512).
|
||||
|
||||
Pre-requisites:
|
||||
|
||||
OpenSSL defines an abstract layer called the "engine" to achieve cryptographic
|
||||
acceleration. The engine_pkcs11 module acts like an interface between the PKCS #11
|
||||
modules and the OpenSSL engine.
|
||||
|
||||
To build and use libssh with PKCS #11 support:
|
||||
1. Enable the cmake option: $ cmake -DWITH_PKCS11_URI=ON
|
||||
2. Build with OpenSSL.
|
||||
3. Install and configure engine_pkcs11 (https://github.com/OpenSC/libp11).
|
||||
4. Plug in a working smart card or configure softhsm (https://www.opendnssec.org/softhsm).
|
||||
|
||||
The functions ssh_pki_import_pubkey_file() and ssh_pki_import_privkey_file() that
|
||||
import the public and private keys from files respectively are now modified to support
|
||||
PKCS #11 URIs. These functions automatically detect if the provided filename is a file path
|
||||
or a PKCS #11 URI (when it begins with "pkcs11:"). If a PKCS #11 URI is detected,
|
||||
the engine is loaded and initialized. Through the engine, the private/public key
|
||||
corresponding to the PKCS #11 URI are loaded from the PKCS #11 device.
|
||||
|
||||
If you wish to authenticate using public keys on your own, follow the steps mentioned under
|
||||
"Authentication with public keys" in Chapter 2 - A deeper insight into authentication.
|
||||
|
||||
The function pki_uri_import() is used to populate the public/private ssh_key from the
|
||||
engine with PKCS #11 URIs as the look up.
|
||||
|
||||
Here is a minimalistic example of public key authentication using PKCS #11 URIs:
|
||||
|
||||
@code
|
||||
int authenticate_pkcs11_URI(ssh_session session)
|
||||
{
|
||||
int rc;
|
||||
char priv_uri[1042] = "pkcs11:token=my-token;object=my-object;type=private?pin-value=1234";
|
||||
|
||||
rc = ssh_options_set(session, SSH_OPTIONS_IDENTITY, priv_uri);
|
||||
assert_int_equal(rc, SSH_OK)
|
||||
|
||||
rc = ssh_userauth_publickey_auto(session, NULL, NULL);
|
||||
|
||||
if (rc == SSH_AUTH_ERROR)
|
||||
{
|
||||
fprintf(stderr, "Authentication with PKCS #11 URIs failed: %s\n",
|
||||
ssh_get_error(session));
|
||||
return SSH_AUTH_ERROR;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
@endcode
|
||||
|
||||
@subsection Caveats
|
||||
|
||||
We recommend the users to provide a specific PKCS #11 URI so that it matches only a single slot in the engine.
|
||||
If the engine discovers multiple slots that could potentially contain the private keys referenced
|
||||
by the provided PKCS #11 URI, the engine will not try to authenticate.
|
||||
|
||||
*/
|
||||
37
doc/scp.dox
@@ -2,7 +2,7 @@
|
||||
@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.
|
||||
The SCP subsystem has far less functionnality than the SFTP subsystem.
|
||||
However, if you only need to copy files from and to the remote system,
|
||||
it does its job.
|
||||
|
||||
@@ -39,16 +39,14 @@ int scp_write(ssh_session session)
|
||||
(session, SSH_SCP_WRITE | SSH_SCP_RECURSIVE, ".");
|
||||
if (scp == NULL)
|
||||
{
|
||||
fprintf(stderr, "Error allocating scp session: %s\n",
|
||||
ssh_get_error(session));
|
||||
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));
|
||||
fprintf(stderr, "Error initializing scp session: %s\n", ssh_get_error(session));
|
||||
ssh_scp_free(scp);
|
||||
return rc;
|
||||
}
|
||||
@@ -73,16 +71,14 @@ int scp_read(ssh_session session)
|
||||
(session, SSH_SCP_READ, "helloworld/helloworld.txt");
|
||||
if (scp == NULL)
|
||||
{
|
||||
fprintf(stderr, "Error allocating scp session: %s\n",
|
||||
ssh_get_error(session));
|
||||
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));
|
||||
fprintf(stderr, "Error initializing scp session: %s\n", ssh_get_error(session));
|
||||
ssh_scp_free(scp);
|
||||
return rc;
|
||||
}
|
||||
@@ -123,8 +119,7 @@ int scp_helloworld(ssh_session session, ssh_scp scp)
|
||||
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));
|
||||
fprintf(stderr, "Can't create remote directory: %s\n", ssh_get_error(session));
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -132,16 +127,14 @@ int scp_helloworld(ssh_session session, ssh_scp scp)
|
||||
(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));
|
||||
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));
|
||||
fprintf(stderr, "Can't write to remote file: %s\n", ssh_get_error(session));
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -158,7 +151,7 @@ Let's say you want to copy the following tree of files to the remote site:
|
||||
+-- file1
|
||||
+-- B --+
|
||||
| +-- file2
|
||||
-- A --+
|
||||
-- A --+
|
||||
| +-- file3
|
||||
+-- C --+
|
||||
+-- file4
|
||||
@@ -202,16 +195,14 @@ int scp_receive(ssh_session session, ssh_scp scp)
|
||||
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));
|
||||
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);
|
||||
printf("Receiving file %s, size %d, permisssions 0%o\n", filename, size, mode);
|
||||
free(filename);
|
||||
|
||||
buffer = malloc(size);
|
||||
@@ -225,8 +216,7 @@ int scp_receive(ssh_session session, ssh_scp scp)
|
||||
rc = ssh_scp_read(scp, buffer, size);
|
||||
if (rc == SSH_ERROR)
|
||||
{
|
||||
fprintf(stderr, "Error receiving file data: %s\n",
|
||||
ssh_get_error(session));
|
||||
fprintf(stderr, "Error receiving file data: %s\n", ssh_get_error(session));
|
||||
free(buffer);
|
||||
return rc;
|
||||
}
|
||||
@@ -238,8 +228,7 @@ int scp_receive(ssh_session session, ssh_scp scp)
|
||||
rc = ssh_scp_pull_request(scp);
|
||||
if (rc != SSH_SCP_REQUEST_EOF)
|
||||
{
|
||||
fprintf(stderr, "Unexpected request: %s\n",
|
||||
ssh_get_error(session));
|
||||
fprintf(stderr, "Unexpected request: %s\n", ssh_get_error(session));
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
|
||||
166
doc/sftp.dox
@@ -53,16 +53,14 @@ int sftp_helloworld(ssh_session session)
|
||||
sftp = sftp_new(session);
|
||||
if (sftp == NULL)
|
||||
{
|
||||
fprintf(stderr, "Error allocating SFTP session: %s\n",
|
||||
ssh_get_error(session));
|
||||
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));
|
||||
fprintf(stderr, "Error initializing SFTP session: %s.\n", sftp_get_error(sftp));
|
||||
sftp_free(sftp);
|
||||
return rc;
|
||||
}
|
||||
@@ -100,7 +98,7 @@ Possible errors are:
|
||||
|
||||
@subsection sftp_mkdir Creating a directory
|
||||
|
||||
The function sftp_mkdir() takes the "SFTP session" we just created as
|
||||
The function sftp_mkdir() tahes the "SFTP session" we juste created as
|
||||
its first argument. It also needs the name of the file to create, and the
|
||||
desired permissions. The permissions are the same as for the usual mkdir()
|
||||
function. To get a comprehensive list of the available permissions, use the
|
||||
@@ -123,8 +121,7 @@ int sftp_helloworld(ssh_session session, sftp_session sftp)
|
||||
{
|
||||
if (sftp_get_error(sftp) != SSH_FX_FILE_ALREADY_EXISTS)
|
||||
{
|
||||
fprintf(stderr, "Can't create directory: %s\n",
|
||||
ssh_get_error(session));
|
||||
fprintf(stderr, "Can't create directory: %s\n", ssh_get_error(session));
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
@@ -170,20 +167,17 @@ int sftp_helloworld(ssh_session session, sftp_session sftp)
|
||||
|
||||
...
|
||||
|
||||
file = sftp_open(sftp, "helloworld/helloworld.txt",
|
||||
access_type, S_IRWXU);
|
||||
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));
|
||||
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));
|
||||
fprintf(stderr, "Can't write data to file: %s\n", ssh_get_error(session));
|
||||
sftp_close(file);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
@@ -191,8 +185,7 @@ int sftp_helloworld(ssh_session session, sftp_session sftp)
|
||||
rc = sftp_close(file);
|
||||
if (rc != SSH_OK)
|
||||
{
|
||||
fprintf(stderr, "Can't close the written file: %s\n",
|
||||
ssh_get_error(session));
|
||||
fprintf(stderr, "Can't close the written file: %s\n", ssh_get_error(session));
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -210,63 +203,48 @@ results to come.
|
||||
|
||||
Synchronous read is done with sftp_read().
|
||||
|
||||
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:
|
||||
The following example prints the contents of remote file "/etc/profile". For
|
||||
each 1024 bytes of information read, it waits until the end of the read operation:
|
||||
|
||||
@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;
|
||||
char buffer[1024];
|
||||
int nbytes, rc;
|
||||
|
||||
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;
|
||||
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));
|
||||
nbytes = sftp_read(file, buffer, sizeof(buffer));
|
||||
while (nbytes > 0)
|
||||
{
|
||||
if (write(1, buffer, nbytes) != nbytes)
|
||||
{
|
||||
sftp_close(file);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
nbytes = sftp_read(file, buffer, sizeof(buffer));
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
if (nbytes < 0)
|
||||
{
|
||||
fprintf(stderr, "Error while reading 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 read file: %s\n",
|
||||
ssh_get_error(session));
|
||||
return rc;
|
||||
if (rc != SSH_OK)
|
||||
{
|
||||
fprintf(stderr, "Can't close the read file: %s\n", ssh_get_error(session));
|
||||
return rc;
|
||||
}
|
||||
|
||||
return SSH_OK;
|
||||
@@ -282,28 +260,24 @@ sftp_async_read() waits for the data to come. To open a file in nonblocking mode
|
||||
call sftp_file_set_nonblocking() right after you opened it. Default is blocking mode.
|
||||
|
||||
The example below reads a very big file in asynchronous, nonblocking, mode. Each
|
||||
time the data is not ready yet, a counter is incremented.
|
||||
time the data are not ready yet, a counter is incrementer.
|
||||
|
||||
@code
|
||||
// Good chunk size
|
||||
#define MAX_XFER_BUF_SIZE 16384
|
||||
|
||||
int sftp_read_async(ssh_session session, sftp_session sftp)
|
||||
{
|
||||
int access_type;
|
||||
sftp_file file;
|
||||
char buffer[MAX_XFER_BUF_SIZE];
|
||||
char buffer[1024];
|
||||
int async_request;
|
||||
int nbytes;
|
||||
long counter;
|
||||
int rc;
|
||||
|
||||
access_type = O_RDONLY;
|
||||
file = sftp_open(sftp, "some_very_big_file",
|
||||
access_type, 0);
|
||||
if (file == NULL) {
|
||||
fprintf(stderr, "Can't open file for reading: %s\n",
|
||||
ssh_get_error(session));
|
||||
file = sftp_open(sftp, "some_very_big_file", access_type, 0);
|
||||
if (file == NULL)
|
||||
{
|
||||
fprintf(stderr, "Can't open file for reading: %s\n", ssh_get_error(session));
|
||||
return SSH_ERROR;
|
||||
}
|
||||
sftp_file_set_nonblocking(file);
|
||||
@@ -311,33 +285,26 @@ int sftp_read_async(ssh_session session, sftp_session sftp)
|
||||
async_request = sftp_async_read_begin(file, sizeof(buffer));
|
||||
counter = 0L;
|
||||
usleep(10000);
|
||||
if (async_request >= 0) {
|
||||
nbytes = sftp_async_read(file, buffer, sizeof(buffer),
|
||||
async_request);
|
||||
} else {
|
||||
nbytes = -1;
|
||||
}
|
||||
|
||||
while (nbytes > 0 || nbytes == SSH_AGAIN) {
|
||||
if (nbytes > 0) {
|
||||
if (async_request >= 0)
|
||||
nbytes = sftp_async_read(file, buffer, sizeof(buffer), async_request);
|
||||
else nbytes = -1;
|
||||
while (nbytes > 0 || nbytes == SSH_AGAIN)
|
||||
{
|
||||
if (nbytes > 0)
|
||||
{
|
||||
write(1, buffer, nbytes);
|
||||
async_request = sftp_async_read_begin(file, sizeof(buffer));
|
||||
} else {
|
||||
counter++;
|
||||
}
|
||||
else counter++;
|
||||
usleep(10000);
|
||||
|
||||
if (async_request >= 0) {
|
||||
nbytes = sftp_async_read(file, buffer, sizeof(buffer),
|
||||
async_request);
|
||||
} else {
|
||||
nbytes = -1;
|
||||
}
|
||||
if (async_request >= 0)
|
||||
nbytes = sftp_async_read(file, buffer, sizeof(buffer), async_request);
|
||||
else nbytes = -1;
|
||||
}
|
||||
|
||||
if (nbytes < 0) {
|
||||
fprintf(stderr, "Error while reading file: %s\n",
|
||||
ssh_get_error(session));
|
||||
if (nbytes < 0)
|
||||
{
|
||||
fprintf(stderr, "Error while reading file: %s\n", ssh_get_error(session));
|
||||
sftp_close(file);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
@@ -345,9 +312,9 @@ int sftp_read_async(ssh_session session, sftp_session sftp)
|
||||
printf("The counter has reached value: %ld\n", counter);
|
||||
|
||||
rc = sftp_close(file);
|
||||
if (rc != SSH_OK) {
|
||||
fprintf(stderr, "Can't close the read file: %s\n",
|
||||
ssh_get_error(session));
|
||||
if (rc != SSH_OK)
|
||||
{
|
||||
fprintf(stderr, "Can't close the read file: %s\n", ssh_get_error(session));
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -358,19 +325,19 @@ int sftp_read_async(ssh_session session, sftp_session sftp)
|
||||
@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.
|
||||
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:
|
||||
to a structure with informations 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
|
||||
- when an error occured
|
||||
|
||||
To tell the difference, call sftp_dir_eof().
|
||||
|
||||
@@ -389,16 +356,15 @@ int sftp_list_dir(ssh_session session, sftp_session sftp)
|
||||
dir = sftp_opendir(sftp, "/var/log");
|
||||
if (!dir)
|
||||
{
|
||||
fprintf(stderr, "Directory not opened: %s\n",
|
||||
ssh_get_error(session));
|
||||
fprintf(stderr, "Directory not opened: %s\n", ssh_get_error(session));
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
printf("Name Size Perms Owner\tGroup\n");
|
||||
printf("Name Size Perms Owner\tGroup\n");
|
||||
|
||||
while ((attributes = sftp_readdir(sftp, dir)) != NULL)
|
||||
{
|
||||
printf("%-20s %10llu %.8o %s(%d)\t%s(%d)\n",
|
||||
printf("%-22s %10llu %.8o %s(%d)\t%s(%d)\n",
|
||||
attributes->name,
|
||||
(long long unsigned int) attributes->size,
|
||||
attributes->permissions,
|
||||
@@ -412,8 +378,7 @@ int sftp_list_dir(ssh_session session, sftp_session sftp)
|
||||
|
||||
if (!sftp_dir_eof(dir))
|
||||
{
|
||||
fprintf(stderr, "Can't list directory: %s\n",
|
||||
ssh_get_error(session));
|
||||
fprintf(stderr, "Can't list directory: %s\n", ssh_get_error(session));
|
||||
sftp_closedir(dir);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
@@ -421,8 +386,7 @@ int sftp_list_dir(ssh_session session, sftp_session sftp)
|
||||
rc = sftp_closedir(dir);
|
||||
if (rc != SSH_OK)
|
||||
{
|
||||
fprintf(stderr, "Can't close directory: %s\n",
|
||||
ssh_get_error(session));
|
||||
fprintf(stderr, "Can't close directory: %s\n", ssh_get_error(session));
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -209,7 +209,7 @@ int interactive_shell_session(ssh_channel channel)
|
||||
|
||||
Of course, this is a poor terminal emulator, since the echo from the keys
|
||||
pressed should not be done locally, but should be done by the remote side.
|
||||
Also, user's input should not be sent once "Enter" key is pressed, but
|
||||
Also, user's input should not be sent once "Enter" key is pressed, but
|
||||
immediately after each key is pressed. This can be accomplished
|
||||
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
|
||||
@@ -245,13 +245,13 @@ provide a more elegant way to wait for data coming from many sources.
|
||||
|
||||
The functions ssh_select() and ssh_channel_select() remind of the standard
|
||||
UNIX select(2) function. The idea is to wait for "something" to happen:
|
||||
incoming data to be read, outgoing data to block, or an exception to
|
||||
incoming data to be read, outcoming data to block, or an exception to
|
||||
occur. Both these functions do a "passive wait", i.e. you can safely use
|
||||
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
|
||||
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.
|
||||
@@ -320,36 +320,18 @@ int interactive_shell_session(ssh_session session, ssh_channel channel)
|
||||
If your remote application is graphical, you can forward the X11 protocol to
|
||||
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().
|
||||
To do that, you first declare that you accept X11 connections with
|
||||
ssh_channel_accept_x11(). Then you create the forwarding tunnel for
|
||||
the X11 protocol with ssh_channel_request_x11().
|
||||
|
||||
The following code performs channel initialization and shell session
|
||||
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;
|
||||
ssh_channel x11channel;
|
||||
|
||||
rc = ssh_channel_request_pty(channel);
|
||||
if (rc != SSH_OK) return rc;
|
||||
@@ -368,15 +350,12 @@ int interactive_shell_session(ssh_channel channel)
|
||||
}
|
||||
@endcode
|
||||
|
||||
Don't forget to check the $DISPLAY environment variable on the remote
|
||||
Don't forget to set the $DISPLAY environment variable on the remote
|
||||
side, or the remote applications won't try using the X11 tunnel:
|
||||
|
||||
@code
|
||||
$ echo $DISPLAY
|
||||
localhost:10.0
|
||||
$ export DISPLAY=:0
|
||||
$ xclock &
|
||||
@endcode
|
||||
|
||||
See an implementation example at https://gitlab.com/libssh/libssh-mirror/-/tree/master/examples/ssh_X11_client.c for details.
|
||||
|
||||
*/
|
||||
|
||||
@@ -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.
|
||||
@@ -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).
|
||||
@@ -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--> <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 -->
|
||||
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
|
Before Width: | Height: | Size: 483 B |
|
Before Width: | Height: | Size: 488 B |
@@ -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);
|
||||
@@ -3,50 +3,63 @@
|
||||
@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
|
||||
- Threading must be initialized during the initialization of libssh. This
|
||||
initialization must be done outside of any threading context.
|
||||
- If pthreads is being used by your application (or your framework's backend),
|
||||
you must link with libssh_threads dynamic library and initialize
|
||||
threading with the ssh_threads_pthreads threading object.
|
||||
- If an other threading library is being used by your application, you must
|
||||
implement all the methods of the ssh_threads_callbacks_struct structure
|
||||
and initialize libssh with it.
|
||||
- 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
|
||||
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.
|
||||
To initialize threading, you must first select the threading model you want to
|
||||
use, using ssh_threads_set_callbacks(), then call ssh_init().
|
||||
|
||||
If libssh is statically linked, call ssh_init() before using any of libssh
|
||||
provided functions.
|
||||
@code
|
||||
#include <libssh/callbacks.h>
|
||||
...
|
||||
ssh_threads_set_callbacks(ssh_threads_get_noop());
|
||||
ssh_init();
|
||||
@endcode
|
||||
|
||||
ssh_threads_noop is the threading structure that does nothing. It's the
|
||||
threading callbacks being used by default when you're not using threading.
|
||||
|
||||
@subsection threads_pthread Using libpthread with libssh
|
||||
|
||||
Since version 0.8.0, libpthread is the default threads library used by libssh.
|
||||
If your application is using libpthread, you may simply use the libpthread
|
||||
threading backend:
|
||||
|
||||
To use libpthread, simply link it to you application.
|
||||
@code
|
||||
#include <libssh/callbacks.h>
|
||||
...
|
||||
ssh_threads_set_callbacks(ssh_threads_get_pthread());
|
||||
ssh_init();
|
||||
@endcode
|
||||
|
||||
However, you must be sure to link with the library ssh_threads. If
|
||||
you're using gcc, you must use the commandline
|
||||
@code
|
||||
gcc -o output input.c -lssh -lssh_threads
|
||||
@endcode
|
||||
|
||||
If you are using libssh statically linked, don't forget to call ssh_init()
|
||||
before using any of libssh provided functions (and ssh_finalize() in the end).
|
||||
|
||||
@subsection threads_other Using another threading library
|
||||
|
||||
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.
|
||||
You must find your way in the ssh_threads_callbacks_struct structure. You must
|
||||
implement the following methods :
|
||||
- mutex_lock
|
||||
- mutex_unlock
|
||||
- mutex_init
|
||||
- mutex_destroy
|
||||
- thread_id
|
||||
|
||||
Good luck !
|
||||
*/
|
||||
|
||||
@@ -6,94 +6,43 @@ set(examples_SRCS
|
||||
connect_ssh.c
|
||||
)
|
||||
|
||||
include_directories(${libssh_BINARY_DIR}/include ${libssh_BINARY_DIR})
|
||||
include_directories(
|
||||
${LIBSSH_PUBLIC_INCLUDE_DIRS}
|
||||
${CMAKE_BINARY_DIR}
|
||||
)
|
||||
|
||||
if (ARGP_INCLUDE_DIR)
|
||||
include_directories(${ARGP_INCLUDE_DIR})
|
||||
endif()
|
||||
|
||||
if (UNIX AND NOT WIN32)
|
||||
if (LINUX)
|
||||
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)
|
||||
target_link_libraries(libssh_scp ${LIBSSH_SHARED_LIBRARY})
|
||||
|
||||
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)
|
||||
target_link_libraries(scp_download ${LIBSSH_SHARED_LIBRARY})
|
||||
|
||||
add_executable(samplessh sample.c ${examples_SRCS})
|
||||
target_link_libraries(samplessh ${LIBSSH_SHARED_LIBRARY})
|
||||
|
||||
add_executable(sshnetcat sshnetcat.c ${examples_SRCS})
|
||||
target_compile_options(sshnetcat PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
|
||||
target_link_libraries(sshnetcat ssh::ssh)
|
||||
target_link_libraries(sshnetcat ${LIBSSH_SHARED_LIBRARY})
|
||||
|
||||
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)
|
||||
target_link_libraries(samplesftp ${LIBSSH_SHARED_LIBRARY})
|
||||
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_LIBRARY 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_LIBRARY} util)
|
||||
|
||||
add_executable(ssh_server_pthread ssh_server.c)
|
||||
target_compile_options(ssh_server_pthread PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
|
||||
target_link_libraries(ssh_server_pthread ssh::ssh ${ARGP_LIBRARY} pthread util)
|
||||
endif (HAVE_LIBUTIL)
|
||||
|
||||
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_LIBRARY})
|
||||
|
||||
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_LIBRARY})
|
||||
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_LIBRARY})
|
||||
|
||||
add_executable(keygen2 keygen2.c ${examples_SRCS})
|
||||
target_compile_options(keygen2 PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
|
||||
target_link_libraries(keygen2 ssh::ssh ${ARGP_LIBRARY})
|
||||
|
||||
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_LIBRARY OR HAVE_ARGP_H)
|
||||
target_link_libraries(samplesshd-cb ${ARGP_LIBRARY})
|
||||
endif(ARGP_LIBRARY OR HAVE_ARGP_H)
|
||||
endif()
|
||||
if (WITH_SERVER)
|
||||
add_executable(samplesshd samplesshd.c)
|
||||
target_link_libraries(samplesshd ${LIBSSH_SHARED_LIBRARY})
|
||||
endif (WITH_SERVER)
|
||||
endif (LINUX)
|
||||
|
||||
add_executable(exec exec.c ${examples_SRCS})
|
||||
target_compile_options(exec PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
|
||||
target_link_libraries(exec ssh::ssh)
|
||||
target_link_libraries(exec ${LIBSSH_SHARED_LIBRARY})
|
||||
|
||||
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)
|
||||
target_link_libraries(senddata ${LIBSSH_SHARED_LIBRARY})
|
||||
|
||||
add_executable(libsshpp libsshpp.cpp)
|
||||
target_link_libraries(libsshpp ssh::ssh)
|
||||
target_link_libraries(libsshpp ${LIBSSH_SHARED_LIBRARY})
|
||||
|
||||
add_executable(libsshpp_noexcept libsshpp_noexcept.cpp)
|
||||
target_link_libraries(libsshpp_noexcept ssh::ssh)
|
||||
target_link_libraries(libsshpp_noexcept ${LIBSSH_SHARED_LIBRARY})
|
||||
|
||||
@@ -24,8 +24,7 @@ clients must be made or how a client should react.
|
||||
#include <libssh/libssh.h>
|
||||
#include "examples_common.h"
|
||||
|
||||
int authenticate_kbdint(ssh_session session, const char *password)
|
||||
{
|
||||
int authenticate_kbdint(ssh_session session, const char *password) {
|
||||
int err;
|
||||
|
||||
err = ssh_userauth_kbdint(session, NULL, NULL);
|
||||
@@ -87,9 +86,7 @@ int authenticate_kbdint(ssh_session session, const char *password)
|
||||
}
|
||||
answer = buffer;
|
||||
}
|
||||
err = ssh_userauth_kbdint_setanswer(session, i, answer);
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
if (err < 0) {
|
||||
if (ssh_userauth_kbdint_setanswer(session, i, answer) < 0) {
|
||||
return SSH_AUTH_ERROR;
|
||||
}
|
||||
}
|
||||
@@ -100,142 +97,68 @@ int authenticate_kbdint(ssh_session session, const char *password)
|
||||
return err;
|
||||
}
|
||||
|
||||
static int auth_keyfile(ssh_session session, char* keyfile)
|
||||
{
|
||||
ssh_key key = NULL;
|
||||
char pubkey[132] = {0}; // +".pub"
|
||||
int rc;
|
||||
static void error(ssh_session session){
|
||||
fprintf(stderr,"Authentication failed: %s\n",ssh_get_error(session));
|
||||
}
|
||||
|
||||
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);
|
||||
int authenticate_console(ssh_session session){
|
||||
int rc;
|
||||
int method;
|
||||
char password[128] = {0};
|
||||
char *banner;
|
||||
|
||||
// Try to authenticate
|
||||
rc = ssh_userauth_none(session, NULL);
|
||||
if (rc == SSH_AUTH_ERROR) {
|
||||
error(session);
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
|
||||
// Try to authenticate
|
||||
rc = ssh_userauth_none(session, NULL);
|
||||
if (rc == SSH_AUTH_ERROR) {
|
||||
error(session);
|
||||
method = ssh_auth_list(session);
|
||||
while (rc != SSH_AUTH_SUCCESS) {
|
||||
// Try to authenticate with public key first
|
||||
if (method & SSH_AUTH_METHOD_PUBLICKEY) {
|
||||
rc = ssh_userauth_autopubkey(session, NULL);
|
||||
if (rc == SSH_AUTH_ERROR) {
|
||||
error(session);
|
||||
return rc;
|
||||
} else if (rc == SSH_AUTH_SUCCESS) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
method = ssh_userauth_list(session, NULL);
|
||||
while (rc != SSH_AUTH_SUCCESS) {
|
||||
if (method & SSH_AUTH_METHOD_GSSAPI_MIC){
|
||||
rc = ssh_userauth_gssapi(session);
|
||||
if(rc == SSH_AUTH_ERROR) {
|
||||
error(session);
|
||||
return rc;
|
||||
} else if (rc == SSH_AUTH_SUCCESS) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Try to authenticate with public key first
|
||||
if (method & SSH_AUTH_METHOD_PUBLICKEY) {
|
||||
rc = ssh_userauth_publickey_auto(session, NULL, NULL);
|
||||
if (rc == SSH_AUTH_ERROR) {
|
||||
error(session);
|
||||
return rc;
|
||||
} else if (rc == SSH_AUTH_SUCCESS) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
{
|
||||
char buffer[128] = {0};
|
||||
char *p = NULL;
|
||||
|
||||
printf("Automatic pubkey failed. "
|
||||
"Do you want to try a specific key? (y/n)\n");
|
||||
if (fgets(buffer, sizeof(buffer), stdin) == NULL) {
|
||||
break;
|
||||
}
|
||||
if ((buffer[0]=='Y') || (buffer[0]=='y')) {
|
||||
printf("private key filename: ");
|
||||
|
||||
if (fgets(buffer, sizeof(buffer), stdin) == NULL) {
|
||||
return SSH_AUTH_ERROR;
|
||||
}
|
||||
|
||||
buffer[sizeof(buffer) - 1] = '\0';
|
||||
if ((p = strchr(buffer, '\n'))) {
|
||||
*p = '\0';
|
||||
}
|
||||
|
||||
rc = auth_keyfile(session, buffer);
|
||||
|
||||
if(rc == SSH_AUTH_SUCCESS) {
|
||||
break;
|
||||
}
|
||||
fprintf(stderr, "failed with key\n");
|
||||
}
|
||||
}
|
||||
|
||||
// Try to authenticate with keyboard interactive";
|
||||
if (method & SSH_AUTH_METHOD_INTERACTIVE) {
|
||||
rc = authenticate_kbdint(session, NULL);
|
||||
if (rc == SSH_AUTH_ERROR) {
|
||||
error(session);
|
||||
return rc;
|
||||
} else if (rc == SSH_AUTH_SUCCESS) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ssh_getpass("Password: ", password, sizeof(password), 0, 0) < 0) {
|
||||
return SSH_AUTH_ERROR;
|
||||
}
|
||||
|
||||
// Try to authenticate with password
|
||||
if (method & SSH_AUTH_METHOD_PASSWORD) {
|
||||
rc = ssh_userauth_password(session, NULL, password);
|
||||
if (rc == SSH_AUTH_ERROR) {
|
||||
error(session);
|
||||
return rc;
|
||||
} else if (rc == SSH_AUTH_SUCCESS) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
memset(password, 0, sizeof(password));
|
||||
// Try to authenticate with keyboard interactive";
|
||||
if (method & SSH_AUTH_METHOD_INTERACTIVE) {
|
||||
rc = authenticate_kbdint(session, NULL);
|
||||
if (rc == SSH_AUTH_ERROR) {
|
||||
error(session);
|
||||
return rc;
|
||||
} else if (rc == SSH_AUTH_SUCCESS) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
banner = ssh_get_issue_banner(session);
|
||||
if (banner) {
|
||||
printf("%s\n",banner);
|
||||
SSH_STRING_FREE_CHAR(banner);
|
||||
if (ssh_getpass("Password: ", password, sizeof(password), 0, 0) < 0) {
|
||||
return SSH_AUTH_ERROR;
|
||||
}
|
||||
|
||||
return rc;
|
||||
// Try to authenticate with password
|
||||
if (method & SSH_AUTH_METHOD_PASSWORD) {
|
||||
rc = ssh_userauth_password(session, NULL, password);
|
||||
if (rc == SSH_AUTH_ERROR) {
|
||||
error(session);
|
||||
return rc;
|
||||
} else if (rc == SSH_AUTH_SUCCESS) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
banner = ssh_get_issue_banner(session);
|
||||
if (banner) {
|
||||
printf("%s\n",banner);
|
||||
ssh_string_free_char(banner);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -14,10 +14,6 @@ clients must be made or how a client should react.
|
||||
#define EXAMPLES_COMMON_H_
|
||||
|
||||
#include <libssh/libssh.h>
|
||||
|
||||
/** Zero a structure */
|
||||
#define ZERO_STRUCT(x) memset((char *)&(x), 0, sizeof(x))
|
||||
|
||||
int authenticate_console(ssh_session session);
|
||||
int authenticate_kbdint(ssh_session session, const char *password);
|
||||
int verify_knownhost(ssh_session session);
|
||||
|
||||
@@ -8,7 +8,7 @@ int main(void) {
|
||||
ssh_session session;
|
||||
ssh_channel channel;
|
||||
char buffer[256];
|
||||
int rbytes, wbytes, total = 0;
|
||||
int nbytes;
|
||||
int rc;
|
||||
|
||||
session = connect_ssh("localhost", NULL, 0);
|
||||
@@ -17,7 +17,7 @@ int main(void) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
channel = ssh_channel_new(session);
|
||||
channel = ssh_channel_new(session);;
|
||||
if (channel == NULL) {
|
||||
ssh_disconnect(session);
|
||||
ssh_free(session);
|
||||
@@ -35,30 +35,15 @@ int main(void) {
|
||||
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) {
|
||||
nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
|
||||
while (nbytes > 0) {
|
||||
if (fwrite(buffer, 1, nbytes, stdout) != (unsigned int) nbytes) {
|
||||
goto failed;
|
||||
}
|
||||
nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
|
||||
}
|
||||
|
||||
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) {
|
||||
if (nbytes < 0) {
|
||||
goto failed;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
/* keygen.c
|
||||
* Sample implementation of ssh-keygen using libssh
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2019 Red Hat, Inc.
|
||||
|
||||
Author: Jakub Jelen <jjelen@redhat.com>
|
||||
|
||||
This file is part of the SSH Library
|
||||
|
||||
You are free to copy this file, modify it in any way, consider it being public
|
||||
domain. This does not apply to the rest of the library though, but it is
|
||||
allowed to cut-and-paste working code from this file to any license of
|
||||
program.
|
||||
*/
|
||||
|
||||
#include <libssh/libssh.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
ssh_key key = NULL;
|
||||
int rv;
|
||||
|
||||
/* Generate a new ED25519 private key file */
|
||||
rv = ssh_pki_generate(SSH_KEYTYPE_ED25519, 0, &key);
|
||||
if (rv != SSH_OK) {
|
||||
fprintf(stderr, "Failed to generate private key");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Write it to a file testkey in the current dirrectory */
|
||||
rv = ssh_pki_export_privkey_file(key, NULL, NULL, NULL, "testkey");
|
||||
if (rv != SSH_OK) {
|
||||
fprintf(stderr, "Failed to write private key file");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,505 +0,0 @@
|
||||
/*
|
||||
* keygen2.c - Generate SSH keys using libssh
|
||||
* Author: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2019 Red Hat, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <libssh/libssh.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <argp.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
||||
struct arguments_st {
|
||||
enum ssh_keytypes_e type;
|
||||
unsigned long bits;
|
||||
char *file;
|
||||
char *passphrase;
|
||||
int action_list;
|
||||
};
|
||||
|
||||
static struct argp_option options[] = {
|
||||
{
|
||||
.name = "bits",
|
||||
.key = 'b',
|
||||
.arg = "BITS",
|
||||
.flags = 0,
|
||||
.doc = "The size of the key to be generated. "
|
||||
"If omitted, a default value is used depending on the TYPE. "
|
||||
"Accepted values are: "
|
||||
"1024, 2048, 3072 (default), 4096, and 8192 for TYPE=\"rsa\"; "
|
||||
"256 (default), 384, and 521 for TYPE=\"ecdsa\"; "
|
||||
"1024 (default) and 2048 for TYPE=\"dsa\"; "
|
||||
"can be omitted for TYPE=\"ed25519\" "
|
||||
"(it will be ignored if provided).\n",
|
||||
.group = 0
|
||||
},
|
||||
{
|
||||
.name = "file",
|
||||
.key = 'f',
|
||||
.arg = "FILE",
|
||||
.flags = 0,
|
||||
.doc = "The output file. "
|
||||
"If not provided, the used file name will be generated "
|
||||
"according to the key type as \"id_TYPE\" "
|
||||
"(e.g. \"id_rsa\" for type \"rsa\"). "
|
||||
"The public key file name is generated from the private key "
|
||||
"file name by appending \".pub\".\n",
|
||||
.group = 0
|
||||
},
|
||||
{
|
||||
.name = "passphrase",
|
||||
.key = 'p',
|
||||
.arg = "PASSPHRASE",
|
||||
.flags = 0,
|
||||
.doc = "The passphrase used to encrypt the private key. "
|
||||
"If omitted the file will not be encrypted.\n",
|
||||
.group = 0
|
||||
},
|
||||
{
|
||||
.name = "type",
|
||||
.key = 't',
|
||||
.arg = "TYPE",
|
||||
.flags = 0,
|
||||
.doc = "The type of the key to be generated. "
|
||||
"Accepted values are: "
|
||||
"\"rsa\", \"ecdsa\", \"ed25519\", and \"dsa\".\n",
|
||||
.group = 0
|
||||
},
|
||||
{
|
||||
.name = "list",
|
||||
.key = 'l',
|
||||
.arg = NULL,
|
||||
.flags = 0,
|
||||
.doc = "List the Fingerprint of the given key\n",
|
||||
.group = 0
|
||||
},
|
||||
{
|
||||
/* End of the options */
|
||||
0
|
||||
},
|
||||
};
|
||||
|
||||
/* Parse a single option. */
|
||||
static error_t parse_opt (int key, char *arg, struct argp_state *state)
|
||||
{
|
||||
/* Get the input argument from argp_parse, which we
|
||||
* know is a pointer to our arguments structure.
|
||||
*/
|
||||
struct arguments_st *arguments = NULL;
|
||||
error_t rc = 0;
|
||||
|
||||
if (state == NULL) {
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
arguments = state->input;
|
||||
if (arguments == NULL) {
|
||||
fprintf(stderr, "Error: NULL pointer to arguments structure "
|
||||
"provided\n");
|
||||
rc = EINVAL;
|
||||
goto end;
|
||||
}
|
||||
|
||||
switch (key) {
|
||||
case 'b':
|
||||
errno = 0;
|
||||
arguments->bits = strtoul(arg, NULL, 10);
|
||||
if (errno != 0) {
|
||||
rc = errno;
|
||||
goto end;
|
||||
}
|
||||
break;
|
||||
case 'f':
|
||||
arguments->file = strdup(arg);
|
||||
if (arguments->file == NULL) {
|
||||
fprintf(stderr, "Error: Out of memory\n");
|
||||
rc = ENOMEM;
|
||||
goto end;
|
||||
}
|
||||
break;
|
||||
case 'p':
|
||||
arguments->passphrase = strdup(arg);
|
||||
if (arguments->passphrase == NULL) {
|
||||
fprintf(stderr, "Error: Out of memory\n");
|
||||
rc = ENOMEM;
|
||||
goto end;
|
||||
}
|
||||
break;
|
||||
case 't':
|
||||
if (!strcmp(arg, "rsa")) {
|
||||
arguments->type = SSH_KEYTYPE_RSA;
|
||||
}
|
||||
else if (!strcmp(arg, "dsa")) {
|
||||
arguments->type = SSH_KEYTYPE_DSS;
|
||||
}
|
||||
else if (!strcmp(arg, "ecdsa")) {
|
||||
arguments->type = SSH_KEYTYPE_ECDSA;
|
||||
}
|
||||
else if (!strcmp(arg, "ed25519")) {
|
||||
arguments->type = SSH_KEYTYPE_ED25519;
|
||||
}
|
||||
else {
|
||||
fprintf(stderr, "Error: Invalid key type\n");
|
||||
argp_usage(state);
|
||||
rc = EINVAL;
|
||||
goto end;
|
||||
}
|
||||
break;
|
||||
case 'l':
|
||||
arguments->action_list = 1;
|
||||
break;
|
||||
case ARGP_KEY_ARG:
|
||||
if (state->arg_num > 0) {
|
||||
/* Too many arguments. */
|
||||
printf("Error: Too many arguments\n");
|
||||
argp_usage(state);
|
||||
}
|
||||
break;
|
||||
case ARGP_KEY_END:
|
||||
break;
|
||||
default:
|
||||
return ARGP_ERR_UNKNOWN;
|
||||
}
|
||||
|
||||
end:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int validate_args(struct arguments_st *args)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if (args == NULL) {
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
/* no other arguments needed for listing key fingerprints */
|
||||
if (args->action_list) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (args->type) {
|
||||
case SSH_KEYTYPE_RSA:
|
||||
switch (args->bits) {
|
||||
case 0:
|
||||
/* If not provided, use default value */
|
||||
args->bits = 3072;
|
||||
break;
|
||||
case 1024:
|
||||
case 2048:
|
||||
case 3072:
|
||||
case 4096:
|
||||
case 8192:
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Error: Invalid bits parameter provided\n");
|
||||
rc = EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (args->file == NULL) {
|
||||
args->file = strdup("id_rsa");
|
||||
if (args->file == NULL) {
|
||||
rc = ENOMEM;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case SSH_KEYTYPE_ECDSA:
|
||||
switch (args->bits) {
|
||||
case 0:
|
||||
/* If not provided, use default value */
|
||||
args->bits = 256;
|
||||
break;
|
||||
case 256:
|
||||
case 384:
|
||||
case 521:
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Error: Invalid bits parameter provided\n");
|
||||
rc = EINVAL;
|
||||
break;
|
||||
}
|
||||
if (args->file == NULL) {
|
||||
args->file = strdup("id_ecdsa");
|
||||
if (args->file == NULL) {
|
||||
rc = ENOMEM;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case SSH_KEYTYPE_DSS:
|
||||
switch (args->bits) {
|
||||
case 0:
|
||||
/* If not provided, use default value */
|
||||
args->bits = 1024;
|
||||
break;
|
||||
case 1024:
|
||||
case 2048:
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Error: Invalid bits parameter provided\n");
|
||||
rc = EINVAL;
|
||||
break;
|
||||
}
|
||||
if (args->file == NULL) {
|
||||
args->file = strdup("id_dsa");
|
||||
if (args->file == NULL) {
|
||||
rc = ENOMEM;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case SSH_KEYTYPE_ED25519:
|
||||
/* Ignore value and overwrite with a zero */
|
||||
args->bits = 0;
|
||||
|
||||
if (args->file == NULL) {
|
||||
args->file = strdup("id_ed25519");
|
||||
if (args->file == NULL) {
|
||||
rc = ENOMEM;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Error: unknown key type\n");
|
||||
rc = EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Program documentation. */
|
||||
static char doc[] = "Generate an SSH key pair. "
|
||||
"The \"--type\" (short: \"-t\") option is required.";
|
||||
|
||||
/* Our argp parser */
|
||||
static struct argp argp = {options, parse_opt, NULL, doc, NULL, NULL, NULL};
|
||||
|
||||
static void
|
||||
list_fingerprint(char *file)
|
||||
{
|
||||
ssh_key key = NULL;
|
||||
unsigned char *hash = NULL;
|
||||
size_t hlen = 0;
|
||||
int rc;
|
||||
|
||||
rc = ssh_pki_import_privkey_file(file, NULL, NULL, NULL, &key);
|
||||
if (rc != SSH_OK) {
|
||||
fprintf(stderr, "Failed to import private key %s\n", file);
|
||||
return;
|
||||
}
|
||||
|
||||
rc = ssh_get_publickey_hash(key, SSH_PUBLICKEY_HASH_SHA256, &hash, &hlen);
|
||||
if (rc != SSH_OK) {
|
||||
fprintf(stderr, "Failed to get key fingerprint\n");
|
||||
return;
|
||||
}
|
||||
ssh_print_hash(SSH_PUBLICKEY_HASH_SHA256, hash, hlen);
|
||||
|
||||
ssh_clean_pubkey_hash(&hash);
|
||||
ssh_key_free(key);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
ssh_key key = NULL;
|
||||
int rc = 0;
|
||||
char overwrite[1024] = "";
|
||||
|
||||
char *pubkey_file = NULL;
|
||||
|
||||
struct arguments_st arguments = {
|
||||
.type = SSH_KEYTYPE_UNKNOWN,
|
||||
.bits = 0,
|
||||
.file = NULL,
|
||||
.passphrase = NULL,
|
||||
.action_list = 0,
|
||||
};
|
||||
|
||||
if (argc < 2) {
|
||||
argp_help(&argp, stdout, ARGP_HELP_DOC | ARGP_HELP_USAGE, argv[0]);
|
||||
goto end;
|
||||
}
|
||||
|
||||
rc = argp_parse(&argp, argc, argv, 0, 0, &arguments);
|
||||
if (rc != 0) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
rc = validate_args(&arguments);
|
||||
if (rc != 0) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (arguments.action_list && arguments.file) {
|
||||
list_fingerprint(arguments.file);
|
||||
goto end;
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
rc = open(arguments.file, O_CREAT | O_EXCL | O_WRONLY, S_IRUSR | S_IWUSR);
|
||||
if (rc < 0) {
|
||||
if (errno == EEXIST) {
|
||||
printf("File \"%s\" exists. Overwrite it? (y|n) ", arguments.file);
|
||||
rc = scanf("%1023s", overwrite);
|
||||
if (rc > 0 && tolower(overwrite[0]) == 'y') {
|
||||
rc = open(arguments.file, O_WRONLY);
|
||||
if (rc > 0) {
|
||||
close(rc);
|
||||
errno = 0;
|
||||
rc = chmod(arguments.file, S_IRUSR | S_IWUSR);
|
||||
if (rc != 0) {
|
||||
fprintf(stderr,
|
||||
"Error(%d): Could not set file permissions\n",
|
||||
errno);
|
||||
goto end;
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr,
|
||||
"Error: Could not create private key file\n");
|
||||
goto end;
|
||||
}
|
||||
} else {
|
||||
goto end;
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "Error opening \"%s\" file\n", arguments.file);
|
||||
goto end;
|
||||
}
|
||||
} else {
|
||||
close(rc);
|
||||
}
|
||||
|
||||
/* Generate a new private key */
|
||||
rc = ssh_pki_generate(arguments.type, arguments.bits, &key);
|
||||
if (rc != SSH_OK) {
|
||||
fprintf(stderr, "Error: Failed to generate keys");
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* Write the private key */
|
||||
rc = ssh_pki_export_privkey_file(key, arguments.passphrase, NULL, NULL,
|
||||
arguments.file);
|
||||
if (rc != SSH_OK) {
|
||||
fprintf(stderr, "Error: Failed to write private key file");
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* If a passphrase was provided, overwrite and free it as it is not needed
|
||||
* anymore */
|
||||
if (arguments.passphrase != NULL) {
|
||||
#ifdef HAVE_EXPLICIT_BZERO
|
||||
explicit_bzero(arguments.passphrase, strlen(arguments.passphrase));
|
||||
#else
|
||||
bzero(arguments.passphrase, strlen(arguments.passphrase));
|
||||
#endif
|
||||
free(arguments.passphrase);
|
||||
arguments.passphrase = NULL;
|
||||
}
|
||||
|
||||
pubkey_file = (char *)malloc(strlen(arguments.file) + 5);
|
||||
if (pubkey_file == NULL) {
|
||||
rc = ENOMEM;
|
||||
goto end;
|
||||
}
|
||||
|
||||
sprintf(pubkey_file, "%s.pub", arguments.file);
|
||||
|
||||
errno = 0;
|
||||
rc = open(pubkey_file,
|
||||
O_CREAT | O_EXCL | O_WRONLY,
|
||||
S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
|
||||
if (rc < 0) {
|
||||
if (errno == EEXIST) {
|
||||
printf("File \"%s\" exists. Overwrite it? (y|n) ", pubkey_file);
|
||||
rc = scanf("%1023s", overwrite);
|
||||
if (rc > 0 && tolower(overwrite[0]) == 'y') {
|
||||
rc = open(pubkey_file, O_WRONLY);
|
||||
if (rc > 0) {
|
||||
close(rc);
|
||||
errno = 0;
|
||||
rc = chmod(pubkey_file,
|
||||
S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
|
||||
if (rc != 0) {
|
||||
fprintf(stderr,
|
||||
"Error(%d): Could not set file permissions\n",
|
||||
errno);
|
||||
goto end;
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr,
|
||||
"Error: Could not create public key file\n");
|
||||
goto end;
|
||||
}
|
||||
} else {
|
||||
goto end;
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "Error opening \"%s\" file\n", pubkey_file);
|
||||
goto end;
|
||||
}
|
||||
} else {
|
||||
close(rc);
|
||||
}
|
||||
|
||||
/* Write the public key */
|
||||
rc = ssh_pki_export_pubkey_file(key, pubkey_file);
|
||||
if (rc != SSH_OK) {
|
||||
fprintf(stderr, "Error: Failed to write public key file");
|
||||
goto end;
|
||||
}
|
||||
|
||||
end:
|
||||
if (key != NULL) {
|
||||
ssh_key_free(key);
|
||||
}
|
||||
|
||||
if (arguments.file != NULL) {
|
||||
free(arguments.file);
|
||||
}
|
||||
|
||||
if (arguments.passphrase != NULL) {
|
||||
#ifdef HAVE_EXPLICIT_BZERO
|
||||
explicit_bzero(arguments.passphrase, strlen(arguments.passphrase));
|
||||
#else
|
||||
bzero(arguments.passphrase, strlen(arguments.passphrase));
|
||||
#endif
|
||||
free(arguments.passphrase);
|
||||
}
|
||||
|
||||
if (pubkey_file != NULL) {
|
||||
free(pubkey_file);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
@@ -17,14 +17,11 @@ The goal is to show the API in action. It's not a reference on how terminal
|
||||
clients must be made or how a client should react.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "libssh/priv.h"
|
||||
#include <libssh/libssh.h>
|
||||
#include "examples_common.h"
|
||||
|
||||
@@ -32,86 +29,70 @@ clients must be made or how a client should react.
|
||||
#define strncasecmp _strnicmp
|
||||
#endif
|
||||
|
||||
int verify_knownhost(ssh_session session)
|
||||
{
|
||||
enum ssh_known_hosts_e state;
|
||||
char buf[10];
|
||||
unsigned char *hash = NULL;
|
||||
size_t hlen;
|
||||
ssh_key srv_pubkey;
|
||||
int rc;
|
||||
int verify_knownhost(ssh_session session){
|
||||
char *hexa;
|
||||
int state;
|
||||
char buf[10];
|
||||
unsigned char *hash = NULL;
|
||||
int hlen;
|
||||
|
||||
rc = ssh_get_server_publickey(session, &srv_pubkey);
|
||||
if (rc < 0) {
|
||||
return -1;
|
||||
}
|
||||
state=ssh_is_server_known(session);
|
||||
|
||||
rc = ssh_get_publickey_hash(srv_pubkey,
|
||||
SSH_PUBLICKEY_HASH_SHA256,
|
||||
&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_CHANGED:
|
||||
fprintf(stderr,"Host key for server changed : server's one is now :\n");
|
||||
ssh_print_hash(SSH_PUBLICKEY_HASH_SHA256, hash, hlen);
|
||||
ssh_clean_pubkey_hash(&hash);
|
||||
fprintf(stderr,"For security reason, connection will be stopped\n");
|
||||
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"
|
||||
"We advise you to rerun the client with -d or -r for more safety.\n");
|
||||
return -1;
|
||||
case SSH_KNOWN_HOSTS_NOT_FOUND:
|
||||
fprintf(stderr,"Could not find known host file. If you accept the host key here,\n");
|
||||
fprintf(stderr,"the file will be automatically created.\n");
|
||||
/* fallback to SSH_SERVER_NOT_KNOWN behavior */
|
||||
FALL_THROUGH;
|
||||
hlen = ssh_get_pubkey_hash(session, &hash);
|
||||
if (hlen < 0) {
|
||||
return -1;
|
||||
}
|
||||
switch(state){
|
||||
case SSH_SERVER_KNOWN_OK:
|
||||
break; /* ok */
|
||||
case SSH_SERVER_KNOWN_CHANGED:
|
||||
fprintf(stderr,"Host key for server changed : server's one is now :\n");
|
||||
ssh_print_hexa("Public key hash",hash, hlen);
|
||||
ssh_clean_pubkey_hash(&hash);
|
||||
fprintf(stderr,"For security reason, connection will be stopped\n");
|
||||
return -1;
|
||||
case SSH_SERVER_FOUND_OTHER:
|
||||
fprintf(stderr,"The host key for this server was not found but an other type of key exists.\n");
|
||||
fprintf(stderr,"An attacker might change the default server key to confuse your client"
|
||||
"into thinking the key does not exist\n"
|
||||
"We advise you to rerun the client with -d or -r for more safety.\n");
|
||||
return -1;
|
||||
case SSH_SERVER_FILE_NOT_FOUND:
|
||||
fprintf(stderr,"Could not find known host file. If you accept the host key here,\n");
|
||||
fprintf(stderr,"the file will be automatically created.\n");
|
||||
/* fallback to SSH_SERVER_NOT_KNOWN behavior */
|
||||
case SSH_SERVER_NOT_KNOWN:
|
||||
fprintf(stderr,
|
||||
"The server is unknown. Do you trust the host key (yes/no)?\n");
|
||||
ssh_print_hash(SSH_PUBLICKEY_HASH_SHA256, hash, hlen);
|
||||
|
||||
if (fgets(buf, sizeof(buf), stdin) == NULL) {
|
||||
ssh_clean_pubkey_hash(&hash);
|
||||
return -1;
|
||||
}
|
||||
if(strncasecmp(buf,"yes",3)!=0){
|
||||
ssh_clean_pubkey_hash(&hash);
|
||||
return -1;
|
||||
}
|
||||
fprintf(stderr,"This new key will be written on disk for further usage. do you agree ?\n");
|
||||
if (fgets(buf, sizeof(buf), stdin) == NULL) {
|
||||
ssh_clean_pubkey_hash(&hash);
|
||||
return -1;
|
||||
}
|
||||
if(strncasecmp(buf,"yes",3)==0){
|
||||
rc = ssh_session_update_known_hosts(session);
|
||||
if (rc != SSH_OK) {
|
||||
ssh_clean_pubkey_hash(&hash);
|
||||
fprintf(stderr, "error %s\n", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case SSH_KNOWN_HOSTS_ERROR:
|
||||
ssh_clean_pubkey_hash(&hash);
|
||||
fprintf(stderr,"%s",ssh_get_error(session));
|
||||
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);
|
||||
if (fgets(buf, sizeof(buf), stdin) == NULL) {
|
||||
ssh_clean_pubkey_hash(&hash);
|
||||
return -1;
|
||||
case SSH_KNOWN_HOSTS_OK:
|
||||
break; /* ok */
|
||||
}
|
||||
}
|
||||
if(strncasecmp(buf,"yes",3)!=0){
|
||||
ssh_clean_pubkey_hash(&hash);
|
||||
return -1;
|
||||
}
|
||||
fprintf(stderr,"This new key will be written on disk for further usage. do you agree ?\n");
|
||||
if (fgets(buf, sizeof(buf), stdin) == NULL) {
|
||||
ssh_clean_pubkey_hash(&hash);
|
||||
return -1;
|
||||
}
|
||||
if(strncasecmp(buf,"yes",3)==0){
|
||||
if (ssh_write_knownhost(session) < 0) {
|
||||
ssh_clean_pubkey_hash(&hash);
|
||||
fprintf(stderr, "error %s\n", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
ssh_clean_pubkey_hash(&hash);
|
||||
|
||||
return 0;
|
||||
break;
|
||||
case SSH_SERVER_ERROR:
|
||||
ssh_clean_pubkey_hash(&hash);
|
||||
fprintf(stderr,"%s",ssh_get_error(session));
|
||||
return -1;
|
||||
}
|
||||
ssh_clean_pubkey_hash(&hash);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -22,233 +22,143 @@ program.
|
||||
#include <libssh/libssh.h>
|
||||
#include "examples_common.h"
|
||||
|
||||
#ifndef BUF_SIZE
|
||||
#define BUF_SIZE 16384
|
||||
#endif
|
||||
|
||||
static char **sources;
|
||||
static int nsources;
|
||||
static char *destination;
|
||||
static int verbosity = 0;
|
||||
char **sources;
|
||||
int nsources;
|
||||
char *destination;
|
||||
int verbosity=0;
|
||||
|
||||
struct location {
|
||||
int is_ssh;
|
||||
char *user;
|
||||
char *host;
|
||||
char *path;
|
||||
ssh_session session;
|
||||
ssh_scp scp;
|
||||
FILE *file;
|
||||
int is_ssh;
|
||||
char *user;
|
||||
char *host;
|
||||
char *path;
|
||||
ssh_session session;
|
||||
ssh_scp scp;
|
||||
FILE *file;
|
||||
};
|
||||
|
||||
enum {
|
||||
READ,
|
||||
WRITE
|
||||
READ,
|
||||
WRITE
|
||||
};
|
||||
|
||||
static void usage(const char *argv0) {
|
||||
fprintf(stderr, "Usage : %s [options] [[user@]host1:]file1 ... \n"
|
||||
" [[user@]host2:]destination\n"
|
||||
"sample scp client - libssh-%s\n",
|
||||
// "Options :\n",
|
||||
// " -r : use RSA to verify host public key\n",
|
||||
argv0,
|
||||
ssh_version(0));
|
||||
exit(0);
|
||||
static void usage(const char *argv0){
|
||||
fprintf(stderr,"Usage : %s [options] [[user@]host1:]file1 ... \n"
|
||||
" [[user@]host2:]destination\n"
|
||||
"sample scp client - libssh-%s\n",
|
||||
// "Options :\n",
|
||||
// " -r : use RSA to verify host public key\n",
|
||||
argv0,
|
||||
ssh_version(0));
|
||||
exit(0);
|
||||
}
|
||||
|
||||
static int opts(int argc, char **argv) {
|
||||
int i;
|
||||
|
||||
while((i = getopt(argc, argv, "v")) != -1) {
|
||||
switch(i) {
|
||||
case 'v':
|
||||
verbosity++;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "unknown option %c\n", optopt);
|
||||
usage(argv[0]);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
nsources = argc - optind - 1;
|
||||
if (nsources < 1) {
|
||||
static int opts(int argc, char **argv){
|
||||
int i;
|
||||
while((i=getopt(argc,argv,"v"))!=-1){
|
||||
switch(i){
|
||||
case 'v':
|
||||
verbosity++;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr,"unknown option %c\n",optopt);
|
||||
usage(argv[0]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
sources = malloc((nsources + 1) * sizeof(char *));
|
||||
if (sources == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
for(i = 0; i < nsources; ++i) {
|
||||
sources[i] = argv[optind];
|
||||
optind++;
|
||||
}
|
||||
|
||||
sources[i] = NULL;
|
||||
destination = argv[optind];
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void location_free(struct location *loc)
|
||||
{
|
||||
if (loc) {
|
||||
if (loc->path) {
|
||||
free(loc->path);
|
||||
}
|
||||
loc->path = NULL;
|
||||
if (loc->is_ssh) {
|
||||
if (loc->host) {
|
||||
free(loc->host);
|
||||
}
|
||||
loc->host = NULL;
|
||||
if (loc->user) {
|
||||
free(loc->user);
|
||||
}
|
||||
loc->user = NULL;
|
||||
}
|
||||
free(loc);
|
||||
}
|
||||
}
|
||||
|
||||
static struct location *parse_location(char *loc) {
|
||||
struct location *location;
|
||||
char *ptr;
|
||||
|
||||
location = malloc(sizeof(struct location));
|
||||
if (location == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
memset(location, 0, sizeof(struct location));
|
||||
|
||||
location->host = location->user = NULL;
|
||||
ptr = strchr(loc, ':');
|
||||
|
||||
if (ptr != NULL) {
|
||||
location->is_ssh = 1;
|
||||
location->path = strdup(ptr+1);
|
||||
*ptr = '\0';
|
||||
ptr = strchr(loc, '@');
|
||||
|
||||
if (ptr != NULL) {
|
||||
location->host = strdup(ptr+1);
|
||||
*ptr = '\0';
|
||||
location->user = strdup(loc);
|
||||
} else {
|
||||
location->host = strdup(loc);
|
||||
}
|
||||
} else {
|
||||
location->is_ssh = 0;
|
||||
location->path = strdup(loc);
|
||||
}
|
||||
return location;
|
||||
}
|
||||
|
||||
static void close_location(struct location *loc) {
|
||||
int rc;
|
||||
|
||||
if (loc) {
|
||||
if (loc->is_ssh) {
|
||||
if (loc->scp) {
|
||||
rc = ssh_scp_close(loc->scp);
|
||||
if (rc == SSH_ERROR) {
|
||||
fprintf(stderr,
|
||||
"Error closing scp: %s\n",
|
||||
ssh_get_error(loc->session));
|
||||
}
|
||||
ssh_scp_free(loc->scp);
|
||||
loc->scp = NULL;
|
||||
}
|
||||
if (loc->session) {
|
||||
ssh_disconnect(loc->session);
|
||||
ssh_free(loc->session);
|
||||
loc->session = NULL;
|
||||
}
|
||||
} else {
|
||||
if (loc->file) {
|
||||
fclose(loc->file);
|
||||
loc->file = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int open_location(struct location *loc, int flag) {
|
||||
if (loc->is_ssh && flag == WRITE) {
|
||||
loc->session = connect_ssh(loc->host, loc->user, verbosity);
|
||||
if (!loc->session) {
|
||||
fprintf(stderr, "Couldn't connect to %s\n", loc->host);
|
||||
return -1;
|
||||
}
|
||||
|
||||
loc->scp = ssh_scp_new(loc->session, SSH_SCP_WRITE, loc->path);
|
||||
if (!loc->scp) {
|
||||
fprintf(stderr, "error : %s\n", ssh_get_error(loc->session));
|
||||
ssh_disconnect(loc->session);
|
||||
ssh_free(loc->session);
|
||||
loc->session = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ssh_scp_init(loc->scp) == SSH_ERROR) {
|
||||
fprintf(stderr, "error : %s\n", ssh_get_error(loc->session));
|
||||
ssh_scp_free(loc->scp);
|
||||
loc->scp = NULL;
|
||||
ssh_disconnect(loc->session);
|
||||
ssh_free(loc->session);
|
||||
loc->session = NULL;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
} else if (loc->is_ssh && flag == READ) {
|
||||
loc->session = connect_ssh(loc->host, loc->user, verbosity);
|
||||
if (!loc->session) {
|
||||
fprintf(stderr, "Couldn't connect to %s\n", loc->host);
|
||||
return -1;
|
||||
}
|
||||
|
||||
loc->scp = ssh_scp_new(loc->session, SSH_SCP_READ, loc->path);
|
||||
if (!loc->scp) {
|
||||
fprintf(stderr, "error : %s\n", ssh_get_error(loc->session));
|
||||
ssh_disconnect(loc->session);
|
||||
ssh_free(loc->session);
|
||||
loc->session = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ssh_scp_init(loc->scp) == SSH_ERROR) {
|
||||
fprintf(stderr, "error : %s\n", ssh_get_error(loc->session));
|
||||
ssh_scp_free(loc->scp);
|
||||
loc->scp = NULL;
|
||||
ssh_disconnect(loc->session);
|
||||
ssh_free(loc->session);
|
||||
loc->session = NULL;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
} else {
|
||||
loc->file = fopen(loc->path, flag == READ ? "r":"w");
|
||||
if (!loc->file) {
|
||||
if (errno == EISDIR) {
|
||||
if (loc->path != NULL && chdir(loc->path)) {
|
||||
fprintf(stderr,
|
||||
"Error changing directory to %s: %s\n",
|
||||
loc->path, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
fprintf(stderr,
|
||||
"Error opening %s: %s\n",
|
||||
loc->path, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
nsources=argc-optind-1;
|
||||
if(nsources < 1){
|
||||
usage(argv[0]);
|
||||
return -1;
|
||||
}
|
||||
sources=malloc((nsources + 1) * sizeof(char *));
|
||||
if(sources == NULL)
|
||||
return -1;
|
||||
for(i=0;i<nsources;++i){
|
||||
sources[i] = argv[optind];
|
||||
optind++;
|
||||
}
|
||||
sources[i]=NULL;
|
||||
destination=argv[optind];
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct location *parse_location(char *loc){
|
||||
struct location *location=malloc(sizeof(struct location));
|
||||
char *ptr;
|
||||
|
||||
location->host=location->user=NULL;
|
||||
ptr=strchr(loc,':');
|
||||
if(ptr != NULL){
|
||||
location->is_ssh=1;
|
||||
location->path=strdup(ptr+1);
|
||||
*ptr='\0';
|
||||
ptr=strchr(loc,'@');
|
||||
if(ptr != NULL){
|
||||
location->host=strdup(ptr+1);
|
||||
*ptr='\0';
|
||||
location->user=strdup(loc);
|
||||
} else {
|
||||
location->host=strdup(loc);
|
||||
}
|
||||
} else {
|
||||
location->is_ssh=0;
|
||||
location->path=strdup(loc);
|
||||
}
|
||||
return location;
|
||||
}
|
||||
|
||||
static int open_location(struct location *loc, int flag){
|
||||
if(loc->is_ssh && flag==WRITE){
|
||||
loc->session=connect_ssh(loc->host,loc->user,verbosity);
|
||||
if(!loc->session){
|
||||
fprintf(stderr,"Couldn't connect to %s\n",loc->host);
|
||||
return -1;
|
||||
}
|
||||
loc->scp=ssh_scp_new(loc->session,SSH_SCP_WRITE,loc->path);
|
||||
if(!loc->scp){
|
||||
fprintf(stderr,"error : %s\n",ssh_get_error(loc->session));
|
||||
return -1;
|
||||
}
|
||||
if(ssh_scp_init(loc->scp)==SSH_ERROR){
|
||||
fprintf(stderr,"error : %s\n",ssh_get_error(loc->session));
|
||||
ssh_scp_free(loc->scp);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
} else if(loc->is_ssh && flag==READ){
|
||||
loc->session=connect_ssh(loc->host, loc->user,verbosity);
|
||||
if(!loc->session){
|
||||
fprintf(stderr,"Couldn't connect to %s\n",loc->host);
|
||||
return -1;
|
||||
}
|
||||
loc->scp=ssh_scp_new(loc->session,SSH_SCP_READ,loc->path);
|
||||
if(!loc->scp){
|
||||
fprintf(stderr,"error : %s\n",ssh_get_error(loc->session));
|
||||
return -1;
|
||||
}
|
||||
if(ssh_scp_init(loc->scp)==SSH_ERROR){
|
||||
fprintf(stderr,"error : %s\n",ssh_get_error(loc->session));
|
||||
ssh_scp_free(loc->scp);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
} else {
|
||||
loc->file=fopen(loc->path,flag==READ ? "r":"w");
|
||||
if(!loc->file){
|
||||
if(errno==EISDIR){
|
||||
if(chdir(loc->path)){
|
||||
fprintf(stderr,"Error changing directory to %s: %s\n",loc->path,strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
fprintf(stderr,"Error opening %s: %s\n",loc->path,strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/** @brief copies files from source location to destination
|
||||
@@ -256,201 +166,139 @@ static int open_location(struct location *loc, int flag) {
|
||||
* @param dest destination location
|
||||
* @param recursive Copy also directories
|
||||
*/
|
||||
static int do_copy(struct location *src, struct location *dest, int recursive) {
|
||||
size_t size;
|
||||
socket_t fd;
|
||||
struct stat s;
|
||||
int w, r;
|
||||
char buffer[BUF_SIZE];
|
||||
size_t total = 0;
|
||||
mode_t mode;
|
||||
char *filename = NULL;
|
||||
|
||||
/* recursive mode doesn't work yet */
|
||||
(void)recursive;
|
||||
/* Get the file name and size*/
|
||||
if (!src->is_ssh) {
|
||||
fd = fileno(src->file);
|
||||
if (fd < 0) {
|
||||
fprintf(stderr,
|
||||
"Invalid file pointer, error: %s\n",
|
||||
strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
r = fstat(fd, &s);
|
||||
if (r < 0) {
|
||||
return -1;
|
||||
}
|
||||
size = s.st_size;
|
||||
mode = s.st_mode & ~S_IFMT;
|
||||
filename = ssh_basename(src->path);
|
||||
} else {
|
||||
size = 0;
|
||||
do {
|
||||
r = ssh_scp_pull_request(src->scp);
|
||||
if (r == SSH_SCP_REQUEST_NEWDIR) {
|
||||
ssh_scp_deny_request(src->scp, "Not in recursive mode");
|
||||
continue;
|
||||
}
|
||||
if (r == SSH_SCP_REQUEST_NEWFILE) {
|
||||
size = ssh_scp_request_get_size(src->scp);
|
||||
filename = strdup(ssh_scp_request_get_filename(src->scp));
|
||||
mode = ssh_scp_request_get_permissions(src->scp);
|
||||
//ssh_scp_accept_request(src->scp);
|
||||
break;
|
||||
}
|
||||
if (r == SSH_ERROR) {
|
||||
fprintf(stderr,
|
||||
"Error: %s\n",
|
||||
ssh_get_error(src->session));
|
||||
SSH_STRING_FREE_CHAR(filename);
|
||||
return -1;
|
||||
}
|
||||
} while(r != SSH_SCP_REQUEST_NEWFILE);
|
||||
}
|
||||
|
||||
if (dest->is_ssh) {
|
||||
r = ssh_scp_push_file(dest->scp, src->path, size, mode);
|
||||
// snprintf(buffer, sizeof(buffer), "C0644 %d %s\n", size, src->path);
|
||||
if (r == SSH_ERROR) {
|
||||
fprintf(stderr,
|
||||
"error: %s\n",
|
||||
ssh_get_error(dest->session));
|
||||
SSH_STRING_FREE_CHAR(filename);
|
||||
ssh_scp_free(dest->scp);
|
||||
dest->scp = NULL;
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
if (!dest->file) {
|
||||
dest->file = fopen(filename, "w");
|
||||
if (!dest->file) {
|
||||
fprintf(stderr,
|
||||
"Cannot open %s for writing: %s\n",
|
||||
filename, strerror(errno));
|
||||
if (src->is_ssh) {
|
||||
ssh_scp_deny_request(src->scp, "Cannot open local file");
|
||||
}
|
||||
SSH_STRING_FREE_CHAR(filename);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (src->is_ssh) {
|
||||
ssh_scp_accept_request(src->scp);
|
||||
}
|
||||
}
|
||||
|
||||
static int do_copy(struct location *src, struct location *dest, int recursive){
|
||||
int size;
|
||||
socket_t fd;
|
||||
struct stat s;
|
||||
int w,r;
|
||||
char buffer[16384];
|
||||
int total=0;
|
||||
int mode;
|
||||
char *filename;
|
||||
/* recursive mode doesn't work yet */
|
||||
(void)recursive;
|
||||
/* Get the file name and size*/
|
||||
if(!src->is_ssh){
|
||||
fd=fileno(src->file);
|
||||
fstat(fd,&s);
|
||||
size=s.st_size;
|
||||
mode = s.st_mode & ~S_IFMT;
|
||||
filename=ssh_basename(src->path);
|
||||
} else {
|
||||
size=0;
|
||||
do {
|
||||
if (src->is_ssh) {
|
||||
r = ssh_scp_read(src->scp, buffer, sizeof(buffer));
|
||||
if (r == SSH_ERROR) {
|
||||
fprintf(stderr,
|
||||
"Error reading scp: %s\n",
|
||||
ssh_get_error(src->session));
|
||||
SSH_STRING_FREE_CHAR(filename);
|
||||
return -1;
|
||||
}
|
||||
r=ssh_scp_pull_request(src->scp);
|
||||
if(r==SSH_SCP_REQUEST_NEWDIR){
|
||||
ssh_scp_deny_request(src->scp,"Not in recursive mode");
|
||||
continue;
|
||||
}
|
||||
if(r==SSH_SCP_REQUEST_NEWFILE){
|
||||
size=ssh_scp_request_get_size(src->scp);
|
||||
filename=strdup(ssh_scp_request_get_filename(src->scp));
|
||||
mode=ssh_scp_request_get_permissions(src->scp);
|
||||
//ssh_scp_accept_request(src->scp);
|
||||
break;
|
||||
}
|
||||
if(r==SSH_ERROR){
|
||||
fprintf(stderr,"Error: %s\n",ssh_get_error(src->session));
|
||||
return -1;
|
||||
}
|
||||
} while(r != SSH_SCP_REQUEST_NEWFILE);
|
||||
}
|
||||
|
||||
if (r == 0) {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
r = fread(buffer, 1, sizeof(buffer), src->file);
|
||||
if (r == 0) {
|
||||
break;
|
||||
}
|
||||
if(dest->is_ssh){
|
||||
r=ssh_scp_push_file(dest->scp,src->path, size, mode);
|
||||
// snprintf(buffer,sizeof(buffer),"C0644 %d %s\n",size,src->path);
|
||||
if(r==SSH_ERROR){
|
||||
fprintf(stderr,"error: %s\n",ssh_get_error(dest->session));
|
||||
ssh_scp_free(dest->scp);
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
if(!dest->file){
|
||||
dest->file=fopen(filename,"w");
|
||||
if(!dest->file){
|
||||
fprintf(stderr,"Cannot open %s for writing: %s\n",filename,strerror(errno));
|
||||
if(src->is_ssh)
|
||||
ssh_scp_deny_request(src->scp,"Cannot open local file");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if(src->is_ssh){
|
||||
ssh_scp_accept_request(src->scp);
|
||||
}
|
||||
}
|
||||
do {
|
||||
if(src->is_ssh){
|
||||
r=ssh_scp_read(src->scp,buffer,sizeof(buffer));
|
||||
if(r==SSH_ERROR){
|
||||
fprintf(stderr,"Error reading scp: %s\n",ssh_get_error(src->session));
|
||||
return -1;
|
||||
}
|
||||
if(r==0)
|
||||
break;
|
||||
} else {
|
||||
r=fread(buffer,1,sizeof(buffer),src->file);
|
||||
if(r==0)
|
||||
break;
|
||||
if(r<0){
|
||||
fprintf(stderr,"Error reading file: %s\n",strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if(dest->is_ssh){
|
||||
w=ssh_scp_write(dest->scp,buffer,r);
|
||||
if(w == SSH_ERROR){
|
||||
fprintf(stderr,"Error writing in scp: %s\n",ssh_get_error(dest->session));
|
||||
ssh_scp_free(dest->scp);
|
||||
dest->scp=NULL;
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
w=fwrite(buffer,r,1,dest->file);
|
||||
if(w<=0){
|
||||
fprintf(stderr,"Error writing in local file: %s\n",strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
total+=r;
|
||||
|
||||
if (r < 0) {
|
||||
fprintf(stderr,
|
||||
"Error reading file: %s\n",
|
||||
strerror(errno));
|
||||
SSH_STRING_FREE_CHAR(filename);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (dest->is_ssh) {
|
||||
w = ssh_scp_write(dest->scp, buffer, r);
|
||||
if (w == SSH_ERROR) {
|
||||
fprintf(stderr,
|
||||
"Error writing in scp: %s\n",
|
||||
ssh_get_error(dest->session));
|
||||
ssh_scp_free(dest->scp);
|
||||
dest->scp = NULL;
|
||||
SSH_STRING_FREE_CHAR(filename);
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
w = fwrite(buffer, r, 1, dest->file);
|
||||
if (w <= 0) {
|
||||
fprintf(stderr,
|
||||
"Error writing in local file: %s\n",
|
||||
strerror(errno));
|
||||
SSH_STRING_FREE_CHAR(filename);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
total += r;
|
||||
|
||||
} while(total < size);
|
||||
|
||||
SSH_STRING_FREE_CHAR(filename);
|
||||
printf("wrote %zu bytes\n", total);
|
||||
return 0;
|
||||
} while(total < size);
|
||||
printf("wrote %d bytes\n",total);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
struct location *dest, *src;
|
||||
int i;
|
||||
int r;
|
||||
if (opts(argc, argv) < 0) {
|
||||
return EXIT_FAILURE;
|
||||
int main(int argc, char **argv){
|
||||
struct location *dest, *src;
|
||||
int i;
|
||||
int r;
|
||||
if(opts(argc,argv)<0)
|
||||
return EXIT_FAILURE;
|
||||
dest=parse_location(destination);
|
||||
if(open_location(dest,WRITE)<0)
|
||||
return EXIT_FAILURE;
|
||||
for(i=0;i<nsources;++i){
|
||||
src=parse_location(sources[i]);
|
||||
if(open_location(src,READ)<0){
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
ssh_init();
|
||||
|
||||
dest = parse_location(destination);
|
||||
if (dest == NULL) {
|
||||
r = EXIT_FAILURE;
|
||||
goto end;
|
||||
if(do_copy(src,dest,0) < 0){
|
||||
break;
|
||||
}
|
||||
|
||||
if (open_location(dest, WRITE) < 0) {
|
||||
location_free(dest);
|
||||
r = EXIT_FAILURE;
|
||||
goto end;
|
||||
}
|
||||
|
||||
for (i = 0; i < nsources; ++i) {
|
||||
src = parse_location(sources[i]);
|
||||
if (src == NULL) {
|
||||
r = EXIT_FAILURE;
|
||||
goto close_dest;
|
||||
}
|
||||
|
||||
if (open_location(src, READ) < 0) {
|
||||
location_free(src);
|
||||
r = EXIT_FAILURE;
|
||||
goto close_dest;
|
||||
}
|
||||
|
||||
if (do_copy(src, dest, 0) < 0) {
|
||||
close_location(src);
|
||||
location_free(src);
|
||||
break;
|
||||
}
|
||||
|
||||
close_location(src);
|
||||
location_free(src);
|
||||
}
|
||||
|
||||
r = 0;
|
||||
|
||||
close_dest:
|
||||
close_location(dest);
|
||||
location_free(dest);
|
||||
end:
|
||||
ssh_finalize();
|
||||
free(sources);
|
||||
return r;
|
||||
}
|
||||
if(dest->is_ssh){
|
||||
r=ssh_scp_close(dest->scp);
|
||||
if(r == SSH_ERROR){
|
||||
fprintf(stderr,"Error closing scp: %s\n",ssh_get_error(dest->session));
|
||||
ssh_scp_free(dest->scp);
|
||||
dest->scp=NULL;
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
fclose(dest->file);
|
||||
dest->file=NULL;
|
||||
}
|
||||
ssh_disconnect(dest->session);
|
||||
ssh_finalize();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ int main(int argc, const char **argv){
|
||||
else
|
||||
session.setOption(SSH_OPTIONS_HOST,"localhost");
|
||||
session.connect();
|
||||
session.userauthPublickeyAuto();
|
||||
session.userauthAutopubkey();
|
||||
session.disconnect();
|
||||
} catch (ssh::SshException e){
|
||||
std::cout << "Error during connection : ";
|
||||
|
||||
@@ -29,7 +29,7 @@ int main(int argc, const char **argv){
|
||||
err=session.connect();
|
||||
if(err==SSH_ERROR)
|
||||
goto error;
|
||||
err=session.userauthPublickeyAuto();
|
||||
err=session.userauthAutopubkey();
|
||||
if(err==SSH_ERROR)
|
||||
goto error;
|
||||
|
||||
|
||||
351
examples/proxy.c
@@ -1,351 +0,0 @@
|
||||
/* This is a sample implementation of a libssh based SSH proxy */
|
||||
/*
|
||||
Copyright 2003-2013 Aris Adamantiadis
|
||||
|
||||
This file is part of the SSH Library
|
||||
|
||||
You are free to copy this file, modify it in any way, consider it being public
|
||||
domain. This does not apply to the rest of the library though, but it is
|
||||
allowed to cut-and-paste working code from this file to any license of
|
||||
program.
|
||||
The goal is to show the API in action. It's not a reference on how terminal
|
||||
clients must be made or how a client should react.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <libssh/libssh.h>
|
||||
#include <libssh/server.h>
|
||||
#include <libssh/callbacks.h>
|
||||
|
||||
#ifdef HAVE_ARGP_H
|
||||
#include <argp.h>
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifndef BUF_SIZE
|
||||
#define BUF_SIZE 2048
|
||||
#endif
|
||||
|
||||
#define USER "myuser"
|
||||
#define PASSWORD "mypassword"
|
||||
|
||||
static int authenticated=0;
|
||||
static int tries = 0;
|
||||
static int error = 0;
|
||||
static ssh_channel chan=NULL;
|
||||
static char *username;
|
||||
static ssh_gssapi_creds client_creds = NULL;
|
||||
|
||||
static int auth_password(ssh_session session, const char *user,
|
||||
const char *password, void *userdata){
|
||||
|
||||
(void)userdata;
|
||||
|
||||
printf("Authenticating user %s pwd %s\n",user, password);
|
||||
if(strcmp(user,USER) == 0 && strcmp(password, PASSWORD) == 0){
|
||||
authenticated = 1;
|
||||
printf("Authenticated\n");
|
||||
return SSH_AUTH_SUCCESS;
|
||||
}
|
||||
if (tries >= 3){
|
||||
printf("Too many authentication tries\n");
|
||||
ssh_disconnect(session);
|
||||
error = 1;
|
||||
return SSH_AUTH_DENIED;
|
||||
}
|
||||
tries++;
|
||||
return SSH_AUTH_DENIED;
|
||||
}
|
||||
|
||||
static int auth_gssapi_mic(ssh_session session, const char *user, const char *principal, void *userdata){
|
||||
(void)userdata;
|
||||
client_creds = ssh_gssapi_get_creds(session);
|
||||
printf("Authenticating user %s with gssapi principal %s\n",user, principal);
|
||||
if (client_creds != NULL)
|
||||
printf("Received some gssapi credentials\n");
|
||||
else
|
||||
printf("Not received any forwardable creds\n");
|
||||
printf("authenticated\n");
|
||||
authenticated = 1;
|
||||
username = strdup(principal);
|
||||
return SSH_AUTH_SUCCESS;
|
||||
}
|
||||
|
||||
static int pty_request(ssh_session session, ssh_channel channel, const char *term,
|
||||
int x,int y, int px, int py, void *userdata){
|
||||
(void) session;
|
||||
(void) channel;
|
||||
(void) term;
|
||||
(void) x;
|
||||
(void) y;
|
||||
(void) px;
|
||||
(void) py;
|
||||
(void) userdata;
|
||||
printf("Allocated terminal\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int shell_request(ssh_session session, ssh_channel channel, void *userdata){
|
||||
(void)session;
|
||||
(void)channel;
|
||||
(void)userdata;
|
||||
printf("Allocated shell\n");
|
||||
return 0;
|
||||
}
|
||||
struct ssh_channel_callbacks_struct channel_cb = {
|
||||
.channel_pty_request_function = pty_request,
|
||||
.channel_shell_request_function = shell_request
|
||||
};
|
||||
|
||||
static ssh_channel new_session_channel(ssh_session session, void *userdata){
|
||||
(void) session;
|
||||
(void) userdata;
|
||||
if(chan != NULL)
|
||||
return NULL;
|
||||
printf("Allocated session channel\n");
|
||||
chan = ssh_channel_new(session);
|
||||
ssh_callbacks_init(&channel_cb);
|
||||
ssh_set_channel_callbacks(chan, &channel_cb);
|
||||
return chan;
|
||||
}
|
||||
|
||||
|
||||
#ifdef HAVE_ARGP_H
|
||||
const char *argp_program_version = "libssh proxy example "
|
||||
SSH_STRINGIFY(LIBSSH_VERSION);
|
||||
const char *argp_program_bug_address = "<libssh@libssh.org>";
|
||||
|
||||
/* Program documentation. */
|
||||
static char doc[] = "libssh -- a Secure Shell protocol implementation";
|
||||
|
||||
/* A description of the arguments we accept. */
|
||||
static char args_doc[] = "BINDADDR";
|
||||
|
||||
/* The options we understand. */
|
||||
static struct argp_option options[] = {
|
||||
{
|
||||
.name = "port",
|
||||
.key = 'p',
|
||||
.arg = "PORT",
|
||||
.flags = 0,
|
||||
.doc = "Set the port to bind.",
|
||||
.group = 0
|
||||
},
|
||||
{
|
||||
.name = "hostkey",
|
||||
.key = 'k',
|
||||
.arg = "FILE",
|
||||
.flags = 0,
|
||||
.doc = "Set the host key.",
|
||||
.group = 0
|
||||
},
|
||||
{
|
||||
.name = "dsakey",
|
||||
.key = 'd',
|
||||
.arg = "FILE",
|
||||
.flags = 0,
|
||||
.doc = "Set the dsa key.",
|
||||
.group = 0
|
||||
},
|
||||
{
|
||||
.name = "rsakey",
|
||||
.key = 'r',
|
||||
.arg = "FILE",
|
||||
.flags = 0,
|
||||
.doc = "Set the rsa key.",
|
||||
.group = 0
|
||||
},
|
||||
{
|
||||
.name = "verbose",
|
||||
.key = 'v',
|
||||
.arg = NULL,
|
||||
.flags = 0,
|
||||
.doc = "Get verbose output.",
|
||||
.group = 0
|
||||
},
|
||||
{NULL, 0, NULL, 0, NULL, 0}
|
||||
};
|
||||
|
||||
/* Parse a single option. */
|
||||
static error_t parse_opt (int key, char *arg, struct argp_state *state) {
|
||||
/* Get the input argument from argp_parse, which we
|
||||
* know is a pointer to our arguments structure.
|
||||
*/
|
||||
ssh_bind sshbind = state->input;
|
||||
|
||||
switch (key) {
|
||||
case 'p':
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_BINDPORT_STR, arg);
|
||||
break;
|
||||
case 'd':
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_DSAKEY, arg);
|
||||
break;
|
||||
case 'k':
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_HOSTKEY, arg);
|
||||
break;
|
||||
case 'r':
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_RSAKEY, arg);
|
||||
break;
|
||||
case 'v':
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_LOG_VERBOSITY_STR, "3");
|
||||
break;
|
||||
case ARGP_KEY_ARG:
|
||||
if (state->arg_num >= 1) {
|
||||
/* Too many arguments. */
|
||||
argp_usage (state);
|
||||
}
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_BINDADDR, arg);
|
||||
break;
|
||||
case ARGP_KEY_END:
|
||||
if (state->arg_num < 1) {
|
||||
/* Not enough arguments. */
|
||||
argp_usage (state);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return ARGP_ERR_UNKNOWN;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Our argp parser. */
|
||||
static struct argp argp = {options, parse_opt, args_doc, doc, NULL, NULL, NULL};
|
||||
#endif /* HAVE_ARGP_H */
|
||||
|
||||
int main(int argc, char **argv){
|
||||
ssh_session session;
|
||||
ssh_bind sshbind;
|
||||
ssh_event mainloop;
|
||||
ssh_session client_session;
|
||||
|
||||
struct ssh_server_callbacks_struct cb = {
|
||||
.userdata = NULL,
|
||||
.auth_password_function = auth_password,
|
||||
.auth_gssapi_mic_function = auth_gssapi_mic,
|
||||
.channel_open_request_session_function = new_session_channel
|
||||
};
|
||||
|
||||
char buf[BUF_SIZE];
|
||||
char host[128]="";
|
||||
char *ptr;
|
||||
int i,r, rc;
|
||||
|
||||
sshbind=ssh_bind_new();
|
||||
session=ssh_new();
|
||||
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_RSAKEY, "sshd_rsa");
|
||||
|
||||
#ifdef HAVE_ARGP_H
|
||||
/*
|
||||
* Parse our arguments; every option seen by parse_opt will
|
||||
* be reflected in arguments.
|
||||
*/
|
||||
argp_parse (&argp, argc, argv, 0, 0, sshbind);
|
||||
#else
|
||||
(void) argc;
|
||||
(void) argv;
|
||||
#endif
|
||||
|
||||
if(ssh_bind_listen(sshbind)<0){
|
||||
printf("Error listening to socket: %s\n",ssh_get_error(sshbind));
|
||||
return 1;
|
||||
}
|
||||
r=ssh_bind_accept(sshbind,session);
|
||||
if(r==SSH_ERROR){
|
||||
printf("error accepting a connection : %s\n",ssh_get_error(sshbind));
|
||||
return 1;
|
||||
}
|
||||
ssh_callbacks_init(&cb);
|
||||
ssh_set_server_callbacks(session, &cb);
|
||||
|
||||
if (ssh_handle_key_exchange(session)) {
|
||||
printf("ssh_handle_key_exchange: %s\n", ssh_get_error(session));
|
||||
return 1;
|
||||
}
|
||||
ssh_set_auth_methods(session,SSH_AUTH_METHOD_PASSWORD | SSH_AUTH_METHOD_GSSAPI_MIC);
|
||||
mainloop = ssh_event_new();
|
||||
ssh_event_add_session(mainloop, session);
|
||||
|
||||
while (!(authenticated && chan != NULL)){
|
||||
if(error)
|
||||
break;
|
||||
r = ssh_event_dopoll(mainloop, -1);
|
||||
if (r == SSH_ERROR){
|
||||
printf("Error : %s\n",ssh_get_error(session));
|
||||
ssh_disconnect(session);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if(error){
|
||||
printf("Error, exiting loop\n");
|
||||
return 1;
|
||||
} else
|
||||
printf("Authenticated and got a channel\n");
|
||||
if (!client_creds){
|
||||
snprintf(buf,sizeof(buf), "Sorry, but you do not have forwardable tickets. Try again with -K\r\n");
|
||||
ssh_channel_write(chan,buf,strlen(buf));
|
||||
printf("%s",buf);
|
||||
ssh_disconnect(session);
|
||||
return 1;
|
||||
}
|
||||
snprintf(buf,sizeof(buf), "Hello %s, welcome to the Sample SSH proxy.\r\nPlease select your destination: ", username);
|
||||
ssh_channel_write(chan, buf, strlen(buf));
|
||||
do{
|
||||
i=ssh_channel_read(chan,buf, sizeof(buf), 0);
|
||||
if(i>0) {
|
||||
ssh_channel_write(chan, buf, i);
|
||||
if(strlen(host) + i < sizeof(host)){
|
||||
strncat(host, buf, i);
|
||||
}
|
||||
if (strchr(host, '\x0d')) {
|
||||
*strchr(host, '\x0d')='\0';
|
||||
ssh_channel_write(chan, "\n", 1);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
printf ("Error: %s\n", ssh_get_error(session) );
|
||||
return 1;
|
||||
}
|
||||
} while (i>0);
|
||||
snprintf(buf,sizeof(buf),"Trying to connect to \"%s\"\r\n", host);
|
||||
ssh_channel_write(chan, buf, strlen(buf));
|
||||
printf("%s",buf);
|
||||
|
||||
client_session = ssh_new();
|
||||
|
||||
/* ssh servers expect username without realm */
|
||||
ptr = strchr(username,'@');
|
||||
if(ptr)
|
||||
*ptr= '\0';
|
||||
ssh_options_set(client_session, SSH_OPTIONS_HOST, host);
|
||||
ssh_options_set(client_session, SSH_OPTIONS_USER, username);
|
||||
ssh_gssapi_set_creds(client_session, client_creds);
|
||||
rc = ssh_connect(client_session);
|
||||
if (rc != SSH_OK){
|
||||
printf("Error connecting to %s: %s", host, ssh_get_error(client_session));
|
||||
return 1;
|
||||
}
|
||||
rc = ssh_userauth_none(client_session, NULL);
|
||||
if(rc == SSH_AUTH_SUCCESS){
|
||||
printf("Authenticated using method none\n");
|
||||
} else {
|
||||
rc = ssh_userauth_gssapi(client_session);
|
||||
if(rc != SSH_AUTH_SUCCESS){
|
||||
printf("GSSAPI Authentication failed: %s\n",ssh_get_error(client_session));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
snprintf(buf,sizeof(buf), "Authentication success\r\n");
|
||||
printf("%s",buf);
|
||||
ssh_channel_write(chan,buf,strlen(buf));
|
||||
ssh_disconnect(client_session);
|
||||
ssh_disconnect(session);
|
||||
ssh_bind_free(sshbind);
|
||||
ssh_finalize();
|
||||
return 0;
|
||||
}
|
||||
|
||||
538
examples/sample.c
Normal file
@@ -0,0 +1,538 @@
|
||||
/* client.c */
|
||||
/*
|
||||
Copyright 2003-2009 Aris Adamantiadis
|
||||
|
||||
This file is part of the SSH Library
|
||||
|
||||
You are free to copy this file, modify it in any way, consider it being public
|
||||
domain. This does not apply to the rest of the library though, but it is
|
||||
allowed to cut-and-paste working code from this file to any license of
|
||||
program.
|
||||
The goal is to show the API in action. It's not a reference on how terminal
|
||||
clients must be made or how a client should react.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <termios.h>
|
||||
|
||||
#include <sys/select.h>
|
||||
#include <sys/time.h>
|
||||
#ifdef HAVE_PTY_H
|
||||
#include <pty.h>
|
||||
#endif
|
||||
#include <sys/ioctl.h>
|
||||
#include <signal.h>
|
||||
#include <errno.h>
|
||||
#include <libssh/callbacks.h>
|
||||
#include <libssh/libssh.h>
|
||||
#include <libssh/sftp.h>
|
||||
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "examples_common.h"
|
||||
#define MAXCMD 10
|
||||
char *host;
|
||||
char *user;
|
||||
char *cmds[MAXCMD];
|
||||
struct termios terminal;
|
||||
|
||||
char *pcap_file=NULL;
|
||||
|
||||
char *proxycommand;
|
||||
|
||||
static int auth_callback(const char *prompt, char *buf, size_t len,
|
||||
int echo, int verify, void *userdata) {
|
||||
char *answer = NULL;
|
||||
char *ptr;
|
||||
|
||||
(void) verify;
|
||||
(void) userdata;
|
||||
|
||||
if (echo) {
|
||||
while ((answer = fgets(buf, len, stdin)) == NULL);
|
||||
if ((ptr = strchr(buf, '\n'))) {
|
||||
*ptr = '\0';
|
||||
}
|
||||
} else {
|
||||
if (ssh_getpass(prompt, buf, len, 0, 0) < 0) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (answer == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
strncpy(buf, answer, len);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct ssh_callbacks_struct cb = {
|
||||
.auth_function=auth_callback,
|
||||
.userdata=NULL
|
||||
};
|
||||
|
||||
static void add_cmd(char *cmd){
|
||||
int n;
|
||||
for(n=0;cmds[n] && (n<MAXCMD);n++);
|
||||
if(n==MAXCMD)
|
||||
return;
|
||||
cmds[n]=strdup(cmd);
|
||||
}
|
||||
|
||||
static void usage(){
|
||||
fprintf(stderr,"Usage : ssh [options] [login@]hostname\n"
|
||||
"sample client - libssh-%s\n"
|
||||
"Options :\n"
|
||||
" -l user : log in as user\n"
|
||||
" -p port : connect to port\n"
|
||||
" -d : use DSS to verify host public key\n"
|
||||
" -r : use RSA to verify host public key\n"
|
||||
#ifdef WITH_PCAP
|
||||
" -P file : create a pcap debugging file\n"
|
||||
#endif
|
||||
#ifndef _WIN32
|
||||
" -T proxycommand : command to execute as a socket proxy\n"
|
||||
#endif
|
||||
,
|
||||
ssh_version(0));
|
||||
exit(0);
|
||||
}
|
||||
|
||||
static int opts(int argc, char **argv){
|
||||
int i;
|
||||
// for(i=0;i<argc;i++)
|
||||
// printf("%d : %s\n",i,argv[i]);
|
||||
/* insert your own arguments here */
|
||||
while((i=getopt(argc,argv,"T:P:"))!=-1){
|
||||
switch(i){
|
||||
case 'P':
|
||||
pcap_file=optarg;
|
||||
break;
|
||||
#ifndef _WIN32
|
||||
case 'T':
|
||||
proxycommand=optarg;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
fprintf(stderr,"unknown option %c\n",optopt);
|
||||
usage();
|
||||
}
|
||||
}
|
||||
if(optind < argc)
|
||||
host=argv[optind++];
|
||||
while(optind < argc)
|
||||
add_cmd(argv[optind++]);
|
||||
if(host==NULL)
|
||||
usage();
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef HAVE_CFMAKERAW
|
||||
static void cfmakeraw(struct termios *termios_p){
|
||||
termios_p->c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
|
||||
termios_p->c_oflag &= ~OPOST;
|
||||
termios_p->c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
|
||||
termios_p->c_cflag &= ~(CSIZE|PARENB);
|
||||
termios_p->c_cflag |= CS8;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static void do_cleanup(int i) {
|
||||
/* unused variable */
|
||||
(void) i;
|
||||
|
||||
tcsetattr(0,TCSANOW,&terminal);
|
||||
}
|
||||
|
||||
static void do_exit(int i) {
|
||||
/* unused variable */
|
||||
(void) i;
|
||||
|
||||
do_cleanup(0);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
ssh_channel chan;
|
||||
int signal_delayed=0;
|
||||
|
||||
static void sigwindowchanged(int i){
|
||||
(void) i;
|
||||
signal_delayed=1;
|
||||
}
|
||||
|
||||
static void setsignal(void){
|
||||
signal(SIGWINCH, sigwindowchanged);
|
||||
signal_delayed=0;
|
||||
}
|
||||
|
||||
static void sizechanged(void){
|
||||
struct winsize win = { 0, 0, 0, 0 };
|
||||
ioctl(1, TIOCGWINSZ, &win);
|
||||
ssh_channel_change_pty_size(chan,win.ws_col, win.ws_row);
|
||||
// printf("Changed pty size\n");
|
||||
setsignal();
|
||||
}
|
||||
|
||||
/* There are two flavors of select loop: the one based on
|
||||
* ssh_select and the one based on channel_select.
|
||||
* The ssh_select one permits you to give your own file descriptors to
|
||||
* follow. It is thus a complete select loop.
|
||||
* The second one only selects on channels. It is simplier to use
|
||||
* but doesn't permit you to fill in your own file descriptor. It is
|
||||
* more adapted if you can't use ssh_select as a main loop (because
|
||||
* you already have another main loop system).
|
||||
*/
|
||||
|
||||
#ifdef USE_CHANNEL_SELECT
|
||||
|
||||
/* channel_select base main loop, with a standard select(2)
|
||||
*/
|
||||
static void select_loop(ssh_session session,ssh_channel channel){
|
||||
fd_set fds;
|
||||
struct timeval timeout;
|
||||
char buffer[4096];
|
||||
ssh_buffer readbuf=ssh_buffer_new();
|
||||
ssh_channel channels[2];
|
||||
int lus;
|
||||
int eof=0;
|
||||
int maxfd;
|
||||
int ret;
|
||||
while(channel){
|
||||
/* when a signal is caught, ssh_select will return
|
||||
* with SSH_EINTR, which means it should be started
|
||||
* again. It lets you handle the signal the faster you
|
||||
* can, like in this window changed example. Of course, if
|
||||
* your signal handler doesn't call libssh at all, you're
|
||||
* free to handle signals directly in sighandler.
|
||||
*/
|
||||
do{
|
||||
FD_ZERO(&fds);
|
||||
if(!eof)
|
||||
FD_SET(0,&fds);
|
||||
timeout.tv_sec=30;
|
||||
timeout.tv_usec=0;
|
||||
FD_SET(ssh_get_fd(session),&fds);
|
||||
maxfd=ssh_get_fd(session)+1;
|
||||
ret=select(maxfd,&fds,NULL,NULL,&timeout);
|
||||
if(ret==EINTR)
|
||||
continue;
|
||||
if(FD_ISSET(0,&fds)){
|
||||
lus=read(0,buffer,sizeof(buffer));
|
||||
if(lus)
|
||||
ssh_channel_write(channel,buffer,lus);
|
||||
else {
|
||||
eof=1;
|
||||
ssh_channel_send_eof(channel);
|
||||
}
|
||||
}
|
||||
if(FD_ISSET(ssh_get_fd(session),&fds)){
|
||||
ssh_set_fd_toread(session);
|
||||
}
|
||||
channels[0]=channel; // set the first channel we want to read from
|
||||
channels[1]=NULL;
|
||||
ret=ssh_channel_select(channels,NULL,NULL,NULL); // no specific timeout - just poll
|
||||
if(signal_delayed)
|
||||
sizechanged();
|
||||
} while (ret==EINTR || ret==SSH_EINTR);
|
||||
|
||||
// we already looked for input from stdin. Now, we are looking for input from the channel
|
||||
|
||||
if(channel && ssh_channel_is_closed(channel)){
|
||||
ssh_log(session,SSH_LOG_RARE,"exit-status : %d",ssh_channel_get_exit_status(channel));
|
||||
|
||||
ssh_channel_free(channel);
|
||||
channel=NULL;
|
||||
channels[0]=NULL;
|
||||
}
|
||||
if(channels[0]){
|
||||
while(channel && ssh_channel_is_open(channel) && ssh_channel_poll(channel,0)>0){
|
||||
lus=channel_read_buffer(channel,readbuf,0,0);
|
||||
if(lus==-1){
|
||||
fprintf(stderr, "Error reading channel: %s\n",
|
||||
ssh_get_error(session));
|
||||
return;
|
||||
}
|
||||
if(lus==0){
|
||||
ssh_log(session,SSH_LOG_RARE,"EOF received");
|
||||
ssh_log(session,SSH_LOG_RARE,"exit-status : %d",ssh_channel_get_exit_status(channel));
|
||||
|
||||
ssh_channel_free(channel);
|
||||
channel=channels[0]=NULL;
|
||||
} else
|
||||
if (write(1,ssh_buffer_get_begin(readbuf),lus) < 0) {
|
||||
fprintf(stderr, "Error writing to buffer\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
while(channel && ssh_channel_is_open(channel) && ssh_channel_poll(channel,1)>0){ /* stderr */
|
||||
lus=channel_read_buffer(channel,readbuf,0,1);
|
||||
if(lus==-1){
|
||||
fprintf(stderr, "Error reading channel: %s\n",
|
||||
ssh_get_error(session));
|
||||
return;
|
||||
}
|
||||
if(lus==0){
|
||||
ssh_log(session,SSH_LOG_RARE,"EOF received");
|
||||
ssh_log(session,SSH_LOG_RARE,"exit-status : %d",ssh_channel_get_exit_status(channel));
|
||||
ssh_channel_free(channel);
|
||||
channel=channels[0]=NULL;
|
||||
} else
|
||||
if (write(2,ssh_buffer_get_begin(readbuf),lus) < 0) {
|
||||
fprintf(stderr, "Error writing to buffer\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(channel && ssh_channel_is_closed(channel)){
|
||||
ssh_channel_free(channel);
|
||||
channel=NULL;
|
||||
}
|
||||
}
|
||||
ssh_buffer_free(readbuf);
|
||||
}
|
||||
#else /* CHANNEL_SELECT */
|
||||
|
||||
static void select_loop(ssh_session session,ssh_channel channel){
|
||||
fd_set fds;
|
||||
struct timeval timeout;
|
||||
char buffer[4096];
|
||||
/* channels will be set to the channels to poll.
|
||||
* outchannels will contain the result of the poll
|
||||
*/
|
||||
ssh_channel channels[2], outchannels[2];
|
||||
int lus;
|
||||
int eof=0;
|
||||
int maxfd;
|
||||
int ret;
|
||||
while(channel){
|
||||
do{
|
||||
FD_ZERO(&fds);
|
||||
if(!eof)
|
||||
FD_SET(0,&fds);
|
||||
timeout.tv_sec=30;
|
||||
timeout.tv_usec=0;
|
||||
FD_SET(ssh_get_fd(session),&fds);
|
||||
maxfd=ssh_get_fd(session)+1;
|
||||
channels[0]=channel; // set the first channel we want to read from
|
||||
channels[1]=NULL;
|
||||
ret=ssh_select(channels,outchannels,maxfd,&fds,&timeout);
|
||||
if(signal_delayed)
|
||||
sizechanged();
|
||||
if(ret==EINTR)
|
||||
continue;
|
||||
if(FD_ISSET(0,&fds)){
|
||||
lus=read(0,buffer,sizeof(buffer));
|
||||
if(lus)
|
||||
ssh_channel_write(channel,buffer,lus);
|
||||
else {
|
||||
eof=1;
|
||||
ssh_channel_send_eof(channel);
|
||||
}
|
||||
}
|
||||
if(channel && ssh_channel_is_closed(channel)){
|
||||
ssh_log(session,SSH_LOG_RARE,"exit-status : %d",ssh_channel_get_exit_status(channel));
|
||||
|
||||
ssh_channel_free(channel);
|
||||
channel=NULL;
|
||||
channels[0]=NULL;
|
||||
}
|
||||
if(outchannels[0]){
|
||||
while(channel && ssh_channel_is_open(channel) && ssh_channel_poll(channel,0)!=0){
|
||||
lus=ssh_channel_read(channel,buffer,sizeof(buffer),0);
|
||||
if(lus==-1){
|
||||
fprintf(stderr, "Error reading channel: %s\n",
|
||||
ssh_get_error(session));
|
||||
return;
|
||||
}
|
||||
if(lus==0){
|
||||
ssh_log(session,SSH_LOG_RARE,"EOF received");
|
||||
ssh_log(session,SSH_LOG_RARE,"exit-status : %d",ssh_channel_get_exit_status(channel));
|
||||
|
||||
ssh_channel_free(channel);
|
||||
channel=channels[0]=NULL;
|
||||
} else
|
||||
if (write(1,buffer,lus) < 0) {
|
||||
fprintf(stderr, "Error writing to buffer\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
while(channel && ssh_channel_is_open(channel) && ssh_channel_poll(channel,1)!=0){ /* stderr */
|
||||
lus=ssh_channel_read(channel,buffer,sizeof(buffer),1);
|
||||
if(lus==-1){
|
||||
fprintf(stderr, "Error reading channel: %s\n",
|
||||
ssh_get_error(session));
|
||||
return;
|
||||
}
|
||||
if(lus==0){
|
||||
ssh_log(session,SSH_LOG_RARE,"EOF received");
|
||||
ssh_log(session,SSH_LOG_RARE,"exit-status : %d",ssh_channel_get_exit_status(channel));
|
||||
ssh_channel_free(channel);
|
||||
channel=channels[0]=NULL;
|
||||
} else
|
||||
if (write(2,buffer,lus) < 0) {
|
||||
fprintf(stderr, "Error writing to buffer\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(channel && ssh_channel_is_closed(channel)){
|
||||
ssh_channel_free(channel);
|
||||
channel=NULL;
|
||||
}
|
||||
} while (ret==EINTR || ret==SSH_EINTR);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static void shell(ssh_session session){
|
||||
ssh_channel channel;
|
||||
struct termios terminal_local;
|
||||
int interactive=isatty(0);
|
||||
channel = ssh_channel_new(session);
|
||||
if(interactive){
|
||||
tcgetattr(0,&terminal_local);
|
||||
memcpy(&terminal,&terminal_local,sizeof(struct termios));
|
||||
}
|
||||
if(ssh_channel_open_session(channel)){
|
||||
printf("error opening channel : %s\n",ssh_get_error(session));
|
||||
return;
|
||||
}
|
||||
chan=channel;
|
||||
if(interactive){
|
||||
ssh_channel_request_pty(channel);
|
||||
sizechanged();
|
||||
}
|
||||
if(ssh_channel_request_shell(channel)){
|
||||
printf("Requesting shell : %s\n",ssh_get_error(session));
|
||||
return;
|
||||
}
|
||||
if(interactive){
|
||||
cfmakeraw(&terminal_local);
|
||||
tcsetattr(0,TCSANOW,&terminal_local);
|
||||
setsignal();
|
||||
}
|
||||
signal(SIGTERM,do_cleanup);
|
||||
select_loop(session,channel);
|
||||
if(interactive)
|
||||
do_cleanup(0);
|
||||
}
|
||||
|
||||
static void batch_shell(ssh_session session){
|
||||
ssh_channel channel;
|
||||
char buffer[1024];
|
||||
int i,s=0;
|
||||
for(i=0;i<MAXCMD && cmds[i];++i) {
|
||||
s+=snprintf(buffer+s,sizeof(buffer)-s,"%s ",cmds[i]);
|
||||
free(cmds[i]);
|
||||
cmds[i] = NULL;
|
||||
}
|
||||
channel=ssh_channel_new(session);
|
||||
ssh_channel_open_session(channel);
|
||||
if(ssh_channel_request_exec(channel,buffer)){
|
||||
printf("error executing \"%s\" : %s\n",buffer,ssh_get_error(session));
|
||||
return;
|
||||
}
|
||||
select_loop(session,channel);
|
||||
}
|
||||
|
||||
static int client(ssh_session session){
|
||||
int auth=0;
|
||||
char *banner;
|
||||
int state;
|
||||
if (user)
|
||||
if (ssh_options_set(session, SSH_OPTIONS_USER, user) < 0)
|
||||
return -1;
|
||||
if (ssh_options_set(session, SSH_OPTIONS_HOST ,host) < 0)
|
||||
return -1;
|
||||
if (proxycommand != NULL){
|
||||
if(ssh_options_set(session, SSH_OPTIONS_PROXYCOMMAND, proxycommand))
|
||||
return -1;
|
||||
}
|
||||
ssh_options_parse_config(session, NULL);
|
||||
|
||||
if(ssh_connect(session)){
|
||||
fprintf(stderr,"Connection failed : %s\n",ssh_get_error(session));
|
||||
return -1;
|
||||
}
|
||||
state=verify_knownhost(session);
|
||||
if (state != 0)
|
||||
return -1;
|
||||
ssh_userauth_none(session, NULL);
|
||||
banner=ssh_get_issue_banner(session);
|
||||
if(banner){
|
||||
printf("%s\n",banner);
|
||||
free(banner);
|
||||
}
|
||||
auth=authenticate_console(session);
|
||||
if(auth != SSH_AUTH_SUCCESS){
|
||||
return -1;
|
||||
}
|
||||
ssh_log(session, SSH_LOG_FUNCTIONS, "Authentication success");
|
||||
if(!cmds[0])
|
||||
shell(session);
|
||||
else
|
||||
batch_shell(session);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ssh_pcap_file pcap;
|
||||
void set_pcap(ssh_session session);
|
||||
void set_pcap(ssh_session session){
|
||||
if(!pcap_file)
|
||||
return;
|
||||
pcap=ssh_pcap_file_new();
|
||||
if(!pcap)
|
||||
return;
|
||||
if(ssh_pcap_file_open(pcap,pcap_file) == SSH_ERROR){
|
||||
printf("Error opening pcap file\n");
|
||||
ssh_pcap_file_free(pcap);
|
||||
pcap=NULL;
|
||||
return;
|
||||
}
|
||||
ssh_set_pcap_file(session,pcap);
|
||||
}
|
||||
|
||||
void cleanup_pcap(void);
|
||||
void cleanup_pcap(){
|
||||
if(pcap)
|
||||
ssh_pcap_file_free(pcap);
|
||||
pcap=NULL;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv){
|
||||
ssh_session session;
|
||||
|
||||
session = ssh_new();
|
||||
|
||||
ssh_callbacks_init(&cb);
|
||||
ssh_set_callbacks(session,&cb);
|
||||
|
||||
if(ssh_options_getopt(session, &argc, argv)) {
|
||||
fprintf(stderr, "error parsing command line :%s\n",
|
||||
ssh_get_error(session));
|
||||
usage();
|
||||
}
|
||||
opts(argc,argv);
|
||||
signal(SIGTERM, do_exit);
|
||||
|
||||
set_pcap(session);
|
||||
client(session);
|
||||
|
||||
ssh_disconnect(session);
|
||||
ssh_free(session);
|
||||
cleanup_pcap();
|
||||
|
||||
ssh_finalize();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -15,13 +15,11 @@ clients must be made or how a client should react.
|
||||
|
||||
#include <sys/statvfs.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <libssh/libssh.h>
|
||||
#include <libssh/sftp.h>
|
||||
@@ -29,265 +27,239 @@ clients must be made or how a client should react.
|
||||
#include "examples_common.h"
|
||||
#ifdef WITH_SFTP
|
||||
|
||||
#ifndef BUF_SIZE
|
||||
#define BUF_SIZE 65536
|
||||
#endif
|
||||
|
||||
static int verbosity;
|
||||
static char *destination;
|
||||
|
||||
static void do_sftp(ssh_session session) {
|
||||
sftp_session sftp = sftp_new(session);
|
||||
int verbosity;
|
||||
char *destination;
|
||||
#define DATALEN 65536
|
||||
static void do_sftp(ssh_session session){
|
||||
sftp_session sftp=sftp_new(session);
|
||||
sftp_dir dir;
|
||||
sftp_attributes file;
|
||||
sftp_statvfs_t sftpstatvfs;
|
||||
struct statvfs sysstatvfs;
|
||||
sftp_file fichier;
|
||||
sftp_file to;
|
||||
int len = 1;
|
||||
int len=1;
|
||||
unsigned int i;
|
||||
char data[BUF_SIZE] = {0};
|
||||
char data[DATALEN]={0};
|
||||
char *lnk;
|
||||
|
||||
unsigned int count;
|
||||
|
||||
if (!sftp) {
|
||||
if(!sftp){
|
||||
fprintf(stderr, "sftp error initialising channel: %s\n",
|
||||
ssh_get_error(session));
|
||||
goto end;
|
||||
ssh_get_error(session));
|
||||
return;
|
||||
}
|
||||
|
||||
if (sftp_init(sftp)) {
|
||||
if(sftp_init(sftp)){
|
||||
fprintf(stderr, "error initialising sftp: %s\n",
|
||||
ssh_get_error(session));
|
||||
goto end;
|
||||
ssh_get_error(session));
|
||||
return;
|
||||
}
|
||||
|
||||
printf("Additional SFTP extensions provided by the server:\n");
|
||||
count = sftp_extensions_get_count(sftp);
|
||||
for (i = 0; i < count; i++) {
|
||||
printf("\t%s, version: %s\n",
|
||||
sftp_extensions_get_name(sftp, i),
|
||||
sftp_extensions_get_data(sftp, i));
|
||||
printf("\t%s, version: %s\n",
|
||||
sftp_extensions_get_name(sftp, i),
|
||||
sftp_extensions_get_data(sftp, i));
|
||||
}
|
||||
|
||||
/* test symlink and readlink */
|
||||
if (sftp_symlink(sftp, "/tmp/this_is_the_link",
|
||||
"/tmp/sftp_symlink_test") < 0)
|
||||
{
|
||||
fprintf(stderr, "Could not create link (%s)\n",
|
||||
ssh_get_error(session));
|
||||
goto end;
|
||||
"/tmp/sftp_symlink_test") < 0) {
|
||||
fprintf(stderr, "Could not create link (%s)\n", ssh_get_error(session));
|
||||
return;
|
||||
}
|
||||
|
||||
lnk = sftp_readlink(sftp, "/tmp/sftp_symlink_test");
|
||||
if (lnk == NULL) {
|
||||
fprintf(stderr, "Could not read link (%s)\n", ssh_get_error(session));
|
||||
goto end;
|
||||
fprintf(stderr, "Could not read link (%s)\n", ssh_get_error(session));
|
||||
return;
|
||||
}
|
||||
printf("readlink /tmp/sftp_symlink_test: %s\n", lnk);
|
||||
|
||||
sftp_unlink(sftp, "/tmp/sftp_symlink_test");
|
||||
|
||||
if (sftp_extension_supported(sftp, "statvfs@openssh.com", "2")) {
|
||||
sftpstatvfs = sftp_statvfs(sftp, "/tmp");
|
||||
if (sftpstatvfs == NULL) {
|
||||
fprintf(stderr, "statvfs failed (%s)\n", ssh_get_error(session));
|
||||
goto end;
|
||||
}
|
||||
sftpstatvfs = sftp_statvfs(sftp, "/tmp");
|
||||
if (sftpstatvfs == NULL) {
|
||||
fprintf(stderr, "statvfs failed (%s)\n", ssh_get_error(session));
|
||||
return;
|
||||
}
|
||||
|
||||
printf("sftp statvfs:\n"
|
||||
"\tfile system block size: %llu\n"
|
||||
"\tfundamental fs block size: %llu\n"
|
||||
"\tnumber of blocks (unit f_frsize): %llu\n"
|
||||
"\tfree blocks in file system: %llu\n"
|
||||
"\tfree blocks for non-root: %llu\n"
|
||||
"\ttotal file inodes: %llu\n"
|
||||
"\tfree file inodes: %llu\n"
|
||||
"\tfree file inodes for to non-root: %llu\n"
|
||||
"\tfile system id: %llu\n"
|
||||
"\tbit mask of f_flag values: %llu\n"
|
||||
"\tmaximum filename length: %llu\n",
|
||||
(unsigned long long) sftpstatvfs->f_bsize,
|
||||
(unsigned long long) sftpstatvfs->f_frsize,
|
||||
(unsigned long long) sftpstatvfs->f_blocks,
|
||||
(unsigned long long) sftpstatvfs->f_bfree,
|
||||
(unsigned long long) sftpstatvfs->f_bavail,
|
||||
(unsigned long long) sftpstatvfs->f_files,
|
||||
(unsigned long long) sftpstatvfs->f_ffree,
|
||||
(unsigned long long) sftpstatvfs->f_favail,
|
||||
(unsigned long long) sftpstatvfs->f_fsid,
|
||||
(unsigned long long) sftpstatvfs->f_flag,
|
||||
(unsigned long long) sftpstatvfs->f_namemax);
|
||||
printf("sftp statvfs:\n"
|
||||
"\tfile system block size: %llu\n"
|
||||
"\tfundamental fs block size: %llu\n"
|
||||
"\tnumber of blocks (unit f_frsize): %llu\n"
|
||||
"\tfree blocks in file system: %llu\n"
|
||||
"\tfree blocks for non-root: %llu\n"
|
||||
"\ttotal file inodes: %llu\n"
|
||||
"\tfree file inodes: %llu\n"
|
||||
"\tfree file inodes for to non-root: %llu\n"
|
||||
"\tfile system id: %llu\n"
|
||||
"\tbit mask of f_flag values: %llu\n"
|
||||
"\tmaximum filename length: %llu\n",
|
||||
(unsigned long long) sftpstatvfs->f_bsize,
|
||||
(unsigned long long) sftpstatvfs->f_frsize,
|
||||
(unsigned long long) sftpstatvfs->f_blocks,
|
||||
(unsigned long long) sftpstatvfs->f_bfree,
|
||||
(unsigned long long) sftpstatvfs->f_bavail,
|
||||
(unsigned long long) sftpstatvfs->f_files,
|
||||
(unsigned long long) sftpstatvfs->f_ffree,
|
||||
(unsigned long long) sftpstatvfs->f_favail,
|
||||
(unsigned long long) sftpstatvfs->f_fsid,
|
||||
(unsigned long long) sftpstatvfs->f_flag,
|
||||
(unsigned long long) sftpstatvfs->f_namemax);
|
||||
|
||||
sftp_statvfs_free(sftpstatvfs);
|
||||
sftp_statvfs_free(sftpstatvfs);
|
||||
|
||||
if (statvfs("/tmp", &sysstatvfs) < 0) {
|
||||
fprintf(stderr, "statvfs failed (%s)\n", strerror(errno));
|
||||
goto end;
|
||||
}
|
||||
if (statvfs("/tmp", &sysstatvfs) < 0) {
|
||||
fprintf(stderr, "statvfs failed (%s)\n", strerror(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
printf("sys statvfs:\n"
|
||||
"\tfile system block size: %llu\n"
|
||||
"\tfundamental fs block size: %llu\n"
|
||||
"\tnumber of blocks (unit f_frsize): %llu\n"
|
||||
"\tfree blocks in file system: %llu\n"
|
||||
"\tfree blocks for non-root: %llu\n"
|
||||
"\ttotal file inodes: %llu\n"
|
||||
"\tfree file inodes: %llu\n"
|
||||
"\tfree file inodes for to non-root: %llu\n"
|
||||
"\tfile system id: %llu\n"
|
||||
"\tbit mask of f_flag values: %llu\n"
|
||||
"\tmaximum filename length: %llu\n",
|
||||
(unsigned long long) sysstatvfs.f_bsize,
|
||||
(unsigned long long) sysstatvfs.f_frsize,
|
||||
(unsigned long long) sysstatvfs.f_blocks,
|
||||
(unsigned long long) sysstatvfs.f_bfree,
|
||||
(unsigned long long) sysstatvfs.f_bavail,
|
||||
(unsigned long long) sysstatvfs.f_files,
|
||||
(unsigned long long) sysstatvfs.f_ffree,
|
||||
(unsigned long long) sysstatvfs.f_favail,
|
||||
(unsigned long long) sysstatvfs.f_fsid,
|
||||
(unsigned long long) sysstatvfs.f_flag,
|
||||
(unsigned long long) sysstatvfs.f_namemax);
|
||||
printf("sys statvfs:\n"
|
||||
"\tfile system block size: %llu\n"
|
||||
"\tfundamental fs block size: %llu\n"
|
||||
"\tnumber of blocks (unit f_frsize): %llu\n"
|
||||
"\tfree blocks in file system: %llu\n"
|
||||
"\tfree blocks for non-root: %llu\n"
|
||||
"\ttotal file inodes: %llu\n"
|
||||
"\tfree file inodes: %llu\n"
|
||||
"\tfree file inodes for to non-root: %llu\n"
|
||||
"\tfile system id: %llu\n"
|
||||
"\tbit mask of f_flag values: %llu\n"
|
||||
"\tmaximum filename length: %llu\n",
|
||||
(unsigned long long) sysstatvfs.f_bsize,
|
||||
(unsigned long long) sysstatvfs.f_frsize,
|
||||
(unsigned long long) sysstatvfs.f_blocks,
|
||||
(unsigned long long) sysstatvfs.f_bfree,
|
||||
(unsigned long long) sysstatvfs.f_bavail,
|
||||
(unsigned long long) sysstatvfs.f_files,
|
||||
(unsigned long long) sysstatvfs.f_ffree,
|
||||
(unsigned long long) sysstatvfs.f_favail,
|
||||
(unsigned long long) sysstatvfs.f_fsid,
|
||||
(unsigned long long) sysstatvfs.f_flag,
|
||||
(unsigned long long) sysstatvfs.f_namemax);
|
||||
}
|
||||
|
||||
/* the connection is made */
|
||||
/* opening a directory */
|
||||
dir = sftp_opendir(sftp, "./");
|
||||
if (!dir) {
|
||||
dir=sftp_opendir(sftp,"./");
|
||||
if(!dir) {
|
||||
fprintf(stderr, "Directory not opened(%s)\n", ssh_get_error(session));
|
||||
goto end;
|
||||
return ;
|
||||
}
|
||||
|
||||
/* reading the whole directory, file by file */
|
||||
while ((file = sftp_readdir(sftp, dir))) {
|
||||
while((file=sftp_readdir(sftp,dir))){
|
||||
fprintf(stderr, "%30s(%.8o) : %s(%.5d) %s(%.5d) : %.10llu bytes\n",
|
||||
file->name,
|
||||
file->permissions,
|
||||
file->owner,
|
||||
file->uid,
|
||||
file->group,
|
||||
file->gid,
|
||||
(long long unsigned int) file->size);
|
||||
file->name,
|
||||
file->permissions,
|
||||
file->owner,
|
||||
file->uid,
|
||||
file->group,
|
||||
file->gid,
|
||||
(long long unsigned int) file->size);
|
||||
sftp_attributes_free(file);
|
||||
}
|
||||
|
||||
/* when file = NULL, an error has occured OR the directory listing is end of
|
||||
* file */
|
||||
if (!sftp_dir_eof(dir)) {
|
||||
/* when file=NULL, an error has occured OR the directory listing is end of file */
|
||||
if(!sftp_dir_eof(dir)){
|
||||
fprintf(stderr, "Error: %s\n", ssh_get_error(session));
|
||||
goto end;
|
||||
return;
|
||||
}
|
||||
|
||||
if (sftp_closedir(dir)) {
|
||||
if(sftp_closedir(dir)){
|
||||
fprintf(stderr, "Error: %s\n", ssh_get_error(session));
|
||||
goto end;
|
||||
return;
|
||||
}
|
||||
/* this will open a file and copy it into your /home directory */
|
||||
/* the small buffer size was intended to stress the library. of course, you
|
||||
* can use a buffer till 20kbytes without problem */
|
||||
/* the small buffer size was intended to stress the library. of course, you can use a buffer till 20kbytes without problem */
|
||||
|
||||
fichier = sftp_open(sftp, "/usr/bin/ssh", O_RDONLY, 0);
|
||||
if (!fichier) {
|
||||
fichier=sftp_open(sftp,"/usr/bin/ssh",O_RDONLY, 0);
|
||||
if(!fichier){
|
||||
fprintf(stderr, "Error opening /usr/bin/ssh: %s\n",
|
||||
ssh_get_error(session));
|
||||
goto end;
|
||||
ssh_get_error(session));
|
||||
return;
|
||||
}
|
||||
|
||||
/* open a file for writing... */
|
||||
to = sftp_open(sftp, "ssh-copy", O_WRONLY | O_CREAT, 0700);
|
||||
if (!to) {
|
||||
to=sftp_open(sftp,"ssh-copy",O_WRONLY | O_CREAT, 0700);
|
||||
if(!to){
|
||||
fprintf(stderr, "Error opening ssh-copy for writing: %s\n",
|
||||
ssh_get_error(session));
|
||||
sftp_close(fichier);
|
||||
goto end;
|
||||
ssh_get_error(session));
|
||||
return;
|
||||
}
|
||||
|
||||
while ((len = sftp_read(fichier, data, 4096)) > 0) {
|
||||
if (sftp_write(to, data, len) != len) {
|
||||
while((len=sftp_read(fichier,data,4096)) > 0){
|
||||
if(sftp_write(to,data,len)!=len){
|
||||
fprintf(stderr, "Error writing %d bytes: %s\n",
|
||||
len, ssh_get_error(session));
|
||||
sftp_close(to);
|
||||
sftp_close(fichier);
|
||||
goto end;
|
||||
len, ssh_get_error(session));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
printf("finished\n");
|
||||
if (len < 0) {
|
||||
if(len<0)
|
||||
fprintf(stderr, "Error reading file: %s\n", ssh_get_error(session));
|
||||
}
|
||||
|
||||
sftp_close(fichier);
|
||||
sftp_close(to);
|
||||
printf("fichiers ferm\n");
|
||||
to = sftp_open(sftp, "/tmp/grosfichier", O_WRONLY|O_CREAT, 0644);
|
||||
|
||||
for (i = 0; i < 1000; ++i) {
|
||||
len = sftp_write(to, data, sizeof(data));
|
||||
printf("wrote %d bytes\n", len);
|
||||
if (len != sizeof(data)) {
|
||||
printf("chunk %d : %d (%s)\n", i, len, ssh_get_error(session));
|
||||
to=sftp_open(sftp,"/tmp/grosfichier",O_WRONLY|O_CREAT, 0644);
|
||||
for(i=0;i<1000;++i){
|
||||
len=sftp_write(to,data,DATALEN);
|
||||
printf("wrote %d bytes\n",len);
|
||||
if(len != DATALEN){
|
||||
printf("chunk %d : %d (%s)\n",i,len,ssh_get_error(session));
|
||||
}
|
||||
}
|
||||
|
||||
sftp_close(to);
|
||||
end:
|
||||
|
||||
/* close the sftp session */
|
||||
sftp_free(sftp);
|
||||
printf("sftp session terminated\n");
|
||||
}
|
||||
|
||||
static void usage(const char *argv0) {
|
||||
fprintf(stderr, "Usage : %s [-v] remotehost\n"
|
||||
"sample sftp test client - libssh-%s\n"
|
||||
"Options :\n"
|
||||
" -v : increase log verbosity\n",
|
||||
argv0,
|
||||
ssh_version(0));
|
||||
exit(0);
|
||||
static void usage(const char *argv0){
|
||||
fprintf(stderr,"Usage : %s [-v] remotehost\n"
|
||||
"sample sftp test client - libssh-%s\n"
|
||||
"Options :\n"
|
||||
" -v : increase log verbosity\n",
|
||||
argv0,
|
||||
ssh_version(0));
|
||||
exit(0);
|
||||
}
|
||||
|
||||
static int opts(int argc, char **argv) {
|
||||
int i;
|
||||
|
||||
while ((i = getopt(argc, argv, "v")) != -1) {
|
||||
switch(i) {
|
||||
case 'v':
|
||||
verbosity++;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "unknown option %c\n", optopt);
|
||||
usage(argv[0]);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
destination = argv[optind];
|
||||
if (destination == NULL) {
|
||||
static int opts(int argc, char **argv){
|
||||
int i;
|
||||
while((i=getopt(argc,argv,"v"))!=-1){
|
||||
switch(i){
|
||||
case 'v':
|
||||
verbosity++;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr,"unknown option %c\n",optopt);
|
||||
usage(argv[0]);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
destination=argv[optind];
|
||||
if(destination == NULL){
|
||||
usage(argv[0]);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
ssh_session session;
|
||||
|
||||
if (opts(argc, argv) < 0) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
session = connect_ssh(destination, NULL, verbosity);
|
||||
if (session == NULL) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
do_sftp(session);
|
||||
ssh_disconnect(session);
|
||||
ssh_free(session);
|
||||
return 0;
|
||||
int main(int argc, char **argv){
|
||||
ssh_session session;
|
||||
if(opts(argc,argv)<0)
|
||||
return EXIT_FAILURE;
|
||||
session=connect_ssh(destination,NULL,verbosity);
|
||||
if(session == NULL)
|
||||
return EXIT_FAILURE;
|
||||
do_sftp(session);
|
||||
ssh_disconnect(session);
|
||||
ssh_free(session);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,356 +0,0 @@
|
||||
/* This is a sample implementation of a libssh based SSH server */
|
||||
/*
|
||||
Copyright 2003-2009 Aris Adamantiadis
|
||||
|
||||
This file is part of the SSH Library
|
||||
|
||||
You are free to copy this file, modify it in any way, consider it being public
|
||||
domain. This does not apply to the rest of the library though, but it is
|
||||
allowed to cut-and-paste working code from this file to any license of
|
||||
program.
|
||||
The goal is to show the API in action. It's not a reference on how terminal
|
||||
clients must be made or how a client should react.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <libssh/libssh.h>
|
||||
#include <libssh/server.h>
|
||||
#include <libssh/callbacks.h>
|
||||
|
||||
#ifdef HAVE_ARGP_H
|
||||
#include <argp.h>
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <io.h>
|
||||
#endif
|
||||
|
||||
#ifndef BUF_SIZE
|
||||
#define BUF_SIZE 2049
|
||||
#endif
|
||||
|
||||
#ifndef KEYS_FOLDER
|
||||
#ifdef _WIN32
|
||||
#define KEYS_FOLDER
|
||||
#else
|
||||
#define KEYS_FOLDER "/etc/ssh/"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define USER "myuser"
|
||||
#define PASSWORD "mypassword"
|
||||
|
||||
static int authenticated=0;
|
||||
static int tries = 0;
|
||||
static int error = 0;
|
||||
static ssh_channel chan=NULL;
|
||||
|
||||
static int auth_none(ssh_session session,
|
||||
const char *user,
|
||||
void *userdata)
|
||||
{
|
||||
ssh_string banner = NULL;
|
||||
|
||||
(void)user; /* unused */
|
||||
(void)userdata; /* unused */
|
||||
|
||||
ssh_set_auth_methods(session,
|
||||
SSH_AUTH_METHOD_PASSWORD | SSH_AUTH_METHOD_GSSAPI_MIC);
|
||||
|
||||
banner = ssh_string_from_char("Banner Example\n");
|
||||
if (banner != NULL) {
|
||||
ssh_send_issue_banner(session, banner);
|
||||
}
|
||||
ssh_string_free(banner);
|
||||
|
||||
return SSH_AUTH_DENIED;
|
||||
}
|
||||
|
||||
static int auth_password(ssh_session session, const char *user,
|
||||
const char *password, void *userdata){
|
||||
(void)userdata;
|
||||
printf("Authenticating user %s pwd %s\n",user, password);
|
||||
if(strcmp(user,USER) == 0 && strcmp(password, PASSWORD) == 0){
|
||||
authenticated = 1;
|
||||
printf("Authenticated\n");
|
||||
return SSH_AUTH_SUCCESS;
|
||||
}
|
||||
if (tries >= 3){
|
||||
printf("Too many authentication tries\n");
|
||||
ssh_disconnect(session);
|
||||
error = 1;
|
||||
return SSH_AUTH_DENIED;
|
||||
}
|
||||
tries++;
|
||||
return SSH_AUTH_DENIED;
|
||||
}
|
||||
|
||||
#ifdef WITH_GSSAPI
|
||||
static int auth_gssapi_mic(ssh_session session, const char *user, const char *principal, void *userdata){
|
||||
ssh_gssapi_creds creds = ssh_gssapi_get_creds(session);
|
||||
(void)userdata;
|
||||
printf("Authenticating user %s with gssapi principal %s\n",user, principal);
|
||||
if (creds != NULL)
|
||||
printf("Received some gssapi credentials\n");
|
||||
else
|
||||
printf("Not received any forwardable creds\n");
|
||||
printf("authenticated\n");
|
||||
authenticated = 1;
|
||||
return SSH_AUTH_SUCCESS;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int pty_request(ssh_session session, ssh_channel channel, const char *term,
|
||||
int x,int y, int px, int py, void *userdata){
|
||||
(void) session;
|
||||
(void) channel;
|
||||
(void) term;
|
||||
(void) x;
|
||||
(void) y;
|
||||
(void) px;
|
||||
(void) py;
|
||||
(void) userdata;
|
||||
printf("Allocated terminal\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int shell_request(ssh_session session, ssh_channel channel, void *userdata){
|
||||
(void)session;
|
||||
(void)channel;
|
||||
(void)userdata;
|
||||
printf("Allocated shell\n");
|
||||
return 0;
|
||||
}
|
||||
struct ssh_channel_callbacks_struct channel_cb = {
|
||||
.channel_pty_request_function = pty_request,
|
||||
.channel_shell_request_function = shell_request
|
||||
};
|
||||
|
||||
static ssh_channel new_session_channel(ssh_session session, void *userdata){
|
||||
(void) session;
|
||||
(void) userdata;
|
||||
if(chan != NULL)
|
||||
return NULL;
|
||||
printf("Allocated session channel\n");
|
||||
chan = ssh_channel_new(session);
|
||||
ssh_callbacks_init(&channel_cb);
|
||||
ssh_set_channel_callbacks(chan, &channel_cb);
|
||||
return chan;
|
||||
}
|
||||
|
||||
|
||||
#ifdef HAVE_ARGP_H
|
||||
const char *argp_program_version = "libssh server example "
|
||||
SSH_STRINGIFY(LIBSSH_VERSION);
|
||||
const char *argp_program_bug_address = "<libssh@libssh.org>";
|
||||
|
||||
/* Program documentation. */
|
||||
static char doc[] = "libssh -- a Secure Shell protocol implementation";
|
||||
|
||||
/* A description of the arguments we accept. */
|
||||
static char args_doc[] = "BINDADDR";
|
||||
|
||||
/* The options we understand. */
|
||||
static struct argp_option options[] = {
|
||||
{
|
||||
.name = "port",
|
||||
.key = 'p',
|
||||
.arg = "PORT",
|
||||
.flags = 0,
|
||||
.doc = "Set the port to bind.",
|
||||
.group = 0
|
||||
},
|
||||
{
|
||||
.name = "hostkey",
|
||||
.key = 'k',
|
||||
.arg = "FILE",
|
||||
.flags = 0,
|
||||
.doc = "Set the host key.",
|
||||
.group = 0
|
||||
},
|
||||
{
|
||||
.name = "dsakey",
|
||||
.key = 'd',
|
||||
.arg = "FILE",
|
||||
.flags = 0,
|
||||
.doc = "Set the dsa key.",
|
||||
.group = 0
|
||||
},
|
||||
{
|
||||
.name = "rsakey",
|
||||
.key = 'r',
|
||||
.arg = "FILE",
|
||||
.flags = 0,
|
||||
.doc = "Set the rsa key.",
|
||||
.group = 0
|
||||
},
|
||||
{
|
||||
.name = "verbose",
|
||||
.key = 'v',
|
||||
.arg = NULL,
|
||||
.flags = 0,
|
||||
.doc = "Get verbose output.",
|
||||
.group = 0
|
||||
},
|
||||
{
|
||||
.name = "config",
|
||||
.key = 'f',
|
||||
.arg = "FILE",
|
||||
.flags = 0,
|
||||
.doc = "Configuration file to use.",
|
||||
.group = 0
|
||||
},
|
||||
{NULL, 0, NULL, 0, NULL, 0}
|
||||
};
|
||||
|
||||
/* Parse a single option. */
|
||||
static error_t parse_opt (int key, char *arg, struct argp_state *state) {
|
||||
/* Get the input argument from argp_parse, which we
|
||||
* know is a pointer to our arguments structure.
|
||||
*/
|
||||
ssh_bind sshbind = state->input;
|
||||
|
||||
switch (key) {
|
||||
case 'p':
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_BINDPORT_STR, arg);
|
||||
break;
|
||||
case 'd':
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_DSAKEY, arg);
|
||||
break;
|
||||
case 'k':
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_HOSTKEY, arg);
|
||||
break;
|
||||
case 'r':
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_RSAKEY, arg);
|
||||
break;
|
||||
case 'v':
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_LOG_VERBOSITY_STR, "3");
|
||||
break;
|
||||
case 'f':
|
||||
ssh_bind_options_parse_config(sshbind, arg);
|
||||
break;
|
||||
case ARGP_KEY_ARG:
|
||||
if (state->arg_num >= 1) {
|
||||
/* Too many arguments. */
|
||||
argp_usage (state);
|
||||
}
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_BINDADDR, arg);
|
||||
break;
|
||||
case ARGP_KEY_END:
|
||||
if (state->arg_num < 1) {
|
||||
/* Not enough arguments. */
|
||||
argp_usage (state);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return ARGP_ERR_UNKNOWN;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Our argp parser. */
|
||||
static struct argp argp = {options, parse_opt, args_doc, doc, NULL, NULL, NULL};
|
||||
#endif /* HAVE_ARGP_H */
|
||||
|
||||
int main(int argc, char **argv){
|
||||
ssh_session session;
|
||||
ssh_bind sshbind;
|
||||
ssh_event mainloop;
|
||||
struct ssh_server_callbacks_struct cb = {
|
||||
.userdata = NULL,
|
||||
.auth_none_function = auth_none,
|
||||
.auth_password_function = auth_password,
|
||||
#ifdef WITH_GSSAPI
|
||||
.auth_gssapi_mic_function = auth_gssapi_mic,
|
||||
#endif
|
||||
.channel_open_request_session_function = new_session_channel
|
||||
};
|
||||
|
||||
char buf[BUF_SIZE];
|
||||
int i;
|
||||
int r;
|
||||
|
||||
sshbind=ssh_bind_new();
|
||||
session=ssh_new();
|
||||
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_DSAKEY, KEYS_FOLDER "ssh_host_dsa_key");
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_RSAKEY, KEYS_FOLDER "ssh_host_rsa_key");
|
||||
|
||||
#ifdef HAVE_ARGP_H
|
||||
/*
|
||||
* Parse our arguments; every option seen by parse_opt will
|
||||
* be reflected in arguments.
|
||||
*/
|
||||
argp_parse (&argp, argc, argv, 0, 0, sshbind);
|
||||
#else
|
||||
(void) argc;
|
||||
(void) argv;
|
||||
#endif
|
||||
|
||||
if(ssh_bind_listen(sshbind)<0){
|
||||
printf("Error listening to socket: %s\n",ssh_get_error(sshbind));
|
||||
return 1;
|
||||
}
|
||||
r=ssh_bind_accept(sshbind,session);
|
||||
if(r==SSH_ERROR){
|
||||
printf("error accepting a connection : %s\n",ssh_get_error(sshbind));
|
||||
return 1;
|
||||
}
|
||||
ssh_callbacks_init(&cb);
|
||||
ssh_set_server_callbacks(session, &cb);
|
||||
|
||||
if (ssh_handle_key_exchange(session)) {
|
||||
printf("ssh_handle_key_exchange: %s\n", ssh_get_error(session));
|
||||
return 1;
|
||||
}
|
||||
ssh_set_auth_methods(session,SSH_AUTH_METHOD_PASSWORD | SSH_AUTH_METHOD_GSSAPI_MIC);
|
||||
mainloop = ssh_event_new();
|
||||
ssh_event_add_session(mainloop, session);
|
||||
|
||||
while (!(authenticated && chan != NULL)){
|
||||
if(error)
|
||||
break;
|
||||
r = ssh_event_dopoll(mainloop, -1);
|
||||
if (r == SSH_ERROR){
|
||||
printf("Error : %s\n",ssh_get_error(session));
|
||||
ssh_disconnect(session);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if(error){
|
||||
printf("Error, exiting loop\n");
|
||||
} else
|
||||
printf("Authenticated and got a channel\n");
|
||||
do{
|
||||
i=ssh_channel_read(chan, buf, sizeof(buf) - 1, 0);
|
||||
if(i>0) {
|
||||
if (ssh_channel_write(chan, buf, i) == SSH_ERROR) {
|
||||
printf("error writing to channel\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
buf[i] = '\0';
|
||||
printf("%s", buf);
|
||||
fflush(stdout);
|
||||
|
||||
if (buf[0] == '\x0d') {
|
||||
if (ssh_channel_write(chan, "\n", 1) == SSH_ERROR) {
|
||||
printf("error writing to channel\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
} while (i>0);
|
||||
ssh_disconnect(session);
|
||||
ssh_bind_free(sshbind);
|
||||
ssh_finalize();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,429 +0,0 @@
|
||||
/* This is a sample implementation of a libssh based SSH server */
|
||||
/*
|
||||
Copyright 2003-2011 Aris Adamantiadis
|
||||
|
||||
This file is part of the SSH Library
|
||||
|
||||
You are free to copy this file, modify it in any way, consider it being public
|
||||
domain. This does not apply to the rest of the library though, but it is
|
||||
allowed to cut-and-paste working code from this file to any license of
|
||||
program.
|
||||
The goal is to show the API in action. It's not a reference on how terminal
|
||||
clients must be made or how a client should react.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <libssh/libssh.h>
|
||||
#include <libssh/server.h>
|
||||
|
||||
#ifdef HAVE_ARGP_H
|
||||
#include <argp.h>
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifndef BUF_SIZE
|
||||
#define BUF_SIZE 2048
|
||||
#endif
|
||||
|
||||
#define SSHD_USER "libssh"
|
||||
#define SSHD_PASSWORD "libssh"
|
||||
|
||||
#ifndef KEYS_FOLDER
|
||||
#ifdef _WIN32
|
||||
#define KEYS_FOLDER
|
||||
#else
|
||||
#define KEYS_FOLDER "/etc/ssh/"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static int port = 22;
|
||||
static bool authenticated = false;
|
||||
|
||||
#ifdef WITH_PCAP
|
||||
static const char *pcap_file = "debug.server.pcap";
|
||||
static ssh_pcap_file pcap;
|
||||
|
||||
static void set_pcap(ssh_session session){
|
||||
if(!pcap_file)
|
||||
return;
|
||||
pcap=ssh_pcap_file_new();
|
||||
if(ssh_pcap_file_open(pcap,pcap_file) == SSH_ERROR){
|
||||
printf("Error opening pcap file\n");
|
||||
ssh_pcap_file_free(pcap);
|
||||
pcap=NULL;
|
||||
return;
|
||||
}
|
||||
ssh_set_pcap_file(session,pcap);
|
||||
}
|
||||
|
||||
static void cleanup_pcap(void) {
|
||||
ssh_pcap_file_free(pcap);
|
||||
pcap=NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static int auth_password(const char *user, const char *password)
|
||||
{
|
||||
int cmp;
|
||||
|
||||
cmp = strcmp(user, SSHD_USER);
|
||||
if (cmp != 0) {
|
||||
return 0;
|
||||
}
|
||||
cmp = strcmp(password, SSHD_PASSWORD);
|
||||
if (cmp != 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
authenticated = true;
|
||||
return 1; // authenticated
|
||||
}
|
||||
#ifdef HAVE_ARGP_H
|
||||
const char *argp_program_version = "libssh server example "
|
||||
SSH_STRINGIFY(LIBSSH_VERSION);
|
||||
const char *argp_program_bug_address = "<libssh@libssh.org>";
|
||||
|
||||
/* Program documentation. */
|
||||
static char doc[] = "libssh -- a Secure Shell protocol implementation";
|
||||
|
||||
/* A description of the arguments we accept. */
|
||||
static char args_doc[] = "BINDADDR";
|
||||
|
||||
/* The options we understand. */
|
||||
static struct argp_option options[] = {
|
||||
{
|
||||
.name = "port",
|
||||
.key = 'p',
|
||||
.arg = "PORT",
|
||||
.flags = 0,
|
||||
.doc = "Set the port to bind.",
|
||||
.group = 0
|
||||
},
|
||||
{
|
||||
.name = "hostkey",
|
||||
.key = 'k',
|
||||
.arg = "FILE",
|
||||
.flags = 0,
|
||||
.doc = "Set the host key.",
|
||||
.group = 0
|
||||
},
|
||||
{
|
||||
.name = "dsakey",
|
||||
.key = 'd',
|
||||
.arg = "FILE",
|
||||
.flags = 0,
|
||||
.doc = "Set the dsa key.",
|
||||
.group = 0
|
||||
},
|
||||
{
|
||||
.name = "rsakey",
|
||||
.key = 'r',
|
||||
.arg = "FILE",
|
||||
.flags = 0,
|
||||
.doc = "Set the rsa key.",
|
||||
.group = 0
|
||||
},
|
||||
{
|
||||
.name = "verbose",
|
||||
.key = 'v',
|
||||
.arg = NULL,
|
||||
.flags = 0,
|
||||
.doc = "Get verbose output.",
|
||||
.group = 0
|
||||
},
|
||||
{NULL, 0, 0, 0, NULL, 0}
|
||||
};
|
||||
|
||||
/* Parse a single option. */
|
||||
static error_t parse_opt (int key, char *arg, struct argp_state *state) {
|
||||
/* Get the input argument from argp_parse, which we
|
||||
* know is a pointer to our arguments structure.
|
||||
*/
|
||||
ssh_bind sshbind = state->input;
|
||||
|
||||
switch (key) {
|
||||
case 'p':
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_BINDPORT_STR, arg);
|
||||
port = atoi(arg);
|
||||
break;
|
||||
case 'd':
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_DSAKEY, arg);
|
||||
break;
|
||||
case 'k':
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_HOSTKEY, arg);
|
||||
break;
|
||||
case 'r':
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_RSAKEY, arg);
|
||||
break;
|
||||
case 'v':
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_LOG_VERBOSITY_STR, "3");
|
||||
break;
|
||||
case ARGP_KEY_ARG:
|
||||
if (state->arg_num >= 1) {
|
||||
/* Too many arguments. */
|
||||
argp_usage (state);
|
||||
}
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_BINDADDR, arg);
|
||||
break;
|
||||
case ARGP_KEY_END:
|
||||
if (state->arg_num < 1) {
|
||||
/* Not enough arguments. */
|
||||
argp_usage (state);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return ARGP_ERR_UNKNOWN;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Our argp parser. */
|
||||
static struct argp argp = {options, parse_opt, args_doc, doc, NULL, NULL, NULL};
|
||||
#endif /* HAVE_ARGP_H */
|
||||
|
||||
static const char *name;
|
||||
static const char *instruction;
|
||||
static const char *prompts[2];
|
||||
static char echo[] = { 1, 0 };
|
||||
|
||||
static int kbdint_check_response(ssh_session session) {
|
||||
int count;
|
||||
|
||||
count = ssh_userauth_kbdint_getnanswers(session);
|
||||
if(count != 2) {
|
||||
instruction = "Something weird happened :(";
|
||||
return 0;
|
||||
}
|
||||
if(strcasecmp("Arthur Dent",
|
||||
ssh_userauth_kbdint_getanswer(session, 0)) != 0) {
|
||||
instruction = "OK, this is not YOUR name, "
|
||||
"but it's a reference to the HGTG...";
|
||||
prompts[0] = "The main character's full name: ";
|
||||
return 0;
|
||||
}
|
||||
if(strcmp("42", ssh_userauth_kbdint_getanswer(session, 1)) != 0) {
|
||||
instruction = "Make an effort !!! What is the Answer to the Ultimate "
|
||||
"Question of Life, the Universe, and Everything ?";
|
||||
prompts[1] = "Answer to the Ultimate Question of Life, the Universe, "
|
||||
"and Everything: ";
|
||||
return 0;
|
||||
}
|
||||
|
||||
authenticated = true;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int authenticate(ssh_session session) {
|
||||
ssh_message message;
|
||||
|
||||
name = "\n\nKeyboard-Interactive Fancy Authentication\n";
|
||||
instruction = "Please enter your real name and your password";
|
||||
prompts[0] = "Real name: ";
|
||||
prompts[1] = "Password: ";
|
||||
|
||||
do {
|
||||
message=ssh_message_get(session);
|
||||
if(!message)
|
||||
break;
|
||||
switch(ssh_message_type(message)){
|
||||
case SSH_REQUEST_AUTH:
|
||||
switch(ssh_message_subtype(message)){
|
||||
case SSH_AUTH_METHOD_PASSWORD:
|
||||
printf("User %s wants to auth with pass %s\n",
|
||||
ssh_message_auth_user(message),
|
||||
ssh_message_auth_password(message));
|
||||
if(auth_password(ssh_message_auth_user(message),
|
||||
ssh_message_auth_password(message))){
|
||||
ssh_message_auth_reply_success(message,0);
|
||||
ssh_message_free(message);
|
||||
return 1;
|
||||
}
|
||||
ssh_message_auth_set_methods(message,
|
||||
SSH_AUTH_METHOD_PASSWORD |
|
||||
SSH_AUTH_METHOD_INTERACTIVE);
|
||||
// not authenticated, send default message
|
||||
ssh_message_reply_default(message);
|
||||
break;
|
||||
|
||||
case SSH_AUTH_METHOD_INTERACTIVE:
|
||||
if(!ssh_message_auth_kbdint_is_response(message)) {
|
||||
printf("User %s wants to auth with kbdint\n",
|
||||
ssh_message_auth_user(message));
|
||||
ssh_message_auth_interactive_request(message, name,
|
||||
instruction, 2, prompts, echo);
|
||||
} else {
|
||||
if(kbdint_check_response(session)) {
|
||||
ssh_message_auth_reply_success(message,0);
|
||||
ssh_message_free(message);
|
||||
return 1;
|
||||
}
|
||||
ssh_message_auth_set_methods(message,
|
||||
SSH_AUTH_METHOD_PASSWORD |
|
||||
SSH_AUTH_METHOD_INTERACTIVE);
|
||||
ssh_message_reply_default(message);
|
||||
}
|
||||
break;
|
||||
case SSH_AUTH_METHOD_NONE:
|
||||
default:
|
||||
printf("User %s wants to auth with unknown auth %d\n",
|
||||
ssh_message_auth_user(message),
|
||||
ssh_message_subtype(message));
|
||||
ssh_message_auth_set_methods(message,
|
||||
SSH_AUTH_METHOD_PASSWORD |
|
||||
SSH_AUTH_METHOD_INTERACTIVE);
|
||||
ssh_message_reply_default(message);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ssh_message_auth_set_methods(message,
|
||||
SSH_AUTH_METHOD_PASSWORD |
|
||||
SSH_AUTH_METHOD_INTERACTIVE);
|
||||
ssh_message_reply_default(message);
|
||||
}
|
||||
ssh_message_free(message);
|
||||
} while (1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv){
|
||||
ssh_session session;
|
||||
ssh_bind sshbind;
|
||||
ssh_message message;
|
||||
ssh_channel chan=0;
|
||||
char buf[BUF_SIZE];
|
||||
int auth=0;
|
||||
int shell=0;
|
||||
int i;
|
||||
int r;
|
||||
|
||||
sshbind=ssh_bind_new();
|
||||
session=ssh_new();
|
||||
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_DSAKEY,
|
||||
KEYS_FOLDER "ssh_host_dsa_key");
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_RSAKEY,
|
||||
KEYS_FOLDER "ssh_host_rsa_key");
|
||||
|
||||
#ifdef HAVE_ARGP_H
|
||||
/*
|
||||
* Parse our arguments; every option seen by parse_opt will
|
||||
* be reflected in arguments.
|
||||
*/
|
||||
argp_parse (&argp, argc, argv, 0, 0, sshbind);
|
||||
#else
|
||||
(void) argc;
|
||||
(void) argv;
|
||||
#endif
|
||||
#ifdef WITH_PCAP
|
||||
set_pcap(session);
|
||||
#endif
|
||||
|
||||
if(ssh_bind_listen(sshbind)<0){
|
||||
printf("Error listening to socket: %s\n", ssh_get_error(sshbind));
|
||||
return 1;
|
||||
}
|
||||
printf("Started sample libssh sshd on port %d\n", port);
|
||||
printf("You can login as the user %s with the password %s\n", SSHD_USER,
|
||||
SSHD_PASSWORD);
|
||||
r = ssh_bind_accept(sshbind, session);
|
||||
if(r==SSH_ERROR){
|
||||
printf("Error accepting a connection: %s\n", ssh_get_error(sshbind));
|
||||
return 1;
|
||||
}
|
||||
if (ssh_handle_key_exchange(session)) {
|
||||
printf("ssh_handle_key_exchange: %s\n", ssh_get_error(session));
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* proceed to authentication */
|
||||
auth = authenticate(session);
|
||||
if (!auth || !authenticated) {
|
||||
printf("Authentication error: %s\n", ssh_get_error(session));
|
||||
ssh_disconnect(session);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* wait for a channel session */
|
||||
do {
|
||||
message = ssh_message_get(session);
|
||||
if(message){
|
||||
if(ssh_message_type(message) == SSH_REQUEST_CHANNEL_OPEN &&
|
||||
ssh_message_subtype(message) == SSH_CHANNEL_SESSION) {
|
||||
chan = ssh_message_channel_request_open_reply_accept(message);
|
||||
ssh_message_free(message);
|
||||
break;
|
||||
} else {
|
||||
ssh_message_reply_default(message);
|
||||
ssh_message_free(message);
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
} while(!chan);
|
||||
|
||||
if(!chan) {
|
||||
printf("Error: cleint did not ask for a channel session (%s)\n",
|
||||
ssh_get_error(session));
|
||||
ssh_finalize();
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* wait for a shell */
|
||||
do {
|
||||
message = ssh_message_get(session);
|
||||
if(message != NULL) {
|
||||
if(ssh_message_type(message) == SSH_REQUEST_CHANNEL &&
|
||||
ssh_message_subtype(message) == SSH_CHANNEL_REQUEST_SHELL) {
|
||||
shell = 1;
|
||||
ssh_message_channel_request_reply_success(message);
|
||||
ssh_message_free(message);
|
||||
break;
|
||||
}
|
||||
ssh_message_reply_default(message);
|
||||
ssh_message_free(message);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
} while(!shell);
|
||||
|
||||
if(!shell) {
|
||||
printf("Error: No shell requested (%s)\n", ssh_get_error(session));
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
printf("it works !\n");
|
||||
do{
|
||||
i=ssh_channel_read(chan,buf, sizeof(buf), 0);
|
||||
if(i>0) {
|
||||
if(*buf == '' || *buf == '')
|
||||
break;
|
||||
if(i == 1 && *buf == '\r')
|
||||
ssh_channel_write(chan, "\r\n", 2);
|
||||
else
|
||||
ssh_channel_write(chan, buf, i);
|
||||
if (write(1,buf,i) < 0) {
|
||||
printf("error writing to buffer\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
} while (i>0);
|
||||
ssh_channel_close(chan);
|
||||
ssh_disconnect(session);
|
||||
ssh_bind_free(sshbind);
|
||||
#ifdef WITH_PCAP
|
||||
cleanup_pcap();
|
||||
#endif
|
||||
ssh_finalize();
|
||||
return 0;
|
||||
}
|
||||
|
||||
308
examples/samplesshd.c
Normal file
@@ -0,0 +1,308 @@
|
||||
/* This is a sample implementation of a libssh based SSH server */
|
||||
/*
|
||||
Copyright 2003-2009 Aris Adamantiadis
|
||||
|
||||
This file is part of the SSH Library
|
||||
|
||||
You are free to copy this file, modify it in any way, consider it being public
|
||||
domain. This does not apply to the rest of the library though, but it is
|
||||
allowed to cut-and-paste working code from this file to any license of
|
||||
program.
|
||||
The goal is to show the API in action. It's not a reference on how terminal
|
||||
clients must be made or how a client should react.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <libssh/libssh.h>
|
||||
#include <libssh/server.h>
|
||||
|
||||
#ifdef HAVE_ARGP_H
|
||||
#include <argp.h>
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifndef KEYS_FOLDER
|
||||
#ifdef _WIN32
|
||||
#define KEYS_FOLDER
|
||||
#else
|
||||
#define KEYS_FOLDER "/etc/ssh/"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef WITH_PCAP
|
||||
const char *pcap_file="debug.server.pcap";
|
||||
ssh_pcap_file pcap;
|
||||
|
||||
void set_pcap(ssh_session session);
|
||||
void set_pcap(ssh_session session){
|
||||
if(!pcap_file)
|
||||
return;
|
||||
pcap=ssh_pcap_file_new();
|
||||
if(ssh_pcap_file_open(pcap,pcap_file) == SSH_ERROR){
|
||||
printf("Error opening pcap file\n");
|
||||
ssh_pcap_file_free(pcap);
|
||||
pcap=NULL;
|
||||
return;
|
||||
}
|
||||
ssh_set_pcap_file(session,pcap);
|
||||
}
|
||||
|
||||
void cleanup_pcap(void);
|
||||
void cleanup_pcap(){
|
||||
ssh_pcap_file_free(pcap);
|
||||
pcap=NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static int auth_password(char *user, char *password){
|
||||
if(strcmp(user,"aris"))
|
||||
return 0;
|
||||
if(strcmp(password,"lala"))
|
||||
return 0;
|
||||
return 1; // authenticated
|
||||
}
|
||||
#ifdef HAVE_ARGP_H
|
||||
const char *argp_program_version = "libssh server example "
|
||||
SSH_STRINGIFY(LIBSSH_VERSION);
|
||||
const char *argp_program_bug_address = "<libssh@libssh.org>";
|
||||
|
||||
/* Program documentation. */
|
||||
static char doc[] = "libssh -- a Secure Shell protocol implementation";
|
||||
|
||||
/* A description of the arguments we accept. */
|
||||
static char args_doc[] = "BINDADDR";
|
||||
|
||||
/* The options we understand. */
|
||||
static struct argp_option options[] = {
|
||||
{
|
||||
.name = "port",
|
||||
.key = 'p',
|
||||
.arg = "PORT",
|
||||
.flags = 0,
|
||||
.doc = "Set the port to bind.",
|
||||
.group = 0
|
||||
},
|
||||
{
|
||||
.name = "hostkey",
|
||||
.key = 'k',
|
||||
.arg = "FILE",
|
||||
.flags = 0,
|
||||
.doc = "Set the host key.",
|
||||
.group = 0
|
||||
},
|
||||
{
|
||||
.name = "dsakey",
|
||||
.key = 'd',
|
||||
.arg = "FILE",
|
||||
.flags = 0,
|
||||
.doc = "Set the dsa key.",
|
||||
.group = 0
|
||||
},
|
||||
{
|
||||
.name = "rsakey",
|
||||
.key = 'r',
|
||||
.arg = "FILE",
|
||||
.flags = 0,
|
||||
.doc = "Set the rsa key.",
|
||||
.group = 0
|
||||
},
|
||||
{
|
||||
.name = "verbose",
|
||||
.key = 'v',
|
||||
.arg = NULL,
|
||||
.flags = 0,
|
||||
.doc = "Get verbose output.",
|
||||
.group = 0
|
||||
},
|
||||
{NULL, 0, 0, 0, NULL, 0}
|
||||
};
|
||||
|
||||
/* Parse a single option. */
|
||||
static error_t parse_opt (int key, char *arg, struct argp_state *state) {
|
||||
/* Get the input argument from argp_parse, which we
|
||||
* know is a pointer to our arguments structure.
|
||||
*/
|
||||
ssh_bind sshbind = state->input;
|
||||
|
||||
switch (key) {
|
||||
case 'p':
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_BINDPORT_STR, arg);
|
||||
break;
|
||||
case 'd':
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_DSAKEY, arg);
|
||||
break;
|
||||
case 'k':
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_HOSTKEY, arg);
|
||||
break;
|
||||
case 'r':
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_RSAKEY, arg);
|
||||
break;
|
||||
case 'v':
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_LOG_VERBOSITY_STR, "3");
|
||||
break;
|
||||
case ARGP_KEY_ARG:
|
||||
if (state->arg_num >= 1) {
|
||||
/* Too many arguments. */
|
||||
argp_usage (state);
|
||||
}
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_BINDADDR, arg);
|
||||
break;
|
||||
case ARGP_KEY_END:
|
||||
if (state->arg_num < 1) {
|
||||
/* Not enough arguments. */
|
||||
argp_usage (state);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return ARGP_ERR_UNKNOWN;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Our argp parser. */
|
||||
static struct argp argp = {options, parse_opt, args_doc, doc, NULL, NULL, NULL};
|
||||
#endif /* HAVE_ARGP_H */
|
||||
|
||||
int main(int argc, char **argv){
|
||||
ssh_session session;
|
||||
ssh_bind sshbind;
|
||||
ssh_message message;
|
||||
ssh_channel chan=0;
|
||||
char buf[2048];
|
||||
int auth=0;
|
||||
int sftp=0;
|
||||
int i;
|
||||
int r;
|
||||
|
||||
sshbind=ssh_bind_new();
|
||||
session=ssh_new();
|
||||
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_DSAKEY, KEYS_FOLDER "ssh_host_dsa_key");
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_RSAKEY, KEYS_FOLDER "ssh_host_rsa_key");
|
||||
|
||||
#ifdef HAVE_ARGP_H
|
||||
/*
|
||||
* Parse our arguments; every option seen by parse_opt will
|
||||
* be reflected in arguments.
|
||||
*/
|
||||
argp_parse (&argp, argc, argv, 0, 0, sshbind);
|
||||
#else
|
||||
(void) argc;
|
||||
(void) argv;
|
||||
#endif
|
||||
#ifdef WITH_PCAP
|
||||
set_pcap(session);
|
||||
#endif
|
||||
|
||||
if(ssh_bind_listen(sshbind)<0){
|
||||
printf("Error listening to socket: %s\n",ssh_get_error(sshbind));
|
||||
return 1;
|
||||
}
|
||||
r=ssh_bind_accept(sshbind,session);
|
||||
if(r==SSH_ERROR){
|
||||
printf("error accepting a connection : %s\n",ssh_get_error(sshbind));
|
||||
return 1;
|
||||
}
|
||||
if (ssh_handle_key_exchange(session)) {
|
||||
printf("ssh_handle_key_exchange: %s\n", ssh_get_error(session));
|
||||
return 1;
|
||||
}
|
||||
do {
|
||||
message=ssh_message_get(session);
|
||||
if(!message)
|
||||
break;
|
||||
switch(ssh_message_type(message)){
|
||||
case SSH_REQUEST_AUTH:
|
||||
switch(ssh_message_subtype(message)){
|
||||
case SSH_AUTH_METHOD_PASSWORD:
|
||||
printf("User %s wants to auth with pass %s\n",
|
||||
ssh_message_auth_user(message),
|
||||
ssh_message_auth_password(message));
|
||||
if(auth_password(ssh_message_auth_user(message),
|
||||
ssh_message_auth_password(message))){
|
||||
auth=1;
|
||||
ssh_message_auth_reply_success(message,0);
|
||||
break;
|
||||
}
|
||||
// not authenticated, send default message
|
||||
case SSH_AUTH_METHOD_NONE:
|
||||
default:
|
||||
ssh_message_auth_set_methods(message,SSH_AUTH_METHOD_PASSWORD);
|
||||
ssh_message_reply_default(message);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ssh_message_reply_default(message);
|
||||
}
|
||||
ssh_message_free(message);
|
||||
} while (!auth);
|
||||
if(!auth){
|
||||
printf("auth error: %s\n",ssh_get_error(session));
|
||||
ssh_disconnect(session);
|
||||
return 1;
|
||||
}
|
||||
do {
|
||||
message=ssh_message_get(session);
|
||||
if(message){
|
||||
switch(ssh_message_type(message)){
|
||||
case SSH_REQUEST_CHANNEL_OPEN:
|
||||
if(ssh_message_subtype(message)==SSH_CHANNEL_SESSION){
|
||||
chan=ssh_message_channel_request_open_reply_accept(message);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
ssh_message_reply_default(message);
|
||||
}
|
||||
ssh_message_free(message);
|
||||
}
|
||||
} while(message && !chan);
|
||||
if(!chan){
|
||||
printf("error : %s\n",ssh_get_error(session));
|
||||
ssh_finalize();
|
||||
return 1;
|
||||
}
|
||||
do {
|
||||
message=ssh_message_get(session);
|
||||
if(message && ssh_message_type(message)==SSH_REQUEST_CHANNEL &&
|
||||
ssh_message_subtype(message)==SSH_CHANNEL_REQUEST_SHELL){
|
||||
// if(!strcmp(ssh_message_channel_request_subsystem(message),"sftp")){
|
||||
sftp=1;
|
||||
ssh_message_channel_request_reply_success(message);
|
||||
break;
|
||||
// }
|
||||
}
|
||||
if(!sftp){
|
||||
ssh_message_reply_default(message);
|
||||
}
|
||||
ssh_message_free(message);
|
||||
} while (message && !sftp);
|
||||
if(!sftp){
|
||||
printf("error : %s\n",ssh_get_error(session));
|
||||
return 1;
|
||||
}
|
||||
printf("it works !\n");
|
||||
do{
|
||||
i=ssh_channel_read(chan,buf, 2048, 0);
|
||||
if(i>0) {
|
||||
ssh_channel_write(chan, buf, i);
|
||||
if (write(1,buf,i) < 0) {
|
||||
printf("error writing to buffer\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
} while (i>0);
|
||||
ssh_disconnect(session);
|
||||
ssh_bind_free(sshbind);
|
||||
#ifdef WITH_PCAP
|
||||
cleanup_pcap();
|
||||
#endif
|
||||
ssh_finalize();
|
||||
return 0;
|
||||
}
|
||||
|
||||