Compare commits
163 Commits
master-fix
...
libssh-0.5
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
05d8421290 | ||
|
|
55b09f4264 | ||
|
|
f128338132 | ||
|
|
ba231d0844 | ||
|
|
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
|
||||||
5
.gitignore
vendored
@@ -1,9 +1,6 @@
|
|||||||
*.a
|
|
||||||
*.o
|
|
||||||
.*
|
.*
|
||||||
*.swp
|
*.swp
|
||||||
*~$
|
*~$
|
||||||
|
build
|
||||||
cscope.*
|
cscope.*
|
||||||
tags
|
tags
|
||||||
/build
|
|
||||||
/obj*
|
|
||||||
|
|||||||
467
.gitlab-ci.yml
@@ -1,467 +0,0 @@
|
|||||||
variables:
|
|
||||||
BUILD_IMAGES_PROJECT: libssh/build-images
|
|
||||||
FEDORA_BUILD: buildenv-fedora
|
|
||||||
CENTOS7_BUILD: buildenv-centos7
|
|
||||||
TUMBLEWEED_BUILD: buildenv-tumbleweed
|
|
||||||
MINGW_BUILD: buildenv-mingw
|
|
||||||
DEBIAN_CROSS_BUILD: buildenv-debian-cross
|
|
||||||
|
|
||||||
# torture_auth fails on centos7 docker images, so we don't use -DCLIENT_TESTING=ON
|
|
||||||
centos7/openssl_1.0.x/x86_64:
|
|
||||||
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$CENTOS7_BUILD
|
|
||||||
script:
|
|
||||||
- mkdir -p obj && cd obj && cmake3
|
|
||||||
-DCMAKE_BUILD_TYPE=RelWithDebInfo
|
|
||||||
-DPICKY_DEVELOPER=ON
|
|
||||||
-DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON
|
|
||||||
-DUNIT_TESTING=ON .. &&
|
|
||||||
make -j$(nproc) && ctest --output-on-failure
|
|
||||||
tags:
|
|
||||||
- shared
|
|
||||||
except:
|
|
||||||
- tags
|
|
||||||
artifacts:
|
|
||||||
expire_in: 1 week
|
|
||||||
when: on_failure
|
|
||||||
paths:
|
|
||||||
- obj/
|
|
||||||
|
|
||||||
fedora/openssl_1.1.x/x86_64:
|
|
||||||
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD
|
|
||||||
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 -DCLIENT_TESTING=ON -DSERVER_TESTING=ON .. &&
|
|
||||||
make -j$(nproc) && ctest --output-on-failure
|
|
||||||
tags:
|
|
||||||
- shared
|
|
||||||
except:
|
|
||||||
- tags
|
|
||||||
artifacts:
|
|
||||||
expire_in: 1 week
|
|
||||||
when: on_failure
|
|
||||||
paths:
|
|
||||||
- obj/
|
|
||||||
|
|
||||||
# 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:
|
|
||||||
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD
|
|
||||||
script:
|
|
||||||
- mkdir -p obj && cd obj && cmake
|
|
||||||
-DCMAKE_BUILD_TYPE=AddressSanitizer
|
|
||||||
-DPICKY_DEVELOPER=ON
|
|
||||||
-DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON
|
|
||||||
-DUNIT_TESTING=ON .. &&
|
|
||||||
make -j$(nproc) && ctest --output-on-failure
|
|
||||||
tags:
|
|
||||||
- shared
|
|
||||||
except:
|
|
||||||
- tags
|
|
||||||
artifacts:
|
|
||||||
expire_in: 1 week
|
|
||||||
when: on_failure
|
|
||||||
paths:
|
|
||||||
- obj/
|
|
||||||
|
|
||||||
fedora/undefined-sanitizer:
|
|
||||||
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD
|
|
||||||
script:
|
|
||||||
- mkdir -p obj && cd obj && cmake
|
|
||||||
-DCMAKE_C_FLAGS="-fsanitize=undefined -fsanitize=null -fsanitize=alignment -fno-sanitize-recover"
|
|
||||||
-DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON
|
|
||||||
-DUNIT_TESTING=ON -DCLIENT_TESTING=ON -DSERVER_TESTING=ON ..
|
|
||||||
&& make -j$(nproc) && ctest --output-on-failure
|
|
||||||
tags:
|
|
||||||
- shared
|
|
||||||
except:
|
|
||||||
- tags
|
|
||||||
artifacts:
|
|
||||||
expire_in: 1 week
|
|
||||||
when: on_failure
|
|
||||||
paths:
|
|
||||||
- obj/
|
|
||||||
|
|
||||||
fedora/csbuild:
|
|
||||||
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD
|
|
||||||
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"
|
|
||||||
|
|
||||||
- csbuild
|
|
||||||
--build-dir=obj-csbuild
|
|
||||||
--prep-cmd="cmake -DCMAKE_BUILD_TYPE=Debug -DPICKY_DEVELOPER=ON -DUNIT_TESTING=ON -DCLIENT_TESTING=ON -DSERVER_TESTING=ON -DFUZZ_TESTING=ON @SRCDIR@"
|
|
||||||
--build-cmd "make clean && make -j$(nproc)"
|
|
||||||
--git-commit-range $CI_COMMIT_RANGE
|
|
||||||
--color
|
|
||||||
--print-current --print-fixed
|
|
||||||
tags:
|
|
||||||
- shared
|
|
||||||
except:
|
|
||||||
- tags
|
|
||||||
artifacts:
|
|
||||||
expire_in: 1 week
|
|
||||||
when: on_failure
|
|
||||||
paths:
|
|
||||||
- obj-csbuild/
|
|
||||||
|
|
||||||
# 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:
|
|
||||||
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 .. &&
|
|
||||||
make && ctest --output-on-failure
|
|
||||||
tags:
|
|
||||||
- freebsd
|
|
||||||
except:
|
|
||||||
- tags
|
|
||||||
only:
|
|
||||||
- branches@libssh/libssh-mirror
|
|
||||||
- branches@cryptomilk/libssh-mirror
|
|
||||||
artifacts:
|
|
||||||
expire_in: 1 week
|
|
||||||
when: on_failure
|
|
||||||
paths:
|
|
||||||
- obj/
|
|
||||||
|
|
||||||
fedora/libgcrypt/x86_64:
|
|
||||||
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD
|
|
||||||
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 -DCLIENT_TESTING=ON -DSERVER_TESTING=ON
|
|
||||||
-DWITH_GCRYPT=ON .. &&
|
|
||||||
make -j$(nproc) && ctest --output-on-failure
|
|
||||||
tags:
|
|
||||||
- shared
|
|
||||||
except:
|
|
||||||
- tags
|
|
||||||
artifacts:
|
|
||||||
expire_in: 1 week
|
|
||||||
when: on_failure
|
|
||||||
paths:
|
|
||||||
- obj/
|
|
||||||
|
|
||||||
fedora/mbedtls/x86_64:
|
|
||||||
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD
|
|
||||||
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 -DCLIENT_TESTING=ON -DSERVER_TESTING=ON
|
|
||||||
-DWITH_MBEDTLS=ON .. &&
|
|
||||||
make -j$(nproc) && ctest --output-on-failure
|
|
||||||
tags:
|
|
||||||
- shared
|
|
||||||
except:
|
|
||||||
- tags
|
|
||||||
artifacts:
|
|
||||||
expire_in: 1 week
|
|
||||||
when: on_failure
|
|
||||||
paths:
|
|
||||||
- obj/
|
|
||||||
|
|
||||||
# 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
|
|
||||||
script:
|
|
||||||
- export WINEPATH=/usr/x86_64-w64-mingw32/sys-root/mingw/bin
|
|
||||||
- export WINEDEBUG=-all
|
|
||||||
- mkdir -p obj && cd obj && mingw64-cmake
|
|
||||||
-DCMAKE_BUILD_TYPE=RelWithDebInfo
|
|
||||||
-DPICKY_DEVELOPER=ON
|
|
||||||
-DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON
|
|
||||||
-DUNIT_TESTING=ON .. &&
|
|
||||||
make -j$(nproc) &&
|
|
||||||
ctest --output-on-failure
|
|
||||||
tags:
|
|
||||||
- shared
|
|
||||||
except:
|
|
||||||
- tags
|
|
||||||
artifacts:
|
|
||||||
expire_in: 1 week
|
|
||||||
when: on_failure
|
|
||||||
paths:
|
|
||||||
- obj/
|
|
||||||
|
|
||||||
# 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
|
|
||||||
script:
|
|
||||||
- export WINEPATH=/usr/i686-w64-mingw32/sys-root/mingw/bin
|
|
||||||
- export WINEDEBUG=-all
|
|
||||||
- mkdir -p obj && cd obj && mingw32-cmake
|
|
||||||
-DCMAKE_BUILD_TYPE=RelWithDebInfo
|
|
||||||
-DPICKY_DEVELOPER=ON
|
|
||||||
-DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON
|
|
||||||
-DUNIT_TESTING=ON .. &&
|
|
||||||
make -j$(nproc) &&
|
|
||||||
ctest --output-on-failure
|
|
||||||
tags:
|
|
||||||
- shared
|
|
||||||
except:
|
|
||||||
- tags
|
|
||||||
artifacts:
|
|
||||||
expire_in: 1 week
|
|
||||||
when: on_failure
|
|
||||||
paths:
|
|
||||||
- obj/
|
|
||||||
|
|
||||||
.Debian.cross.template: &Debian_cross_template
|
|
||||||
stage: test
|
|
||||||
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$DEBIAN_CROSS_BUILD
|
|
||||||
script:
|
|
||||||
- build=$(dpkg-architecture -qDEB_HOST_GNU_TYPE)
|
|
||||||
- host="${CI_JOB_NAME#*.cross.}"
|
|
||||||
- mkdir -p obj && cd obj && cmake
|
|
||||||
-DCMAKE_C_COMPILER="$(which $host-gcc)"
|
|
||||||
-DCMAKE_CXX_COMPILER="$(which $host-g++)"
|
|
||||||
-DCMAKE_BUILD_TYPE=RelWithDebInfo
|
|
||||||
-DUNIT_TESTING=ON -DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON
|
|
||||||
-DWITH_PCAP=ON .. &&
|
|
||||||
make -j$(nproc) &&
|
|
||||||
ctest --output-on-failure
|
|
||||||
tags:
|
|
||||||
- shared
|
|
||||||
except:
|
|
||||||
- tags
|
|
||||||
artifacts:
|
|
||||||
expire_in: 1 week
|
|
||||||
when: on_failure
|
|
||||||
paths:
|
|
||||||
- obj/
|
|
||||||
|
|
||||||
Debian.cross.mips-linux-gnu:
|
|
||||||
<<: *Debian_cross_template
|
|
||||||
|
|
||||||
tumbleweed/openssl_1.1.x/x86_64/gcc:
|
|
||||||
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$TUMBLEWEED_BUILD
|
|
||||||
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
|
|
||||||
-DKRB5_CONFIG=/usr/lib/mit/bin/krb5-config
|
|
||||||
-DUNIT_TESTING=ON -DCLIENT_TESTING=ON -DSERVER_TESTING=ON .. &&
|
|
||||||
make -j$(nproc) && ctest --output-on-failure
|
|
||||||
tags:
|
|
||||||
- shared
|
|
||||||
except:
|
|
||||||
- tags
|
|
||||||
artifacts:
|
|
||||||
expire_in: 1 week
|
|
||||||
when: on_failure
|
|
||||||
paths:
|
|
||||||
- obj/
|
|
||||||
|
|
||||||
tumbleweed/openssl_1.1.x/x86/gcc:
|
|
||||||
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$TUMBLEWEED_BUILD
|
|
||||||
script:
|
|
||||||
- mkdir -p obj && cd obj && cmake
|
|
||||||
-DCMAKE_TOOLCHAIN_FILE=../cmake/Toolchain-cross-m32.cmake
|
|
||||||
-DCMAKE_BUILD_TYPE=RelWithDebInfo
|
|
||||||
-DPICKY_DEVELOPER=ON
|
|
||||||
-DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON
|
|
||||||
-DUNIT_TESTING=ON .. &&
|
|
||||||
make -j$(nproc) && ctest --output-on-failure
|
|
||||||
tags:
|
|
||||||
- shared
|
|
||||||
except:
|
|
||||||
- tags
|
|
||||||
artifacts:
|
|
||||||
expire_in: 1 week
|
|
||||||
when: on_failure
|
|
||||||
paths:
|
|
||||||
- obj/
|
|
||||||
|
|
||||||
tumbleweed/openssl_1.1.x/x86_64/gcc7:
|
|
||||||
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$TUMBLEWEED_BUILD
|
|
||||||
script:
|
|
||||||
- mkdir -p obj && cd obj && cmake
|
|
||||||
-DCMAKE_C_COMPILER=gcc-7 -DCMAKE_CXX_COMPILER=g++-7
|
|
||||||
-DCMAKE_BUILD_TYPE=RelWithDebInfo
|
|
||||||
-DPICKY_DEVELOPER=ON
|
|
||||||
-DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON
|
|
||||||
-DKRB5_CONFIG=/usr/lib/mit/bin/krb5-config
|
|
||||||
-DUNIT_TESTING=ON -DCLIENT_TESTING=ON -DSERVER_TESTING=ON .. &&
|
|
||||||
make -j$(nproc) && ctest --output-on-failure
|
|
||||||
tags:
|
|
||||||
- shared
|
|
||||||
except:
|
|
||||||
- tags
|
|
||||||
artifacts:
|
|
||||||
expire_in: 1 week
|
|
||||||
when: on_failure
|
|
||||||
paths:
|
|
||||||
- obj/
|
|
||||||
|
|
||||||
tumbleweed/openssl_1.1.x/x86/gcc7:
|
|
||||||
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$TUMBLEWEED_BUILD
|
|
||||||
script:
|
|
||||||
- mkdir -p obj && cd obj && cmake
|
|
||||||
-DCMAKE_TOOLCHAIN_FILE=../cmake/Toolchain-cross-m32.cmake
|
|
||||||
-DCMAKE_C_COMPILER=gcc-7 -DCMAKE_CXX_COMPILER=g++-7
|
|
||||||
-DCMAKE_BUILD_TYPE=RelWithDebInfo
|
|
||||||
-DPICKY_DEVELOPER=ON
|
|
||||||
-DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON
|
|
||||||
-DUNIT_TESTING=ON .. &&
|
|
||||||
make -j$(nproc) && ctest --output-on-failure
|
|
||||||
tags:
|
|
||||||
- shared
|
|
||||||
except:
|
|
||||||
- tags
|
|
||||||
artifacts:
|
|
||||||
expire_in: 1 week
|
|
||||||
when: on_failure
|
|
||||||
paths:
|
|
||||||
- obj/
|
|
||||||
|
|
||||||
tumbleweed/openssl_1.1.x/x86_64/clang:
|
|
||||||
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$TUMBLEWEED_BUILD
|
|
||||||
script:
|
|
||||||
- mkdir -p obj && cd obj && cmake
|
|
||||||
-DCMAKE_BUILD_TYPE=RelWithDebInfo
|
|
||||||
-DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++
|
|
||||||
-DPICKY_DEVELOPER=ON
|
|
||||||
-DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON
|
|
||||||
-DKRB5_CONFIG=/usr/lib/mit/bin/krb5-config
|
|
||||||
-DUNIT_TESTING=ON -DCLIENT_TESTING=ON -DSERVER_TESTING=ON .. &&
|
|
||||||
make -j$(nproc) && ctest --output-on-failure
|
|
||||||
tags:
|
|
||||||
- shared
|
|
||||||
except:
|
|
||||||
- tags
|
|
||||||
artifacts:
|
|
||||||
expire_in: 1 week
|
|
||||||
when: on_failure
|
|
||||||
paths:
|
|
||||||
- obj/
|
|
||||||
|
|
||||||
tumbleweed/docs:
|
|
||||||
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$TUMBLEWEED_BUILD
|
|
||||||
script:
|
|
||||||
- mkdir -p obj && cd obj && cmake .. && make docs
|
|
||||||
tags:
|
|
||||||
- shared
|
|
||||||
except:
|
|
||||||
- tags
|
|
||||||
artifacts:
|
|
||||||
expire_in: 1 week
|
|
||||||
when: on_failure
|
|
||||||
paths:
|
|
||||||
- obj/
|
|
||||||
|
|
||||||
tumbleweed/undefined-sanitizer:
|
|
||||||
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$TUMBLEWEED_BUILD
|
|
||||||
script:
|
|
||||||
- mkdir -p obj && cd obj && cmake
|
|
||||||
-DCMAKE_BUILD_TYPE=UndefinedSanitizer
|
|
||||||
-DPICKY_DEVELOPER=ON
|
|
||||||
-DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON
|
|
||||||
-DUNIT_TESTING=ON -DCLIENT_TESTING=ON -DSERVER_TESTING=ON .. &&
|
|
||||||
make -j$(nproc) && ctest --output-on-failure
|
|
||||||
tags:
|
|
||||||
- shared
|
|
||||||
except:
|
|
||||||
- tags
|
|
||||||
artifacts:
|
|
||||||
expire_in: 1 week
|
|
||||||
when: on_failure
|
|
||||||
paths:
|
|
||||||
- obj/
|
|
||||||
|
|
||||||
tumbleweed/static-analysis:
|
|
||||||
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$TUMBLEWEED_BUILD
|
|
||||||
script:
|
|
||||||
- export CCC_CC=clang
|
|
||||||
- export CCC_CXX=clang++
|
|
||||||
- mkdir -p obj && cd obj && scan-build cmake
|
|
||||||
-DCMAKE_BUILD_TYPE=Debug
|
|
||||||
-DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++
|
|
||||||
-DPICKY_DEVELOPER=ON
|
|
||||||
-DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON
|
|
||||||
-DUNIT_TESTING=ON -DCLIENT_TESTING=ON -DSERVER_TESTING=ON .. &&
|
|
||||||
scan-build --status-bugs -o scan make -j$(nproc)
|
|
||||||
tags:
|
|
||||||
- shared
|
|
||||||
except:
|
|
||||||
- tags
|
|
||||||
artifacts:
|
|
||||||
expire_in: 1 week
|
|
||||||
when: on_failure
|
|
||||||
paths:
|
|
||||||
- obj/scan
|
|
||||||
|
|
||||||
visualstudio/x86_64:
|
|
||||||
script:
|
|
||||||
- $env:VCPKG_DEFAULT_TRIPLET="x64-windows"
|
|
||||||
- cd obj
|
|
||||||
- cmake
|
|
||||||
-A x64
|
|
||||||
-DCMAKE_TOOLCHAIN_FILE="$env:VCPKG_TOOLCHAIN_FILE"
|
|
||||||
-DPICKY_DEVELOPER=ON
|
|
||||||
-DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON
|
|
||||||
-DUNIT_TESTING=ON ..
|
|
||||||
- cmake --build .
|
|
||||||
- ctest --output-on-failure
|
|
||||||
tags:
|
|
||||||
- vs2017
|
|
||||||
- windows
|
|
||||||
except:
|
|
||||||
- tags
|
|
||||||
only:
|
|
||||||
- branches@libssh/libssh-mirror
|
|
||||||
- branches@ansasaki/libssh-mirror
|
|
||||||
- branches@cryptomilk/libssh-mirror
|
|
||||||
artifacts:
|
|
||||||
expire_in: 1 week
|
|
||||||
when: on_failure
|
|
||||||
paths:
|
|
||||||
- obj/
|
|
||||||
|
|
||||||
visualstudio/x86:
|
|
||||||
script:
|
|
||||||
- $env:VCPKG_DEFAULT_TRIPLET="x86-windows"
|
|
||||||
- cd obj
|
|
||||||
- cmake
|
|
||||||
-DCMAKE_TOOLCHAIN_FILE="$env:VCPKG_TOOLCHAIN_FILE"
|
|
||||||
-DPICKY_DEVELOPER=ON
|
|
||||||
-DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON -DWITH_PCAP=ON
|
|
||||||
-DUNIT_TESTING=ON ..
|
|
||||||
- cmake --build .
|
|
||||||
- ctest --output-on-failure
|
|
||||||
tags:
|
|
||||||
- vs2017
|
|
||||||
- windows
|
|
||||||
except:
|
|
||||||
- tags
|
|
||||||
only:
|
|
||||||
- branches@libssh/libssh-mirror
|
|
||||||
- branches@ansasaki/libssh-mirror
|
|
||||||
- branches@cryptomilk/libssh-mirror
|
|
||||||
artifacts:
|
|
||||||
expire_in: 1 week
|
|
||||||
when: on_failure
|
|
||||||
paths:
|
|
||||||
- obj/
|
|
||||||
2
AUTHORS
@@ -1,7 +1,7 @@
|
|||||||
Author(s):
|
Author(s):
|
||||||
Aris Adamantiadis <aris@0xbadc0de.be> (project initiator)
|
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)
|
Nick Zitzmann <seiryu (at) comcast (dot) net> (mostly client SFTP stuff)
|
||||||
|
|
||||||
|
|||||||
196
CMakeLists.txt
@@ -1,20 +1,17 @@
|
|||||||
cmake_minimum_required(VERSION 3.3.0)
|
project(libssh C)
|
||||||
cmake_policy(SET CMP0048 NEW)
|
|
||||||
|
|
||||||
# Specify search path for CMake modules to be loaded by include()
|
# Required cmake version
|
||||||
# and find_package()
|
cmake_minimum_required(VERSION 2.6.0)
|
||||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules")
|
|
||||||
|
|
||||||
# Add defaults for cmake
|
# global needed variables
|
||||||
# Those need to be set before the project() call.
|
|
||||||
include(DefineCMakeDefaults)
|
|
||||||
include(DefineCompilerFlags)
|
|
||||||
|
|
||||||
project(libssh VERSION 0.8.90 LANGUAGES C)
|
|
||||||
|
|
||||||
# global needed variable
|
|
||||||
set(APPLICATION_NAME ${PROJECT_NAME})
|
set(APPLICATION_NAME ${PROJECT_NAME})
|
||||||
|
|
||||||
|
set(APPLICATION_VERSION_MAJOR "0")
|
||||||
|
set(APPLICATION_VERSION_MINOR "5")
|
||||||
|
set(APPLICATION_VERSION_PATCH "4")
|
||||||
|
|
||||||
|
set(APPLICATION_VERSION "${APPLICATION_VERSION_MAJOR}.${APPLICATION_VERSION_MINOR}.${APPLICATION_VERSION_PATCH}")
|
||||||
|
|
||||||
# SOVERSION scheme: CURRENT.AGE.REVISION
|
# SOVERSION scheme: CURRENT.AGE.REVISION
|
||||||
# If there was an incompatible interface change:
|
# If there was an incompatible interface change:
|
||||||
# Increment CURRENT. Set AGE and REVISION to 0
|
# Increment CURRENT. Set AGE and REVISION to 0
|
||||||
@@ -22,85 +19,54 @@ set(APPLICATION_NAME ${PROJECT_NAME})
|
|||||||
# Increment AGE. Set REVISION to 0
|
# Increment AGE. Set REVISION to 0
|
||||||
# If the source code was changed, but there were no interface changes:
|
# If the source code was changed, but there were no interface changes:
|
||||||
# Increment REVISION.
|
# Increment REVISION.
|
||||||
set(LIBRARY_VERSION "4.7.2")
|
set(LIBRARY_VERSION "4.2.4")
|
||||||
set(LIBRARY_SOVERSION "4")
|
set(LIBRARY_SOVERSION "4")
|
||||||
|
|
||||||
# where to look first for cmake modules, before ${CMAKE_ROOT}/Modules/ is checked
|
# where to look first for cmake modules, before ${CMAKE_ROOT}/Modules/ is checked
|
||||||
|
set(CMAKE_MODULE_PATH
|
||||||
|
${CMAKE_SOURCE_DIR}/cmake/Modules
|
||||||
|
)
|
||||||
|
|
||||||
# add definitions
|
# add definitions
|
||||||
|
include(DefineCMakeDefaults)
|
||||||
include(DefinePlatformDefaults)
|
include(DefinePlatformDefaults)
|
||||||
|
include(DefineCompilerFlags)
|
||||||
include(DefineInstallationPaths)
|
include(DefineInstallationPaths)
|
||||||
include(DefineOptions.cmake)
|
include(DefineOptions.cmake)
|
||||||
include(CPackConfig.cmake)
|
include(CPackConfig.cmake)
|
||||||
|
|
||||||
include(CompilerChecks.cmake)
|
|
||||||
|
|
||||||
# disallow in-source build
|
# disallow in-source build
|
||||||
include(MacroEnsureOutOfSourceBuild)
|
include(MacroEnsureOutOfSourceBuild)
|
||||||
macro_ensure_out_of_source_build("${PROJECT_NAME} requires an out of source build. Please create a separate build directory and run 'cmake /path/to/${PROJECT_NAME} [options]' there.")
|
macro_ensure_out_of_source_build("${PROJECT_NAME} requires an out of source build. Please create a separate build directory and run 'cmake /path/to/${PROJECT_NAME} [options]' there.")
|
||||||
|
|
||||||
# Copy library files to a lib sub-directory
|
# add macros
|
||||||
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib")
|
include(MacroAddPlugin)
|
||||||
|
include(MacroCopyFile)
|
||||||
|
|
||||||
# search for libraries
|
# search for libraries
|
||||||
if (WITH_ZLIB)
|
if (WITH_LIBZ)
|
||||||
find_package(ZLIB REQUIRED)
|
find_package(ZLIB REQUIRED)
|
||||||
endif (WITH_ZLIB)
|
endif (WITH_LIBZ)
|
||||||
|
|
||||||
if (WITH_GCRYPT)
|
if (WITH_GCRYPT)
|
||||||
find_package(GCrypt 1.5.0 REQUIRED)
|
find_package(GCrypt REQUIRED)
|
||||||
if (NOT GCRYPT_FOUND)
|
if (NOT GCRYPT_FOUND)
|
||||||
message(FATAL_ERROR "Could not find GCrypt")
|
message(FATAL_ERROR "Could not find GCrypt")
|
||||||
endif (NOT GCRYPT_FOUND)
|
endif (NOT GCRYPT_FOUND)
|
||||||
elseif(WITH_MBEDTLS)
|
|
||||||
find_package(MbedTLS REQUIRED)
|
|
||||||
if (NOT MBEDTLS_FOUND)
|
|
||||||
message(FATAL_ERROR "Could not find mbedTLS")
|
|
||||||
endif (NOT MBEDTLS_FOUND)
|
|
||||||
else (WITH_GCRYPT)
|
else (WITH_GCRYPT)
|
||||||
find_package(OpenSSL)
|
find_package(OpenSSL)
|
||||||
if (NOT OPENSSL_FOUND)
|
if (NOT OPENSSL_FOUND)
|
||||||
find_package(GCrypt)
|
find_package(GCrypt)
|
||||||
if (NOT GCRYPT_FOUND)
|
if (NOT GCRYPT_FOUND)
|
||||||
find_package(MbedTLS)
|
message(FATAL_ERROR "Could not find OpenSSL or GCrypt")
|
||||||
if (NOT MBEDTLS_FOUND)
|
|
||||||
message(FATAL_ERROR "Could not find OpenSSL, GCrypt or mbedTLS")
|
|
||||||
endif (NOT MBEDTLS_FOUND)
|
|
||||||
endif (NOT GCRYPT_FOUND)
|
endif (NOT GCRYPT_FOUND)
|
||||||
endif (NOT OPENSSL_FOUND)
|
endif (NOT OPENSSL_FOUND)
|
||||||
endif(WITH_GCRYPT)
|
endif(WITH_GCRYPT)
|
||||||
|
|
||||||
if (UNIT_TESTING)
|
|
||||||
find_package(CMocka REQUIRED)
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
# Find out if we have threading available
|
# Find out if we have threading available
|
||||||
set(CMAKE_THREAD_PREFER_PTHREADS ON)
|
set(CMAKE_THREAD_PREFER_PTHREADS ON)
|
||||||
set(THREADS_PREFER_PTHREAD_FLAG ON)
|
|
||||||
find_package(Threads)
|
find_package(Threads)
|
||||||
|
|
||||||
if (WITH_GSSAPI)
|
|
||||||
find_package(GSSAPI)
|
|
||||||
endif (WITH_GSSAPI)
|
|
||||||
|
|
||||||
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)
|
|
||||||
find_package(Argp)
|
|
||||||
endif (BSD OR SOLARIS OR OSX)
|
|
||||||
|
|
||||||
# Disable symbol versioning in non UNIX platforms
|
|
||||||
if (UNIX)
|
|
||||||
find_package(ABIMap 0.3.1)
|
|
||||||
else (UNIX)
|
|
||||||
set(WITH_SYMBOL_VERSIONING OFF)
|
|
||||||
endif (UNIX)
|
|
||||||
|
|
||||||
# config.h checks
|
# config.h checks
|
||||||
include(ConfigureChecks.cmake)
|
include(ConfigureChecks.cmake)
|
||||||
configure_file(config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config.h)
|
configure_file(config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config.h)
|
||||||
@@ -111,135 +77,43 @@ add_subdirectory(include)
|
|||||||
add_subdirectory(src)
|
add_subdirectory(src)
|
||||||
|
|
||||||
# pkg-config file
|
# pkg-config file
|
||||||
if (UNIX)
|
|
||||||
configure_file(libssh.pc.cmake ${CMAKE_CURRENT_BINARY_DIR}/libssh.pc)
|
configure_file(libssh.pc.cmake ${CMAKE_CURRENT_BINARY_DIR}/libssh.pc)
|
||||||
|
configure_file(libssh_threads.pc.cmake ${CMAKE_CURRENT_BINARY_DIR}/libssh_threads.pc)
|
||||||
install(
|
install(
|
||||||
FILES
|
FILES
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/libssh.pc
|
${CMAKE_CURRENT_BINARY_DIR}/libssh.pc
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}/libssh_threads.pc
|
||||||
DESTINATION
|
DESTINATION
|
||||||
${LIB_INSTALL_DIR}/pkgconfig
|
${LIB_INSTALL_DIR}/pkgconfig
|
||||||
COMPONENT
|
COMPONENT
|
||||||
pkgconfig
|
pkgconfig
|
||||||
)
|
)
|
||||||
endif (UNIX)
|
|
||||||
|
|
||||||
# CMake config files
|
add_subdirectory(examples)
|
||||||
include(CMakePackageConfigHelpers)
|
|
||||||
|
|
||||||
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)
|
|
||||||
|
|
||||||
# libssh-config.cmake
|
|
||||||
configure_package_config_file(${PROJECT_NAME}-config.cmake.in
|
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config.cmake
|
|
||||||
INSTALL_DESTINATION ${CMAKE_INSTALL_DIR}/${PROJECT_NAME}
|
|
||||||
PATH_VARS INCLUDE_INSTALL_DIR LIB_INSTALL_DIR)
|
|
||||||
|
|
||||||
install(
|
|
||||||
FILES
|
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config.cmake
|
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config-version.cmake
|
|
||||||
DESTINATION
|
|
||||||
${CMAKE_INSTALL_DIR}/${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})
|
|
||||||
|
|
||||||
message(STATUS "********************************************")
|
message(STATUS "********************************************")
|
||||||
message(STATUS "********** ${PROJECT_NAME} build options : **********")
|
message(STATUS "********** ${PROJECT_NAME} build options : **********")
|
||||||
|
|
||||||
message(STATUS "zlib support: ${WITH_ZLIB}")
|
message(STATUS "zlib support: ${WITH_LIBZ}")
|
||||||
message(STATUS "libgcrypt support: ${WITH_GCRYPT}")
|
message(STATUS "libgcrypt support: ${WITH_GCRYPT}")
|
||||||
message(STATUS "libmbedTLS support: ${WITH_MBEDTLS}")
|
message(STATUS "SSH-1 support: ${WITH_SSH1}")
|
||||||
message(STATUS "libnacl support: ${WITH_NACL}")
|
|
||||||
message(STATUS "SFTP support: ${WITH_SFTP}")
|
message(STATUS "SFTP support: ${WITH_SFTP}")
|
||||||
message(STATUS "Server support : ${WITH_SERVER}")
|
message(STATUS "Server support : ${WITH_SERVER}")
|
||||||
message(STATUS "GSSAPI support : ${WITH_GSSAPI}")
|
|
||||||
message(STATUS "Pcap debugging support : ${WITH_PCAP}")
|
message(STATUS "Pcap debugging support : ${WITH_PCAP}")
|
||||||
message(STATUS "With static library: ${WITH_STATIC_LIB}")
|
message(STATUS "Unit testing: ${WITH_TESTING}")
|
||||||
message(STATUS "Unit testing: ${UNIT_TESTING}")
|
message(STATUS "Client code Unit testing: ${WITH_CLIENT_TESTING}")
|
||||||
message(STATUS "Client code testing: ${CLIENT_TESTING}")
|
|
||||||
set(_SERVER_TESTING OFF)
|
|
||||||
if (WITH_SERVER)
|
|
||||||
set(_SERVER_TESTING ${SERVER_TESTING})
|
|
||||||
endif()
|
|
||||||
message(STATUS "Server code testing: ${_SERVER_TESTING}")
|
|
||||||
if (WITH_INTERNAL_DOC)
|
if (WITH_INTERNAL_DOC)
|
||||||
message(STATUS "Internal documentation generation")
|
message(STATUS "Internal documentation generation")
|
||||||
else (WITH_INTERNAL_DOC)
|
else (WITH_INTERNAL_DOC)
|
||||||
message(STATUS "Public API documentation generation")
|
message(STATUS "Public API documentation generation")
|
||||||
endif (WITH_INTERNAL_DOC)
|
endif (WITH_INTERNAL_DOC)
|
||||||
message(STATUS "Benchmarks: ${WITH_BENCHMARKS}")
|
message(STATUS "Benchmarks: ${WITH_BENCHMARKS}")
|
||||||
message(STATUS "Symbol versioning: ${WITH_SYMBOL_VERSIONING}")
|
|
||||||
message(STATUS "Allow ABI break: ${WITH_ABI_BREAK}")
|
|
||||||
message(STATUS "Release is final: ${WITH_FINAL}")
|
|
||||||
message(STATUS "********************************************")
|
message(STATUS "********************************************")
|
||||||
|
|
||||||
|
|||||||
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
|
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||||
DAMAGES.
|
DAMAGES.
|
||||||
|
|
||||||
Linking with OpenSSL
|
Linking with OpenSSL
|
||||||
|
17. In addition, as a special exception, we give permission to link the code of its release of libssh with the OpenSSL project's "OpenSSL" library (or with modified versions of it that use the same license as the "OpenSSL" library), and distribute the linked executables. You must obey the GNU Lesser General Public License in all respects for all of the code used other than "OpenSSL". If you modify this file, you may extend this exception to your version of the file, but you are not obligated to do so. If you do not wish to do so, delete this exception statement from your version.
|
||||||
17. In addition, as a special exception, we give permission to link the code
|
|
||||||
of its release of libssh with the OpenSSL project's "OpenSSL" library (or with
|
|
||||||
modified versions of it that use the same license as the "OpenSSL" library),
|
|
||||||
and distribute the linked executables. You must obey the GNU Lesser General
|
|
||||||
Public License in all respects for all of the code used other than "OpenSSL".
|
|
||||||
If you modify this file, you may extend this exception to your version of the
|
|
||||||
file, but you are not obligated to do so. If you do not wish to do so, delete
|
|
||||||
this exception statement from your version.
|
|
||||||
|
|
||||||
END OF TERMS AND CONDITIONS
|
END OF TERMS AND CONDITIONS
|
||||||
|
|||||||
@@ -1,19 +1,27 @@
|
|||||||
### GENERAL SETTINGS
|
# For help take a look at:
|
||||||
set(CPACK_PACKAGE_NAME ${PROJECT_NAME})
|
# http://www.cmake.org/Wiki/CMake:CPackConfiguration
|
||||||
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "The SSH Library")
|
|
||||||
set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/README")
|
### general settings
|
||||||
|
set(CPACK_PACKAGE_NAME ${APPLICATION_NAME})
|
||||||
|
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "The SSH library")
|
||||||
|
set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_SOURCE_DIR}/README")
|
||||||
set(CPACK_PACKAGE_VENDOR "The SSH Library Development Team")
|
set(CPACK_PACKAGE_VENDOR "The SSH Library Development Team")
|
||||||
set(CPACK_PACKAGE_INSTALL_DIRECTORY ${CPACK_PACKAGE_NAME})
|
set(CPACK_PACKAGE_INSTALL_DIRECTORY ${CPACK_PACKAGE_NAME})
|
||||||
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/COPYING")
|
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/COPYING")
|
||||||
|
|
||||||
set(CPACK_PACKAGE_VERSION ${PROJECT_VERSION})
|
|
||||||
|
|
||||||
# SOURCE GENERATOR
|
### versions
|
||||||
set(CPACK_SOURCE_GENERATOR "TXZ")
|
set(CPACK_PACKAGE_VERSION_MAJOR "0")
|
||||||
set(CPACK_SOURCE_IGNORE_FILES "~$;[.]swp$;/[.]git/;.gitignore;/build*;/obj*;tags;cscope.*")
|
set(CPACK_PACKAGE_VERSION_MINOR "5")
|
||||||
|
set(CPACK_PACKAGE_VERSION_PATCH "4")
|
||||||
|
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}")
|
set(CPACK_SOURCE_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}")
|
||||||
|
|
||||||
### NSIS INSTALLER
|
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
set(CPACK_GENERATOR "ZIP")
|
set(CPACK_GENERATOR "ZIP")
|
||||||
|
|
||||||
@@ -38,6 +46,7 @@ set(CPACK_COMPONENT_LIBRARIES_DESCRIPTION
|
|||||||
set(CPACK_COMPONENT_HEADERS_DESCRIPTION
|
set(CPACK_COMPONENT_HEADERS_DESCRIPTION
|
||||||
"C/C++ header files for use with libssh")
|
"C/C++ header files for use with libssh")
|
||||||
set(CPACK_COMPONENT_HEADERS_DEPENDS libraries)
|
set(CPACK_COMPONENT_HEADERS_DEPENDS libraries)
|
||||||
|
#set(CPACK_COMPONENT_APPLICATIONS_GROUP "Runtime")
|
||||||
set(CPACK_COMPONENT_LIBRARIES_GROUP "Development")
|
set(CPACK_COMPONENT_LIBRARIES_GROUP "Development")
|
||||||
set(CPACK_COMPONENT_HEADERS_GROUP "Development")
|
set(CPACK_COMPONENT_HEADERS_GROUP "Development")
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
set(UPDATE_TYPE "true")
|
set(UPDATE_TYPE "true")
|
||||||
|
|
||||||
set(CTEST_PROJECT_NAME "libssh")
|
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_SITE "test.libssh.org")
|
||||||
set(CTEST_DROP_LOCATION "/submit.php?project=libssh")
|
set(CTEST_DROP_LOCATION "/submit.php?project=libssh")
|
||||||
set(CTEST_DROP_SITE_CDASH TRUE)
|
set(CTEST_DROP_SITE_CDASH TRUE)
|
||||||
|
|||||||
129
ChangeLog
@@ -1,135 +1,6 @@
|
|||||||
ChangeLog
|
ChangeLog
|
||||||
==========
|
==========
|
||||||
|
|
||||||
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)
|
version 0.5.4 (released 2013-01-22)
|
||||||
* CVE-2013-0176 - NULL dereference leads to denial of service
|
* CVE-2013-0176 - NULL dereference leads to denial of service
|
||||||
* Fixed several NULL pointer dereferences in SSHv1.
|
* Fixed several NULL pointer dereferences in SSHv1.
|
||||||
|
|||||||
@@ -1,120 +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)
|
|
||||||
|
|
||||||
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)
|
|
||||||
|
|
||||||
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()
|
|
||||||
|
|
||||||
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,14 +1,13 @@
|
|||||||
include(CheckIncludeFile)
|
include(CheckIncludeFile)
|
||||||
include(CheckIncludeFiles)
|
|
||||||
include(CheckSymbolExists)
|
include(CheckSymbolExists)
|
||||||
include(CheckFunctionExists)
|
include(CheckFunctionExists)
|
||||||
include(CheckLibraryExists)
|
include(CheckLibraryExists)
|
||||||
include(CheckTypeSize)
|
include(CheckTypeSize)
|
||||||
include(CheckStructHasMember)
|
include(CheckCXXSourceCompiles)
|
||||||
include(TestBigEndian)
|
include(TestBigEndian)
|
||||||
|
|
||||||
set(PACKAGE ${PROJECT_NAME})
|
set(PACKAGE ${APPLICATION_NAME})
|
||||||
set(VERSION ${PROJECT_VERSION})
|
set(VERSION ${APPLICATION_VERSION})
|
||||||
set(DATADIR ${DATA_INSTALL_DIR})
|
set(DATADIR ${DATA_INSTALL_DIR})
|
||||||
set(LIBDIR ${LIB_INSTALL_DIR})
|
set(LIBDIR ${LIB_INSTALL_DIR})
|
||||||
set(PLUGINDIR "${PLUGIN_INSTALL_DIR}-${LIBRARY_SOVERSION}")
|
set(PLUGINDIR "${PLUGIN_INSTALL_DIR}-${LIBRARY_SOVERSION}")
|
||||||
@@ -37,190 +36,73 @@ endfunction()
|
|||||||
if(CMAKE_COMPILER_IS_GNUCC AND NOT MINGW AND NOT OS2)
|
if(CMAKE_COMPILER_IS_GNUCC AND NOT MINGW AND NOT OS2)
|
||||||
compiler_dumpversion(GNUCC_VERSION)
|
compiler_dumpversion(GNUCC_VERSION)
|
||||||
if (NOT GNUCC_VERSION EQUAL 34)
|
if (NOT GNUCC_VERSION EQUAL 34)
|
||||||
set(CMAKE_REQUIRED_FLAGS "-fvisibility=hidden")
|
check_c_compiler_flag("-fvisibility=hidden" WITH_VISIBILITY_HIDDEN)
|
||||||
check_c_source_compiles(
|
|
||||||
"void __attribute__((visibility(\"default\"))) test() {}
|
|
||||||
int main(void){ return 0; }
|
|
||||||
" WITH_VISIBILITY_HIDDEN)
|
|
||||||
unset(CMAKE_REQUIRED_FLAGS)
|
|
||||||
endif (NOT GNUCC_VERSION EQUAL 34)
|
endif (NOT GNUCC_VERSION EQUAL 34)
|
||||||
endif(CMAKE_COMPILER_IS_GNUCC AND NOT MINGW AND NOT OS2)
|
endif(CMAKE_COMPILER_IS_GNUCC AND NOT MINGW AND NOT OS2)
|
||||||
|
|
||||||
# HEADER FILES
|
# HEADER FILES
|
||||||
set(CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES} ${ARGP_INCLUDE_DIR})
|
|
||||||
check_include_file(argp.h HAVE_ARGP_H)
|
check_include_file(argp.h HAVE_ARGP_H)
|
||||||
unset(CMAKE_REQUIRED_INCLUDES)
|
|
||||||
|
|
||||||
check_include_file(pty.h HAVE_PTY_H)
|
check_include_file(pty.h HAVE_PTY_H)
|
||||||
check_include_file(utmp.h HAVE_UTMP_H)
|
|
||||||
check_include_file(termios.h HAVE_TERMIOS_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)
|
if (WIN32)
|
||||||
check_include_file(io.h HAVE_IO_H)
|
check_include_file(wspiapi.h HAVE_WSPIAPI_H)
|
||||||
|
|
||||||
check_include_files("winsock2.h;ws2tcpip.h;wspiapi.h" HAVE_WSPIAPI_H)
|
|
||||||
if (NOT HAVE_WSPIAPI_H)
|
if (NOT HAVE_WSPIAPI_H)
|
||||||
message(STATUS "WARNING: Without wspiapi.h, this build will only work on Windows XP and newer versions")
|
message(STATUS "WARNING: Without wspiapi.h, this build will only work on Windows XP and newer versions")
|
||||||
endif (NOT HAVE_WSPIAPI_H)
|
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)
|
endif (WIN32)
|
||||||
|
|
||||||
if (OPENSSL_FOUND)
|
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIRS})
|
||||||
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
|
check_include_file(openssl/aes.h HAVE_OPENSSL_AES_H)
|
||||||
check_include_file(openssl/des.h HAVE_OPENSSL_DES_H)
|
|
||||||
if (NOT HAVE_OPENSSL_DES_H)
|
|
||||||
message(FATAL_ERROR "Could not detect openssl/des.h")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
|
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIRS})
|
||||||
check_include_file(openssl/aes.h HAVE_OPENSSL_AES_H)
|
check_include_file(openssl/blowfish.h HAVE_OPENSSL_BLOWFISH_H)
|
||||||
if (NOT HAVE_OPENSSL_AES_H)
|
|
||||||
message(FATAL_ERROR "Could not detect openssl/aes.h")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
|
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIRS})
|
||||||
check_include_file(openssl/blowfish.h HAVE_OPENSSL_BLOWFISH_H)
|
check_include_file(openssl/des.h HAVE_OPENSSL_DES_H)
|
||||||
|
|
||||||
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_LIBRARY})
|
|
||||||
check_function_exists(EVP_aes_128_ctr HAVE_OPENSSL_EVP_AES_CTR)
|
|
||||||
|
|
||||||
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
|
|
||||||
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARY})
|
|
||||||
check_function_exists(EVP_aes_128_cbc HAVE_OPENSSL_EVP_AES_CBC)
|
|
||||||
|
|
||||||
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
|
|
||||||
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARY})
|
|
||||||
check_function_exists(EVP_aes_128_gcm HAVE_OPENSSL_EVP_AES_GCM)
|
|
||||||
|
|
||||||
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
|
|
||||||
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARY})
|
|
||||||
check_function_exists(CRYPTO_THREADID_set_callback HAVE_OPENSSL_CRYPTO_THREADID_SET_CALLBACK)
|
|
||||||
|
|
||||||
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
|
|
||||||
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARY})
|
|
||||||
check_function_exists(CRYPTO_ctr128_encrypt HAVE_OPENSSL_CRYPTO_CTR128_ENCRYPT)
|
|
||||||
|
|
||||||
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
|
|
||||||
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARY})
|
|
||||||
check_function_exists(EVP_CIPHER_CTX_new HAVE_OPENSSL_EVP_CIPHER_CTX_NEW)
|
|
||||||
|
|
||||||
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
|
|
||||||
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARY})
|
|
||||||
check_function_exists(RAND_priv_bytes HAVE_OPENSSL_RAND_PRIV_BYTES)
|
|
||||||
|
|
||||||
check_function_exists(OPENSSL_ia32cap_loc HAVE_OPENSSL_IA32CAP_LOC)
|
|
||||||
|
|
||||||
unset(CMAKE_REQUIRED_INCLUDES)
|
|
||||||
unset(CMAKE_REQUIRED_LIBRARIES)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if (CMAKE_HAVE_PTHREAD_H)
|
if (CMAKE_HAVE_PTHREAD_H)
|
||||||
set(HAVE_PTHREAD_H 1)
|
set(HAVE_PTHREAD_H 1)
|
||||||
endif (CMAKE_HAVE_PTHREAD_H)
|
endif (CMAKE_HAVE_PTHREAD_H)
|
||||||
|
|
||||||
if (NOT WITH_GCRYPT AND NOT WITH_MBEDTLS)
|
|
||||||
if (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)
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
if (NOT WITH_MBEDTLS)
|
|
||||||
set(HAVE_DSA 1)
|
|
||||||
endif (NOT WITH_MBEDTLS)
|
|
||||||
|
|
||||||
# FUNCTIONS
|
# FUNCTIONS
|
||||||
|
|
||||||
check_function_exists(isblank HAVE_ISBLANK)
|
|
||||||
check_function_exists(strncpy HAVE_STRNCPY)
|
check_function_exists(strncpy HAVE_STRNCPY)
|
||||||
check_function_exists(strndup HAVE_STRNDUP)
|
check_function_exists(vsnprintf HAVE_VSNPRINTF)
|
||||||
check_function_exists(strtoull HAVE_STRTOULL)
|
check_function_exists(snprintf HAVE_SNPRINTF)
|
||||||
check_function_exists(explicit_bzero HAVE_EXPLICIT_BZERO)
|
|
||||||
check_function_exists(memset_s HAVE_MEMSET_S)
|
|
||||||
|
|
||||||
if (HAVE_GLOB_H)
|
|
||||||
check_struct_has_member(glob_t gl_flags glob.h HAVE_GLOB_GL_FLAGS_MEMBER)
|
|
||||||
check_function_exists(glob HAVE_GLOB)
|
|
||||||
endif (HAVE_GLOB_H)
|
|
||||||
|
|
||||||
if (NOT WIN32)
|
|
||||||
check_function_exists(vsnprintf HAVE_VSNPRINTF)
|
|
||||||
check_function_exists(snprintf HAVE_SNPRINTF)
|
|
||||||
endif (NOT WIN32)
|
|
||||||
|
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
check_symbol_exists(vsnprintf "stdio.h" HAVE_VSNPRINTF)
|
check_function_exists(_vsnprintf_s HAVE__VSNPRINTF_S)
|
||||||
check_symbol_exists(snprintf "stdio.h" HAVE_SNPRINTF)
|
check_function_exists(_vsnprintf HAVE__VSNPRINTF)
|
||||||
|
check_function_exists(_snprintf HAVE__SNPRINTF)
|
||||||
check_symbol_exists(_vsnprintf_s "stdio.h" HAVE__VSNPRINTF_S)
|
check_function_exists(_snprintf_s HAVE__SNPRINTF_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)
|
|
||||||
endif (WIN32)
|
endif (WIN32)
|
||||||
|
|
||||||
|
|
||||||
if (UNIX)
|
if (UNIX)
|
||||||
if (NOT LINUX)
|
if (NOT LINUX)
|
||||||
# libsocket (Solaris)
|
# libsocket (Solaris)
|
||||||
check_library_exists(socket getaddrinfo "" HAVE_LIBSOCKET)
|
check_library_exists(socket getaddrinfo "" HAVE_LIBSOCKET)
|
||||||
if (HAVE_LIBSOCKET)
|
if (HAVE_LIBSOCKET)
|
||||||
set(HAVE_GETADDRINFO TRUE)
|
set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} socket)
|
||||||
set(_REQUIRED_LIBRARIES ${_REQUIRED_LIBRARIES} socket)
|
|
||||||
endif (HAVE_LIBSOCKET)
|
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)
|
# libnsl/inet_pton (Solaris)
|
||||||
check_library_exists(nsl inet_pton "" HAVE_LIBNSL)
|
check_library_exists(nsl inet_pton "" HAVE_LIBNSL)
|
||||||
if (HAVE_LIBNSL)
|
if (HAVE_LIBNSL)
|
||||||
set(_REQUIRED_LIBRARIES ${_REQUIRED_LIBRARIES} nsl)
|
set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} nsl)
|
||||||
endif (HAVE_LIBNSL)
|
endif (HAVE_LIBNSL)
|
||||||
|
|
||||||
# librt
|
# librt
|
||||||
@@ -229,15 +111,18 @@ if (UNIX)
|
|||||||
|
|
||||||
check_library_exists(rt clock_gettime "" HAVE_CLOCK_GETTIME)
|
check_library_exists(rt clock_gettime "" HAVE_CLOCK_GETTIME)
|
||||||
if (HAVE_LIBRT OR HAVE_CLOCK_GETTIME)
|
if (HAVE_LIBRT OR HAVE_CLOCK_GETTIME)
|
||||||
set(_REQUIRED_LIBRARIES ${_REQUIRED_LIBRARIES} rt)
|
set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} rt)
|
||||||
endif (HAVE_LIBRT OR HAVE_CLOCK_GETTIME)
|
endif (HAVE_LIBRT OR HAVE_CLOCK_GETTIME)
|
||||||
|
|
||||||
check_library_exists(util forkpty "" HAVE_LIBUTIL)
|
check_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(cfmakeraw HAVE_CFMAKERAW)
|
||||||
check_function_exists(__strtoull HAVE___STRTOULL)
|
check_function_exists(regcomp HAVE_REGCOMP)
|
||||||
|
check_function_exists(ntohll HAVE_NTOHLL)
|
||||||
endif (UNIX)
|
endif (UNIX)
|
||||||
|
|
||||||
set(LIBSSH_REQUIRED_LIBRARIES ${_REQUIRED_LIBRARIES} CACHE INTERNAL "libssh required system libraries")
|
set(LIBSSH_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} CACHE INTERNAL "libssh required system libraries")
|
||||||
|
|
||||||
# LIBRARIES
|
# LIBRARIES
|
||||||
if (OPENSSL_FOUND)
|
if (OPENSSL_FOUND)
|
||||||
@@ -245,209 +130,28 @@ if (OPENSSL_FOUND)
|
|||||||
endif (OPENSSL_FOUND)
|
endif (OPENSSL_FOUND)
|
||||||
|
|
||||||
if (GCRYPT_FOUND)
|
if (GCRYPT_FOUND)
|
||||||
set(HAVE_LIBGCRYPT 1)
|
set(HAVE_LIBGCRYPT 1)
|
||||||
if (GCRYPT_VERSION VERSION_GREATER "1.4.6")
|
|
||||||
set(HAVE_GCRYPT_ECC 1)
|
|
||||||
set(HAVE_ECC 1)
|
|
||||||
endif (GCRYPT_VERSION VERSION_GREATER "1.4.6")
|
|
||||||
endif (GCRYPT_FOUND)
|
endif (GCRYPT_FOUND)
|
||||||
|
|
||||||
if (MBEDTLS_FOUND)
|
if (ZLIB_LIBRARY)
|
||||||
set(HAVE_LIBMBEDCRYPTO 1)
|
set(HAVE_LIBZ 1)
|
||||||
set(HAVE_ECC 1)
|
endif (ZLIB_LIBRARY)
|
||||||
endif (MBEDTLS_FOUND)
|
|
||||||
|
|
||||||
if (CMAKE_USE_PTHREADS_INIT)
|
if (CMAKE_HAVE_THREADS_LIBRARY)
|
||||||
set(HAVE_PTHREAD 1)
|
if (CMAKE_USE_PTHREADS_INIT)
|
||||||
endif (CMAKE_USE_PTHREADS_INIT)
|
set(HAVE_PTHREAD 1)
|
||||||
|
endif (CMAKE_USE_PTHREADS_INIT)
|
||||||
if (UNIT_TESTING)
|
endif (CMAKE_HAVE_THREADS_LIBRARY)
|
||||||
if (CMOCKA_FOUND)
|
|
||||||
set(CMAKE_REQUIRED_LIBRARIES ${CMOCKA_LIBRARIES})
|
|
||||||
check_function_exists(cmocka_set_test_filter HAVE_CMOCKA_SET_TEST_FILTER)
|
|
||||||
unset(CMAKE_REQUIRED_LIBRARIES)
|
|
||||||
endif ()
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
# OPTIONS
|
# OPTIONS
|
||||||
check_c_source_compiles("
|
|
||||||
__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)
|
|
||||||
|
|
||||||
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>
|
|
||||||
#define __VA_NARG__(...) (__VA_NARG_(_0, ## __VA_ARGS__, __RSEQ_N()) - 1)
|
|
||||||
#define __VA_NARG_(...) __VA_ARG_N(__VA_ARGS__)
|
|
||||||
#define __VA_ARG_N( _1, _2, _3, _4, _5, _6, _7, _8, _9,_10,N,...) N
|
|
||||||
#define __RSEQ_N() 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
|
|
||||||
#define myprintf(format, ...) printf((format), __VA_NARG__(__VA_ARGS__), __VA_ARGS__)
|
|
||||||
int main(void) {
|
|
||||||
myprintf(\"%d %d %d %d\",1,2,3);
|
|
||||||
return 0;
|
|
||||||
}" HAVE_GCC_NARG_MACRO)
|
|
||||||
|
|
||||||
check_c_source_compiles("
|
|
||||||
#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)
|
if (WITH_DEBUG_CRYPTO)
|
||||||
set(DEBUG_CRYPTO 1)
|
set(DEBUG_CRYPTO 1)
|
||||||
endif (WITH_DEBUG_CRYPTO)
|
endif (WITH_DEBUG_CRYPTO)
|
||||||
|
|
||||||
if (WITH_DEBUG_PACKET)
|
|
||||||
set(DEBUG_PACKET 1)
|
|
||||||
endif (WITH_DEBUG_PACKET)
|
|
||||||
|
|
||||||
if (WITH_DEBUG_CALLTRACE)
|
if (WITH_DEBUG_CALLTRACE)
|
||||||
set(DEBUG_CALLTRACE 1)
|
set(DEBUG_CALLTRACE 1)
|
||||||
endif (WITH_DEBUG_CALLTRACE)
|
endif (WITH_DEBUG_CALLTRACE)
|
||||||
|
|
||||||
if (WITH_GSSAPI AND NOT GSSAPI_FOUND)
|
|
||||||
set(WITH_GSSAPI 0)
|
|
||||||
endif (WITH_GSSAPI AND NOT GSSAPI_FOUND)
|
|
||||||
|
|
||||||
# ENDIAN
|
# ENDIAN
|
||||||
if (NOT WIN32)
|
if (NOT WIN32)
|
||||||
test_big_endian(WORDS_BIGENDIAN)
|
test_big_endian(WORDS_BIGENDIAN)
|
||||||
|
|||||||
@@ -1,49 +1,21 @@
|
|||||||
option(WITH_GSSAPI "Build with GSSAPI support" ON)
|
option(WITH_LIBZ "Build with ZLIB support" ON)
|
||||||
option(WITH_ZLIB "Build with ZLIB support" ON)
|
option(WITH_SSH1 "Build with SSH1 support" OFF)
|
||||||
option(WITH_SFTP "Build with SFTP support" ON)
|
option(WITH_SFTP "Build with SFTP support" ON)
|
||||||
option(WITH_SERVER "Build with SSH server support" ON)
|
option(WITH_SERVER "Build with SSH server support" ON)
|
||||||
option(WITH_STATIC_LIB "Build with a static library" OFF)
|
option(WITH_STATIC_LIB "Build with a static library" OFF)
|
||||||
option(WITH_DEBUG_CRYPTO "Build with cryto debug output" OFF)
|
option(WITH_DEBUG_CRYPTO "Build with cryto debug output" OFF)
|
||||||
option(WITH_DEBUG_PACKET "Build with packet debug output" OFF)
|
|
||||||
option(WITH_DEBUG_CALLTRACE "Build with calltrace debug output" ON)
|
option(WITH_DEBUG_CALLTRACE "Build with calltrace debug output" ON)
|
||||||
option(WITH_GCRYPT "Compile against libgcrypt" OFF)
|
option(WITH_GCRYPT "Compile against libgcrypt" OFF)
|
||||||
option(WITH_MBEDTLS "Compile against libmbedtls" OFF)
|
|
||||||
option(WITH_PCAP "Compile with Pcap generation support" ON)
|
option(WITH_PCAP "Compile with Pcap generation support" ON)
|
||||||
option(WITH_INTERNAL_DOC "Compile doxygen internal documentation" OFF)
|
option(WITH_INTERNAL_DOC "Compile doxygen internal documentation" OFF)
|
||||||
option(UNIT_TESTING "Build with unit tests" OFF)
|
option(WITH_TESTING "Build with unit tests" OFF)
|
||||||
option(CLIENT_TESTING "Build with client tests; requires openssh" OFF)
|
option(WITH_CLIENT_TESTING "Build with client tests; requires a running sshd" OFF)
|
||||||
option(SERVER_TESTING "Build with server tests; requires openssh and dropbear" OFF)
|
|
||||||
option(WITH_BENCHMARKS "Build benchmarks tools" OFF)
|
option(WITH_BENCHMARKS "Build benchmarks tools" OFF)
|
||||||
option(WITH_EXAMPLES "Build examples" ON)
|
|
||||||
option(WITH_NACL "Build with libnacl (curve25519)" ON)
|
|
||||||
option(WITH_SYMBOL_VERSIONING "Build with symbol versioning" ON)
|
|
||||||
option(WITH_ABI_BREAK "Allow ABI break" OFF)
|
|
||||||
option(FUZZ_TESTING "Build with fuzzer for the server" OFF)
|
|
||||||
option(PICKY_DEVELOPER "Build with picky developer flags" OFF)
|
|
||||||
|
|
||||||
if (WITH_ZLIB)
|
if(WITH_BENCHMARKS)
|
||||||
set(WITH_LIBZ ON)
|
set(WITH_TESTING ON)
|
||||||
else (WITH_ZLIB)
|
endif(WITH_BENCHMARKS)
|
||||||
set(WITH_LIBZ OFF)
|
|
||||||
endif (WITH_ZLIB)
|
|
||||||
|
|
||||||
if (WITH_BENCHMARKS)
|
if (WITH_TESTING)
|
||||||
set(UNIT_TESTING ON)
|
set(WITH_STATIC_LIB ON)
|
||||||
set(CLIENT_TESTING ON)
|
endif (WITH_TESTING)
|
||||||
endif()
|
|
||||||
|
|
||||||
if (WITH_STATIC_LIB)
|
|
||||||
set(BUILD_STATIC_LIB ON)
|
|
||||||
endif (WITH_STATIC_LIB)
|
|
||||||
|
|
||||||
if (UNIT_TESTING)
|
|
||||||
set(BUILD_STATIC_LIB ON)
|
|
||||||
endif (UNIT_TESTING)
|
|
||||||
|
|
||||||
if (WITH_NACL)
|
|
||||||
set(WITH_NACL ON)
|
|
||||||
endif (WITH_NACL)
|
|
||||||
|
|
||||||
if (WITH_ABI_BREAK)
|
|
||||||
set(WITH_SYMBOL_VERSIONING ON)
|
|
||||||
endif (WITH_ABI_BREAK)
|
|
||||||
|
|||||||
47
INSTALL
@@ -14,48 +14,20 @@ or
|
|||||||
|
|
||||||
optional:
|
optional:
|
||||||
- [libz](http://www.zlib.net) >= 1.2
|
- [libz](http://www.zlib.net) >= 1.2
|
||||||
- [socket_wrapper](https://cwrap.org/) >= 1.1.5
|
|
||||||
- [nss_wrapper](https://cwrap.org/) >= 1.1.2
|
|
||||||
- [uid_wrapper](https://cwrap.org/) >= 1.2.0
|
|
||||||
- [pam_wrapper](https://cwrap.org/) >= 1.0.1
|
|
||||||
|
|
||||||
Note that these version numbers are version we know works correctly. If you
|
Note that these version numbers are version we know works correctly. If you
|
||||||
build and run libssh successfully with an older version, please let us know.
|
build and run libssh successfully with an older version, please let us know.
|
||||||
|
|
||||||
For Windows use vcpkg:
|
|
||||||
|
|
||||||
https://github.com/Microsoft/vcpkg
|
|
||||||
|
|
||||||
which you can use to install openssl and zilib. libssh itself is also part of
|
|
||||||
vcpkg!
|
|
||||||
|
|
||||||
## Building
|
## Building
|
||||||
First, you need to configure the compilation, using CMake. Go inside the
|
First, you need to configure the compilation, using CMake. Go inside the
|
||||||
`build` dir. Create it if it doesn't exist.
|
`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
|
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
|
### CMake standard options
|
||||||
Here is a list of the most interesting options provided out of the box by
|
Here is a list of the most interesting options provided out of the box by
|
||||||
CMake.
|
CMake.
|
||||||
@@ -75,7 +47,7 @@ Options are defined in the following files:
|
|||||||
|
|
||||||
They can be changed with the -D option:
|
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
|
### Browsing/editing CMake options
|
||||||
|
|
||||||
@@ -87,17 +59,6 @@ and MacOS X).
|
|||||||
- On Windows: run `cmakesetup`
|
- On Windows: run `cmakesetup`
|
||||||
- On GNU/Linux and MacOS X: run `ccmake ..`
|
- 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
|
## Installing
|
||||||
|
|
||||||
If you want to install libssh after compilation run:
|
If you want to install libssh after compilation run:
|
||||||
@@ -106,7 +67,7 @@ If you want to install libssh after compilation run:
|
|||||||
|
|
||||||
## Running
|
## 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
|
You can use `build/examples/samplessh` which is a sample client to
|
||||||
test libssh on UNIX.
|
test libssh on UNIX.
|
||||||
|
|
||||||
|
|||||||
136
README
@@ -1,12 +1,5 @@
|
|||||||
_ _ _ _
|
libssh: the SSH library
|
||||||
(_) (_) (_) (_)
|
~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
(_) _ (_) _ _ _ _ _ (_) _
|
|
||||||
(_) (_) (_)(_) _ (_)(_) (_)(_) (_)(_) _
|
|
||||||
(_) (_) (_) (_) _ (_) _ (_) (_) (_)
|
|
||||||
(_) (_) (_)(_)(_) (_)(_) (_)(_) (_) (_).org
|
|
||||||
|
|
||||||
The SSH library
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
1* Why ?
|
1* Why ?
|
||||||
-_-_-_-_-_
|
-_-_-_-_-_
|
||||||
@@ -33,11 +26,130 @@ If you ask yourself how to compile libssh, please read INSTALL before anything.
|
|||||||
|
|
||||||
http://www.libssh.org
|
http://www.libssh.org
|
||||||
|
|
||||||
4* Contributing
|
4* API Changes !
|
||||||
-_-_-_-_-_-_-_-_-_
|
-_-_-_-_-_-_-_-_-_
|
||||||
|
|
||||||
Please read the file 'SubmittingPatches' next to this README file. It explains
|
Changes between 0.4 and 0.5
|
||||||
our copyright policy and how you should send patches for upstream inclusion.
|
---------------------------
|
||||||
|
|
||||||
|
We use the ssh_ prefix as namespace for every function now. There is a legacy.h
|
||||||
|
which could be used to get the old function names.
|
||||||
|
|
||||||
|
Changes between 0.3 and 0.4
|
||||||
|
---------------------------
|
||||||
|
|
||||||
|
We changed libssh to be typesafe now:
|
||||||
|
|
||||||
|
SSH_SESSION *session -> ssh_session session
|
||||||
|
SFTP_SESSION *sftp -> sftp_session sftp
|
||||||
|
CHANNEL *channel -> ssh_channel channel
|
||||||
|
STRING *string -> ssh_string string
|
||||||
|
...
|
||||||
|
|
||||||
|
The options structure has been removed and there is a new function. This
|
||||||
|
function can set all available options now. You can find the enum in the
|
||||||
|
header file and it is documented. Example:
|
||||||
|
|
||||||
|
ssh_options_set(session, SSH_OPTIONS_HOST, "localhost");
|
||||||
|
|
||||||
|
5* Copyright policy
|
||||||
|
-_-_-_-_-_-_-_-_-_-_
|
||||||
|
|
||||||
|
libssh is a project with distributed copyright ownership, which means we prefer
|
||||||
|
the copyright on parts of libssh to be held by individuals rather than
|
||||||
|
corporations if possible. There are historical legal reasons for this, but one
|
||||||
|
of the best ways to explain it is that 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!
|
Have fun and happy libssh hacking!
|
||||||
|
|
||||||
|
|||||||
@@ -1,375 +0,0 @@
|
|||||||
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)))
|
|
||||||
|
|
||||||
|
|
||||||
Vim
|
|
||||||
----
|
|
||||||
|
|
||||||
For the basic vi editor included with all variants of \*nix, add the
|
|
||||||
following to $HOME/.vimrc:
|
|
||||||
|
|
||||||
set ts=4 sw=4 et cindent
|
|
||||||
|
|
||||||
You can use the Vim gitmodline plugin to store this in the git config:
|
|
||||||
|
|
||||||
http://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.
|
|
||||||
@@ -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.
|
|
||||||
44
README.md
@@ -1,44 +0,0 @@
|
|||||||
[](https://gitlab.com/libssh/libssh-mirror/commits/master)
|
|
||||||
|
|
||||||
```
|
|
||||||
_ _ _ _
|
|
||||||
(_) (_) (_) (_)
|
|
||||||
(_) _ (_) _ _ _ _ _ (_) _
|
|
||||||
(_) (_) (_)(_) _ (_)(_) (_)(_) (_)(_) _
|
|
||||||
(_) (_) (_) (_) _ (_) _ (_) (_) (_)
|
|
||||||
(_) (_) (_)(_)(_) (_)(_) (_)(_) (_) (_).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 'SubmittingPatches' 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
|
|
||||||
@@ -1,118 +0,0 @@
|
|||||||
How to contribute a patch to libssh
|
|
||||||
====================================
|
|
||||||
|
|
||||||
Please checkout the libssh source code using git. Change the code and then
|
|
||||||
use "git format-patch" to create a patch. The patch should be signed (see
|
|
||||||
below) and send it to libssh@libssh.org, or attach it to a bug report at
|
|
||||||
https://red.libssh.org/
|
|
||||||
|
|
||||||
For larger code changes, breaking the changes up into a set of simple
|
|
||||||
patches, each of which does a single thing, are much easier to review.
|
|
||||||
Patch sets like that will most likely have an easier time being merged
|
|
||||||
into the libssh code than large single patches that make lots of
|
|
||||||
changes in one large diff.
|
|
||||||
|
|
||||||
Ownership of the contributed code
|
|
||||||
==================================
|
|
||||||
|
|
||||||
libssh is a project with distributed copyright ownership, which means
|
|
||||||
we prefer the copyright on parts of libssh to be held by individuals
|
|
||||||
rather than corporations if possible. There are historical legal
|
|
||||||
reasons for this, but one of the best ways to explain it is that it's
|
|
||||||
much easier to work with individuals who have ownership than corporate
|
|
||||||
legal departments if we ever need to make reasonable compromises with
|
|
||||||
people using and working with libssh.
|
|
||||||
|
|
||||||
We track the ownership of every part of libssh via http://git.libssh.org,
|
|
||||||
our source code control system, so we know the provenance of every piece
|
|
||||||
of code that is committed to libssh.
|
|
||||||
|
|
||||||
So if possible, if you're doing libssh changes on behalf of a company
|
|
||||||
who normally owns all the work you do please get them to assign
|
|
||||||
personal copyright ownership of your changes to you as an individual,
|
|
||||||
that makes things very easy for us to work with and avoids bringing
|
|
||||||
corporate legal departments into the picture.
|
|
||||||
|
|
||||||
If you can't do this we can still accept patches from you owned by
|
|
||||||
your employer under a standard employment contract with corporate
|
|
||||||
copyright ownership. It just requires a simple set-up process first.
|
|
||||||
|
|
||||||
We use a process very similar to the way things are done in the Linux
|
|
||||||
Kernel community, so it should be very easy to get a sign off from
|
|
||||||
your corporate legal department. The only changes we've made are to
|
|
||||||
accommodate the license we use, which is LGPLv2 (or later) whereas the
|
|
||||||
Linux kernel uses GPLv2.
|
|
||||||
|
|
||||||
The process is called signing.
|
|
||||||
|
|
||||||
How to sign your work
|
|
||||||
----------------------
|
|
||||||
|
|
||||||
Once you have permission to contribute to libssh from your employer, simply
|
|
||||||
email a copy of the following text from your corporate email address to:
|
|
||||||
|
|
||||||
contributing@libssh.org
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
libssh Developer's Certificate of Origin. Version 1.0
|
|
||||||
|
|
||||||
|
|
||||||
By making a contribution to this project, I certify that:
|
|
||||||
|
|
||||||
(a) The contribution was created in whole or in part by me and I
|
|
||||||
have the right to submit it under the appropriate
|
|
||||||
version of the GNU General Public License; or
|
|
||||||
|
|
||||||
(b) The contribution is based upon previous work that, to the best of
|
|
||||||
my knowledge, is covered under an appropriate open source license
|
|
||||||
and I have the right under that license to submit that work with
|
|
||||||
modifications, whether created in whole or in part by me, under
|
|
||||||
the GNU General Public License, in the appropriate version; or
|
|
||||||
|
|
||||||
(c) The contribution was provided directly to me by some other
|
|
||||||
person who certified (a) or (b) and I have not modified it.
|
|
||||||
|
|
||||||
(d) I understand and agree that this project and the contribution are
|
|
||||||
public and that a record of the contribution (including all
|
|
||||||
metadata and personal information I submit with it, including my
|
|
||||||
sign-off) is maintained indefinitely and may be redistributed
|
|
||||||
consistent with the libssh Team's policies and the requirements of
|
|
||||||
the GNU GPL where they are relevant.
|
|
||||||
|
|
||||||
(e) I am granting this work to this project under the terms of the
|
|
||||||
GNU Lesser General Public License as published by the
|
|
||||||
Free Software Foundation; either version 2.1 of
|
|
||||||
the License, or (at the option of the project) any later version.
|
|
||||||
|
|
||||||
http://www.gnu.org/licenses/lgpl-2.1.html
|
|
||||||
|
|
||||||
|
|
||||||
We will maintain a copy of that email as a record that you have the
|
|
||||||
rights to contribute code to libssh under the required licenses whilst
|
|
||||||
working for the company where the email came from.
|
|
||||||
|
|
||||||
Then when sending in a patch via the normal mechanisms described
|
|
||||||
above, add a line that states:
|
|
||||||
|
|
||||||
Signed-off-by: Random J Developer <random@developer.example.org>
|
|
||||||
|
|
||||||
using your real name and the email address you sent the original email
|
|
||||||
you used to send the libssh Developer's Certificate of Origin to us
|
|
||||||
(sorry, no pseudonyms or anonymous contributions.)
|
|
||||||
|
|
||||||
That's it! Such code can then quite happily contain changes that have
|
|
||||||
copyright messages such as:
|
|
||||||
|
|
||||||
(c) Example Corporation.
|
|
||||||
|
|
||||||
and can be merged into the libssh codebase in the same way as patches
|
|
||||||
from any other individual. You don't need to send in a copy of the
|
|
||||||
libssh Developer's Certificate of Origin for each patch, or inside each
|
|
||||||
patch. Just the sign-off message is all that is required once we've
|
|
||||||
received the initial email.
|
|
||||||
|
|
||||||
Have fun and happy libssh hacking !
|
|
||||||
|
|
||||||
The libssh Team
|
|
||||||
|
|
||||||
@@ -4,7 +4,7 @@
|
|||||||
#
|
#
|
||||||
# Script to build libssh on UNIX.
|
# Script to build libssh on UNIX.
|
||||||
#
|
#
|
||||||
# Copyright (c) 2006-2007 Andreas Schneider <asn@cryptomilk.org>
|
# Copyright (c) 2006-2007 Andreas Schneider <mail@cynapses.org>
|
||||||
#
|
#
|
||||||
|
|
||||||
SOURCE_DIR=".."
|
SOURCE_DIR=".."
|
||||||
@@ -63,7 +63,7 @@ function clean_build_dir() {
|
|||||||
|
|
||||||
function usage () {
|
function usage () {
|
||||||
echo "Usage: `basename $0` [--prefix /install_prefix|--build [debug|final]|--clean|--verbose|--libsuffix (32|64)|--help|--clang|--cmakedir /directory|--make
|
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|--withserver|--withoutsymbolversioning]"
|
(gmake|make)|--ccompiler (gcc|cc)|--withstaticlib|--unittesting|--clientunittesting|--withssh1|--withserver]"
|
||||||
cleanup_and_exit
|
cleanup_and_exit
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -137,20 +137,17 @@ while test -n "$1"; do
|
|||||||
OPTIONS="${OPTIONS} -DWITH_STATIC_LIB=ON"
|
OPTIONS="${OPTIONS} -DWITH_STATIC_LIB=ON"
|
||||||
;;
|
;;
|
||||||
*-unittesting)
|
*-unittesting)
|
||||||
OPTIONS="${OPTIONS} -DUNIT_TESTING=ON"
|
OPTIONS="${OPTIONS} -DWITH_TESTING=ON"
|
||||||
;;
|
;;
|
||||||
*-clientunittesting)
|
*-clientunittesting)
|
||||||
OPTIONS="${OPTIONS} -DCLIENT_TESTING=ON"
|
OPTIONS="${OPTIONS} -DWITH_CLIENT_TESTING=ON"
|
||||||
|
;;
|
||||||
|
*-withssh1)
|
||||||
|
OPTIONS="${OPTIONS} -DWITH_SSH1=ON"
|
||||||
;;
|
;;
|
||||||
*-withserver)
|
*-withserver)
|
||||||
OPTIONS="${OPTIONS} -DWITH_SERVER=ON"
|
OPTIONS="${OPTIONS} -DWITH_SERVER=ON"
|
||||||
;;
|
;;
|
||||||
*-withoutsymbolversioning)
|
|
||||||
OPTIONS="${OPTIONS} -DWITH_SYMBOL_VERSIONING=OFF"
|
|
||||||
;;
|
|
||||||
*-finalrelease)
|
|
||||||
OPTIONS="${OPTIONS} -DWITH_FINAL=ON"
|
|
||||||
;;
|
|
||||||
----noarg)
|
----noarg)
|
||||||
echo "$ARG does not take an argument"
|
echo "$ARG does not take an argument"
|
||||||
cleanup_and_exit
|
cleanup_and_exit
|
||||||
@@ -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
|
# since cmake 2.4.0
|
||||||
set(CMAKE_COLOR_MAKEFILE ON)
|
set(CMAKE_COLOR_MAKEFILE ON)
|
||||||
|
|
||||||
# Create the compile command database for clang by default
|
# Define the generic version of the libraries here
|
||||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
set(GENERIC_LIB_VERSION "0.1.0")
|
||||||
|
set(GENERIC_LIB_SOVERSION "0")
|
||||||
|
|
||||||
# Always build with -fPIC
|
# Set the default build type to release with debug info
|
||||||
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
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,37 +1,71 @@
|
|||||||
|
# define system dependent compiler flags
|
||||||
|
|
||||||
|
include(CheckCCompilerFlag)
|
||||||
|
include(MacroCheckCCompilerFlagSSP)
|
||||||
|
|
||||||
if (UNIX AND NOT WIN32)
|
if (UNIX AND NOT WIN32)
|
||||||
# Activate with: -DCMAKE_BUILD_TYPE=Profiling
|
#
|
||||||
set(CMAKE_C_FLAGS_PROFILING "-O0 -g -fprofile-arcs -ftest-coverage"
|
# Define GNUCC compiler flags
|
||||||
CACHE STRING "Flags used by the C compiler during PROFILING builds.")
|
#
|
||||||
set(CMAKE_CXX_FLAGS_PROFILING "-O0 -g -fprofile-arcs -ftest-coverage"
|
if (${CMAKE_C_COMPILER_ID} MATCHES GNU)
|
||||||
CACHE STRING "Flags used by the CXX compiler during PROFILING builds.")
|
# add -Wconversion ?
|
||||||
set(CMAKE_SHARED_LINKER_FLAGS_PROFILING "-fprofile-arcs -ftest-coverage"
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99 -pedantic -pedantic-errors")
|
||||||
CACHE STRING "Flags used by the linker during the creation of shared libraries during PROFILING builds.")
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wshadow -Wmissing-prototypes -Wdeclaration-after-statement")
|
||||||
set(CMAKE_MODULE_LINKER_FLAGS_PROFILING "-fprofile-arcs -ftest-coverage"
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wunused -Wfloat-equal -Wpointer-arith -Wwrite-strings -Wformat-security")
|
||||||
CACHE STRING "Flags used by the linker during the creation of shared libraries during PROFILING builds.")
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wmissing-format-attribute")
|
||||||
set(CMAKE_EXEC_LINKER_FLAGS_PROFILING "-fprofile-arcs -ftest-coverage"
|
|
||||||
CACHE STRING "Flags used by the linker during PROFILING builds.")
|
|
||||||
|
|
||||||
# Activate with: -DCMAKE_BUILD_TYPE=AddressSanitizer
|
# with -fPIC
|
||||||
set(CMAKE_C_FLAGS_ADDRESSSANITIZER "-g -O1 -fsanitize=address -fno-omit-frame-pointer"
|
check_c_compiler_flag("-fPIC" WITH_FPIC)
|
||||||
CACHE STRING "Flags used by the C compiler during ADDRESSSANITIZER builds.")
|
if (WITH_FPIC)
|
||||||
set(CMAKE_CXX_FLAGS_ADDRESSSANITIZER "-g -O1 -fsanitize=address -fno-omit-frame-pointer"
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC")
|
||||||
CACHE STRING "Flags used by the CXX compiler during ADDRESSSANITIZER builds.")
|
endif (WITH_FPIC)
|
||||||
set(CMAKE_SHARED_LINKER_FLAGS_ADDRESSSANITIZER "-fsanitize=address"
|
|
||||||
CACHE STRING "Flags used by the linker during the creation of shared libraries during ADDRESSSANITIZER builds.")
|
|
||||||
set(CMAKE_MODULE_LINKER_FLAGS_ADDRESSSANITIZER "-fsanitize=address"
|
|
||||||
CACHE STRING "Flags used by the linker during the creation of shared libraries during ADDRESSSANITIZER builds.")
|
|
||||||
set(CMAKE_EXEC_LINKER_FLAGS_ADDRESSSANITIZER "-fsanitize=address"
|
|
||||||
CACHE STRING "Flags used by the linker during ADDRESSSANITIZER builds.")
|
|
||||||
|
|
||||||
# Activate with: -DCMAKE_BUILD_TYPE=UndefinedSanitizer
|
check_c_compiler_flag_ssp("-fstack-protector" WITH_STACK_PROTECTOR)
|
||||||
set(CMAKE_C_FLAGS_UNDEFINEDSANITIZER "-g -O1 -fsanitize=undefined -fsanitize=null -fsanitize=alignment -fno-sanitize-recover"
|
if (WITH_STACK_PROTECTOR)
|
||||||
CACHE STRING "Flags used by the C compiler during UNDEFINEDSANITIZER builds.")
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fstack-protector")
|
||||||
set(CMAKE_CXX_FLAGS_UNDEFINEDSANITIZER "-g -O1 -fsanitize=undefined -fsanitize=null -fsanitize=alignment -fno-sanitize-recover"
|
endif (WITH_STACK_PROTECTOR)
|
||||||
CACHE STRING "Flags used by the CXX compiler during UNDEFINEDSANITIZER builds.")
|
|
||||||
set(CMAKE_SHARED_LINKER_FLAGS_UNDEFINEDSANITIZER "-fsanitize=undefined"
|
check_c_compiler_flag("-D_FORTIFY_SOURCE=2" WITH_FORTIFY_SOURCE)
|
||||||
CACHE STRING "Flags used by the linker during the creation of shared libraries during UNDEFINEDSANITIZER builds.")
|
if (WITH_FORTIFY_SOURCE)
|
||||||
set(CMAKE_MODULE_LINKER_FLAGS_UNDEFINEDSANITIZER "-fsanitize=undefined"
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_FORTIFY_SOURCE=2")
|
||||||
CACHE STRING "Flags used by the linker during the creation of shared libraries during UNDEFINEDSANITIZER builds.")
|
endif (WITH_FORTIFY_SOURCE)
|
||||||
set(CMAKE_EXEC_LINKER_FLAGS_UNDEFINEDSANITIZER "-fsanitize=undefined"
|
endif (${CMAKE_C_COMPILER_ID} MATCHES GNU)
|
||||||
CACHE STRING "Flags used by the linker during UNDEFINEDSANITIZER builds.")
|
|
||||||
endif()
|
#
|
||||||
|
# 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)
|
||||||
|
|||||||
@@ -1,4 +1,15 @@
|
|||||||
if (UNIX OR OS2)
|
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)
|
IF (NOT APPLICATION_NAME)
|
||||||
MESSAGE(STATUS "${PROJECT_NAME} is used as APPLICATION_NAME")
|
MESSAGE(STATUS "${PROJECT_NAME} is used as APPLICATION_NAME")
|
||||||
SET(APPLICATION_NAME ${PROJECT_NAME})
|
SET(APPLICATION_NAME ${PROJECT_NAME})
|
||||||
@@ -47,10 +58,6 @@ if (UNIX OR OS2)
|
|||||||
CACHE PATH "The subdirectory to the header prefix (default prefix/include)"
|
CACHE PATH "The subdirectory to the header prefix (default prefix/include)"
|
||||||
)
|
)
|
||||||
|
|
||||||
set(CMAKE_INSTALL_DIR
|
|
||||||
"${LIB_INSTALL_DIR}/cmake"
|
|
||||||
CACHE PATH "The subdirectory to install cmake config files")
|
|
||||||
|
|
||||||
SET(DATA_INSTALL_DIR
|
SET(DATA_INSTALL_DIR
|
||||||
"${DATA_INSTALL_PREFIX}"
|
"${DATA_INSTALL_PREFIX}"
|
||||||
CACHE PATH "The parent directory where applications can install their data (default prefix/share/${APPLICATION_NAME})"
|
CACHE PATH "The parent directory where applications can install their data (default prefix/share/${APPLICATION_NAME})"
|
||||||
@@ -94,16 +101,4 @@ if (UNIX OR OS2)
|
|||||||
"${SHARE_INSTALL_PREFIX}/info"
|
"${SHARE_INSTALL_PREFIX}/info"
|
||||||
CACHE PATH "The ${APPLICATION_NAME} info install dir (default prefix/info)"
|
CACHE PATH "The ${APPLICATION_NAME} info install dir (default prefix/info)"
|
||||||
)
|
)
|
||||||
else()
|
|
||||||
# Same same
|
|
||||||
set(BIN_INSTALL_DIR "bin" CACHE PATH "-")
|
|
||||||
set(SBIN_INSTALL_DIR "sbin" CACHE PATH "-")
|
|
||||||
set(LIB_INSTALL_DIR "lib${LIB_SUFFIX}" CACHE PATH "-")
|
|
||||||
set(INCLUDE_INSTALL_DIR "include" CACHE PATH "-")
|
|
||||||
set(CMAKE_INSTALL_DIR "CMake" CACHE PATH "-")
|
|
||||||
set(PLUGIN_INSTALL_DIR "plugins" CACHE PATH "-")
|
|
||||||
set(HTML_INSTALL_DIR "doc/HTML" CACHE PATH "-")
|
|
||||||
set(ICON_INSTALL_DIR "icons" CACHE PATH "-")
|
|
||||||
set(SOUND_INSTALL_DIR "soudns" CACHE PATH "-")
|
|
||||||
set(LOCALE_INSTALL_DIR "lang" CACHE PATH "-")
|
|
||||||
endif ()
|
endif ()
|
||||||
|
|||||||
@@ -26,7 +26,3 @@ endif (CMAKE_SYSTEM_NAME MATCHES "(Solaris|SunOS)")
|
|||||||
if (CMAKE_SYSTEM_NAME MATCHES "OS2")
|
if (CMAKE_SYSTEM_NAME MATCHES "OS2")
|
||||||
set(OS2 TRUE)
|
set(OS2 TRUE)
|
||||||
endif (CMAKE_SYSTEM_NAME MATCHES "OS2")
|
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,486 +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"
|
|
||||||
)
|
|
||||||
|
|
||||||
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}"
|
|
||||||
)
|
|
||||||
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"
|
|
||||||
)
|
|
||||||
|
|
||||||
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}"
|
|
||||||
)
|
|
||||||
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}"
|
|
||||||
)
|
|
||||||
|
|
||||||
# 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}
|
|
||||||
)
|
|
||||||
|
|
||||||
if (DEFINED _generate_map_file_COPY_TO)
|
|
||||||
# Copy the generated map back to the COPY_TO
|
|
||||||
add_custom_target(${_TARGET_NAME} 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}"
|
|
||||||
)
|
|
||||||
else()
|
|
||||||
add_custom_target(${_TARGET_NAME} 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
|
# Once done this will define
|
||||||
#
|
#
|
||||||
# ARGP_ROOT_DIR - Set this variable to the root installation of ARGP
|
# ARGP_FOUND - system has Argp
|
||||||
|
# ARGP_INCLUDE_DIRS - the Argp include directory
|
||||||
|
# ARGP_LIBRARIES - Link these to use Argp
|
||||||
|
# ARGP_DEFINITIONS - Compiler switches required for using Argp
|
||||||
#
|
#
|
||||||
# Read-Only variables:
|
# Copyright (c) 2010 Andreas Schneider <asn@cynapses.org>
|
||||||
# ARGP_FOUND - system has ARGP
|
|
||||||
# ARGP_INCLUDE_DIR - the ARGP include directory
|
|
||||||
# ARGP_LIBRARIES - Link these to use ARGP
|
|
||||||
# ARGP_DEFINITIONS - Compiler switches required for using ARGP
|
|
||||||
#
|
#
|
||||||
#=============================================================================
|
# Redistribution and use is allowed according to the terms of the New
|
||||||
# Copyright (c) 2011-2016 Andreas Schneider <asn@cryptomilk.org>
|
# BSD license.
|
||||||
#
|
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
|
||||||
# Distributed under the OSI-approved BSD License (the "License");
|
|
||||||
# see accompanying file Copyright.txt for details.
|
|
||||||
#
|
|
||||||
# This software is distributed WITHOUT ANY WARRANTY; without even the
|
|
||||||
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
||||||
# See the License for more information.
|
|
||||||
#=============================================================================
|
|
||||||
#
|
#
|
||||||
|
|
||||||
set(_ARGP_ROOT_HINTS
|
|
||||||
)
|
|
||||||
|
|
||||||
set(_ARGP_ROOT_PATHS
|
if (ARGP_LIBRARIES AND ARGP_INCLUDE_DIRS)
|
||||||
"$ENV{PROGRAMFILES}/argp"
|
# in cache already
|
||||||
)
|
set(ARGP_FOUND TRUE)
|
||||||
|
else (ARGP_LIBRARIES AND ARGP_INCLUDE_DIRS)
|
||||||
|
|
||||||
find_path(ARGP_ROOT_DIR
|
find_path(ARGP_INCLUDE_DIR
|
||||||
NAMES
|
NAMES
|
||||||
include/argp.h
|
argp.h
|
||||||
HINTS
|
|
||||||
${_ARGP_ROOT_HINTS}
|
|
||||||
PATHS
|
PATHS
|
||||||
${_ARGP_ROOT_PATHS}
|
/usr/include
|
||||||
)
|
/usr/local/include
|
||||||
mark_as_advanced(ARGP_ROOT_DIR)
|
/opt/local/include
|
||||||
|
/sw/include
|
||||||
find_path(ARGP_INCLUDE_DIR
|
|
||||||
NAMES
|
|
||||||
argp.h
|
|
||||||
PATHS
|
|
||||||
${ARGP_ROOT_DIR}/include
|
|
||||||
)
|
|
||||||
|
|
||||||
find_library(ARGP_LIBRARY
|
|
||||||
NAMES
|
|
||||||
argp
|
|
||||||
PATHS
|
|
||||||
${ARGP_ROOT_DIR}/lib
|
|
||||||
)
|
|
||||||
|
|
||||||
if (ARGP_LIBRARY)
|
|
||||||
set(ARGP_LIBRARIES
|
|
||||||
${ARGP_LIBRARIES}
|
|
||||||
${ARGP_LIBRARY}
|
|
||||||
)
|
)
|
||||||
endif (ARGP_LIBRARY)
|
|
||||||
|
|
||||||
include(FindPackageHandleStandardArgs)
|
find_library(ARGP_LIBRARY
|
||||||
find_package_handle_standard_args(ARGP DEFAULT_MSG ARGP_LIBRARIES ARGP_INCLUDE_DIR)
|
NAMES
|
||||||
|
argp
|
||||||
|
PATHS
|
||||||
|
/usr/lib
|
||||||
|
/usr/local/lib
|
||||||
|
/opt/local/lib
|
||||||
|
/sw/lib
|
||||||
|
)
|
||||||
|
|
||||||
|
set(ARGP_INCLUDE_DIRS
|
||||||
|
${ARGP_INCLUDE_DIR}
|
||||||
|
)
|
||||||
|
|
||||||
|
if (ARGP_LIBRARY)
|
||||||
|
set(ARGP_LIBRARIES
|
||||||
|
${ARGP_LIBRARIES}
|
||||||
|
${ARGP_LIBRARY}
|
||||||
|
)
|
||||||
|
endif (ARGP_LIBRARY)
|
||||||
|
|
||||||
|
include(FindPackageHandleStandardArgs)
|
||||||
|
find_package_handle_standard_args(Argp DEFAULT_MSG ARGP_LIBRARIES ARGP_INCLUDE_DIRS)
|
||||||
|
|
||||||
|
# show the ARGP_INCLUDE_DIRS and ARGP_LIBRARIES variables only in the advanced view
|
||||||
|
mark_as_advanced(ARGP_INCLUDE_DIRS ARGP_LIBRARIES)
|
||||||
|
|
||||||
|
endif (ARGP_LIBRARIES AND ARGP_INCLUDE_DIRS)
|
||||||
|
|
||||||
# show the ARGP_INCLUDE_DIR and ARGP_LIBRARIES variables only in the advanced view
|
|
||||||
mark_as_advanced(ARGP_INCLUDE_DIR ARGP_LIBRARIES)
|
|
||||||
|
|||||||
@@ -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
|
# 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");
|
# Distributed under the OSI-approved BSD License (the "License");
|
||||||
# see accompanying file Copyright.txt for details.
|
# see accompanying file Copyright.txt for details.
|
||||||
@@ -18,70 +18,53 @@
|
|||||||
#=============================================================================
|
#=============================================================================
|
||||||
#
|
#
|
||||||
|
|
||||||
set(_GCRYPT_ROOT_HINTS
|
if (GCRYPT_LIBRARIES AND GCRYPT_INCLUDE_DIRS)
|
||||||
$ENV{GCRYTPT_ROOT_DIR}
|
# in cache already
|
||||||
${GCRYPT_ROOT_DIR})
|
# set(GCRYPT_FOUND TRUE)
|
||||||
|
else (GCRYPT_LIBRARIES AND GCRYPT_INCLUDE_DIRS)
|
||||||
|
|
||||||
set(_GCRYPT_ROOT_PATHS
|
set(_GCRYPT_ROOT_PATHS
|
||||||
"$ENV{PROGRAMFILES}/libgcrypt")
|
"$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"
|
|
||||||
)
|
)
|
||||||
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
|
find_path(GCRYPT_ROOT_DIR
|
||||||
mark_as_advanced(GCRYPT_INCLUDE_DIR GCRYPT_LIBRARIES)
|
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
|
# - Try to find NSIS
|
||||||
# Once done this will define
|
# 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:
|
# Read-Only variables:
|
||||||
#
|
|
||||||
# NSIS_FOUND - system has NSIS
|
# NSIS_FOUND - system has NSIS
|
||||||
# NSIS_MAKE - NSIS creator executable
|
# 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");
|
# Distributed under the OSI-approved BSD License (the "License");
|
||||||
# see accompanying file Copyright.txt for details.
|
# see accompanying file Copyright.txt for details.
|
||||||
@@ -20,35 +19,21 @@
|
|||||||
#=============================================================================
|
#=============================================================================
|
||||||
#
|
#
|
||||||
|
|
||||||
if (WIN32)
|
set(_NSIS_ROOT_PATHS
|
||||||
set(_x86 "(x86)")
|
C:/NSIS/Bin
|
||||||
|
"$ENV{PROGRAMFILES}/NSIS"
|
||||||
set(_NSIS_ROOT_PATHS
|
)
|
||||||
"$ENV{ProgramFiles}/NSIS"
|
|
||||||
"$ENV{ProgramFiles${_x86}}/NSIS"
|
|
||||||
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\NSIS;Default]")
|
|
||||||
|
|
||||||
find_path(NSIS_ROOT_PATH
|
|
||||||
NAMES
|
|
||||||
Include/Library.nsh
|
|
||||||
PATHS
|
|
||||||
${_NSIS_ROOT_PATHS}
|
|
||||||
)
|
|
||||||
mark_as_advanced(NSIS_ROOT_PATH)
|
|
||||||
endif (WIN32)
|
|
||||||
|
|
||||||
find_program(NSIS_MAKE
|
find_program(NSIS_MAKE
|
||||||
NAMES
|
NAMES
|
||||||
makensis
|
makensis
|
||||||
PATHS
|
PATHS
|
||||||
${NSIS_ROOT_PATH}
|
${NSIS_ROOT_PATH}
|
||||||
|
${NSIS_ROOT_PATH}/Bin
|
||||||
|
${_NSIS_ROOT_PATHS}
|
||||||
)
|
)
|
||||||
|
|
||||||
include(FindPackageHandleStandardArgs)
|
include(FindPackageHandleStandardArgs)
|
||||||
find_package_handle_standard_args(NSIS DEFAULT_MSG NSIS_MAKE)
|
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)
|
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,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
|
# - Check whether the C compiler supports a given flag in the
|
||||||
# context of a stack checking compiler option.
|
# context of a stack checking compiler option.
|
||||||
|
|
||||||
# CHECK_C_COMPILER_FLAG_SSP(FLAG VARIABLE)
|
# CHECK_C_COMPILER_FLAG_SSP(FLAG VARIABLE)
|
||||||
#
|
#
|
||||||
# FLAG - the compiler flag
|
# FLAG - the compiler flag
|
||||||
# VARIABLE - variable to store the result
|
# 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
|
# See help for CheckCSourceCompiles for a listing of variables
|
||||||
# that can modify the build.
|
# that can modify the build.
|
||||||
|
|
||||||
@@ -15,15 +14,13 @@
|
|||||||
# Redistribution and use is allowed according to the terms of the BSD license.
|
# Redistribution and use is allowed according to the terms of the BSD license.
|
||||||
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
|
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
|
||||||
|
|
||||||
# Requires cmake 3.10
|
|
||||||
#include_guard(GLOBAL)
|
|
||||||
include(CheckCSourceCompiles)
|
|
||||||
|
|
||||||
macro(CHECK_C_COMPILER_FLAG_SSP _FLAG _RESULT)
|
INCLUDE(CheckCSourceCompiles)
|
||||||
set(SAFE_CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS}")
|
|
||||||
set(CMAKE_REQUIRED_FLAGS "${_FLAG}")
|
|
||||||
|
|
||||||
check_c_source_compiles("int main(int argc, char **argv) { char buffer[256]; return buffer[argc]=0;}" ${_RESULT})
|
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()
|
|
||||||
154
config.h.cmake
@@ -1,8 +1,8 @@
|
|||||||
/* Name of package */
|
/* Name of package */
|
||||||
#cmakedefine PACKAGE "${PROJECT_NAME}"
|
#cmakedefine PACKAGE "${APPLICATION_NAME}"
|
||||||
|
|
||||||
/* Version number of package */
|
/* Version number of package */
|
||||||
#cmakedefine VERSION "${PROJECT_VERSION}"
|
#cmakedefine VERSION "${APPLICATION_VERSION}"
|
||||||
|
|
||||||
#cmakedefine LOCALEDIR "${LOCALE_INSTALL_DIR}"
|
#cmakedefine LOCALEDIR "${LOCALE_INSTALL_DIR}"
|
||||||
#cmakedefine DATADIR "${DATADIR}"
|
#cmakedefine DATADIR "${DATADIR}"
|
||||||
@@ -17,45 +17,12 @@
|
|||||||
/* Define to 1 if you have the <argp.h> header file. */
|
/* Define to 1 if you have the <argp.h> header file. */
|
||||||
#cmakedefine HAVE_ARGP_H 1
|
#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. */
|
/* Define to 1 if you have the <pty.h> header file. */
|
||||||
#cmakedefine HAVE_PTY_H 1
|
#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. */
|
/* Define to 1 if you have the <termios.h> header file. */
|
||||||
#cmakedefine HAVE_TERMIOS_H 1
|
#cmakedefine HAVE_TERMIOS_H 1
|
||||||
|
|
||||||
/* Define to 1 if you have the <unistd.h> header file. */
|
|
||||||
#cmakedefine HAVE_UNISTD_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <stdint.h> header file. */
|
|
||||||
#cmakedefine HAVE_STDINT_H 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <openssl/aes.h> header file. */
|
/* Define to 1 if you have the <openssl/aes.h> header file. */
|
||||||
#cmakedefine HAVE_OPENSSL_AES_H 1
|
#cmakedefine HAVE_OPENSSL_AES_H 1
|
||||||
|
|
||||||
@@ -68,56 +35,12 @@
|
|||||||
/* Define to 1 if you have the <openssl/des.h> header file. */
|
/* Define to 1 if you have the <openssl/des.h> header file. */
|
||||||
#cmakedefine HAVE_OPENSSL_DES_H 1
|
#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. */
|
/* Define to 1 if you have the <pthread.h> header file. */
|
||||||
#cmakedefine HAVE_PTHREAD_H 1
|
#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
|
|
||||||
|
|
||||||
/*************************** FUNCTIONS ***************************/
|
/*************************** FUNCTIONS ***************************/
|
||||||
|
|
||||||
/* Define to 1 if you have the `EVP_aes128_ctr' function. */
|
|
||||||
#cmakedefine HAVE_OPENSSL_EVP_AES_CTR 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `EVP_aes128_cbc' function. */
|
|
||||||
#cmakedefine HAVE_OPENSSL_EVP_AES_CBC 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `EVP_aes128_gcm' function. */
|
|
||||||
#cmakedefine HAVE_OPENSSL_EVP_AES_GCM 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `CRYPTO_THREADID_set_callback' function. */
|
|
||||||
#cmakedefine HAVE_OPENSSL_CRYPTO_THREADID_SET_CALLBACK 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `CRYPTO_ctr128_encrypt' function. */
|
|
||||||
#cmakedefine HAVE_OPENSSL_CRYPTO_CTR128_ENCRYPT 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `EVP_CIPHER_CTX_new' function. */
|
|
||||||
#cmakedefine HAVE_OPENSSL_EVP_CIPHER_CTX_NEW 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `OPENSSL_ia32cap_loc' function. */
|
|
||||||
#cmakedefine HAVE_OPENSSL_IA32CAP_LOC 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `snprintf' function. */
|
/* Define to 1 if you have the `snprintf' function. */
|
||||||
#cmakedefine HAVE_SNPRINTF 1
|
#cmakedefine HAVE_SNPRINTF 1
|
||||||
|
|
||||||
@@ -136,15 +59,9 @@
|
|||||||
/* Define to 1 if you have the `_vsnprintf_s' function. */
|
/* Define to 1 if you have the `_vsnprintf_s' function. */
|
||||||
#cmakedefine HAVE__VSNPRINTF_S 1
|
#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. */
|
/* Define to 1 if you have the `strncpy' function. */
|
||||||
#cmakedefine HAVE_STRNCPY 1
|
#cmakedefine HAVE_STRNCPY 1
|
||||||
|
|
||||||
/* Define to 1 if you have the `strndup' function. */
|
|
||||||
#cmakedefine HAVE_STRNDUP 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `cfmakeraw' function. */
|
/* Define to 1 if you have the `cfmakeraw' function. */
|
||||||
#cmakedefine HAVE_CFMAKERAW 1
|
#cmakedefine HAVE_CFMAKERAW 1
|
||||||
|
|
||||||
@@ -157,39 +74,15 @@
|
|||||||
/* Define to 1 if you have the `select' function. */
|
/* Define to 1 if you have the `select' function. */
|
||||||
#cmakedefine HAVE_SELECT 1
|
#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. */
|
/* Define to 1 if you have the `clock_gettime' function. */
|
||||||
#cmakedefine HAVE_CLOCK_GETTIME 1
|
#cmakedefine HAVE_CLOCK_GETTIME 1
|
||||||
|
|
||||||
/* Define to 1 if you have the `ntohll' function. */
|
/* Define to 1 if you have the `ntohll' function. */
|
||||||
#cmakedefine HAVE_NTOHLL 1
|
#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 ***************************/
|
/*************************** LIBRARIES ***************************/
|
||||||
|
|
||||||
/* Define to 1 if you have the `crypto' library (-lcrypto). */
|
/* Define to 1 if you have the `crypto' library (-lcrypto). */
|
||||||
@@ -198,61 +91,36 @@
|
|||||||
/* Define to 1 if you have the `gcrypt' library (-lgcrypt). */
|
/* Define to 1 if you have the `gcrypt' library (-lgcrypt). */
|
||||||
#cmakedefine HAVE_LIBGCRYPT 1
|
#cmakedefine HAVE_LIBGCRYPT 1
|
||||||
|
|
||||||
/* Define to 1 if you have the 'mbedTLS' library (-lmbedtls). */
|
/* Define to 1 if you have the `z' library (-lz). */
|
||||||
#cmakedefine HAVE_LIBMBEDCRYPTO 1
|
#cmakedefine HAVE_LIBZ 1
|
||||||
|
|
||||||
/* Define to 1 if you have the `pthread' library (-lpthread). */
|
/* Define to 1 if you have the `pthread' library (-lpthread). */
|
||||||
#cmakedefine HAVE_PTHREAD 1
|
#cmakedefine HAVE_PTHREAD 1
|
||||||
|
|
||||||
/* Define to 1 if you have the `cmocka' library (-lcmocka). */
|
|
||||||
#cmakedefine HAVE_CMOCKA 1
|
|
||||||
|
|
||||||
/**************************** OPTIONS ****************************/
|
/**************************** OPTIONS ****************************/
|
||||||
|
|
||||||
#cmakedefine HAVE_GCC_THREAD_LOCAL_STORAGE 1
|
|
||||||
#cmakedefine HAVE_MSC_THREAD_LOCAL_STORAGE 1
|
|
||||||
|
|
||||||
#cmakedefine HAVE_FALLTHROUGH_ATTRIBUTE 1
|
|
||||||
#cmakedefine HAVE_UNUSED_ATTRIBUTE 1
|
|
||||||
|
|
||||||
#cmakedefine HAVE_CONSTRUCTOR_ATTRIBUTE 1
|
|
||||||
#cmakedefine HAVE_DESTRUCTOR_ATTRIBUTE 1
|
|
||||||
|
|
||||||
#cmakedefine HAVE_GCC_VOLATILE_MEMORY_PROTECTION 1
|
|
||||||
#cmakedefine HAVE_GCC_NARG_MACRO 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 */
|
/* Define to 1 if you want to enable ZLIB */
|
||||||
#cmakedefine WITH_ZLIB 1
|
#cmakedefine WITH_LIBZ 1
|
||||||
|
|
||||||
/* Define to 1 if you want to enable SFTP */
|
/* Define to 1 if you want to enable SFTP */
|
||||||
#cmakedefine WITH_SFTP 1
|
#cmakedefine WITH_SFTP 1
|
||||||
|
|
||||||
|
/* Define to 1 if you want to enable SSH1 */
|
||||||
|
#cmakedefine WITH_SSH1 1
|
||||||
|
|
||||||
/* Define to 1 if you want to enable server support */
|
/* Define to 1 if you want to enable server support */
|
||||||
#cmakedefine WITH_SERVER 1
|
#cmakedefine WITH_SERVER 1
|
||||||
|
|
||||||
/* Define to 1 if you want to enable debug output for crypto functions */
|
/* Define to 1 if you want to enable debug output for crypto functions */
|
||||||
#cmakedefine DEBUG_CRYPTO 1
|
#cmakedefine DEBUG_CRYPTO 1
|
||||||
|
|
||||||
/* Define to 1 if you want to enable debug output for packet functions */
|
|
||||||
#cmakedefine DEBUG_PACKET 1
|
|
||||||
|
|
||||||
/* Define to 1 if you want to enable pcap output support (experimental) */
|
/* Define to 1 if you want to enable pcap output support (experimental) */
|
||||||
#cmakedefine WITH_PCAP 1
|
#cmakedefine WITH_PCAP 1
|
||||||
|
|
||||||
/* Define to 1 if you want to enable calltrace debug output */
|
/* Define to 1 if you want to enable calltrace debug output */
|
||||||
#cmakedefine DEBUG_CALLTRACE 1
|
#cmakedefine DEBUG_CALLTRACE 1
|
||||||
|
|
||||||
/* Define to 1 if you want to enable NaCl support */
|
|
||||||
#cmakedefine WITH_NACL 1
|
|
||||||
|
|
||||||
/*************************** ENDIAN *****************************/
|
/*************************** ENDIAN *****************************/
|
||||||
|
|
||||||
/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
|
/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
|
||||||
|
|||||||
@@ -1,46 +1,5 @@
|
|||||||
#
|
#
|
||||||
# Build the documentation
|
# Build the documentation
|
||||||
#
|
#
|
||||||
if (${CMAKE_VERSION} VERSION_GREATER "3.8.99")
|
include(UseDoxygen OPTIONAL)
|
||||||
|
|
||||||
find_package(Doxygen)
|
|
||||||
|
|
||||||
if (DOXYGEN_FOUND)
|
|
||||||
set(DOXYGEN_PROJECT_NAME ${PROJECT_NAME})
|
|
||||||
set(DOXYGEN_PROJECT_NUMBER ${PROJECT_VERSION})
|
|
||||||
set(DOXYGEN_PROJECT_BRIEF "The SSH library")
|
|
||||||
|
|
||||||
set(DOXYGEN_TAB_SIZE 4)
|
|
||||||
set(DOXYGEN_OPTIMIZE_OUTPUT_FOR_C YES)
|
|
||||||
set(DOXYGEN_MARKDOWN_SUPPORT YES)
|
|
||||||
|
|
||||||
set(DOXYGEN_PREDEFINED DOXYGEN
|
|
||||||
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
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.
|
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
|
libssh is fully compatible with the openssh public and private keys. You
|
||||||
can either use the automatic public key authentication method provided by
|
can either use the automatic public key authentication method provided by
|
||||||
@@ -40,21 +40,22 @@ The function ssh_userauth_autopubkey() does this using the available keys in
|
|||||||
- SSH_AUTH_DENIED: no key matched
|
- SSH_AUTH_DENIED: no key matched
|
||||||
- SSH_AUTH_SUCCESS: you are now authenticated
|
- SSH_AUTH_SUCCESS: you are now authenticated
|
||||||
- SSH_AUTH_PARTIAL: some key matched but you still have to provide an other
|
- 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.
|
SSH agent, if you have one running, or the "none" method otherwise.
|
||||||
|
|
||||||
If you wish to authenticate with public key by your own, follow these steps:
|
If you wish to authenticate with public key by your own, follow these steps:
|
||||||
- Retrieve the public key with ssh_pki_import_pubkey_file().
|
- Retrieve the public key in a ssh_string using publickey_from_file().
|
||||||
- Offer the public key to the SSH server using ssh_userauth_try_publickey().
|
- Offer the public key to the SSH server using ssh_userauth_offer_pubkey().
|
||||||
If the return value is SSH_AUTH_SUCCESS, the SSH server accepts to
|
If the return value is SSH_AUTH_SUCCESS, the SSH server accepts to
|
||||||
authenticate using the public key and you can go to the next step.
|
authenticate using the public key and you can go to the next step.
|
||||||
- Retrieve the private key, using the ssh_pki_import_privkey_file() function.
|
- Retrieve the private key, using the privatekey_from_file() function. If
|
||||||
If a passphrase is needed, either the passphrase specified as argument or
|
a passphrase is needed, either the passphrase specified as argument or
|
||||||
a callback will be used.
|
a callback (see callbacks section) will be used.
|
||||||
- Authenticate using ssh_userauth_publickey() with your private key.
|
- Authenticate using ssh_userauth_pubkey() with your public key string
|
||||||
- Do not forget cleaning up memory using ssh_key_free().
|
and private key.
|
||||||
|
- Do not forget cleaning up memory using string_free() and privatekey_free().
|
||||||
|
|
||||||
Here is a minimalistic example of public key authentication:
|
Here is a minimalistic example of public key authentication:
|
||||||
|
|
||||||
@@ -63,7 +64,7 @@ int authenticate_pubkey(ssh_session session)
|
|||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
rc = ssh_userauth_publickey_auto(session, NULL);
|
rc = ssh_userauth_autopubkey(session, NULL);
|
||||||
|
|
||||||
if (rc == SSH_AUTH_ERROR)
|
if (rc == SSH_AUTH_ERROR)
|
||||||
{
|
{
|
||||||
@@ -76,12 +77,14 @@ int authenticate_pubkey(ssh_session session)
|
|||||||
}
|
}
|
||||||
@endcode
|
@endcode
|
||||||
|
|
||||||
@see ssh_userauth_publickey_auto()
|
@see ssh_userauth_autopubkey
|
||||||
@see ssh_userauth_try_publickey()
|
@see ssh_userauth_offer_pubkey
|
||||||
@see ssh_userauth_publickey()
|
@see ssh_userauth_pubkey
|
||||||
@see ssh_pki_import_pubkey_file()
|
@see publickey_from_file
|
||||||
@see ssh_pki_import_privkey_file()
|
@see publickey_from_privatekey
|
||||||
@see ssh_key_free()
|
@see string_free
|
||||||
|
@see privatekey_from_file
|
||||||
|
@see privatekey_free
|
||||||
|
|
||||||
|
|
||||||
@subsection password Authenticating with a password
|
@subsection password Authenticating with a password
|
||||||
@@ -127,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,
|
server will issue one or more challenges that the user has to answer,
|
||||||
until the server takes an authentication decision.
|
until the server takes an authentication decision.
|
||||||
|
|
||||||
ssh_userauth_kbdint() is the the main keyboard-interactive function.
|
ssh_userauth_kbdint() is the the main keyboard-interactive function.
|
||||||
It will return SSH_AUTH_SUCCESS,SSH_AUTH_DENIED, SSH_AUTH_PARTIAL,
|
It will return SSH_AUTH_SUCCESS,SSH_AUTH_DENIED, SSH_AUTH_PARTIAL,
|
||||||
SSH_AUTH_ERROR, or SSH_AUTH_INFO, depending on the result of the request.
|
SSH_AUTH_ERROR, or SSH_AUTH_INFO, depending on the result of the request.
|
||||||
|
|
||||||
@@ -154,9 +157,9 @@ Here are a few remarks:
|
|||||||
- Even the first call can return SSH_AUTH_DENIED or SSH_AUTH_SUCCESS.
|
- Even the first call can return SSH_AUTH_DENIED or SSH_AUTH_SUCCESS.
|
||||||
- The server can send an empty question set (this is the default behavior
|
- The server can send an empty question set (this is the default behavior
|
||||||
on my system) after you have sent the answers to the first questions.
|
on my system) after you have sent the answers to the first questions.
|
||||||
You must still parse the answer, it might contain some
|
You must still parse the answer, it might contain some
|
||||||
message from the server saying hello or such things. Just call
|
message from the server saying hello or such things. Just call
|
||||||
ssh_userauth_kbdint() until needed.
|
ssh_userauth_kbdint() until needed.
|
||||||
- The meaning of "name", "prompt", "instruction" may be a little
|
- The meaning of "name", "prompt", "instruction" may be a little
|
||||||
confusing. An explanation is given in the RFC section that follows.
|
confusing. An explanation is given in the RFC section that follows.
|
||||||
|
|
||||||
@@ -164,13 +167,13 @@ Here is a little note about how to use the information from
|
|||||||
keyboard-interactive authentication, coming from the RFC itself (rfc4256):
|
keyboard-interactive authentication, coming from the RFC itself (rfc4256):
|
||||||
|
|
||||||
@verbatim
|
@verbatim
|
||||||
|
|
||||||
3.3 User Interface Upon receiving a request message, the client SHOULD
|
3.3 User Interface Upon receiving a request message, the client SHOULD
|
||||||
prompt the user as follows: A command line interface (CLI) 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
|
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
|
each prompt in turn, the client SHOULD display the prompt and read the
|
||||||
user input.
|
user input.
|
||||||
|
|
||||||
A graphical user interface (GUI) client has many choices on how to prompt
|
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
|
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
|
with the application's name) as the title of a dialog window in which
|
||||||
@@ -181,18 +184,18 @@ keyboard-interactive authentication, coming from the RFC itself (rfc4256):
|
|||||||
titles; it SHOULD instead find another way to display this information. If
|
titles; it SHOULD instead find another way to display this information. If
|
||||||
prompts are presented in a dialog window, then the client SHOULD NOT
|
prompts are presented in a dialog window, then the client SHOULD NOT
|
||||||
present each prompt in a separate window.
|
present each prompt in a separate window.
|
||||||
|
|
||||||
All clients MUST properly handle an instruction field with embedded
|
All clients MUST properly handle an instruction field with embedded
|
||||||
newlines. They SHOULD also be able to display at least 30 characters for
|
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
|
the name and prompts. If the server presents names or prompts longer than 30
|
||||||
characters, the client MAY truncate these fields to the length it can
|
characters, the client MAY truncate these fields to the length it can
|
||||||
display. If the client does truncate any fields, there MUST be an obvious
|
display. If the client does truncate any fields, there MUST be an obvious
|
||||||
indication that such truncation has occurred.
|
indication that such truncation has occured.
|
||||||
|
|
||||||
The instruction field SHOULD NOT be truncated. Clients SHOULD use control
|
The instruction field SHOULD NOT be truncated. Clients SHOULD use control
|
||||||
character filtering as discussed in [SSH-ARCH] to avoid attacks by
|
character filtering as discussed in [SSH-ARCH] to avoid attacks by
|
||||||
including terminal control characters in the fields to be displayed.
|
including terminal control characters in the fields to be displayed.
|
||||||
|
|
||||||
For each prompt, the corresponding echo field indicates whether or not
|
For each prompt, the corresponding echo field indicates whether or not
|
||||||
the user input should be echoed as characters are typed. Clients SHOULD
|
the user input should be echoed as characters are typed. Clients SHOULD
|
||||||
correctly echo/mask user input for each prompt independently of other
|
correctly echo/mask user input for each prompt independently of other
|
||||||
@@ -262,10 +265,10 @@ int authenticate_kbdint(ssh_session session)
|
|||||||
@endcode
|
@endcode
|
||||||
|
|
||||||
@see ssh_userauth_kbdint()
|
@see ssh_userauth_kbdint()
|
||||||
@see ssh_userauth_kbdint_getnprompts()
|
@see ssh_userauth_kbdint_getnprompts
|
||||||
@see ssh_userauth_kbdint_getname()
|
@see ssh_userauth_kbdint_getname
|
||||||
@see ssh_userauth_kbdint_getinstruction()
|
@see ssh_userauth_kbdint_getinstruction
|
||||||
@see ssh_userauth_kbdint_getprompt()
|
@see ssh_userauth_kbdint_getprompt
|
||||||
@see ssh_userauth_kbdint_setanswer()
|
@see ssh_userauth_kbdint_setanswer()
|
||||||
|
|
||||||
|
|
||||||
@@ -285,7 +288,7 @@ int authenticate_kbdint(ssh_session session)
|
|||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
rc = ssh_userauth_none(session, NULL);
|
rc = ssh_userauth_none(session, NULL, NULL);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
@endcode
|
@endcode
|
||||||
@@ -304,11 +307,6 @@ int test_several_auth_methods(ssh_session session)
|
|||||||
{
|
{
|
||||||
int method, rc;
|
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);
|
method = ssh_userauth_list(session, NULL);
|
||||||
|
|
||||||
if (method & SSH_AUTH_METHOD_NONE)
|
if (method & SSH_AUTH_METHOD_NONE)
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ If an error has been encountered, it returns a negative value:
|
|||||||
|
|
||||||
@code
|
@code
|
||||||
char buffer[256];
|
char buffer[256];
|
||||||
int nbytes;
|
unsigned int nbytes;
|
||||||
|
|
||||||
nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
|
nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
|
||||||
while (nbytes > 0)
|
while (nbytes > 0)
|
||||||
|
|||||||
@@ -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] http://tools.ietf.org/html/rfc5656
|
|
||||||
[SCHNEIER] https://www.schneier.com/blog/archives/2013/09/the_nsa_is_brea.html#c1675929
|
|
||||||
[DJB] http://cr.yp.to/talks/2013.05.31/slides-dan+tanja-20130531-4x3.pdf
|
|
||||||
[Curve25519] "Curve25519: new Diffie-Hellman speed records."
|
|
||||||
http://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:
|
Port forwarding comes in SSH protocol in two different flavours:
|
||||||
direct or reverse port forwarding. Direct port forwarding is also
|
direct or reverse port forwarding. Direct port forwarding is also
|
||||||
named local port forwarding, and reverse port forwarding is also called
|
named local port forwardind, and reverse port forwarding is also called
|
||||||
remote port forwarding. SSH also allows X11 tunnels.
|
remote port forwarding. SSH also allows X11 tunnels.
|
||||||
|
|
||||||
|
|
||||||
@@ -23,15 +23,15 @@ Mail client application Google Mail
|
|||||||
5555 (arbitrary) |
|
5555 (arbitrary) |
|
||||||
| 143 (IMAP2)
|
| 143 (IMAP2)
|
||||||
V |
|
V |
|
||||||
SSH client =====> SSH server
|
SSH client =====> SSH server
|
||||||
|
|
||||||
Legend:
|
Legend:
|
||||||
--P-->: port connections through port P
|
--P-->: port connexion through port P
|
||||||
=====>: SSH tunnel
|
=====>: SSH tunnel
|
||||||
@endverbatim
|
@endverbatim
|
||||||
A mail client connects to port 5555 of a client. An encrypted tunnel is
|
A mail client connects to port 5555 of a client. An encrypted tunnel is
|
||||||
established to the server. The server connects to port 143 of Google Mail (the
|
established to the server. The server connects to port 143 of Google Mail (the
|
||||||
end point). Now the local mail client can retrieve mail.
|
end point). Now the local mail client can retreive mail.
|
||||||
|
|
||||||
|
|
||||||
@subsection forwarding_reverse Reverse port forwarding
|
@subsection forwarding_reverse Reverse port forwarding
|
||||||
@@ -51,7 +51,7 @@ Example of use of reverse port forwarding:
|
|||||||
SSH client <===== SSH server
|
SSH client <===== SSH server
|
||||||
|
|
||||||
Legend:
|
Legend:
|
||||||
--P-->: port connections through port P
|
--P-->: port connexion through port P
|
||||||
=====>: SSH tunnel
|
=====>: SSH tunnel
|
||||||
@endverbatim
|
@endverbatim
|
||||||
In this example, the SSH client establishes the tunnel,
|
In this example, the SSH client establishes the tunnel,
|
||||||
@@ -85,7 +85,7 @@ this tutorial.
|
|||||||
|
|
||||||
@subsection libssh_direct Doing direct port forwarding with libssh
|
@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;
|
- you need a separate channel for the tunnel as first parameter;
|
||||||
- second and third parameters are the remote endpoint;
|
- second and third parameters are the remote endpoint;
|
||||||
- fourth and fifth parameters are sent to the remote server
|
- fourth and fifth parameters are sent to the remote server
|
||||||
@@ -106,13 +106,11 @@ int direct_forwarding(ssh_session session)
|
|||||||
int nbytes, nwritten;
|
int nbytes, nwritten;
|
||||||
|
|
||||||
forwarding_channel = ssh_channel_new(session);
|
forwarding_channel = ssh_channel_new(session);
|
||||||
if (forwarding_channel == NULL) {
|
if (rc != SSH_OK) return rc;
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = ssh_channel_open_forward(forwarding_channel,
|
rc = channel_open_forward(forwarding_channel,
|
||||||
"www.google.com", 80,
|
"www.google.com", 80,
|
||||||
"localhost", 5555);
|
"localhost", 5555);
|
||||||
if (rc != SSH_OK)
|
if (rc != SSH_OK)
|
||||||
{
|
{
|
||||||
ssh_channel_free(forwarding_channel);
|
ssh_channel_free(forwarding_channel);
|
||||||
@@ -120,9 +118,7 @@ int direct_forwarding(ssh_session session)
|
|||||||
}
|
}
|
||||||
|
|
||||||
nbytes = strlen(http_get);
|
nbytes = strlen(http_get);
|
||||||
nwritten = ssh_channel_write(forwarding_channel,
|
nwritten = channel_write(forwarding_channel, http_get, nbytes);
|
||||||
http_get,
|
|
||||||
nbytes);
|
|
||||||
if (nbytes != nwritten)
|
if (nbytes != nwritten)
|
||||||
{
|
{
|
||||||
ssh_channel_free(forwarding_channel);
|
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
|
@subsection libssh_reverse Doing reverse port forwarding with libssh
|
||||||
|
|
||||||
To do reverse port forwarding, call ssh_channel_listen_forward(),
|
To do reverse port forwarding, call ssh_channel_forward_listen(),
|
||||||
then ssh_channel_accept_forward().
|
then ssh_channel_forward_accept().
|
||||||
|
|
||||||
When you call ssh_channel_listen_forward(), you can let the remote server
|
When you call ssh_channel_forward_listen(), you can let the remote server
|
||||||
chose the non-privileged port it should listen to. Otherwise, you can chose
|
chose the non-priviledged port it should listen to. Otherwise, you can chose
|
||||||
your own privileged or non-privileged port. Beware that you should have
|
your own priviledged or non-priviledged port. Beware that you should have
|
||||||
administrative privileges on the remote server to open a privileged port
|
administrative priviledges on the remote server to open a priviledged port
|
||||||
(port number < 1024).
|
(port number < 1024).
|
||||||
|
|
||||||
Below is an example of a very rough web server waiting for connections on port
|
Below is an example of a very rough web server waiting for connections on port
|
||||||
@@ -164,7 +160,6 @@ int web_server(ssh_session session)
|
|||||||
ssh_channel channel;
|
ssh_channel channel;
|
||||||
char buffer[256];
|
char buffer[256];
|
||||||
int nbytes, nwritten;
|
int nbytes, nwritten;
|
||||||
int port = 0;
|
|
||||||
char *helloworld = ""
|
char *helloworld = ""
|
||||||
"HTTP/1.1 200 OK\n"
|
"HTTP/1.1 200 OK\n"
|
||||||
"Content-Type: text/html\n"
|
"Content-Type: text/html\n"
|
||||||
@@ -179,19 +174,17 @@ int web_server(ssh_session session)
|
|||||||
" </body>\n"
|
" </body>\n"
|
||||||
"</html>\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)
|
if (rc != SSH_OK)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Error opening remote port: %s\n",
|
fprintf(stderr, "Error opening remote port: %s\n", ssh_get_error(session));
|
||||||
ssh_get_error(session));
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
channel = ssh_channel_accept_forward(session, 60000, &port);
|
channel = ssh_channel_forward_accept(session, 60000);
|
||||||
if (channel == NULL)
|
if (channel == NULL)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Error waiting for incoming connection: %s\n",
|
fprintf(stderr, "Error waiting for incoming connection: %s\n", ssh_get_error(session));
|
||||||
ssh_get_error(session));
|
|
||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -200,8 +193,7 @@ int web_server(ssh_session session)
|
|||||||
nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
|
nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
|
||||||
if (nbytes < 0)
|
if (nbytes < 0)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Error reading incoming data: %s\n",
|
fprintf(stderr, "Error reading incoming data: %s\n", ssh_get_error(session));
|
||||||
ssh_get_error(session));
|
|
||||||
ssh_channel_send_eof(channel);
|
ssh_channel_send_eof(channel);
|
||||||
ssh_channel_free(channel);
|
ssh_channel_free(channel);
|
||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
@@ -212,8 +204,7 @@ int web_server(ssh_session session)
|
|||||||
nwritten = ssh_channel_write(channel, helloworld, nbytes);
|
nwritten = ssh_channel_write(channel, helloworld, nbytes);
|
||||||
if (nwritten != nbytes)
|
if (nwritten != nbytes)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Error sending answer: %s\n",
|
fprintf(stderr, "Error sending answer: %s\n", ssh_get_error(session));
|
||||||
ssh_get_error(session));
|
|
||||||
ssh_channel_send_eof(channel);
|
ssh_channel_send_eof(channel);
|
||||||
ssh_channel_free(channel);
|
ssh_channel_free(channel);
|
||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
|
|||||||
@@ -31,20 +31,20 @@ A SSH session goes through the following steps:
|
|||||||
- Invoke your own subsystem. This is outside the scope of this document,
|
- Invoke your own subsystem. This is outside the scope of this document,
|
||||||
but can be done.
|
but can be done.
|
||||||
|
|
||||||
- When everything is finished, just close the channels, and then the connection.
|
- When everything is finished, just close the channels, and then the connection.
|
||||||
|
|
||||||
The sftp and scp subsystems use channels, but libssh hides them to
|
The sftp and scp subsystems use channels, but libssh hides them to
|
||||||
the programmer. If you want to use those subsystems, instead of a channel,
|
the programmer. If you want to use those subsystems, instead of a channel,
|
||||||
you'll usually open a "sftp session" or a "scp session".
|
you'll usually open a "sftp session" or a "scp session".
|
||||||
|
|
||||||
|
|
||||||
@subsection setup Creating the session and setting options
|
@subsection setup Creating the session and setting options
|
||||||
|
|
||||||
The most important object in a SSH connection is the SSH session. In order
|
The most important object in a SSH connection is the SSH session. In order
|
||||||
to allocate a new SSH session, you use ssh_new(). Don't forget to
|
to allocate a new SSH session, you use ssh_new(). Don't forget to
|
||||||
always verify that the allocation succeeded.
|
always verify that the allocation successed.
|
||||||
@code
|
@code
|
||||||
#include <libssh/libssh.h>
|
#include <libssh/libssh.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
@@ -69,12 +69,12 @@ The ssh_options_set() function sets the options of the session. The most importa
|
|||||||
|
|
||||||
The complete list of options can be found in the documentation of ssh_options_set().
|
The complete list of options can be found in the documentation of ssh_options_set().
|
||||||
The only mandatory option is SSH_OPTIONS_HOST. If you don't use SSH_OPTIONS_USER,
|
The only mandatory option is SSH_OPTIONS_HOST. If you don't use SSH_OPTIONS_USER,
|
||||||
the local username of your account will be used.
|
the local username of your account will be used.
|
||||||
|
|
||||||
Here is a small example of how to use it:
|
Here is a small example of how to use it:
|
||||||
|
|
||||||
@code
|
@code
|
||||||
#include <libssh/libssh.h>
|
#include <libssh/libssh.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
@@ -122,7 +122,7 @@ Here's an example:
|
|||||||
@code
|
@code
|
||||||
#include <libssh/libssh.h>
|
#include <libssh/libssh.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
@@ -158,7 +158,7 @@ you just connected to is known and safe to use (remember, SSH is about security
|
|||||||
authentication).
|
authentication).
|
||||||
|
|
||||||
There are two ways of doing this:
|
There are two ways of doing this:
|
||||||
- The first way (recommended) is to use the ssh_session_is_known_server()
|
- The first way (recommended) is to use the ssh_is_server_known()
|
||||||
function. This function will look into the known host file
|
function. This function will look into the known host file
|
||||||
(~/.ssh/known_hosts on UNIX), look for the server hostname's pattern,
|
(~/.ssh/known_hosts on UNIX), look for the server hostname's pattern,
|
||||||
and determine whether this host is present or not in the list.
|
and determine whether this host is present or not in the list.
|
||||||
@@ -185,89 +185,74 @@ examples/ directory:
|
|||||||
|
|
||||||
int verify_knownhost(ssh_session session)
|
int verify_knownhost(ssh_session session)
|
||||||
{
|
{
|
||||||
enum ssh_known_hosts_e state;
|
int state, hlen;
|
||||||
unsigned char *hash = NULL;
|
unsigned char *hash = NULL;
|
||||||
ssh_key srv_pubkey = NULL;
|
char *hexa;
|
||||||
size_t hlen;
|
char buf[10];
|
||||||
char buf[10];
|
|
||||||
char *hexa;
|
|
||||||
char *p;
|
|
||||||
int cmp;
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
rc = ssh_get_server_publickey(session, &srv_pubkey);
|
state = ssh_is_server_known(session);
|
||||||
if (rc < 0) {
|
|
||||||
|
hlen = ssh_get_pubkey_hash(session, &hash);
|
||||||
|
if (hlen < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
switch (state)
|
||||||
|
{
|
||||||
|
case SSH_SERVER_KNOWN_OK:
|
||||||
|
break; /* ok */
|
||||||
|
|
||||||
|
case SSH_SERVER_KNOWN_CHANGED:
|
||||||
|
fprintf(stderr, "Host key for server changed: it is now:\n");
|
||||||
|
ssh_print_hexa("Public key hash", hash, hlen);
|
||||||
|
fprintf(stderr, "For security reasons, connection will be stopped\n");
|
||||||
|
free(hash);
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
case SSH_SERVER_FOUND_OTHER:
|
||||||
|
fprintf(stderr, "The host key for this server was not found but an other"
|
||||||
|
"type of key exists.\n");
|
||||||
|
fprintf(stderr, "An attacker might change the default server key to"
|
||||||
|
"confuse your client into thinking the key does not exist\n");
|
||||||
|
free(hash);
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
case SSH_SERVER_FILE_NOT_FOUND:
|
||||||
|
fprintf(stderr, "Could not find known host file.\n");
|
||||||
|
fprintf(stderr, "If you accept the host key here, the file will be"
|
||||||
|
"automatically created.\n");
|
||||||
|
/* fallback to SSH_SERVER_NOT_KNOWN behavior */
|
||||||
|
|
||||||
|
case SSH_SERVER_NOT_KNOWN:
|
||||||
|
hexa = ssh_get_hexa(hash, hlen);
|
||||||
|
fprintf(stderr,"The server is unknown. Do you trust the host key?\n");
|
||||||
|
fprintf(stderr, "Public key hash: %s\n", hexa);
|
||||||
|
free(hexa);
|
||||||
|
if (fgets(buf, sizeof(buf), stdin) == NULL)
|
||||||
|
{
|
||||||
|
free(hash);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
if (strncasecmp(buf, "yes", 3) != 0)
|
||||||
rc = ssh_get_publickey_hash(srv_pubkey,
|
{
|
||||||
SSH_PUBLICKEY_HASH_SHA1,
|
free(hash);
|
||||||
&hash,
|
|
||||||
&hlen);
|
|
||||||
ssh_key_free(srv_pubkey);
|
|
||||||
if (rc < 0) {
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
if (ssh_write_knownhost(session) < 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Error %s\n", strerror(errno));
|
||||||
|
free(hash);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
state = ssh_session_is_known_server(session);
|
case SSH_SERVER_ERROR:
|
||||||
switch (state) {
|
fprintf(stderr, "Error %s", ssh_get_error(session));
|
||||||
case SSH_KNOWN_HOSTS_OK:
|
free(hash);
|
||||||
/* OK */
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
free(hash);
|
||||||
case SSH_KNOWN_HOSTS_CHANGED:
|
return 0;
|
||||||
fprintf(stderr, "Host key for server changed: it is now:\n");
|
|
||||||
ssh_print_hexa("Public key hash", hash, hlen);
|
|
||||||
fprintf(stderr, "For security reasons, connection will be stopped\n");
|
|
||||||
ssh_clean_pubkey_hash(&hash);
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
case SSH_KNOWN_HOSTS_OTHER:
|
|
||||||
fprintf(stderr, "The host key for this server was not found but an other"
|
|
||||||
"type of key exists.\n");
|
|
||||||
fprintf(stderr, "An attacker might change the default server key to"
|
|
||||||
"confuse your client into thinking the key does not exist\n");
|
|
||||||
ssh_clean_pubkey_hash(&hash);
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
case SSH_KNOWN_HOSTS_NOT_FOUND:
|
|
||||||
fprintf(stderr, "Could not find known host file.\n");
|
|
||||||
fprintf(stderr, "If you accept the host key here, the file will be"
|
|
||||||
"automatically created.\n");
|
|
||||||
|
|
||||||
/* FALL THROUGH to SSH_SERVER_NOT_KNOWN behavior */
|
|
||||||
|
|
||||||
case SSH_KNOWN_HOSTS_UNKNOWN:
|
|
||||||
hexa = ssh_get_hexa(hash, hlen);
|
|
||||||
fprintf(stderr,"The server is unknown. Do you trust the host key?\n");
|
|
||||||
fprintf(stderr, "Public key hash: %s\n", hexa);
|
|
||||||
ssh_string_free_char(hexa);
|
|
||||||
ssh_clean_pubkey_hash(&hash);
|
|
||||||
p = fgets(buf, sizeof(buf), stdin);
|
|
||||||
if (p == NULL) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
cmp = strncasecmp(buf, "yes", 3);
|
|
||||||
if (cmp != 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = ssh_session_update_known_hosts(session);
|
|
||||||
if (rc < 0) {
|
|
||||||
fprintf(stderr, "Error %s\n", strerror(errno));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
case SSH_KNOWN_HOSTS_ERROR:
|
|
||||||
fprintf(stderr, "Error %s", ssh_get_error(session));
|
|
||||||
ssh_clean_pubkey_hash(&hash);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
ssh_clean_pubkey_hash(&hash);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
@endcode
|
@endcode
|
||||||
|
|
||||||
@@ -275,19 +260,18 @@ int verify_knownhost(ssh_session session)
|
|||||||
@see ssh_disconnect
|
@see ssh_disconnect
|
||||||
@see ssh_get_error
|
@see ssh_get_error
|
||||||
@see ssh_get_error_code
|
@see ssh_get_error_code
|
||||||
@see ssh_get_server_publickey
|
@see ssh_get_pubkey_hash
|
||||||
@see ssh_get_publickey_hash
|
@see ssh_is_server_known
|
||||||
@see ssh_session_is_known_server
|
@see ssh_write_knownhost
|
||||||
@see ssh_session_update_known_hosts
|
|
||||||
|
|
||||||
|
|
||||||
@subsection auth Authenticating the user
|
@subsection auth Authenticating the user
|
||||||
|
|
||||||
The authentication process is the way a service provider can identify a
|
The authentication process is the way a service provider can identify a
|
||||||
user and verify his/her identity. The authorization process is about enabling
|
user and verify his/her identity. The authorization process is about enabling
|
||||||
the authenticated user the access to resources. In SSH, the two concepts
|
the authenticated user the access to ressources. In SSH, the two concepts
|
||||||
are linked. After authentication, the server can grant the user access to
|
are linked. After authentication, the server can grant the user access to
|
||||||
several resources such as port forwarding, shell, sftp subsystem, and so on.
|
several ressources such as port forwarding, shell, sftp subsystem, and so on.
|
||||||
|
|
||||||
libssh supports several methods of authentication:
|
libssh supports several methods of authentication:
|
||||||
- "none" method. This method allows to get the available authentications
|
- "none" method. This method allows to get the available authentications
|
||||||
@@ -313,7 +297,7 @@ The example below shows an authentication with password:
|
|||||||
@code
|
@code
|
||||||
#include <libssh/libssh.h>
|
#include <libssh/libssh.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
@@ -338,7 +322,7 @@ int main()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Verify the server's identity
|
// Verify the server's identity
|
||||||
// For the source code of verify_knownhost(), check previous example
|
// For the source code of verify_knowhost(), check previous example
|
||||||
if (verify_knownhost(my_ssh_session) < 0)
|
if (verify_knownhost(my_ssh_session) < 0)
|
||||||
{
|
{
|
||||||
ssh_disconnect(my_ssh_session);
|
ssh_disconnect(my_ssh_session);
|
||||||
@@ -383,7 +367,7 @@ int show_remote_processes(ssh_session session)
|
|||||||
ssh_channel channel;
|
ssh_channel channel;
|
||||||
int rc;
|
int rc;
|
||||||
char buffer[256];
|
char buffer[256];
|
||||||
int nbytes;
|
unsigned int nbytes;
|
||||||
|
|
||||||
channel = ssh_channel_new(session);
|
channel = ssh_channel_new(session);
|
||||||
if (channel == NULL)
|
if (channel == NULL)
|
||||||
@@ -407,7 +391,7 @@ int show_remote_processes(ssh_session session)
|
|||||||
nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
|
nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
|
||||||
while (nbytes > 0)
|
while (nbytes > 0)
|
||||||
{
|
{
|
||||||
if (write(1, buffer, nbytes) != (unsigned int) nbytes)
|
if (write(1, buffer, nbytes) != nbytes)
|
||||||
{
|
{
|
||||||
ssh_channel_close(channel);
|
ssh_channel_close(channel);
|
||||||
ssh_channel_free(channel);
|
ssh_channel_free(channel);
|
||||||
@@ -415,7 +399,7 @@ int show_remote_processes(ssh_session session)
|
|||||||
}
|
}
|
||||||
nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
|
nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nbytes < 0)
|
if (nbytes < 0)
|
||||||
{
|
{
|
||||||
ssh_channel_close(channel);
|
ssh_channel_close(channel);
|
||||||
@@ -456,13 +440,14 @@ might be recoverable. SSH_FATAL means the connection has an important
|
|||||||
problem and isn't probably recoverable.
|
problem and isn't probably recoverable.
|
||||||
|
|
||||||
Most of time, the error returned are SSH_FATAL, but some functions
|
Most of time, the error returned are SSH_FATAL, but some functions
|
||||||
(generally the ssh_request_xxx ones) may fail because of server denying request.
|
(generaly the ssh_request_xxx ones) may fail because of server denying request.
|
||||||
In these cases, SSH_REQUEST_DENIED is returned.
|
In these cases, SSH_REQUEST_DENIED is returned.
|
||||||
|
|
||||||
For thread safety, errors are bound to ssh_session objects.
|
ssh_get_error() and ssh_get_error_code() take a ssh_session as a parameter.
|
||||||
As long as your ssh_session object is not NULL, you can retrieve the last error
|
That's for thread safety, error messages that can be attached to a session
|
||||||
message and error code from the ssh_session using ssh_get_error() and
|
aren't static anymore. Any error that happens during ssh_options_xxx()
|
||||||
ssh_get_error_code() respectively.
|
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.
|
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
|
libssh is a Free Software / Open Source project. The libssh library
|
||||||
is distributed under LGPL license. The libssh project has nothing to do with
|
is distributed under LGPL license. The libssh project has nothing to do with
|
||||||
"libssh2", which is a completely different and independent project.
|
"libssh2", which is a completly different and independant project.
|
||||||
|
|
||||||
libssh can run on top of either libgcrypt or libcrypto,
|
libssh can run on top of either libgcrypt (http://directory.fsf.org/project/libgcrypt/)
|
||||||
two general-purpose cryptographic libraries.
|
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.
|
This tutorial concentrates for its main part on the "client" side of libssh.
|
||||||
To learn how to accept incoming SSH connections (how to write a SSH server),
|
To learn how to accept incoming SSH connexions (how to write a SSH server),
|
||||||
you'll have to jump to the end of this document.
|
you'll have to jump to the end of this document.
|
||||||
|
|
||||||
This tutorial describes libssh version 0.5.0. This version is a little different
|
This tutorial describes libssh version 0.5.0. This version is a little different
|
||||||
|
|||||||
@@ -17,14 +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
|
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.
|
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
|
On Windows you need to define LIBSSH_STATIC in the compiler command
|
||||||
LIBSSH_STATIC as a define in the compiler command line or define it before you
|
line. This is required cause the dynamic library needs to specify the
|
||||||
include libssh.h. This is required cause the dynamic library needs to specify
|
dllimport attribute.
|
||||||
the dllimport attribute.
|
|
||||||
|
|
||||||
@code
|
|
||||||
#define LIBSSH_STATIC 1
|
|
||||||
#include <libssh/libssh.h>
|
|
||||||
@endcode
|
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -19,29 +19,24 @@ the interesting functions as you go.
|
|||||||
|
|
||||||
The libssh library provides:
|
The libssh library provides:
|
||||||
|
|
||||||
- <strong>Key Exchange Methods</strong>: <i>curve25519-sha256, curve25519-sha256@libssh.org, ecdh-sha2-nistp256, ecdh-sha2-nistp384, ecdh-sha2-nistp521</i>, diffie-hellman-group1-sha1, diffie-hellman-group14-sha1
|
- Full C library functions for manipulating a client-side SSH connection
|
||||||
- <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
|
- SSH2 and SSH1 protocol compliant
|
||||||
- <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, none
|
- Fully configurable sessions
|
||||||
- <strong>Compression Schemes</strong>: zlib, <i>zlib@openssh.com</i>, none
|
- Server support
|
||||||
- <strong>MAC hashes</strong>: hmac-sha1, hmac-sha2-256, hmac-sha2-384, hmac-sha2-512, hmac-md5, none
|
- SSH agent authentication support
|
||||||
- <strong>Authentication</strong>: none, password, public-key, keyboard-interactive, <i>gssapi-with-mic</i>
|
- Support for AES-128, AES-192, AES-256, Blowfish, 3DES in CBC mode, and AES in CTR mode
|
||||||
- <strong>Channels</strong>: shell, exec (incl. SCP wrapper), direct-tcpip, subsystem, <i>auth-agent-req@openssh.com</i>
|
- Supports OpenSSL and GCrypt
|
||||||
- <strong>Global Requests</strong>: tcpip-forward, forwarded-tcpip
|
- Use multiple SSH connections in a same process, at same time
|
||||||
- <strong>Channel Requests</strong>: x11, pty, <i>exit-status, signal, exit-signal, keepalive@openssh.com, auth-agent-req@openssh.com</i>
|
- Use multiple channels in the same connection
|
||||||
- <strong>Subsystems</strong>: sftp(version 3), <i>OpenSSH Extensions</i>
|
- Thread safety when using different sessions at same time
|
||||||
- <strong>SFTP</strong>: <i>statvfs@openssh.com, fstatvfs@openssh.com</i>
|
- POSIX-like SFTP (Secure File Transfer) implementation with openssh extension support
|
||||||
- <strong>Thread-safe</strong>: Just don't share sessions
|
- SCP implementation
|
||||||
- <strong>Non-blocking</strong>: it can be used both blocking and non-blocking
|
- Large file system support (files bigger than 4GB)
|
||||||
- <strong>Your sockets</strong>: the app hands over the socket, or uses libssh sockets
|
- RSA and DSS server public key supported
|
||||||
- <b>OpenSSL</b> or <b>gcrypt</b>: builds with either
|
- Compression support (with zlib)
|
||||||
|
- Public key (RSA and DSS), password and keyboard-interactive authentication
|
||||||
@section main-additional-features Additional Features
|
- 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
|
||||||
- Client <b>and</b> server support
|
|
||||||
- SSHv2 and SSHv1 protocol support
|
|
||||||
- Supports <a href="http://test.libssh.org/" target="_blank">Linux, UNIX, BSD, Solaris, OS/2 and Windows</a>
|
|
||||||
- Automated test cases with nightly <a href="http://test.libssh.org/" target="_blank">tests</a>
|
|
||||||
- Event model based on poll(2), or a poll(2)-emulation.
|
|
||||||
|
|
||||||
@section main-copyright Copyright Policy
|
@section main-copyright Copyright Policy
|
||||||
|
|
||||||
@@ -184,8 +179,6 @@ It was later modified and expanded by the following RFCs.
|
|||||||
Authentication and Key Exchange for the Secure Shell (SSH) Protocol
|
Authentication and Key Exchange for the Secure Shell (SSH) Protocol
|
||||||
- <a href="http://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
|
The Secure Shell (SSH) Public Key File Format
|
||||||
- <a href="http://tools.ietf.org/html/rfc5647" target="_blank">RFC 5647</a>,
|
|
||||||
AES Galois Counter Mode for the Secure Shell Transport Layer Protocol
|
|
||||||
- <a href="http://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
|
Elliptic Curve Algorithm Integration in the Secure Shell Transport Layer
|
||||||
|
|
||||||
@@ -205,12 +198,6 @@ do the same in libssh.
|
|||||||
|
|
||||||
@subsection main-rfc-extensions Secure Shell Extensions
|
@subsection main-rfc-extensions Secure Shell Extensions
|
||||||
|
|
||||||
The libssh project has an extension to support Curve25519 which is also supported by
|
|
||||||
the OpenSSH project.
|
|
||||||
|
|
||||||
- <a href="http://git.libssh.org/projects/libssh.git/tree/doc/curve25519-sha256@libssh.org.txt" target="_blank">curve25519-sha256@libssh.org</a>,
|
|
||||||
Curve25519-SHA256 for ECDH KEX
|
|
||||||
|
|
||||||
The OpenSSH project has defined some extensions to the protocol. We support some of
|
The OpenSSH project has defined some extensions to the protocol. We support some of
|
||||||
them like the statvfs calls in SFTP or the ssh-agent.
|
them like the statvfs calls in SFTP or the ssh-agent.
|
||||||
|
|
||||||
@@ -218,7 +205,5 @@ them like the statvfs calls in SFTP or the ssh-agent.
|
|||||||
OpenSSH's deviations and extensions</a>
|
OpenSSH's deviations and extensions</a>
|
||||||
- <a href="http://api.libssh.org/rfc/PROTOCOL.agent" target="_blank">
|
- <a href="http://api.libssh.org/rfc/PROTOCOL.agent" target="_blank">
|
||||||
OpenSSH's ssh-agent</a>
|
OpenSSH's ssh-agent</a>
|
||||||
- <a href="http://api.libssh.org/rfc/PROTOCOL.certkeys" target="_blank">
|
|
||||||
OpenSSH's pubkey certificate authentication</a>
|
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|||||||
37
doc/scp.dox
@@ -2,7 +2,7 @@
|
|||||||
@page libssh_tutor_scp Chapter 6: The SCP subsystem
|
@page libssh_tutor_scp Chapter 6: The SCP subsystem
|
||||||
@section scp_subsystem The SCP subsystem
|
@section scp_subsystem The SCP subsystem
|
||||||
|
|
||||||
The SCP subsystem has far less functionality than the SFTP subsystem.
|
The SCP subsystem has far less functionnality than the SFTP subsystem.
|
||||||
However, if you only need to copy files from and to the remote system,
|
However, if you only need to copy files from and to the remote system,
|
||||||
it does its job.
|
it does its job.
|
||||||
|
|
||||||
@@ -39,16 +39,14 @@ int scp_write(ssh_session session)
|
|||||||
(session, SSH_SCP_WRITE | SSH_SCP_RECURSIVE, ".");
|
(session, SSH_SCP_WRITE | SSH_SCP_RECURSIVE, ".");
|
||||||
if (scp == NULL)
|
if (scp == NULL)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Error allocating scp session: %s\n",
|
fprintf(stderr, "Error allocating scp session: %s\n", ssh_get_error(session));
|
||||||
ssh_get_error(session));
|
|
||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = ssh_scp_init(scp);
|
rc = ssh_scp_init(scp);
|
||||||
if (rc != SSH_OK)
|
if (rc != SSH_OK)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Error initializing scp session: %s\n",
|
fprintf(stderr, "Error initializing scp session: %s\n", ssh_get_error(session));
|
||||||
ssh_get_error(session));
|
|
||||||
ssh_scp_free(scp);
|
ssh_scp_free(scp);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
@@ -73,16 +71,14 @@ int scp_read(ssh_session session)
|
|||||||
(session, SSH_SCP_READ, "helloworld/helloworld.txt");
|
(session, SSH_SCP_READ, "helloworld/helloworld.txt");
|
||||||
if (scp == NULL)
|
if (scp == NULL)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Error allocating scp session: %s\n",
|
fprintf(stderr, "Error allocating scp session: %s\n", ssh_get_error(session));
|
||||||
ssh_get_error(session));
|
|
||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = ssh_scp_init(scp);
|
rc = ssh_scp_init(scp);
|
||||||
if (rc != SSH_OK)
|
if (rc != SSH_OK)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Error initializing scp session: %s\n",
|
fprintf(stderr, "Error initializing scp session: %s\n", ssh_get_error(session));
|
||||||
ssh_get_error(session));
|
|
||||||
ssh_scp_free(scp);
|
ssh_scp_free(scp);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
@@ -123,8 +119,7 @@ int scp_helloworld(ssh_session session, ssh_scp scp)
|
|||||||
rc = ssh_scp_push_directory(scp, "helloworld", S_IRWXU);
|
rc = ssh_scp_push_directory(scp, "helloworld", S_IRWXU);
|
||||||
if (rc != SSH_OK)
|
if (rc != SSH_OK)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Can't create remote directory: %s\n",
|
fprintf(stderr, "Can't create remote directory: %s\n", ssh_get_error(session));
|
||||||
ssh_get_error(session));
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -132,16 +127,14 @@ int scp_helloworld(ssh_session session, ssh_scp scp)
|
|||||||
(scp, "helloworld.txt", length, S_IRUSR | S_IWUSR);
|
(scp, "helloworld.txt", length, S_IRUSR | S_IWUSR);
|
||||||
if (rc != SSH_OK)
|
if (rc != SSH_OK)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Can't open remote file: %s\n",
|
fprintf(stderr, "Can't open remote file: %s\n", ssh_get_error(session));
|
||||||
ssh_get_error(session));
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = ssh_scp_write(scp, helloworld, length);
|
rc = ssh_scp_write(scp, helloworld, length);
|
||||||
if (rc != SSH_OK)
|
if (rc != SSH_OK)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Can't write to remote file: %s\n",
|
fprintf(stderr, "Can't write to remote file: %s\n", ssh_get_error(session));
|
||||||
ssh_get_error(session));
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -158,7 +151,7 @@ Let's say you want to copy the following tree of files to the remote site:
|
|||||||
+-- file1
|
+-- file1
|
||||||
+-- B --+
|
+-- B --+
|
||||||
| +-- file2
|
| +-- file2
|
||||||
-- A --+
|
-- A --+
|
||||||
| +-- file3
|
| +-- file3
|
||||||
+-- C --+
|
+-- C --+
|
||||||
+-- file4
|
+-- file4
|
||||||
@@ -202,16 +195,14 @@ int scp_receive(ssh_session session, ssh_scp scp)
|
|||||||
rc = ssh_scp_pull_request(scp);
|
rc = ssh_scp_pull_request(scp);
|
||||||
if (rc != SSH_SCP_REQUEST_NEWFILE)
|
if (rc != SSH_SCP_REQUEST_NEWFILE)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Error receiving information about file: %s\n",
|
fprintf(stderr, "Error receiving information about file: %s\n", ssh_get_error(session));
|
||||||
ssh_get_error(session));
|
|
||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
size = ssh_scp_request_get_size(scp);
|
size = ssh_scp_request_get_size(scp);
|
||||||
filename = strdup(ssh_scp_request_get_filename(scp));
|
filename = strdup(ssh_scp_request_get_filename(scp));
|
||||||
mode = ssh_scp_request_get_permissions(scp);
|
mode = ssh_scp_request_get_permissions(scp);
|
||||||
printf("Receiving file %s, size %d, permissions 0%o\n",
|
printf("Receiving file %s, size %d, permisssions 0%o\n", filename, size, mode);
|
||||||
filename, size, mode);
|
|
||||||
free(filename);
|
free(filename);
|
||||||
|
|
||||||
buffer = malloc(size);
|
buffer = malloc(size);
|
||||||
@@ -225,8 +216,7 @@ int scp_receive(ssh_session session, ssh_scp scp)
|
|||||||
rc = ssh_scp_read(scp, buffer, size);
|
rc = ssh_scp_read(scp, buffer, size);
|
||||||
if (rc == SSH_ERROR)
|
if (rc == SSH_ERROR)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Error receiving file data: %s\n",
|
fprintf(stderr, "Error receiving file data: %s\n", ssh_get_error(session));
|
||||||
ssh_get_error(session));
|
|
||||||
free(buffer);
|
free(buffer);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
@@ -238,8 +228,7 @@ int scp_receive(ssh_session session, ssh_scp scp)
|
|||||||
rc = ssh_scp_pull_request(scp);
|
rc = ssh_scp_pull_request(scp);
|
||||||
if (rc != SSH_SCP_REQUEST_EOF)
|
if (rc != SSH_SCP_REQUEST_EOF)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Unexpected request: %s\n",
|
fprintf(stderr, "Unexpected request: %s\n", ssh_get_error(session));
|
||||||
ssh_get_error(session));
|
|
||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
166
doc/sftp.dox
@@ -53,16 +53,14 @@ int sftp_helloworld(ssh_session session)
|
|||||||
sftp = sftp_new(session);
|
sftp = sftp_new(session);
|
||||||
if (sftp == NULL)
|
if (sftp == NULL)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Error allocating SFTP session: %s\n",
|
fprintf(stderr, "Error allocating SFTP session: %s\n", ssh_get_error(session));
|
||||||
ssh_get_error(session));
|
|
||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = sftp_init(sftp);
|
rc = sftp_init(sftp);
|
||||||
if (rc != SSH_OK)
|
if (rc != SSH_OK)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Error initializing SFTP session: %s.\n",
|
fprintf(stderr, "Error initializing SFTP session: %s.\n", sftp_get_error(sftp));
|
||||||
sftp_get_error(sftp));
|
|
||||||
sftp_free(sftp);
|
sftp_free(sftp);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
@@ -100,7 +98,7 @@ Possible errors are:
|
|||||||
|
|
||||||
@subsection sftp_mkdir Creating a directory
|
@subsection sftp_mkdir Creating a directory
|
||||||
|
|
||||||
The function sftp_mkdir() takes the "SFTP session" we just created as
|
The function sftp_mkdir() tahes the "SFTP session" we juste created as
|
||||||
its first argument. It also needs the name of the file to create, and the
|
its first argument. It also needs the name of the file to create, and the
|
||||||
desired permissions. The permissions are the same as for the usual mkdir()
|
desired permissions. The permissions are the same as for the usual mkdir()
|
||||||
function. To get a comprehensive list of the available permissions, use the
|
function. To get a comprehensive list of the available permissions, use the
|
||||||
@@ -123,8 +121,7 @@ int sftp_helloworld(ssh_session session, sftp_session sftp)
|
|||||||
{
|
{
|
||||||
if (sftp_get_error(sftp) != SSH_FX_FILE_ALREADY_EXISTS)
|
if (sftp_get_error(sftp) != SSH_FX_FILE_ALREADY_EXISTS)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Can't create directory: %s\n",
|
fprintf(stderr, "Can't create directory: %s\n", ssh_get_error(session));
|
||||||
ssh_get_error(session));
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -170,20 +167,17 @@ int sftp_helloworld(ssh_session session, sftp_session sftp)
|
|||||||
|
|
||||||
...
|
...
|
||||||
|
|
||||||
file = sftp_open(sftp, "helloworld/helloworld.txt",
|
file = sftp_open(sftp, "helloworld/helloworld.txt", access_type, S_IRWXU);
|
||||||
access_type, S_IRWXU);
|
|
||||||
if (file == NULL)
|
if (file == NULL)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Can't open file for writing: %s\n",
|
fprintf(stderr, "Can't open file for writing: %s\n", ssh_get_error(session));
|
||||||
ssh_get_error(session));
|
|
||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
nwritten = sftp_write(file, helloworld, length);
|
nwritten = sftp_write(file, helloworld, length);
|
||||||
if (nwritten != length)
|
if (nwritten != length)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Can't write data to file: %s\n",
|
fprintf(stderr, "Can't write data to file: %s\n", ssh_get_error(session));
|
||||||
ssh_get_error(session));
|
|
||||||
sftp_close(file);
|
sftp_close(file);
|
||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
}
|
}
|
||||||
@@ -191,8 +185,7 @@ int sftp_helloworld(ssh_session session, sftp_session sftp)
|
|||||||
rc = sftp_close(file);
|
rc = sftp_close(file);
|
||||||
if (rc != SSH_OK)
|
if (rc != SSH_OK)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Can't close the written file: %s\n",
|
fprintf(stderr, "Can't close the written file: %s\n", ssh_get_error(session));
|
||||||
ssh_get_error(session));
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -210,63 +203,48 @@ results to come.
|
|||||||
|
|
||||||
Synchronous read is done with sftp_read().
|
Synchronous read is done with sftp_read().
|
||||||
|
|
||||||
Files are normally transferred in chunks. A good chunk size is 16 KB. The following
|
The following example prints the contents of remote file "/etc/profile". For
|
||||||
example transfers the remote file "/etc/profile" in 16 KB chunks. For each chunk we
|
each 1024 bytes of information read, it waits until the end of the read operation:
|
||||||
request, sftp_read blocks till the data has been received:
|
|
||||||
|
|
||||||
@code
|
@code
|
||||||
// Good chunk size
|
|
||||||
#define MAX_XFER_BUF_SIZE 16384
|
|
||||||
|
|
||||||
int sftp_read_sync(ssh_session session, sftp_session sftp)
|
int sftp_read_sync(ssh_session session, sftp_session sftp)
|
||||||
{
|
{
|
||||||
int access_type;
|
int access_type;
|
||||||
sftp_file file;
|
sftp_file file;
|
||||||
char buffer[MAX_XFER_BUF_SIZE];
|
char buffer[1024];
|
||||||
int nbytes, nwritten, rc;
|
int nbytes, rc;
|
||||||
int fd;
|
|
||||||
|
|
||||||
access_type = O_RDONLY;
|
access_type = O_RDONLY;
|
||||||
file = sftp_open(sftp, "/etc/profile",
|
file = sftp_open(sftp, "/etc/profile", access_type, 0);
|
||||||
access_type, 0);
|
if (file == NULL)
|
||||||
if (file == NULL) {
|
{
|
||||||
fprintf(stderr, "Can't open file for reading: %s\n",
|
fprintf(stderr, "Can't open file for reading: %s\n", ssh_get_error(session));
|
||||||
ssh_get_error(session));
|
return SSH_ERROR;
|
||||||
return SSH_ERROR;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fd = open("/path/to/profile", O_CREAT);
|
nbytes = sftp_read(file, buffer, sizeof(buffer));
|
||||||
if (fd < 0) {
|
while (nbytes > 0)
|
||||||
fprintf(stderr, "Can't open file for writing: %s\n",
|
{
|
||||||
strerror(errno));
|
if (write(1, buffer, nbytes) != nbytes)
|
||||||
|
{
|
||||||
|
sftp_close(file);
|
||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
nbytes = sftp_read(file, buffer, sizeof(buffer));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (;;) {
|
if (nbytes < 0)
|
||||||
nbytes = sftp_read(file, buffer, sizeof(buffer));
|
{
|
||||||
if (nbytes == 0) {
|
fprintf(stderr, "Error while reading file: %s\n", ssh_get_error(session));
|
||||||
break; // EOF
|
sftp_close(file);
|
||||||
} else if (nbytes < 0) {
|
return SSH_ERROR;
|
||||||
fprintf(stderr, "Error while reading file: %s\n",
|
|
||||||
ssh_get_error(session));
|
|
||||||
sftp_close(file);
|
|
||||||
return SSH_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
nwritten = write(fd, buffer, nbytes);
|
|
||||||
if (nwritten != nbytes) {
|
|
||||||
fprintf(stderr, "Error writing: %s\n",
|
|
||||||
strerror(errno));
|
|
||||||
sftp_close(file);
|
|
||||||
return SSH_ERROR;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = sftp_close(file);
|
rc = sftp_close(file);
|
||||||
if (rc != SSH_OK) {
|
if (rc != SSH_OK)
|
||||||
fprintf(stderr, "Can't close the read file: %s\n",
|
{
|
||||||
ssh_get_error(session));
|
fprintf(stderr, "Can't close the read file: %s\n", ssh_get_error(session));
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
return SSH_OK;
|
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.
|
call sftp_file_set_nonblocking() right after you opened it. Default is blocking mode.
|
||||||
|
|
||||||
The example below reads a very big file in asynchronous, nonblocking, mode. Each
|
The example below reads a very big file in asynchronous, nonblocking, mode. Each
|
||||||
time the data is not ready yet, a counter is incremented.
|
time the data are not ready yet, a counter is incrementer.
|
||||||
|
|
||||||
@code
|
@code
|
||||||
// Good chunk size
|
|
||||||
#define MAX_XFER_BUF_SIZE 16384
|
|
||||||
|
|
||||||
int sftp_read_async(ssh_session session, sftp_session sftp)
|
int sftp_read_async(ssh_session session, sftp_session sftp)
|
||||||
{
|
{
|
||||||
int access_type;
|
int access_type;
|
||||||
sftp_file file;
|
sftp_file file;
|
||||||
char buffer[MAX_XFER_BUF_SIZE];
|
char buffer[1024];
|
||||||
int async_request;
|
int async_request;
|
||||||
int nbytes;
|
int nbytes;
|
||||||
long counter;
|
long counter;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
access_type = O_RDONLY;
|
access_type = O_RDONLY;
|
||||||
file = sftp_open(sftp, "some_very_big_file",
|
file = sftp_open(sftp, "some_very_big_file", access_type, 0);
|
||||||
access_type, 0);
|
if (file == NULL)
|
||||||
if (file == NULL) {
|
{
|
||||||
fprintf(stderr, "Can't open file for reading: %s\n",
|
fprintf(stderr, "Can't open file for reading: %s\n", ssh_get_error(session));
|
||||||
ssh_get_error(session));
|
|
||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
}
|
}
|
||||||
sftp_file_set_nonblocking(file);
|
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));
|
async_request = sftp_async_read_begin(file, sizeof(buffer));
|
||||||
counter = 0L;
|
counter = 0L;
|
||||||
usleep(10000);
|
usleep(10000);
|
||||||
if (async_request >= 0) {
|
if (async_request >= 0)
|
||||||
nbytes = sftp_async_read(file, buffer, sizeof(buffer),
|
nbytes = sftp_async_read(file, buffer, sizeof(buffer), async_request);
|
||||||
async_request);
|
else nbytes = -1;
|
||||||
} else {
|
while (nbytes > 0 || nbytes == SSH_AGAIN)
|
||||||
nbytes = -1;
|
{
|
||||||
}
|
if (nbytes > 0)
|
||||||
|
{
|
||||||
while (nbytes > 0 || nbytes == SSH_AGAIN) {
|
|
||||||
if (nbytes > 0) {
|
|
||||||
write(1, buffer, nbytes);
|
write(1, buffer, nbytes);
|
||||||
async_request = sftp_async_read_begin(file, sizeof(buffer));
|
async_request = sftp_async_read_begin(file, sizeof(buffer));
|
||||||
} else {
|
|
||||||
counter++;
|
|
||||||
}
|
}
|
||||||
|
else counter++;
|
||||||
usleep(10000);
|
usleep(10000);
|
||||||
|
if (async_request >= 0)
|
||||||
if (async_request >= 0) {
|
nbytes = sftp_async_read(file, buffer, sizeof(buffer), async_request);
|
||||||
nbytes = sftp_async_read(file, buffer, sizeof(buffer),
|
else nbytes = -1;
|
||||||
async_request);
|
|
||||||
} else {
|
|
||||||
nbytes = -1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nbytes < 0) {
|
if (nbytes < 0)
|
||||||
fprintf(stderr, "Error while reading file: %s\n",
|
{
|
||||||
ssh_get_error(session));
|
fprintf(stderr, "Error while reading file: %s\n", ssh_get_error(session));
|
||||||
sftp_close(file);
|
sftp_close(file);
|
||||||
return SSH_ERROR;
|
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);
|
printf("The counter has reached value: %ld\n", counter);
|
||||||
|
|
||||||
rc = sftp_close(file);
|
rc = sftp_close(file);
|
||||||
if (rc != SSH_OK) {
|
if (rc != SSH_OK)
|
||||||
fprintf(stderr, "Can't close the read file: %s\n",
|
{
|
||||||
ssh_get_error(session));
|
fprintf(stderr, "Can't close the read file: %s\n", ssh_get_error(session));
|
||||||
return rc;
|
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
|
@subsection sftp_ls Listing the contents of a directory
|
||||||
|
|
||||||
The functions sftp_opendir(), sftp_readdir(), sftp_dir_eof(),
|
The functions sftp_opendir(), sftp_readdir(), sftp_dir_eof(),
|
||||||
and sftp_closedir() enable to list the contents of a directory.
|
and sftp_closedir() enable to list the contents of a directory.
|
||||||
They use a new handle_type, "sftp_dir", which gives access to the
|
They use a new handle_type, "sftp_dir", which gives access to the
|
||||||
directory being read.
|
directory being read.
|
||||||
|
|
||||||
In addition, sftp_readdir() returns a "sftp_attributes" which is a pointer
|
In addition, sftp_readdir() returns a "sftp_attributes" which is a pointer
|
||||||
to a structure with information about a directory entry:
|
to a structure with informations about a directory entry:
|
||||||
- name: the name of the file or directory
|
- name: the name of the file or directory
|
||||||
- size: its size in bytes
|
- size: its size in bytes
|
||||||
- etc.
|
- etc.
|
||||||
|
|
||||||
sftp_readdir() might return NULL under two conditions:
|
sftp_readdir() might return NULL under two conditions:
|
||||||
- when the end of the directory has been met
|
- when the end of the directory has been met
|
||||||
- when an error occurred
|
- when an error occured
|
||||||
|
|
||||||
To tell the difference, call sftp_dir_eof().
|
To tell the difference, call sftp_dir_eof().
|
||||||
|
|
||||||
@@ -389,16 +356,15 @@ int sftp_list_dir(ssh_session session, sftp_session sftp)
|
|||||||
dir = sftp_opendir(sftp, "/var/log");
|
dir = sftp_opendir(sftp, "/var/log");
|
||||||
if (!dir)
|
if (!dir)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Directory not opened: %s\n",
|
fprintf(stderr, "Directory not opened: %s\n", ssh_get_error(session));
|
||||||
ssh_get_error(session));
|
|
||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("Name Size Perms Owner\tGroup\n");
|
printf("Name Size Perms Owner\tGroup\n");
|
||||||
|
|
||||||
while ((attributes = sftp_readdir(sftp, dir)) != NULL)
|
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,
|
attributes->name,
|
||||||
(long long unsigned int) attributes->size,
|
(long long unsigned int) attributes->size,
|
||||||
attributes->permissions,
|
attributes->permissions,
|
||||||
@@ -412,8 +378,7 @@ int sftp_list_dir(ssh_session session, sftp_session sftp)
|
|||||||
|
|
||||||
if (!sftp_dir_eof(dir))
|
if (!sftp_dir_eof(dir))
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Can't list directory: %s\n",
|
fprintf(stderr, "Can't list directory: %s\n", ssh_get_error(session));
|
||||||
ssh_get_error(session));
|
|
||||||
sftp_closedir(dir);
|
sftp_closedir(dir);
|
||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
}
|
}
|
||||||
@@ -421,8 +386,7 @@ int sftp_list_dir(ssh_session session, sftp_session sftp)
|
|||||||
rc = sftp_closedir(dir);
|
rc = sftp_closedir(dir);
|
||||||
if (rc != SSH_OK)
|
if (rc != SSH_OK)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Can't close directory: %s\n",
|
fprintf(stderr, "Can't close directory: %s\n", ssh_get_error(session));
|
||||||
ssh_get_error(session));
|
|
||||||
return rc;
|
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
|
Of course, this is a poor terminal emulator, since the echo from the keys
|
||||||
pressed should not be done locally, but should be done by the remote side.
|
pressed should not be done locally, but should be done by the remote side.
|
||||||
Also, user's input should not be sent once "Enter" key is pressed, but
|
Also, user's input should not be sent once "Enter" key is pressed, but
|
||||||
immediately after each key is pressed. This can be accomplished
|
immediately after each key is pressed. This can be accomplished
|
||||||
by setting the local terminal to "raw" mode with the cfmakeraw(3) function.
|
by setting the local terminal to "raw" mode with the cfmakeraw(3) function.
|
||||||
cfmakeraw() is a standard function under Linux, on other systems you can
|
cfmakeraw() is a standard function under Linux, on other systems you can
|
||||||
@@ -245,13 +245,13 @@ provide a more elegant way to wait for data coming from many sources.
|
|||||||
|
|
||||||
The functions ssh_select() and ssh_channel_select() remind of the standard
|
The functions ssh_select() and ssh_channel_select() remind of the standard
|
||||||
UNIX select(2) function. The idea is to wait for "something" to happen:
|
UNIX select(2) function. The idea is to wait for "something" to happen:
|
||||||
incoming data to be read, outgoing data to block, or an exception to
|
incoming data to be read, outcoming data to block, or an exception to
|
||||||
occur. Both these functions do a "passive wait", i.e. you can safely use
|
occur. Both these functions do a "passive wait", i.e. you can safely use
|
||||||
them repeatedly in a loop, it will not consume exaggerate processor time
|
them repeatedly in a loop, it will not consume exaggerate processor time
|
||||||
and make your computer unresponsive. It is quite common to use these
|
and make your computer unresponsive. It is quite common to use these
|
||||||
functions in your application's main loop.
|
functions in your application's main loop.
|
||||||
|
|
||||||
The difference between ssh_select() and ssh_channel_select() is that
|
The difference between ssh_select() and ssh_channel_select() is that
|
||||||
ssh_channel_select() is simpler, but allows you only to watch SSH channels.
|
ssh_channel_select() is simpler, but allows you only to watch SSH channels.
|
||||||
ssh_select() is more complete and enables watching regular file descriptors
|
ssh_select() is more complete and enables watching regular file descriptors
|
||||||
as well, in the same function call.
|
as well, in the same function call.
|
||||||
|
|||||||
@@ -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
|
@section threads_with_libssh How to use libssh with threads
|
||||||
|
|
||||||
libssh may be used in multithreaded applications, but under several conditions :
|
libssh may be used in multithreaded applications, but under several conditions :
|
||||||
- Your system must support libpthread or, in Windows environment,
|
- Threading must be initialized during the initialization of libssh. This
|
||||||
CriticalSection based mutex control.
|
initialization must be done outside of any threading context.
|
||||||
- Since version 0.8.0, threads initialization is called automatically in the
|
- If pthreads is being used by your application (or your framework's backend),
|
||||||
library constructor if libssh is dynamically linked. This means it is no
|
you must link with libssh_threads dynamic library and initialize
|
||||||
longer necessary to call ssh_init()/ssh_finalize().
|
threading with the ssh_threads_pthreads threading object.
|
||||||
- If libssh is statically linked, threading must be initialized by calling
|
- If an other threading library is being used by your application, you must
|
||||||
ssh_init() before using any of libssh provided functions. This initialization
|
implement all the methods of the ssh_threads_callbacks_struct structure
|
||||||
must be done outside of any threading context. Don't forget to call
|
and initialize libssh with it.
|
||||||
ssh_finalize() to avoid memory leak
|
|
||||||
- At all times, you may use different sessions inside threads, make parallel
|
- At all times, you may use different sessions inside threads, make parallel
|
||||||
connections, read/write on different sessions and so on. You *cannot* use a
|
connections, read/write on different sessions and so on. You *cannot* use a
|
||||||
single session (or channels for a single session) in several threads at the same
|
single session (or channels for a single session) in several threads at the same
|
||||||
time. This will most likely lead to internal state corruption. This limitation is
|
time. This will most likely lead to internal state corruption. This limitation is
|
||||||
being worked out and will maybe disappear later.
|
being worked out and will maybe disappear later.
|
||||||
|
|
||||||
@subsection threads_init Initialization of threads
|
@subsection threads_init Initialization of threads
|
||||||
|
|
||||||
Since version 0.8.0, it is no longer necessary to call ssh_init()/ssh_finalize()
|
To initialize threading, you must first select the threading model you want to
|
||||||
if libssh is dynamically linked.
|
use, using ssh_threads_set_callbacks(), then call ssh_init().
|
||||||
|
|
||||||
If libssh is statically linked, call ssh_init() before using any of libssh
|
@code
|
||||||
provided functions.
|
#include <libssh/callbacks.h>
|
||||||
|
...
|
||||||
|
ssh_threads_set_callbacks(ssh_threads_get_noop());
|
||||||
|
ssh_init();
|
||||||
|
@endcode
|
||||||
|
|
||||||
|
ssh_threads_noop is the threading structure that does nothing. It's the
|
||||||
|
threading callbacks being used by default when you're not using threading.
|
||||||
|
|
||||||
@subsection threads_pthread Using libpthread with libssh
|
@subsection threads_pthread Using libpthread with libssh
|
||||||
|
|
||||||
Since version 0.8.0, libpthread is the default threads library used by libssh.
|
If your application is using libpthread, you may simply use the libpthread
|
||||||
|
threading backend:
|
||||||
|
|
||||||
To use libpthread, simply link it to you application.
|
@code
|
||||||
|
#include <libssh/callbacks.h>
|
||||||
|
...
|
||||||
|
ssh_threads_set_callbacks(ssh_threads_get_pthread());
|
||||||
|
ssh_init();
|
||||||
|
@endcode
|
||||||
|
|
||||||
|
However, you must be sure to link with the library ssh_threads. If
|
||||||
|
you're using gcc, you must use the commandline
|
||||||
|
@code
|
||||||
|
gcc -o output input.c -lssh -lssh_threads
|
||||||
|
@endcode
|
||||||
|
|
||||||
If you are using libssh statically linked, don't forget to call ssh_init()
|
|
||||||
before using any of libssh provided functions (and ssh_finalize() in the end).
|
|
||||||
|
|
||||||
@subsection threads_other Using another threading library
|
@subsection threads_other Using another threading library
|
||||||
|
|
||||||
Since version 0.8.0, libssh does not support custom threading libraries.
|
You must find your way in the ssh_threads_callbacks_struct structure. You must
|
||||||
The change makes sense since the newer versions for libcrypto (OpenSSL) and
|
implement the following methods :
|
||||||
libgcrypt don't support custom threading libraries.
|
- mutex_lock
|
||||||
|
- mutex_unlock
|
||||||
The default used threading library is libpthread.
|
- mutex_init
|
||||||
Alternatively, in Windows environment, CriticalSection based mutex control can
|
- mutex_destroy
|
||||||
be used.
|
- thread_id
|
||||||
|
|
||||||
If your system does not support libpthread nor CriticalSection based mutex
|
|
||||||
control, unfortunately, you cannot use libssh in multithreaded scenarios.
|
|
||||||
|
|
||||||
Good luck !
|
Good luck !
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -11,63 +11,34 @@ include_directories(
|
|||||||
${CMAKE_BINARY_DIR}
|
${CMAKE_BINARY_DIR}
|
||||||
)
|
)
|
||||||
|
|
||||||
if (ARGP_INCLUDE_DIR)
|
if (LINUX)
|
||||||
include_directories(${ARGP_INCLUDE_DIR})
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if (UNIX AND NOT WIN32)
|
|
||||||
add_executable(libssh_scp libssh_scp.c ${examples_SRCS})
|
add_executable(libssh_scp libssh_scp.c ${examples_SRCS})
|
||||||
target_compile_options(libssh_scp PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
|
|
||||||
target_link_libraries(libssh_scp ${LIBSSH_SHARED_LIBRARY})
|
target_link_libraries(libssh_scp ${LIBSSH_SHARED_LIBRARY})
|
||||||
|
|
||||||
add_executable(scp_download scp_download.c ${examples_SRCS})
|
add_executable(scp_download scp_download.c ${examples_SRCS})
|
||||||
target_compile_options(scp_download PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
|
|
||||||
target_link_libraries(scp_download ${LIBSSH_SHARED_LIBRARY})
|
target_link_libraries(scp_download ${LIBSSH_SHARED_LIBRARY})
|
||||||
|
|
||||||
|
add_executable(samplessh sample.c ${examples_SRCS})
|
||||||
|
target_link_libraries(samplessh ${LIBSSH_SHARED_LIBRARY})
|
||||||
|
|
||||||
add_executable(sshnetcat sshnetcat.c ${examples_SRCS})
|
add_executable(sshnetcat sshnetcat.c ${examples_SRCS})
|
||||||
target_compile_options(sshnetcat PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
|
|
||||||
target_link_libraries(sshnetcat ${LIBSSH_SHARED_LIBRARY})
|
target_link_libraries(sshnetcat ${LIBSSH_SHARED_LIBRARY})
|
||||||
|
|
||||||
if (WITH_SFTP)
|
if (WITH_SFTP)
|
||||||
add_executable(samplesftp samplesftp.c ${examples_SRCS})
|
add_executable(samplesftp samplesftp.c ${examples_SRCS})
|
||||||
target_compile_options(samplesftp PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
|
|
||||||
target_link_libraries(samplesftp ${LIBSSH_SHARED_LIBRARY})
|
target_link_libraries(samplesftp ${LIBSSH_SHARED_LIBRARY})
|
||||||
endif (WITH_SFTP)
|
endif (WITH_SFTP)
|
||||||
|
|
||||||
add_executable(ssh-client ssh_client.c ${examples_SRCS})
|
if (WITH_SERVER)
|
||||||
target_compile_options(ssh-client PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
|
add_executable(samplesshd samplesshd.c)
|
||||||
target_link_libraries(ssh-client ${LIBSSH_SHARED_LIBRARY})
|
target_link_libraries(samplesshd ${LIBSSH_SHARED_LIBRARY})
|
||||||
|
endif (WITH_SERVER)
|
||||||
if (WITH_SERVER AND (ARGP_LIBRARY OR HAVE_ARGP_H))
|
endif (LINUX)
|
||||||
if (HAVE_LIBUTIL)
|
|
||||||
add_executable(ssh_server_fork ssh_server_fork.c)
|
|
||||||
target_compile_options(ssh_server_fork PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
|
|
||||||
target_link_libraries(ssh_server_fork ${LIBSSH_SHARED_LIBRARY} ${ARGP_LIBRARY} util)
|
|
||||||
endif (HAVE_LIBUTIL)
|
|
||||||
|
|
||||||
if (WITH_GSSAPI AND GSSAPI_FOUND)
|
|
||||||
add_executable(samplesshd-cb samplesshd-cb.c)
|
|
||||||
target_compile_options(samplesshd-cb PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
|
|
||||||
target_link_libraries(samplesshd-cb ${LIBSSH_SHARED_LIBRARY} ${ARGP_LIBRARY})
|
|
||||||
|
|
||||||
add_executable(proxy proxy.c)
|
|
||||||
target_compile_options(proxy PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
|
|
||||||
target_link_libraries(proxy ${LIBSSH_SHARED_LIBRARY} ${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 ${LIBSSH_SHARED_LIBRARY} ${ARGP_LIBRARY})
|
|
||||||
|
|
||||||
endif()
|
|
||||||
endif (UNIX AND NOT WIN32)
|
|
||||||
|
|
||||||
add_executable(exec exec.c ${examples_SRCS})
|
add_executable(exec exec.c ${examples_SRCS})
|
||||||
target_compile_options(exec PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
|
|
||||||
target_link_libraries(exec ${LIBSSH_SHARED_LIBRARY})
|
target_link_libraries(exec ${LIBSSH_SHARED_LIBRARY})
|
||||||
|
|
||||||
add_executable(senddata senddata.c ${examples_SRCS})
|
add_executable(senddata senddata.c ${examples_SRCS})
|
||||||
target_compile_options(senddata PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
|
|
||||||
target_link_libraries(senddata ${LIBSSH_SHARED_LIBRARY})
|
target_link_libraries(senddata ${LIBSSH_SHARED_LIBRARY})
|
||||||
|
|
||||||
add_executable(libsshpp libsshpp.cpp)
|
add_executable(libsshpp libsshpp.cpp)
|
||||||
|
|||||||
@@ -24,8 +24,7 @@ clients must be made or how a client should react.
|
|||||||
#include <libssh/libssh.h>
|
#include <libssh/libssh.h>
|
||||||
#include "examples_common.h"
|
#include "examples_common.h"
|
||||||
|
|
||||||
int authenticate_kbdint(ssh_session session, const char *password)
|
int authenticate_kbdint(ssh_session session, const char *password) {
|
||||||
{
|
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
err = ssh_userauth_kbdint(session, NULL, NULL);
|
err = ssh_userauth_kbdint(session, NULL, NULL);
|
||||||
@@ -87,9 +86,7 @@ int authenticate_kbdint(ssh_session session, const char *password)
|
|||||||
}
|
}
|
||||||
answer = buffer;
|
answer = buffer;
|
||||||
}
|
}
|
||||||
err = ssh_userauth_kbdint_setanswer(session, i, answer);
|
if (ssh_userauth_kbdint_setanswer(session, i, answer) < 0) {
|
||||||
memset(buffer, 0, sizeof(buffer));
|
|
||||||
if (err < 0) {
|
|
||||||
return SSH_AUTH_ERROR;
|
return SSH_AUTH_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -100,80 +97,68 @@ int authenticate_kbdint(ssh_session session, const char *password)
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void error(ssh_session session)
|
static void error(ssh_session session){
|
||||||
{
|
fprintf(stderr,"Authentication failed: %s\n",ssh_get_error(session));
|
||||||
fprintf(stderr,"Authentication failed: %s\n",ssh_get_error(session));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int authenticate_console(ssh_session session)
|
int authenticate_console(ssh_session session){
|
||||||
{
|
int rc;
|
||||||
int rc;
|
int method;
|
||||||
int method;
|
char password[128] = {0};
|
||||||
char password[128] = {0};
|
char *banner;
|
||||||
char *banner;
|
|
||||||
|
|
||||||
// Try to authenticate
|
|
||||||
rc = ssh_userauth_none(session, NULL);
|
|
||||||
if (rc == SSH_AUTH_ERROR) {
|
|
||||||
error(session);
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
method = ssh_userauth_list(session, NULL);
|
|
||||||
while (rc != SSH_AUTH_SUCCESS) {
|
|
||||||
if (method & SSH_AUTH_METHOD_GSSAPI_MIC){
|
|
||||||
rc = ssh_userauth_gssapi(session);
|
|
||||||
if(rc == SSH_AUTH_ERROR) {
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try to authenticate with keyboard interactive";
|
|
||||||
if (method & SSH_AUTH_METHOD_INTERACTIVE) {
|
|
||||||
rc = authenticate_kbdint(session, NULL);
|
|
||||||
if (rc == SSH_AUTH_ERROR) {
|
|
||||||
error(session);
|
|
||||||
return rc;
|
|
||||||
} else if (rc == SSH_AUTH_SUCCESS) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ssh_getpass("Password: ", password, sizeof(password), 0, 0) < 0) {
|
|
||||||
return SSH_AUTH_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try to authenticate with password
|
|
||||||
if (method & SSH_AUTH_METHOD_PASSWORD) {
|
|
||||||
rc = ssh_userauth_password(session, NULL, password);
|
|
||||||
if (rc == SSH_AUTH_ERROR) {
|
|
||||||
error(session);
|
|
||||||
return rc;
|
|
||||||
} else if (rc == SSH_AUTH_SUCCESS) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
memset(password, 0, sizeof(password));
|
|
||||||
}
|
|
||||||
|
|
||||||
banner = ssh_get_issue_banner(session);
|
|
||||||
if (banner) {
|
|
||||||
printf("%s\n",banner);
|
|
||||||
ssh_string_free_char(banner);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// Try to authenticate
|
||||||
|
rc = ssh_userauth_none(session, NULL);
|
||||||
|
if (rc == SSH_AUTH_ERROR) {
|
||||||
|
error(session);
|
||||||
return rc;
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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_
|
#define EXAMPLES_COMMON_H_
|
||||||
|
|
||||||
#include <libssh/libssh.h>
|
#include <libssh/libssh.h>
|
||||||
|
|
||||||
/** Zero a structure */
|
|
||||||
#define ZERO_STRUCT(x) memset((char *)&(x), 0, sizeof(x))
|
|
||||||
|
|
||||||
int authenticate_console(ssh_session session);
|
int authenticate_console(ssh_session session);
|
||||||
int authenticate_kbdint(ssh_session session, const char *password);
|
int authenticate_kbdint(ssh_session session, const char *password);
|
||||||
int verify_knownhost(ssh_session session);
|
int verify_knownhost(ssh_session session);
|
||||||
|
|||||||
@@ -17,14 +17,11 @@ The goal is to show the API in action. It's not a reference on how terminal
|
|||||||
clients must be made or how a client should react.
|
clients must be made or how a client should react.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "libssh/priv.h"
|
|
||||||
#include <libssh/libssh.h>
|
#include <libssh/libssh.h>
|
||||||
#include "examples_common.h"
|
#include "examples_common.h"
|
||||||
|
|
||||||
@@ -32,86 +29,70 @@ clients must be made or how a client should react.
|
|||||||
#define strncasecmp _strnicmp
|
#define strncasecmp _strnicmp
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int verify_knownhost(ssh_session session)
|
int verify_knownhost(ssh_session session){
|
||||||
{
|
char *hexa;
|
||||||
enum ssh_known_hosts_e state;
|
int state;
|
||||||
char buf[10];
|
char buf[10];
|
||||||
unsigned char *hash = NULL;
|
unsigned char *hash = NULL;
|
||||||
size_t hlen;
|
int hlen;
|
||||||
ssh_key srv_pubkey;
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
rc = ssh_get_server_publickey(session, &srv_pubkey);
|
state=ssh_is_server_known(session);
|
||||||
if (rc < 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = ssh_get_publickey_hash(srv_pubkey,
|
hlen = ssh_get_pubkey_hash(session, &hash);
|
||||||
SSH_PUBLICKEY_HASH_SHA256,
|
if (hlen < 0) {
|
||||||
&hash,
|
return -1;
|
||||||
&hlen);
|
}
|
||||||
ssh_key_free(srv_pubkey);
|
switch(state){
|
||||||
if (rc < 0) {
|
case SSH_SERVER_KNOWN_OK:
|
||||||
return -1;
|
break; /* ok */
|
||||||
}
|
case SSH_SERVER_KNOWN_CHANGED:
|
||||||
|
fprintf(stderr,"Host key for server changed : server's one is now :\n");
|
||||||
state = ssh_session_is_known_server(session);
|
ssh_print_hexa("Public key hash",hash, hlen);
|
||||||
|
ssh_clean_pubkey_hash(&hash);
|
||||||
switch(state) {
|
fprintf(stderr,"For security reason, connection will be stopped\n");
|
||||||
case SSH_KNOWN_HOSTS_CHANGED:
|
return -1;
|
||||||
fprintf(stderr,"Host key for server changed : server's one is now :\n");
|
case SSH_SERVER_FOUND_OTHER:
|
||||||
ssh_print_hash(SSH_PUBLICKEY_HASH_SHA256, hash, hlen);
|
fprintf(stderr,"The host key for this server was not found but an other type of key exists.\n");
|
||||||
ssh_clean_pubkey_hash(&hash);
|
fprintf(stderr,"An attacker might change the default server key to confuse your client"
|
||||||
fprintf(stderr,"For security reason, connection will be stopped\n");
|
"into thinking the key does not exist\n"
|
||||||
return -1;
|
"We advise you to rerun the client with -d or -r for more safety.\n");
|
||||||
case SSH_KNOWN_HOSTS_OTHER:
|
return -1;
|
||||||
fprintf(stderr,"The host key for this server was not found but an other type of key exists.\n");
|
case SSH_SERVER_FILE_NOT_FOUND:
|
||||||
fprintf(stderr,"An attacker might change the default server key to confuse your client"
|
fprintf(stderr,"Could not find known host file. If you accept the host key here,\n");
|
||||||
"into thinking the key does not exist\n"
|
fprintf(stderr,"the file will be automatically created.\n");
|
||||||
"We advise you to rerun the client with -d or -r for more safety.\n");
|
/* fallback to SSH_SERVER_NOT_KNOWN behavior */
|
||||||
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;
|
|
||||||
case SSH_SERVER_NOT_KNOWN:
|
case SSH_SERVER_NOT_KNOWN:
|
||||||
fprintf(stderr,
|
hexa = ssh_get_hexa(hash, hlen);
|
||||||
"The server is unknown. Do you trust the host key (yes/no)?\n");
|
fprintf(stderr,"The server is unknown. Do you trust the host key ?\n");
|
||||||
ssh_print_hash(SSH_PUBLICKEY_HASH_SHA256, hash, hlen);
|
fprintf(stderr, "Public key hash: %s\n", hexa);
|
||||||
|
ssh_string_free_char(hexa);
|
||||||
if (fgets(buf, sizeof(buf), stdin) == NULL) {
|
if (fgets(buf, sizeof(buf), stdin) == NULL) {
|
||||||
ssh_clean_pubkey_hash(&hash);
|
ssh_clean_pubkey_hash(&hash);
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if(strncasecmp(buf,"yes",3)!=0){
|
|
||||||
ssh_clean_pubkey_hash(&hash);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
fprintf(stderr,"This new key will be written on disk for further usage. do you agree ?\n");
|
|
||||||
if (fgets(buf, sizeof(buf), stdin) == NULL) {
|
|
||||||
ssh_clean_pubkey_hash(&hash);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if(strncasecmp(buf,"yes",3)==0){
|
|
||||||
rc = ssh_session_update_known_hosts(session);
|
|
||||||
if (rc != SSH_OK) {
|
|
||||||
ssh_clean_pubkey_hash(&hash);
|
|
||||||
fprintf(stderr, "error %s\n", strerror(errno));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
case SSH_KNOWN_HOSTS_ERROR:
|
|
||||||
ssh_clean_pubkey_hash(&hash);
|
|
||||||
fprintf(stderr,"%s",ssh_get_error(session));
|
|
||||||
return -1;
|
return -1;
|
||||||
case SSH_KNOWN_HOSTS_OK:
|
}
|
||||||
break; /* ok */
|
if(strncasecmp(buf,"yes",3)!=0){
|
||||||
}
|
ssh_clean_pubkey_hash(&hash);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
fprintf(stderr,"This new key will be written on disk for further usage. do you agree ?\n");
|
||||||
|
if (fgets(buf, sizeof(buf), stdin) == NULL) {
|
||||||
|
ssh_clean_pubkey_hash(&hash);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if(strncasecmp(buf,"yes",3)==0){
|
||||||
|
if (ssh_write_knownhost(session) < 0) {
|
||||||
|
ssh_clean_pubkey_hash(&hash);
|
||||||
|
fprintf(stderr, "error %s\n", strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ssh_clean_pubkey_hash(&hash);
|
break;
|
||||||
|
case SSH_SERVER_ERROR:
|
||||||
return 0;
|
ssh_clean_pubkey_hash(&hash);
|
||||||
|
fprintf(stderr,"%s",ssh_get_error(session));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
ssh_clean_pubkey_hash(&hash);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,233 +22,143 @@ program.
|
|||||||
#include <libssh/libssh.h>
|
#include <libssh/libssh.h>
|
||||||
#include "examples_common.h"
|
#include "examples_common.h"
|
||||||
|
|
||||||
static char **sources;
|
char **sources;
|
||||||
static int nsources;
|
int nsources;
|
||||||
static char *destination;
|
char *destination;
|
||||||
static int verbosity = 0;
|
int verbosity=0;
|
||||||
|
|
||||||
struct location {
|
struct location {
|
||||||
int is_ssh;
|
int is_ssh;
|
||||||
char *user;
|
char *user;
|
||||||
char *host;
|
char *host;
|
||||||
char *path;
|
char *path;
|
||||||
ssh_session session;
|
ssh_session session;
|
||||||
ssh_scp scp;
|
ssh_scp scp;
|
||||||
FILE *file;
|
FILE *file;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
READ,
|
READ,
|
||||||
WRITE
|
WRITE
|
||||||
};
|
};
|
||||||
|
|
||||||
static void usage(const char *argv0) {
|
static void usage(const char *argv0){
|
||||||
fprintf(stderr, "Usage : %s [options] [[user@]host1:]file1 ... \n"
|
fprintf(stderr,"Usage : %s [options] [[user@]host1:]file1 ... \n"
|
||||||
" [[user@]host2:]destination\n"
|
" [[user@]host2:]destination\n"
|
||||||
"sample scp client - libssh-%s\n",
|
"sample scp client - libssh-%s\n",
|
||||||
// "Options :\n",
|
// "Options :\n",
|
||||||
// " -r : use RSA to verify host public key\n",
|
// " -r : use RSA to verify host public key\n",
|
||||||
argv0,
|
argv0,
|
||||||
ssh_version(0));
|
ssh_version(0));
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int opts(int argc, char **argv) {
|
static int opts(int argc, char **argv){
|
||||||
int i;
|
int i;
|
||||||
|
while((i=getopt(argc,argv,"v"))!=-1){
|
||||||
while((i = getopt(argc, argv, "v")) != -1) {
|
switch(i){
|
||||||
switch(i) {
|
case 'v':
|
||||||
case 'v':
|
verbosity++;
|
||||||
verbosity++;
|
break;
|
||||||
break;
|
default:
|
||||||
default:
|
fprintf(stderr,"unknown option %c\n",optopt);
|
||||||
fprintf(stderr, "unknown option %c\n", optopt);
|
|
||||||
usage(argv[0]);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
nsources = argc - optind - 1;
|
|
||||||
if (nsources < 1) {
|
|
||||||
usage(argv[0]);
|
usage(argv[0]);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
sources = malloc((nsources + 1) * sizeof(char *));
|
nsources=argc-optind-1;
|
||||||
if (sources == NULL) {
|
if(nsources < 1){
|
||||||
return -1;
|
usage(argv[0]);
|
||||||
}
|
|
||||||
|
|
||||||
for(i = 0; i < nsources; ++i) {
|
|
||||||
sources[i] = argv[optind];
|
|
||||||
optind++;
|
|
||||||
}
|
|
||||||
|
|
||||||
sources[i] = NULL;
|
|
||||||
destination = argv[optind];
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void location_free(struct location *loc)
|
|
||||||
{
|
|
||||||
if (loc) {
|
|
||||||
if (loc->path) {
|
|
||||||
free(loc->path);
|
|
||||||
}
|
|
||||||
loc->path = NULL;
|
|
||||||
if (loc->is_ssh) {
|
|
||||||
if (loc->host) {
|
|
||||||
free(loc->host);
|
|
||||||
}
|
|
||||||
loc->host = NULL;
|
|
||||||
if (loc->user) {
|
|
||||||
free(loc->user);
|
|
||||||
}
|
|
||||||
loc->user = NULL;
|
|
||||||
if (loc->host) {
|
|
||||||
free(loc->host);
|
|
||||||
}
|
|
||||||
loc->host = 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 (chdir(loc->path)) {
|
|
||||||
fprintf(stderr,
|
|
||||||
"Error changing directory to %s: %s\n",
|
|
||||||
loc->path, strerror(errno));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
fprintf(stderr,
|
|
||||||
"Error opening %s: %s\n",
|
|
||||||
loc->path, strerror(errno));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
sources=malloc((nsources + 1) * sizeof(char *));
|
||||||
|
if(sources == NULL)
|
||||||
|
return -1;
|
||||||
|
for(i=0;i<nsources;++i){
|
||||||
|
sources[i] = argv[optind];
|
||||||
|
optind++;
|
||||||
|
}
|
||||||
|
sources[i]=NULL;
|
||||||
|
destination=argv[optind];
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct location *parse_location(char *loc){
|
||||||
|
struct location *location=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
|
/** @brief copies files from source location to destination
|
||||||
@@ -256,197 +166,139 @@ static int open_location(struct location *loc, int flag) {
|
|||||||
* @param dest destination location
|
* @param dest destination location
|
||||||
* @param recursive Copy also directories
|
* @param recursive Copy also directories
|
||||||
*/
|
*/
|
||||||
static int do_copy(struct location *src, struct location *dest, int recursive) {
|
static int do_copy(struct location *src, struct location *dest, int recursive){
|
||||||
int size;
|
int size;
|
||||||
socket_t fd;
|
socket_t fd;
|
||||||
struct stat s;
|
struct stat s;
|
||||||
int w, r;
|
int w,r;
|
||||||
char buffer[16384];
|
char buffer[16384];
|
||||||
int total = 0;
|
int total=0;
|
||||||
int mode;
|
int mode;
|
||||||
char *filename = NULL;
|
char *filename;
|
||||||
/* recursive mode doesn't work yet */
|
/* recursive mode doesn't work yet */
|
||||||
(void)recursive;
|
(void)recursive;
|
||||||
/* Get the file name and size*/
|
/* Get the file name and size*/
|
||||||
if (!src->is_ssh) {
|
if(!src->is_ssh){
|
||||||
fd = fileno(src->file);
|
fd=fileno(src->file);
|
||||||
if (fd < 0) {
|
fstat(fd,&s);
|
||||||
fprintf(stderr,
|
size=s.st_size;
|
||||||
"Invalid file pointer, error: %s\n",
|
mode = s.st_mode & ~S_IFMT;
|
||||||
strerror(errno));
|
filename=ssh_basename(src->path);
|
||||||
return -1;
|
} else {
|
||||||
}
|
size=0;
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if (src->is_ssh) {
|
r=ssh_scp_pull_request(src->scp);
|
||||||
r = ssh_scp_read(src->scp, buffer, sizeof(buffer));
|
if(r==SSH_SCP_REQUEST_NEWDIR){
|
||||||
if (r == SSH_ERROR) {
|
ssh_scp_deny_request(src->scp,"Not in recursive mode");
|
||||||
fprintf(stderr,
|
continue;
|
||||||
"Error reading scp: %s\n",
|
}
|
||||||
ssh_get_error(src->session));
|
if(r==SSH_SCP_REQUEST_NEWFILE){
|
||||||
ssh_string_free_char(filename);
|
size=ssh_scp_request_get_size(src->scp);
|
||||||
return -1;
|
filename=strdup(ssh_scp_request_get_filename(src->scp));
|
||||||
}
|
mode=ssh_scp_request_get_permissions(src->scp);
|
||||||
|
//ssh_scp_accept_request(src->scp);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(r==SSH_ERROR){
|
||||||
|
fprintf(stderr,"Error: %s\n",ssh_get_error(src->session));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
} while(r != SSH_SCP_REQUEST_NEWFILE);
|
||||||
|
}
|
||||||
|
|
||||||
if (r == 0) {
|
if(dest->is_ssh){
|
||||||
break;
|
r=ssh_scp_push_file(dest->scp,src->path, size, mode);
|
||||||
}
|
// snprintf(buffer,sizeof(buffer),"C0644 %d %s\n",size,src->path);
|
||||||
} else {
|
if(r==SSH_ERROR){
|
||||||
r = fread(buffer, 1, sizeof(buffer), src->file);
|
fprintf(stderr,"error: %s\n",ssh_get_error(dest->session));
|
||||||
if (r == 0) {
|
ssh_scp_free(dest->scp);
|
||||||
break;
|
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) {
|
} while(total < size);
|
||||||
fprintf(stderr,
|
printf("wrote %d bytes\n",total);
|
||||||
"Error reading file: %s\n",
|
return 0;
|
||||||
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 %d bytes\n", total);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv){
|
||||||
struct location *dest, *src;
|
struct location *dest, *src;
|
||||||
int i;
|
int i;
|
||||||
int r;
|
int r;
|
||||||
if (opts(argc, argv) < 0) {
|
if(opts(argc,argv)<0)
|
||||||
r = EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
goto end;
|
dest=parse_location(destination);
|
||||||
|
if(open_location(dest,WRITE)<0)
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
for(i=0;i<nsources;++i){
|
||||||
|
src=parse_location(sources[i]);
|
||||||
|
if(open_location(src,READ)<0){
|
||||||
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
if(do_copy(src,dest,0) < 0){
|
||||||
dest = parse_location(destination);
|
break;
|
||||||
if (dest == NULL) {
|
|
||||||
r = EXIT_FAILURE;
|
|
||||||
goto end;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (open_location(dest, WRITE) < 0) {
|
if(dest->is_ssh){
|
||||||
location_free(dest);
|
r=ssh_scp_close(dest->scp);
|
||||||
r = EXIT_FAILURE;
|
if(r == SSH_ERROR){
|
||||||
goto end;
|
fprintf(stderr,"Error closing scp: %s\n",ssh_get_error(dest->session));
|
||||||
}
|
ssh_scp_free(dest->scp);
|
||||||
|
dest->scp=NULL;
|
||||||
for (i = 0; i < nsources; ++i) {
|
return -1;
|
||||||
src = parse_location(sources[i]);
|
}
|
||||||
if (src == NULL) {
|
} else {
|
||||||
r = EXIT_FAILURE;
|
fclose(dest->file);
|
||||||
goto close_dest;
|
dest->file=NULL;
|
||||||
}
|
}
|
||||||
|
ssh_disconnect(dest->session);
|
||||||
if (open_location(src, READ) < 0) {
|
ssh_finalize();
|
||||||
location_free(src);
|
return 0;
|
||||||
r = EXIT_FAILURE;
|
|
||||||
goto close_dest;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (do_copy(src, dest, 0) < 0) {
|
|
||||||
close_location(src);
|
|
||||||
location_free(src);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
close_location(src);
|
|
||||||
location_free(src);
|
|
||||||
}
|
|
||||||
|
|
||||||
r = 0;
|
|
||||||
|
|
||||||
close_dest:
|
|
||||||
close_location(dest);
|
|
||||||
location_free(dest);
|
|
||||||
end:
|
|
||||||
return r;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ int main(int argc, const char **argv){
|
|||||||
else
|
else
|
||||||
session.setOption(SSH_OPTIONS_HOST,"localhost");
|
session.setOption(SSH_OPTIONS_HOST,"localhost");
|
||||||
session.connect();
|
session.connect();
|
||||||
session.userauthPublickeyAuto();
|
session.userauthAutopubkey();
|
||||||
session.disconnect();
|
session.disconnect();
|
||||||
} catch (ssh::SshException e){
|
} catch (ssh::SshException e){
|
||||||
std::cout << "Error during connection : ";
|
std::cout << "Error during connection : ";
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ int main(int argc, const char **argv){
|
|||||||
err=session.connect();
|
err=session.connect();
|
||||||
if(err==SSH_ERROR)
|
if(err==SSH_ERROR)
|
||||||
goto error;
|
goto error;
|
||||||
err=session.userauthPublickeyAuto();
|
err=session.userauthAutopubkey();
|
||||||
if(err==SSH_ERROR)
|
if(err==SSH_ERROR)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
|
|||||||
347
examples/proxy.c
@@ -1,347 +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>
|
|
||||||
|
|
||||||
#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[2048];
|
|
||||||
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, 2048, 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 <sys/statvfs.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#ifdef HAVE_UNISTD_H
|
|
||||||
#include <unistd.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <libssh/libssh.h>
|
#include <libssh/libssh.h>
|
||||||
#include <libssh/sftp.h>
|
#include <libssh/sftp.h>
|
||||||
@@ -29,263 +27,239 @@ clients must be made or how a client should react.
|
|||||||
#include "examples_common.h"
|
#include "examples_common.h"
|
||||||
#ifdef WITH_SFTP
|
#ifdef WITH_SFTP
|
||||||
|
|
||||||
static int verbosity;
|
int verbosity;
|
||||||
static char *destination;
|
char *destination;
|
||||||
|
|
||||||
#define DATALEN 65536
|
#define DATALEN 65536
|
||||||
|
static void do_sftp(ssh_session session){
|
||||||
static void do_sftp(ssh_session session) {
|
sftp_session sftp=sftp_new(session);
|
||||||
sftp_session sftp = sftp_new(session);
|
|
||||||
sftp_dir dir;
|
sftp_dir dir;
|
||||||
sftp_attributes file;
|
sftp_attributes file;
|
||||||
sftp_statvfs_t sftpstatvfs;
|
sftp_statvfs_t sftpstatvfs;
|
||||||
struct statvfs sysstatvfs;
|
struct statvfs sysstatvfs;
|
||||||
sftp_file fichier;
|
sftp_file fichier;
|
||||||
sftp_file to;
|
sftp_file to;
|
||||||
int len = 1;
|
int len=1;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
char data[DATALEN] = {0};
|
char data[DATALEN]={0};
|
||||||
char *lnk;
|
char *lnk;
|
||||||
|
|
||||||
unsigned int count;
|
unsigned int count;
|
||||||
|
|
||||||
if (!sftp) {
|
if(!sftp){
|
||||||
fprintf(stderr, "sftp error initialising channel: %s\n",
|
fprintf(stderr, "sftp error initialising channel: %s\n",
|
||||||
ssh_get_error(session));
|
ssh_get_error(session));
|
||||||
goto end;
|
return;
|
||||||
}
|
}
|
||||||
|
if(sftp_init(sftp)){
|
||||||
if (sftp_init(sftp)) {
|
|
||||||
fprintf(stderr, "error initialising sftp: %s\n",
|
fprintf(stderr, "error initialising sftp: %s\n",
|
||||||
ssh_get_error(session));
|
ssh_get_error(session));
|
||||||
goto end;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("Additional SFTP extensions provided by the server:\n");
|
printf("Additional SFTP extensions provided by the server:\n");
|
||||||
count = sftp_extensions_get_count(sftp);
|
count = sftp_extensions_get_count(sftp);
|
||||||
for (i = 0; i < count; i++) {
|
for (i = 0; i < count; i++) {
|
||||||
printf("\t%s, version: %s\n",
|
printf("\t%s, version: %s\n",
|
||||||
sftp_extensions_get_name(sftp, i),
|
sftp_extensions_get_name(sftp, i),
|
||||||
sftp_extensions_get_data(sftp, i));
|
sftp_extensions_get_data(sftp, i));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* test symlink and readlink */
|
/* test symlink and readlink */
|
||||||
if (sftp_symlink(sftp, "/tmp/this_is_the_link",
|
if (sftp_symlink(sftp, "/tmp/this_is_the_link",
|
||||||
"/tmp/sftp_symlink_test") < 0)
|
"/tmp/sftp_symlink_test") < 0) {
|
||||||
{
|
fprintf(stderr, "Could not create link (%s)\n", ssh_get_error(session));
|
||||||
fprintf(stderr, "Could not create link (%s)\n",
|
return;
|
||||||
ssh_get_error(session));
|
|
||||||
goto end;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
lnk = sftp_readlink(sftp, "/tmp/sftp_symlink_test");
|
lnk = sftp_readlink(sftp, "/tmp/sftp_symlink_test");
|
||||||
if (lnk == NULL) {
|
if (lnk == NULL) {
|
||||||
fprintf(stderr, "Could not read link (%s)\n", ssh_get_error(session));
|
fprintf(stderr, "Could not read link (%s)\n", ssh_get_error(session));
|
||||||
goto end;
|
return;
|
||||||
}
|
}
|
||||||
printf("readlink /tmp/sftp_symlink_test: %s\n", lnk);
|
printf("readlink /tmp/sftp_symlink_test: %s\n", lnk);
|
||||||
|
|
||||||
sftp_unlink(sftp, "/tmp/sftp_symlink_test");
|
sftp_unlink(sftp, "/tmp/sftp_symlink_test");
|
||||||
|
|
||||||
if (sftp_extension_supported(sftp, "statvfs@openssh.com", "2")) {
|
if (sftp_extension_supported(sftp, "statvfs@openssh.com", "2")) {
|
||||||
sftpstatvfs = sftp_statvfs(sftp, "/tmp");
|
sftpstatvfs = sftp_statvfs(sftp, "/tmp");
|
||||||
if (sftpstatvfs == NULL) {
|
if (sftpstatvfs == NULL) {
|
||||||
fprintf(stderr, "statvfs failed (%s)\n", ssh_get_error(session));
|
fprintf(stderr, "statvfs failed (%s)\n", ssh_get_error(session));
|
||||||
goto end;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("sftp statvfs:\n"
|
printf("sftp statvfs:\n"
|
||||||
"\tfile system block size: %llu\n"
|
"\tfile system block size: %llu\n"
|
||||||
"\tfundamental fs block size: %llu\n"
|
"\tfundamental fs block size: %llu\n"
|
||||||
"\tnumber of blocks (unit f_frsize): %llu\n"
|
"\tnumber of blocks (unit f_frsize): %llu\n"
|
||||||
"\tfree blocks in file system: %llu\n"
|
"\tfree blocks in file system: %llu\n"
|
||||||
"\tfree blocks for non-root: %llu\n"
|
"\tfree blocks for non-root: %llu\n"
|
||||||
"\ttotal file inodes: %llu\n"
|
"\ttotal file inodes: %llu\n"
|
||||||
"\tfree file inodes: %llu\n"
|
"\tfree file inodes: %llu\n"
|
||||||
"\tfree file inodes for to non-root: %llu\n"
|
"\tfree file inodes for to non-root: %llu\n"
|
||||||
"\tfile system id: %llu\n"
|
"\tfile system id: %llu\n"
|
||||||
"\tbit mask of f_flag values: %llu\n"
|
"\tbit mask of f_flag values: %llu\n"
|
||||||
"\tmaximum filename length: %llu\n",
|
"\tmaximum filename length: %llu\n",
|
||||||
(unsigned long long) sftpstatvfs->f_bsize,
|
(unsigned long long) sftpstatvfs->f_bsize,
|
||||||
(unsigned long long) sftpstatvfs->f_frsize,
|
(unsigned long long) sftpstatvfs->f_frsize,
|
||||||
(unsigned long long) sftpstatvfs->f_blocks,
|
(unsigned long long) sftpstatvfs->f_blocks,
|
||||||
(unsigned long long) sftpstatvfs->f_bfree,
|
(unsigned long long) sftpstatvfs->f_bfree,
|
||||||
(unsigned long long) sftpstatvfs->f_bavail,
|
(unsigned long long) sftpstatvfs->f_bavail,
|
||||||
(unsigned long long) sftpstatvfs->f_files,
|
(unsigned long long) sftpstatvfs->f_files,
|
||||||
(unsigned long long) sftpstatvfs->f_ffree,
|
(unsigned long long) sftpstatvfs->f_ffree,
|
||||||
(unsigned long long) sftpstatvfs->f_favail,
|
(unsigned long long) sftpstatvfs->f_favail,
|
||||||
(unsigned long long) sftpstatvfs->f_fsid,
|
(unsigned long long) sftpstatvfs->f_fsid,
|
||||||
(unsigned long long) sftpstatvfs->f_flag,
|
(unsigned long long) sftpstatvfs->f_flag,
|
||||||
(unsigned long long) sftpstatvfs->f_namemax);
|
(unsigned long long) sftpstatvfs->f_namemax);
|
||||||
|
|
||||||
sftp_statvfs_free(sftpstatvfs);
|
sftp_statvfs_free(sftpstatvfs);
|
||||||
|
|
||||||
if (statvfs("/tmp", &sysstatvfs) < 0) {
|
if (statvfs("/tmp", &sysstatvfs) < 0) {
|
||||||
fprintf(stderr, "statvfs failed (%s)\n", strerror(errno));
|
fprintf(stderr, "statvfs failed (%s)\n", strerror(errno));
|
||||||
goto end;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("sys statvfs:\n"
|
printf("sys statvfs:\n"
|
||||||
"\tfile system block size: %llu\n"
|
"\tfile system block size: %llu\n"
|
||||||
"\tfundamental fs block size: %llu\n"
|
"\tfundamental fs block size: %llu\n"
|
||||||
"\tnumber of blocks (unit f_frsize): %llu\n"
|
"\tnumber of blocks (unit f_frsize): %llu\n"
|
||||||
"\tfree blocks in file system: %llu\n"
|
"\tfree blocks in file system: %llu\n"
|
||||||
"\tfree blocks for non-root: %llu\n"
|
"\tfree blocks for non-root: %llu\n"
|
||||||
"\ttotal file inodes: %llu\n"
|
"\ttotal file inodes: %llu\n"
|
||||||
"\tfree file inodes: %llu\n"
|
"\tfree file inodes: %llu\n"
|
||||||
"\tfree file inodes for to non-root: %llu\n"
|
"\tfree file inodes for to non-root: %llu\n"
|
||||||
"\tfile system id: %llu\n"
|
"\tfile system id: %llu\n"
|
||||||
"\tbit mask of f_flag values: %llu\n"
|
"\tbit mask of f_flag values: %llu\n"
|
||||||
"\tmaximum filename length: %llu\n",
|
"\tmaximum filename length: %llu\n",
|
||||||
(unsigned long long) sysstatvfs.f_bsize,
|
(unsigned long long) sysstatvfs.f_bsize,
|
||||||
(unsigned long long) sysstatvfs.f_frsize,
|
(unsigned long long) sysstatvfs.f_frsize,
|
||||||
(unsigned long long) sysstatvfs.f_blocks,
|
(unsigned long long) sysstatvfs.f_blocks,
|
||||||
(unsigned long long) sysstatvfs.f_bfree,
|
(unsigned long long) sysstatvfs.f_bfree,
|
||||||
(unsigned long long) sysstatvfs.f_bavail,
|
(unsigned long long) sysstatvfs.f_bavail,
|
||||||
(unsigned long long) sysstatvfs.f_files,
|
(unsigned long long) sysstatvfs.f_files,
|
||||||
(unsigned long long) sysstatvfs.f_ffree,
|
(unsigned long long) sysstatvfs.f_ffree,
|
||||||
(unsigned long long) sysstatvfs.f_favail,
|
(unsigned long long) sysstatvfs.f_favail,
|
||||||
(unsigned long long) sysstatvfs.f_fsid,
|
(unsigned long long) sysstatvfs.f_fsid,
|
||||||
(unsigned long long) sysstatvfs.f_flag,
|
(unsigned long long) sysstatvfs.f_flag,
|
||||||
(unsigned long long) sysstatvfs.f_namemax);
|
(unsigned long long) sysstatvfs.f_namemax);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* the connection is made */
|
/* the connection is made */
|
||||||
/* opening a directory */
|
/* opening a directory */
|
||||||
dir = sftp_opendir(sftp, "./");
|
dir=sftp_opendir(sftp,"./");
|
||||||
if (!dir) {
|
if(!dir) {
|
||||||
fprintf(stderr, "Directory not opened(%s)\n", ssh_get_error(session));
|
fprintf(stderr, "Directory not opened(%s)\n", ssh_get_error(session));
|
||||||
goto end;
|
return ;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* reading the whole directory, file by file */
|
/* reading the whole directory, file by file */
|
||||||
while ((file = sftp_readdir(sftp, dir))) {
|
while((file=sftp_readdir(sftp,dir))){
|
||||||
fprintf(stderr, "%30s(%.8o) : %s(%.5d) %s(%.5d) : %.10llu bytes\n",
|
fprintf(stderr, "%30s(%.8o) : %s(%.5d) %s(%.5d) : %.10llu bytes\n",
|
||||||
file->name,
|
file->name,
|
||||||
file->permissions,
|
file->permissions,
|
||||||
file->owner,
|
file->owner,
|
||||||
file->uid,
|
file->uid,
|
||||||
file->group,
|
file->group,
|
||||||
file->gid,
|
file->gid,
|
||||||
(long long unsigned int) file->size);
|
(long long unsigned int) file->size);
|
||||||
sftp_attributes_free(file);
|
sftp_attributes_free(file);
|
||||||
}
|
}
|
||||||
|
/* when file=NULL, an error has occured OR the directory listing is end of file */
|
||||||
/* when file = NULL, an error has occured OR the directory listing is end of
|
if(!sftp_dir_eof(dir)){
|
||||||
* file */
|
|
||||||
if (!sftp_dir_eof(dir)) {
|
|
||||||
fprintf(stderr, "Error: %s\n", ssh_get_error(session));
|
fprintf(stderr, "Error: %s\n", ssh_get_error(session));
|
||||||
goto end;
|
return;
|
||||||
}
|
}
|
||||||
|
if(sftp_closedir(dir)){
|
||||||
if (sftp_closedir(dir)) {
|
|
||||||
fprintf(stderr, "Error: %s\n", ssh_get_error(session));
|
fprintf(stderr, "Error: %s\n", ssh_get_error(session));
|
||||||
goto end;
|
return;
|
||||||
}
|
}
|
||||||
/* this will open a file and copy it into your /home directory */
|
/* this will open a file and copy it into your /home directory */
|
||||||
/* the small buffer size was intended to stress the library. of course, you
|
/* the small buffer size was intended to stress the library. of course, you can use a buffer till 20kbytes without problem */
|
||||||
* can use a buffer till 20kbytes without problem */
|
|
||||||
|
|
||||||
fichier = sftp_open(sftp, "/usr/bin/ssh", O_RDONLY, 0);
|
fichier=sftp_open(sftp,"/usr/bin/ssh",O_RDONLY, 0);
|
||||||
if (!fichier) {
|
if(!fichier){
|
||||||
fprintf(stderr, "Error opening /usr/bin/ssh: %s\n",
|
fprintf(stderr, "Error opening /usr/bin/ssh: %s\n",
|
||||||
ssh_get_error(session));
|
ssh_get_error(session));
|
||||||
goto end;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* open a file for writing... */
|
/* open a file for writing... */
|
||||||
to = sftp_open(sftp, "ssh-copy", O_WRONLY | O_CREAT, 0700);
|
to=sftp_open(sftp,"ssh-copy",O_WRONLY | O_CREAT, 0700);
|
||||||
if (!to) {
|
if(!to){
|
||||||
fprintf(stderr, "Error opening ssh-copy for writing: %s\n",
|
fprintf(stderr, "Error opening ssh-copy for writing: %s\n",
|
||||||
ssh_get_error(session));
|
ssh_get_error(session));
|
||||||
sftp_close(fichier);
|
return;
|
||||||
goto end;
|
|
||||||
}
|
}
|
||||||
|
while((len=sftp_read(fichier,data,4096)) > 0){
|
||||||
while ((len = sftp_read(fichier, data, 4096)) > 0) {
|
if(sftp_write(to,data,len)!=len){
|
||||||
if (sftp_write(to, data, len) != len) {
|
|
||||||
fprintf(stderr, "Error writing %d bytes: %s\n",
|
fprintf(stderr, "Error writing %d bytes: %s\n",
|
||||||
len, ssh_get_error(session));
|
len, ssh_get_error(session));
|
||||||
sftp_close(to);
|
return;
|
||||||
sftp_close(fichier);
|
|
||||||
goto end;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("finished\n");
|
printf("finished\n");
|
||||||
if (len < 0) {
|
if(len<0)
|
||||||
fprintf(stderr, "Error reading file: %s\n", ssh_get_error(session));
|
fprintf(stderr, "Error reading file: %s\n", ssh_get_error(session));
|
||||||
}
|
|
||||||
|
|
||||||
sftp_close(fichier);
|
sftp_close(fichier);
|
||||||
sftp_close(to);
|
sftp_close(to);
|
||||||
printf("fichiers ferm\n");
|
printf("fichiers ferm\n");
|
||||||
to = sftp_open(sftp, "/tmp/grosfichier", O_WRONLY|O_CREAT, 0644);
|
to=sftp_open(sftp,"/tmp/grosfichier",O_WRONLY|O_CREAT, 0644);
|
||||||
|
for(i=0;i<1000;++i){
|
||||||
for (i = 0; i < 1000; ++i) {
|
len=sftp_write(to,data,DATALEN);
|
||||||
len = sftp_write(to, data, DATALEN);
|
printf("wrote %d bytes\n",len);
|
||||||
printf("wrote %d bytes\n", len);
|
if(len != DATALEN){
|
||||||
if (len != DATALEN) {
|
printf("chunk %d : %d (%s)\n",i,len,ssh_get_error(session));
|
||||||
printf("chunk %d : %d (%s)\n", i, len, ssh_get_error(session));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sftp_close(to);
|
sftp_close(to);
|
||||||
end:
|
|
||||||
/* close the sftp session */
|
/* close the sftp session */
|
||||||
sftp_free(sftp);
|
sftp_free(sftp);
|
||||||
printf("sftp session terminated\n");
|
printf("sftp session terminated\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void usage(const char *argv0) {
|
static void usage(const char *argv0){
|
||||||
fprintf(stderr, "Usage : %s [-v] remotehost\n"
|
fprintf(stderr,"Usage : %s [-v] remotehost\n"
|
||||||
"sample sftp test client - libssh-%s\n"
|
"sample sftp test client - libssh-%s\n"
|
||||||
"Options :\n"
|
"Options :\n"
|
||||||
" -v : increase log verbosity\n",
|
" -v : increase log verbosity\n",
|
||||||
argv0,
|
argv0,
|
||||||
ssh_version(0));
|
ssh_version(0));
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int opts(int argc, char **argv) {
|
static int opts(int argc, char **argv){
|
||||||
int i;
|
int i;
|
||||||
|
while((i=getopt(argc,argv,"v"))!=-1){
|
||||||
while ((i = getopt(argc, argv, "v")) != -1) {
|
switch(i){
|
||||||
switch(i) {
|
case 'v':
|
||||||
case 'v':
|
verbosity++;
|
||||||
verbosity++;
|
break;
|
||||||
break;
|
default:
|
||||||
default:
|
fprintf(stderr,"unknown option %c\n",optopt);
|
||||||
fprintf(stderr, "unknown option %c\n", optopt);
|
|
||||||
usage(argv[0]);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
destination = argv[optind];
|
|
||||||
if (destination == NULL) {
|
|
||||||
usage(argv[0]);
|
usage(argv[0]);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return 0;
|
}
|
||||||
|
|
||||||
|
destination=argv[optind];
|
||||||
|
if(destination == NULL){
|
||||||
|
usage(argv[0]);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv){
|
||||||
ssh_session session;
|
ssh_session session;
|
||||||
|
if(opts(argc,argv)<0)
|
||||||
if (opts(argc, argv) < 0) {
|
return EXIT_FAILURE;
|
||||||
return EXIT_FAILURE;
|
session=connect_ssh(destination,NULL,verbosity);
|
||||||
}
|
if(session == NULL)
|
||||||
|
return EXIT_FAILURE;
|
||||||
session = connect_ssh(destination, NULL, verbosity);
|
do_sftp(session);
|
||||||
if (session == NULL) {
|
ssh_disconnect(session);
|
||||||
return EXIT_FAILURE;
|
ssh_free(session);
|
||||||
}
|
return 0;
|
||||||
|
|
||||||
do_sftp(session);
|
|
||||||
ssh_disconnect(session);
|
|
||||||
ssh_free(session);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,306 +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>
|
|
||||||
|
|
||||||
#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_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){
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
},
|
|
||||||
{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;
|
|
||||||
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[2048];
|
|
||||||
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, 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;
|
|
||||||
}
|
|
||||||
if (buf[0] == '\x0d') {
|
|
||||||
if (write(1, "\n", 1) < 0) {
|
|
||||||
printf("error writing to buffer\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
ssh_channel_write(chan, "\n", 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} while (i>0);
|
|
||||||
ssh_disconnect(session);
|
|
||||||
ssh_bind_free(sshbind);
|
|
||||||
ssh_finalize();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,425 +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>
|
|
||||||
|
|
||||||
#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[2048];
|
|
||||||
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, 2048, 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;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -22,12 +22,9 @@ program.
|
|||||||
#include <libssh/libssh.h>
|
#include <libssh/libssh.h>
|
||||||
#include "examples_common.h"
|
#include "examples_common.h"
|
||||||
|
|
||||||
static int verbosity = 0;
|
int verbosity=0;
|
||||||
static const char *createcommand =
|
const char *createcommand="rm -fr /tmp/libssh_tests && mkdir /tmp/libssh_tests && cd /tmp/libssh_tests && date > a && date > b && mkdir c && date > d";
|
||||||
"rm -fr /tmp/libssh_tests && mkdir /tmp/libssh_tests && "
|
char *host=NULL;
|
||||||
"cd /tmp/libssh_tests && date > a && date > b && mkdir c && date > d";
|
|
||||||
static char *host = NULL;
|
|
||||||
|
|
||||||
static void usage(const char *argv0){
|
static void usage(const char *argv0){
|
||||||
fprintf(stderr,"Usage : %s [options] host\n"
|
fprintf(stderr,"Usage : %s [options] host\n"
|
||||||
"sample tiny scp downloader client - libssh-%s\n"
|
"sample tiny scp downloader client - libssh-%s\n"
|
||||||
@@ -61,8 +58,6 @@ static int opts(int argc, char **argv){
|
|||||||
static void create_files(ssh_session session){
|
static void create_files(ssh_session session){
|
||||||
ssh_channel channel=ssh_channel_new(session);
|
ssh_channel channel=ssh_channel_new(session);
|
||||||
char buffer[1];
|
char buffer[1];
|
||||||
int rc;
|
|
||||||
|
|
||||||
if(channel == NULL){
|
if(channel == NULL){
|
||||||
fprintf(stderr,"Error creating channel: %s\n",ssh_get_error(session));
|
fprintf(stderr,"Error creating channel: %s\n",ssh_get_error(session));
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
@@ -79,16 +74,8 @@ static void create_files(ssh_session session){
|
|||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
while(!ssh_channel_is_eof(channel)){
|
while(!ssh_channel_is_eof(channel)){
|
||||||
rc = ssh_channel_read(channel,buffer,1,1);
|
ssh_channel_read(channel,buffer,1,1);
|
||||||
if (rc != 1) {
|
if (write(1,buffer,1) < 0) {
|
||||||
fprintf(stderr, "Error reading from channel\n");
|
|
||||||
ssh_channel_close(channel);
|
|
||||||
ssh_channel_free(channel);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = write(1, buffer, 1);
|
|
||||||
if (rc < 0) {
|
|
||||||
fprintf(stderr, "Error writing to buffer\n");
|
fprintf(stderr, "Error writing to buffer\n");
|
||||||
ssh_channel_close(channel);
|
ssh_channel_close(channel);
|
||||||
ssh_channel_free(channel);
|
ssh_channel_free(channel);
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
#include <libssh/libssh.h>
|
#include <libssh/libssh.h>
|
||||||
#include "examples_common.h"
|
#include "examples_common.h"
|
||||||
|
|
||||||
#define LIMIT 0x100000000UL
|
#define LIMIT 0x100000000
|
||||||
|
|
||||||
int main(void) {
|
int main(void) {
|
||||||
ssh_session session;
|
ssh_session session;
|
||||||
|
|||||||
@@ -1,407 +0,0 @@
|
|||||||
/* client.c */
|
|
||||||
/*
|
|
||||||
Copyright 2003-2009 Aris Adamantiadis
|
|
||||||
|
|
||||||
This file is part of the SSH Library
|
|
||||||
|
|
||||||
You are free to copy this file, modify it in any way, consider it being public
|
|
||||||
domain. This does not apply to the rest of the library though, but it is
|
|
||||||
allowed to cut-and-paste working code from this file to any license of
|
|
||||||
program.
|
|
||||||
The goal is to show the API in action. It's not a reference on how terminal
|
|
||||||
clients must be made or how a client should react.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include <sys/select.h>
|
|
||||||
#include <sys/time.h>
|
|
||||||
|
|
||||||
#ifdef HAVE_TERMIOS_H
|
|
||||||
#include <termios.h>
|
|
||||||
#endif
|
|
||||||
#ifdef HAVE_UNISTD_H
|
|
||||||
#include <unistd.h>
|
|
||||||
#endif
|
|
||||||
#ifdef HAVE_PTY_H
|
|
||||||
#include <pty.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <sys/ioctl.h>
|
|
||||||
#include <signal.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
|
|
||||||
#include <libssh/callbacks.h>
|
|
||||||
#include <libssh/libssh.h>
|
|
||||||
#include <libssh/sftp.h>
|
|
||||||
|
|
||||||
|
|
||||||
#include "examples_common.h"
|
|
||||||
#define MAXCMD 10
|
|
||||||
|
|
||||||
static char *host;
|
|
||||||
static char *user;
|
|
||||||
static char *cmds[MAXCMD];
|
|
||||||
static struct termios terminal;
|
|
||||||
|
|
||||||
static char *pcap_file = NULL;
|
|
||||||
|
|
||||||
static char *proxycommand;
|
|
||||||
|
|
||||||
static int auth_callback(const char *prompt,
|
|
||||||
char *buf,
|
|
||||||
size_t len,
|
|
||||||
int echo,
|
|
||||||
int verify,
|
|
||||||
void *userdata)
|
|
||||||
{
|
|
||||||
(void) verify;
|
|
||||||
(void) userdata;
|
|
||||||
|
|
||||||
return ssh_getpass(prompt, buf, len, echo, verify);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct ssh_callbacks_struct cb = {
|
|
||||||
.auth_function = auth_callback,
|
|
||||||
.userdata = NULL,
|
|
||||||
};
|
|
||||||
|
|
||||||
static void add_cmd(char *cmd)
|
|
||||||
{
|
|
||||||
int n;
|
|
||||||
|
|
||||||
for (n = 0; (n < MAXCMD) && cmds[n] != NULL; n++);
|
|
||||||
|
|
||||||
if (n == MAXCMD) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
cmds[n] = strdup(cmd);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void usage(void)
|
|
||||||
{
|
|
||||||
fprintf(stderr,
|
|
||||||
"Usage : ssh [options] [login@]hostname\n"
|
|
||||||
"sample client - libssh-%s\n"
|
|
||||||
"Options :\n"
|
|
||||||
" -l user : log in as user\n"
|
|
||||||
" -p port : connect to port\n"
|
|
||||||
" -d : use DSS to verify host public key\n"
|
|
||||||
" -r : use RSA to verify host public key\n"
|
|
||||||
#ifdef WITH_PCAP
|
|
||||||
" -P file : create a pcap debugging file\n"
|
|
||||||
#endif
|
|
||||||
#ifndef _WIN32
|
|
||||||
" -T proxycommand : command to execute as a socket proxy\n"
|
|
||||||
#endif
|
|
||||||
"\n",
|
|
||||||
ssh_version(0));
|
|
||||||
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int opts(int argc, char **argv)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
while((i = getopt(argc,argv,"T:P:")) != -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);
|
|
||||||
}
|
|
||||||
|
|
||||||
static ssh_channel chan;
|
|
||||||
static 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 = {
|
|
||||||
.ws_row = 0,
|
|
||||||
};
|
|
||||||
|
|
||||||
ioctl(1, TIOCGWINSZ, &win);
|
|
||||||
ssh_channel_change_pty_size(chan,win.ws_col, win.ws_row);
|
|
||||||
setsignal();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void select_loop(ssh_session session,ssh_channel channel)
|
|
||||||
{
|
|
||||||
ssh_connector connector_in, connector_out, connector_err;
|
|
||||||
|
|
||||||
ssh_event event = ssh_event_new();
|
|
||||||
|
|
||||||
/* stdin */
|
|
||||||
connector_in = ssh_connector_new(session);
|
|
||||||
ssh_connector_set_out_channel(connector_in, channel, SSH_CONNECTOR_STDOUT);
|
|
||||||
ssh_connector_set_in_fd(connector_in, 0);
|
|
||||||
ssh_event_add_connector(event, connector_in);
|
|
||||||
|
|
||||||
/* stdout */
|
|
||||||
connector_out = ssh_connector_new(session);
|
|
||||||
ssh_connector_set_out_fd(connector_out, 1);
|
|
||||||
ssh_connector_set_in_channel(connector_out, channel, SSH_CONNECTOR_STDOUT);
|
|
||||||
ssh_event_add_connector(event, connector_out);
|
|
||||||
|
|
||||||
/* stderr */
|
|
||||||
connector_err = ssh_connector_new(session);
|
|
||||||
ssh_connector_set_out_fd(connector_err, 2);
|
|
||||||
ssh_connector_set_in_channel(connector_err, channel, SSH_CONNECTOR_STDERR);
|
|
||||||
ssh_event_add_connector(event, connector_err);
|
|
||||||
|
|
||||||
while (ssh_channel_is_open(channel)) {
|
|
||||||
if (signal_delayed) {
|
|
||||||
sizechanged();
|
|
||||||
}
|
|
||||||
ssh_event_dopoll(event, 60000);
|
|
||||||
}
|
|
||||||
ssh_event_remove_connector(event, connector_in);
|
|
||||||
ssh_event_remove_connector(event, connector_out);
|
|
||||||
ssh_event_remove_connector(event, connector_err);
|
|
||||||
|
|
||||||
ssh_connector_free(connector_in);
|
|
||||||
ssh_connector_free(connector_out);
|
|
||||||
ssh_connector_free(connector_err);
|
|
||||||
|
|
||||||
ssh_event_free(event);
|
|
||||||
ssh_channel_free(channel);
|
|
||||||
}
|
|
||||||
|
|
||||||
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];
|
|
||||||
size_t i;
|
|
||||||
int s = 0;
|
|
||||||
|
|
||||||
for (i = 0; i < MAXCMD && cmds[i]; ++i) {
|
|
||||||
s += snprintf(buffer + s, sizeof(buffer) - s, "%s ", cmds[i]);
|
|
||||||
free(cmds[i]);
|
|
||||||
cmds[i] = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
channel = ssh_channel_new(session);
|
|
||||||
ssh_channel_open_session(channel);
|
|
||||||
if (ssh_channel_request_exec(channel, buffer)) {
|
|
||||||
printf("Error executing '%s' : %s\n", buffer, ssh_get_error(session));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
select_loop(session, channel);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int client(ssh_session session)
|
|
||||||
{
|
|
||||||
int auth = 0;
|
|
||||||
char *banner;
|
|
||||||
int state;
|
|
||||||
|
|
||||||
if (user) {
|
|
||||||
if (ssh_options_set(session, SSH_OPTIONS_USER, user) < 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (ssh_options_set(session, SSH_OPTIONS_HOST ,host) < 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (proxycommand != NULL) {
|
|
||||||
if (ssh_options_set(session, SSH_OPTIONS_PROXYCOMMAND, proxycommand)) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ssh_options_parse_config(session, NULL);
|
|
||||||
|
|
||||||
if (ssh_connect(session)) {
|
|
||||||
fprintf(stderr, "Connection failed : %s\n", ssh_get_error(session));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
state = verify_knownhost(session);
|
|
||||||
if (state != 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
ssh_userauth_none(session, NULL);
|
|
||||||
banner = ssh_get_issue_banner(session);
|
|
||||||
if (banner) {
|
|
||||||
printf("%s\n", banner);
|
|
||||||
free(banner);
|
|
||||||
}
|
|
||||||
auth = authenticate_console(session);
|
|
||||||
if (auth != SSH_AUTH_SUCCESS) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (cmds[0] == NULL) {
|
|
||||||
shell(session);
|
|
||||||
} else {
|
|
||||||
batch_shell(session);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static ssh_pcap_file pcap;
|
|
||||||
static void set_pcap(ssh_session session)
|
|
||||||
{
|
|
||||||
if (pcap_file == NULL) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
pcap = ssh_pcap_file_new();
|
|
||||||
if (pcap == NULL) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ssh_pcap_file_open(pcap, pcap_file) == SSH_ERROR) {
|
|
||||||
printf("Error opening pcap file\n");
|
|
||||||
ssh_pcap_file_free(pcap);
|
|
||||||
pcap = NULL;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
ssh_set_pcap_file(session, pcap);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void cleanup_pcap(void)
|
|
||||||
{
|
|
||||||
if (pcap != NULL) {
|
|
||||||
ssh_pcap_file_free(pcap);
|
|
||||||
}
|
|
||||||
pcap = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
|
||||||
{
|
|
||||||
ssh_session session;
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
@@ -1,708 +0,0 @@
|
|||||||
/* This is a sample implementation of a libssh based SSH server */
|
|
||||||
/*
|
|
||||||
Copyright 2014 Audrius Butkevicius
|
|
||||||
|
|
||||||
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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
#include <libssh/callbacks.h>
|
|
||||||
#include <libssh/server.h>
|
|
||||||
|
|
||||||
#include <poll.h>
|
|
||||||
#ifdef HAVE_ARGP_H
|
|
||||||
#include <argp.h>
|
|
||||||
#endif
|
|
||||||
#include <fcntl.h>
|
|
||||||
#ifdef HAVE_LIBUTIL_H
|
|
||||||
#include <libutil.h>
|
|
||||||
#endif
|
|
||||||
#ifdef HAVE_PTY_H
|
|
||||||
#include <pty.h>
|
|
||||||
#endif
|
|
||||||
#include <signal.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#ifdef HAVE_UTMP_H
|
|
||||||
#include <utmp.h>
|
|
||||||
#endif
|
|
||||||
#ifdef HAVE_UTIL_H
|
|
||||||
#include <util.h>
|
|
||||||
#endif
|
|
||||||
#include <sys/ioctl.h>
|
|
||||||
#include <sys/wait.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#ifndef KEYS_FOLDER
|
|
||||||
#ifdef _WIN32
|
|
||||||
#define KEYS_FOLDER
|
|
||||||
#else
|
|
||||||
#define KEYS_FOLDER "/etc/ssh/"
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define USER "myuser"
|
|
||||||
#define PASS "mypassword"
|
|
||||||
#define BUF_SIZE 1048576
|
|
||||||
#define SESSION_END (SSH_CLOSED | SSH_CLOSED_ERROR)
|
|
||||||
#define SFTP_SERVER_PATH "/usr/lib/sftp-server"
|
|
||||||
|
|
||||||
static void set_default_keys(ssh_bind sshbind,
|
|
||||||
int rsa_already_set,
|
|
||||||
int dsa_already_set,
|
|
||||||
int ecdsa_already_set) {
|
|
||||||
if (!rsa_already_set) {
|
|
||||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_RSAKEY,
|
|
||||||
KEYS_FOLDER "ssh_host_rsa_key");
|
|
||||||
}
|
|
||||||
if (!dsa_already_set) {
|
|
||||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_DSAKEY,
|
|
||||||
KEYS_FOLDER "ssh_host_dsa_key");
|
|
||||||
}
|
|
||||||
if (!ecdsa_already_set) {
|
|
||||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_ECDSAKEY,
|
|
||||||
KEYS_FOLDER "ssh_host_ecdsa_key");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#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 a host key. Can be used multiple times. "
|
|
||||||
"Implies no default keys.",
|
|
||||||
.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 = "ecdsakey",
|
|
||||||
.key = 'e',
|
|
||||||
.arg = "FILE",
|
|
||||||
.flags = 0,
|
|
||||||
.doc = "Set the ecdsa key.",
|
|
||||||
.group = 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.name = "no-default-keys",
|
|
||||||
.key = 'n',
|
|
||||||
.arg = NULL,
|
|
||||||
.flags = 0,
|
|
||||||
.doc = "Do not set default key locations.",
|
|
||||||
.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;
|
|
||||||
static int no_default_keys = 0;
|
|
||||||
static int rsa_already_set = 0, dsa_already_set = 0, ecdsa_already_set = 0;
|
|
||||||
|
|
||||||
switch (key) {
|
|
||||||
case 'n':
|
|
||||||
no_default_keys = 1;
|
|
||||||
break;
|
|
||||||
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);
|
|
||||||
dsa_already_set = 1;
|
|
||||||
break;
|
|
||||||
case 'k':
|
|
||||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_HOSTKEY, arg);
|
|
||||||
/* We can't track the types of keys being added with this
|
|
||||||
option, so let's ensure we keep the keys we're adding
|
|
||||||
by just not setting the default keys */
|
|
||||||
no_default_keys = 1;
|
|
||||||
break;
|
|
||||||
case 'r':
|
|
||||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_RSAKEY, arg);
|
|
||||||
rsa_already_set = 1;
|
|
||||||
break;
|
|
||||||
case 'e':
|
|
||||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_ECDSAKEY, arg);
|
|
||||||
ecdsa_already_set = 1;
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!no_default_keys) {
|
|
||||||
set_default_keys(sshbind,
|
|
||||||
rsa_already_set,
|
|
||||||
dsa_already_set,
|
|
||||||
ecdsa_already_set);
|
|
||||||
}
|
|
||||||
|
|
||||||
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 */
|
|
||||||
|
|
||||||
/* A userdata struct for channel. */
|
|
||||||
struct channel_data_struct {
|
|
||||||
/* pid of the child process the channel will spawn. */
|
|
||||||
pid_t pid;
|
|
||||||
/* For PTY allocation */
|
|
||||||
socket_t pty_master;
|
|
||||||
socket_t pty_slave;
|
|
||||||
/* For communication with the child process. */
|
|
||||||
socket_t child_stdin;
|
|
||||||
socket_t child_stdout;
|
|
||||||
/* Only used for subsystem and exec requests. */
|
|
||||||
socket_t child_stderr;
|
|
||||||
/* Event which is used to poll the above descriptors. */
|
|
||||||
ssh_event event;
|
|
||||||
/* Terminal size struct. */
|
|
||||||
struct winsize *winsize;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* A userdata struct for session. */
|
|
||||||
struct session_data_struct {
|
|
||||||
/* Pointer to the channel the session will allocate. */
|
|
||||||
ssh_channel channel;
|
|
||||||
int auth_attempts;
|
|
||||||
int authenticated;
|
|
||||||
};
|
|
||||||
|
|
||||||
static int data_function(ssh_session session, ssh_channel channel, void *data,
|
|
||||||
uint32_t len, int is_stderr, void *userdata) {
|
|
||||||
struct channel_data_struct *cdata = (struct channel_data_struct *) userdata;
|
|
||||||
|
|
||||||
(void) session;
|
|
||||||
(void) channel;
|
|
||||||
(void) is_stderr;
|
|
||||||
|
|
||||||
if (len == 0 || cdata->pid < 1 || kill(cdata->pid, 0) < 0) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return write(cdata->child_stdin, (char *) data, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int pty_request(ssh_session session, ssh_channel channel,
|
|
||||||
const char *term, int cols, int rows, int py, int px,
|
|
||||||
void *userdata) {
|
|
||||||
struct channel_data_struct *cdata = (struct channel_data_struct *)userdata;
|
|
||||||
|
|
||||||
(void) session;
|
|
||||||
(void) channel;
|
|
||||||
(void) term;
|
|
||||||
|
|
||||||
cdata->winsize->ws_row = rows;
|
|
||||||
cdata->winsize->ws_col = cols;
|
|
||||||
cdata->winsize->ws_xpixel = px;
|
|
||||||
cdata->winsize->ws_ypixel = py;
|
|
||||||
|
|
||||||
if (openpty(&cdata->pty_master, &cdata->pty_slave, NULL, NULL,
|
|
||||||
cdata->winsize) != 0) {
|
|
||||||
fprintf(stderr, "Failed to open pty\n");
|
|
||||||
return SSH_ERROR;
|
|
||||||
}
|
|
||||||
return SSH_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int pty_resize(ssh_session session, ssh_channel channel, int cols,
|
|
||||||
int rows, int py, int px, void *userdata) {
|
|
||||||
struct channel_data_struct *cdata = (struct channel_data_struct *)userdata;
|
|
||||||
|
|
||||||
(void) session;
|
|
||||||
(void) channel;
|
|
||||||
|
|
||||||
cdata->winsize->ws_row = rows;
|
|
||||||
cdata->winsize->ws_col = cols;
|
|
||||||
cdata->winsize->ws_xpixel = px;
|
|
||||||
cdata->winsize->ws_ypixel = py;
|
|
||||||
|
|
||||||
if (cdata->pty_master != -1) {
|
|
||||||
return ioctl(cdata->pty_master, TIOCSWINSZ, cdata->winsize);
|
|
||||||
}
|
|
||||||
|
|
||||||
return SSH_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int exec_pty(const char *mode, const char *command,
|
|
||||||
struct channel_data_struct *cdata) {
|
|
||||||
switch(cdata->pid = fork()) {
|
|
||||||
case -1:
|
|
||||||
close(cdata->pty_master);
|
|
||||||
close(cdata->pty_slave);
|
|
||||||
fprintf(stderr, "Failed to fork\n");
|
|
||||||
return SSH_ERROR;
|
|
||||||
case 0:
|
|
||||||
close(cdata->pty_master);
|
|
||||||
if (login_tty(cdata->pty_slave) != 0) {
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
execl("/bin/sh", "sh", mode, command, NULL);
|
|
||||||
exit(0);
|
|
||||||
default:
|
|
||||||
close(cdata->pty_slave);
|
|
||||||
/* pty fd is bi-directional */
|
|
||||||
cdata->child_stdout = cdata->child_stdin = cdata->pty_master;
|
|
||||||
}
|
|
||||||
return SSH_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int exec_nopty(const char *command, struct channel_data_struct *cdata) {
|
|
||||||
int in[2], out[2], err[2];
|
|
||||||
|
|
||||||
/* Do the plumbing to be able to talk with the child process. */
|
|
||||||
if (pipe(in) != 0) {
|
|
||||||
goto stdin_failed;
|
|
||||||
}
|
|
||||||
if (pipe(out) != 0) {
|
|
||||||
goto stdout_failed;
|
|
||||||
}
|
|
||||||
if (pipe(err) != 0) {
|
|
||||||
goto stderr_failed;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch(cdata->pid = fork()) {
|
|
||||||
case -1:
|
|
||||||
goto fork_failed;
|
|
||||||
case 0:
|
|
||||||
/* Finish the plumbing in the child process. */
|
|
||||||
close(in[1]);
|
|
||||||
close(out[0]);
|
|
||||||
close(err[0]);
|
|
||||||
dup2(in[0], STDIN_FILENO);
|
|
||||||
dup2(out[1], STDOUT_FILENO);
|
|
||||||
dup2(err[1], STDERR_FILENO);
|
|
||||||
close(in[0]);
|
|
||||||
close(out[1]);
|
|
||||||
close(err[1]);
|
|
||||||
/* exec the requested command. */
|
|
||||||
execl("/bin/sh", "sh", "-c", command, NULL);
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
close(in[0]);
|
|
||||||
close(out[1]);
|
|
||||||
close(err[1]);
|
|
||||||
|
|
||||||
cdata->child_stdin = in[1];
|
|
||||||
cdata->child_stdout = out[0];
|
|
||||||
cdata->child_stderr = err[0];
|
|
||||||
|
|
||||||
return SSH_OK;
|
|
||||||
|
|
||||||
fork_failed:
|
|
||||||
close(err[0]);
|
|
||||||
close(err[1]);
|
|
||||||
stderr_failed:
|
|
||||||
close(out[0]);
|
|
||||||
close(out[1]);
|
|
||||||
stdout_failed:
|
|
||||||
close(in[0]);
|
|
||||||
close(in[1]);
|
|
||||||
stdin_failed:
|
|
||||||
return SSH_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int exec_request(ssh_session session, ssh_channel channel,
|
|
||||||
const char *command, void *userdata) {
|
|
||||||
struct channel_data_struct *cdata = (struct channel_data_struct *) userdata;
|
|
||||||
|
|
||||||
|
|
||||||
(void) session;
|
|
||||||
(void) channel;
|
|
||||||
|
|
||||||
if(cdata->pid > 0) {
|
|
||||||
return SSH_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cdata->pty_master != -1 && cdata->pty_slave != -1) {
|
|
||||||
return exec_pty("-c", command, cdata);
|
|
||||||
}
|
|
||||||
return exec_nopty(command, cdata);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int shell_request(ssh_session session, ssh_channel channel,
|
|
||||||
void *userdata) {
|
|
||||||
struct channel_data_struct *cdata = (struct channel_data_struct *) userdata;
|
|
||||||
|
|
||||||
(void) session;
|
|
||||||
(void) channel;
|
|
||||||
|
|
||||||
if(cdata->pid > 0) {
|
|
||||||
return SSH_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cdata->pty_master != -1 && cdata->pty_slave != -1) {
|
|
||||||
return exec_pty("-l", NULL, cdata);
|
|
||||||
}
|
|
||||||
/* Client requested a shell without a pty, let's pretend we allow that */
|
|
||||||
return SSH_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int subsystem_request(ssh_session session, ssh_channel channel,
|
|
||||||
const char *subsystem, void *userdata) {
|
|
||||||
/* subsystem requests behave simillarly to exec requests. */
|
|
||||||
if (strcmp(subsystem, "sftp") == 0) {
|
|
||||||
return exec_request(session, channel, SFTP_SERVER_PATH, userdata);
|
|
||||||
}
|
|
||||||
return SSH_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int auth_password(ssh_session session, const char *user,
|
|
||||||
const char *pass, void *userdata) {
|
|
||||||
struct session_data_struct *sdata = (struct session_data_struct *) userdata;
|
|
||||||
|
|
||||||
(void) session;
|
|
||||||
|
|
||||||
if (strcmp(user, USER) == 0 && strcmp(pass, PASS) == 0) {
|
|
||||||
sdata->authenticated = 1;
|
|
||||||
return SSH_AUTH_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
sdata->auth_attempts++;
|
|
||||||
return SSH_AUTH_DENIED;
|
|
||||||
}
|
|
||||||
|
|
||||||
static ssh_channel channel_open(ssh_session session, void *userdata) {
|
|
||||||
struct session_data_struct *sdata = (struct session_data_struct *) userdata;
|
|
||||||
|
|
||||||
sdata->channel = ssh_channel_new(session);
|
|
||||||
return sdata->channel;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int process_stdout(socket_t fd, int revents, void *userdata) {
|
|
||||||
char buf[BUF_SIZE];
|
|
||||||
int n = -1;
|
|
||||||
ssh_channel channel = (ssh_channel) userdata;
|
|
||||||
|
|
||||||
if (channel != NULL && (revents & POLLIN) != 0) {
|
|
||||||
n = read(fd, buf, BUF_SIZE);
|
|
||||||
if (n > 0) {
|
|
||||||
ssh_channel_write(channel, buf, n);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int process_stderr(socket_t fd, int revents, void *userdata) {
|
|
||||||
char buf[BUF_SIZE];
|
|
||||||
int n = -1;
|
|
||||||
ssh_channel channel = (ssh_channel) userdata;
|
|
||||||
|
|
||||||
if (channel != NULL && (revents & POLLIN) != 0) {
|
|
||||||
n = read(fd, buf, BUF_SIZE);
|
|
||||||
if (n > 0) {
|
|
||||||
ssh_channel_write_stderr(channel, buf, n);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void handle_session(ssh_event event, ssh_session session) {
|
|
||||||
int n;
|
|
||||||
int rc = 0;
|
|
||||||
|
|
||||||
/* Structure for storing the pty size. */
|
|
||||||
struct winsize wsize = {
|
|
||||||
.ws_row = 0,
|
|
||||||
.ws_col = 0,
|
|
||||||
.ws_xpixel = 0,
|
|
||||||
.ws_ypixel = 0
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Our struct holding information about the channel. */
|
|
||||||
struct channel_data_struct cdata = {
|
|
||||||
.pid = 0,
|
|
||||||
.pty_master = -1,
|
|
||||||
.pty_slave = -1,
|
|
||||||
.child_stdin = -1,
|
|
||||||
.child_stdout = -1,
|
|
||||||
.child_stderr = -1,
|
|
||||||
.event = NULL,
|
|
||||||
.winsize = &wsize
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Our struct holding information about the session. */
|
|
||||||
struct session_data_struct sdata = {
|
|
||||||
.channel = NULL,
|
|
||||||
.auth_attempts = 0,
|
|
||||||
.authenticated = 0
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ssh_channel_callbacks_struct channel_cb = {
|
|
||||||
.userdata = &cdata,
|
|
||||||
.channel_pty_request_function = pty_request,
|
|
||||||
.channel_pty_window_change_function = pty_resize,
|
|
||||||
.channel_shell_request_function = shell_request,
|
|
||||||
.channel_exec_request_function = exec_request,
|
|
||||||
.channel_data_function = data_function,
|
|
||||||
.channel_subsystem_request_function = subsystem_request
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ssh_server_callbacks_struct server_cb = {
|
|
||||||
.userdata = &sdata,
|
|
||||||
.auth_password_function = auth_password,
|
|
||||||
.channel_open_request_session_function = channel_open,
|
|
||||||
};
|
|
||||||
|
|
||||||
ssh_callbacks_init(&server_cb);
|
|
||||||
ssh_callbacks_init(&channel_cb);
|
|
||||||
|
|
||||||
ssh_set_server_callbacks(session, &server_cb);
|
|
||||||
|
|
||||||
if (ssh_handle_key_exchange(session) != SSH_OK) {
|
|
||||||
fprintf(stderr, "%s\n", ssh_get_error(session));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ssh_set_auth_methods(session, SSH_AUTH_METHOD_PASSWORD);
|
|
||||||
ssh_event_add_session(event, session);
|
|
||||||
|
|
||||||
n = 0;
|
|
||||||
while (sdata.authenticated == 0 || sdata.channel == NULL) {
|
|
||||||
/* If the user has used up all attempts, or if he hasn't been able to
|
|
||||||
* authenticate in 10 seconds (n * 100ms), disconnect. */
|
|
||||||
if (sdata.auth_attempts >= 3 || n >= 100) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ssh_event_dopoll(event, 100) == SSH_ERROR) {
|
|
||||||
fprintf(stderr, "%s\n", ssh_get_error(session));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
n++;
|
|
||||||
}
|
|
||||||
|
|
||||||
ssh_set_channel_callbacks(sdata.channel, &channel_cb);
|
|
||||||
|
|
||||||
do {
|
|
||||||
/* Poll the main event which takes care of the session, the channel and
|
|
||||||
* even our child process's stdout/stderr (once it's started). */
|
|
||||||
if (ssh_event_dopoll(event, -1) == SSH_ERROR) {
|
|
||||||
ssh_channel_close(sdata.channel);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If child process's stdout/stderr has been registered with the event,
|
|
||||||
* or the child process hasn't started yet, continue. */
|
|
||||||
if (cdata.event != NULL || cdata.pid == 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
/* Executed only once, once the child process starts. */
|
|
||||||
cdata.event = event;
|
|
||||||
/* If stdout valid, add stdout to be monitored by the poll event. */
|
|
||||||
if (cdata.child_stdout != -1) {
|
|
||||||
if (ssh_event_add_fd(event, cdata.child_stdout, POLLIN, process_stdout,
|
|
||||||
sdata.channel) != SSH_OK) {
|
|
||||||
fprintf(stderr, "Failed to register stdout to poll context\n");
|
|
||||||
ssh_channel_close(sdata.channel);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If stderr valid, add stderr to be monitored by the poll event. */
|
|
||||||
if (cdata.child_stderr != -1){
|
|
||||||
if (ssh_event_add_fd(event, cdata.child_stderr, POLLIN, process_stderr,
|
|
||||||
sdata.channel) != SSH_OK) {
|
|
||||||
fprintf(stderr, "Failed to register stderr to poll context\n");
|
|
||||||
ssh_channel_close(sdata.channel);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} while(ssh_channel_is_open(sdata.channel) &&
|
|
||||||
(cdata.pid == 0 || waitpid(cdata.pid, &rc, WNOHANG) == 0));
|
|
||||||
|
|
||||||
close(cdata.pty_master);
|
|
||||||
close(cdata.child_stdin);
|
|
||||||
close(cdata.child_stdout);
|
|
||||||
close(cdata.child_stderr);
|
|
||||||
|
|
||||||
/* Remove the descriptors from the polling context, since they are now
|
|
||||||
* closed, they will always trigger during the poll calls. */
|
|
||||||
ssh_event_remove_fd(event, cdata.child_stdout);
|
|
||||||
ssh_event_remove_fd(event, cdata.child_stderr);
|
|
||||||
|
|
||||||
/* If the child process exited. */
|
|
||||||
if (kill(cdata.pid, 0) < 0 && WIFEXITED(rc)) {
|
|
||||||
rc = WEXITSTATUS(rc);
|
|
||||||
ssh_channel_request_send_exit_status(sdata.channel, rc);
|
|
||||||
/* If client terminated the channel or the process did not exit nicely,
|
|
||||||
* but only if something has been forked. */
|
|
||||||
} else if (cdata.pid > 0) {
|
|
||||||
kill(cdata.pid, SIGKILL);
|
|
||||||
}
|
|
||||||
|
|
||||||
ssh_channel_send_eof(sdata.channel);
|
|
||||||
ssh_channel_close(sdata.channel);
|
|
||||||
|
|
||||||
/* Wait up to 5 seconds for the client to terminate the session. */
|
|
||||||
for (n = 0; n < 50 && (ssh_get_status(session) & SESSION_END) == 0; n++) {
|
|
||||||
ssh_event_dopoll(event, 100);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* SIGCHLD handler for cleaning up dead children. */
|
|
||||||
static void sigchld_handler(int signo) {
|
|
||||||
(void) signo;
|
|
||||||
while (waitpid(-1, NULL, WNOHANG) > 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
|
||||||
ssh_bind sshbind;
|
|
||||||
ssh_session session;
|
|
||||||
ssh_event event;
|
|
||||||
struct sigaction sa;
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
/* Set up SIGCHLD handler. */
|
|
||||||
sa.sa_handler = sigchld_handler;
|
|
||||||
sigemptyset(&sa.sa_mask);
|
|
||||||
sa.sa_flags = SA_RESTART | SA_NOCLDSTOP;
|
|
||||||
if (sigaction(SIGCHLD, &sa, NULL) != 0) {
|
|
||||||
fprintf(stderr, "Failed to register SIGCHLD handler\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = ssh_init();
|
|
||||||
if (rc < 0) {
|
|
||||||
fprintf(stderr, "ssh_init failed\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
sshbind = ssh_bind_new();
|
|
||||||
if (sshbind == NULL) {
|
|
||||||
fprintf(stderr, "ssh_bind_new failed\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef HAVE_ARGP_H
|
|
||||||
argp_parse(&argp, argc, argv, 0, 0, sshbind);
|
|
||||||
#else
|
|
||||||
(void) argc;
|
|
||||||
(void) argv;
|
|
||||||
|
|
||||||
set_default_keys(sshbind, 0, 0, 0);
|
|
||||||
#endif /* HAVE_ARGP_H */
|
|
||||||
|
|
||||||
if(ssh_bind_listen(sshbind) < 0) {
|
|
||||||
fprintf(stderr, "%s\n", ssh_get_error(sshbind));
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (1) {
|
|
||||||
session = ssh_new();
|
|
||||||
if (session == NULL) {
|
|
||||||
fprintf(stderr, "Failed to allocate session\n");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Blocks until there is a new incoming connection. */
|
|
||||||
if(ssh_bind_accept(sshbind, session) != SSH_ERROR) {
|
|
||||||
switch(fork()) {
|
|
||||||
case 0:
|
|
||||||
/* Remove the SIGCHLD handler inherited from parent. */
|
|
||||||
sa.sa_handler = SIG_DFL;
|
|
||||||
sigaction(SIGCHLD, &sa, NULL);
|
|
||||||
/* Remove socket binding, which allows us to restart the
|
|
||||||
* parent process, without terminating existing sessions. */
|
|
||||||
ssh_bind_free(sshbind);
|
|
||||||
|
|
||||||
event = ssh_event_new();
|
|
||||||
if (event != NULL) {
|
|
||||||
/* Blocks until the SSH session ends by either
|
|
||||||
* child process exiting, or client disconnecting. */
|
|
||||||
handle_session(event, session);
|
|
||||||
ssh_event_free(event);
|
|
||||||
} else {
|
|
||||||
fprintf(stderr, "Could not create polling context\n");
|
|
||||||
}
|
|
||||||
ssh_disconnect(session);
|
|
||||||
ssh_free(session);
|
|
||||||
|
|
||||||
exit(0);
|
|
||||||
case -1:
|
|
||||||
fprintf(stderr, "Failed to fork\n");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
fprintf(stderr, "%s\n", ssh_get_error(sshbind));
|
|
||||||
}
|
|
||||||
/* Since the session has been passed to a child fork, do some cleaning
|
|
||||||
* up at the parent process. */
|
|
||||||
ssh_disconnect(session);
|
|
||||||
ssh_free(session);
|
|
||||||
}
|
|
||||||
|
|
||||||
ssh_bind_free(sshbind);
|
|
||||||
ssh_finalize();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
@@ -13,14 +13,10 @@ clients must be made or how a client should react.
|
|||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#ifdef HAVE_TERMIOS_H
|
|
||||||
#include <termios.h>
|
#include <termios.h>
|
||||||
#endif
|
|
||||||
#ifdef HAVE_UNISTD_H
|
|
||||||
#include <unistd.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <sys/select.h>
|
#include <sys/select.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
@@ -43,8 +39,7 @@ const char *port="22";
|
|||||||
char *pcap_file=NULL;
|
char *pcap_file=NULL;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void usage(void)
|
static void usage(){
|
||||||
{
|
|
||||||
fprintf(stderr,"Usage : sshnetcat [user@]host forwarded_host forwarded_port\n");
|
fprintf(stderr,"Usage : sshnetcat [user@]host forwarded_host forwarded_port\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
@@ -88,24 +83,13 @@ static void select_loop(ssh_session session,ssh_channel channel){
|
|||||||
int ret;
|
int ret;
|
||||||
while(channel){
|
while(channel){
|
||||||
do{
|
do{
|
||||||
int fd;
|
|
||||||
|
|
||||||
ZERO_STRUCT(fds);
|
|
||||||
FD_ZERO(&fds);
|
FD_ZERO(&fds);
|
||||||
if(!eof)
|
if(!eof)
|
||||||
FD_SET(0,&fds);
|
FD_SET(0,&fds);
|
||||||
timeout.tv_sec=30;
|
timeout.tv_sec=30;
|
||||||
timeout.tv_usec=0;
|
timeout.tv_usec=0;
|
||||||
|
FD_SET(ssh_get_fd(session),&fds);
|
||||||
fd = ssh_get_fd(session);
|
maxfd=ssh_get_fd(session)+1;
|
||||||
if (fd == -1) {
|
|
||||||
fprintf(stderr, "Error getting the session file descriptor: %s\n",
|
|
||||||
ssh_get_error(session));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
FD_SET(fd, &fds);
|
|
||||||
maxfd = fd + 1;
|
|
||||||
|
|
||||||
channels[0]=channel; // set the first channel we want to read from
|
channels[0]=channel; // set the first channel we want to read from
|
||||||
channels[1]=NULL;
|
channels[1]=NULL;
|
||||||
ret=ssh_select(channels,outchannels,maxfd,&fds,&timeout);
|
ret=ssh_select(channels,outchannels,maxfd,&fds,&timeout);
|
||||||
@@ -114,27 +98,32 @@ static void select_loop(ssh_session session,ssh_channel channel){
|
|||||||
if(FD_ISSET(0,&fds)){
|
if(FD_ISSET(0,&fds)){
|
||||||
lus=read(0,buffer,sizeof(buffer));
|
lus=read(0,buffer,sizeof(buffer));
|
||||||
if(lus)
|
if(lus)
|
||||||
ssh_channel_write(channel,buffer,lus);
|
channel_write(channel,buffer,lus);
|
||||||
else {
|
else {
|
||||||
eof=1;
|
eof=1;
|
||||||
ssh_channel_send_eof(channel);
|
channel_send_eof(channel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(channel && ssh_channel_is_closed(channel)){
|
if(channel && channel_is_closed(channel)){
|
||||||
ssh_channel_free(channel);
|
ssh_log(session,SSH_LOG_RARE,"exit-status : %d\n",channel_get_exit_status(channel));
|
||||||
|
|
||||||
|
channel_free(channel);
|
||||||
channel=NULL;
|
channel=NULL;
|
||||||
channels[0]=NULL;
|
channels[0]=NULL;
|
||||||
}
|
}
|
||||||
if(outchannels[0]){
|
if(outchannels[0]){
|
||||||
while(channel && ssh_channel_is_open(channel) && ssh_channel_poll(channel,0)){
|
while(channel && channel_is_open(channel) && channel_poll(channel,0)){
|
||||||
lus = ssh_channel_read(channel,buffer,sizeof(buffer),0);
|
lus=channel_read(channel,buffer,sizeof(buffer),0);
|
||||||
if(lus==-1){
|
if(lus==-1){
|
||||||
fprintf(stderr, "Error reading channel: %s\n",
|
fprintf(stderr, "Error reading channel: %s\n",
|
||||||
ssh_get_error(session));
|
ssh_get_error(session));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(lus==0){
|
if(lus==0){
|
||||||
ssh_channel_free(channel);
|
ssh_log(session,SSH_LOG_RARE,"EOF received\n");
|
||||||
|
ssh_log(session,SSH_LOG_RARE,"exit-status : %d\n",channel_get_exit_status(channel));
|
||||||
|
|
||||||
|
channel_free(channel);
|
||||||
channel=channels[0]=NULL;
|
channel=channels[0]=NULL;
|
||||||
} else {
|
} else {
|
||||||
ret = write(1, buffer, lus);
|
ret = write(1, buffer, lus);
|
||||||
@@ -145,28 +134,29 @@ static void select_loop(ssh_session session,ssh_channel channel){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
while(channel && ssh_channel_is_open(channel) && ssh_channel_poll(channel,1)){ /* stderr */
|
while(channel && channel_is_open(channel) && channel_poll(channel,1)){ /* stderr */
|
||||||
lus = ssh_channel_read(channel, buffer, sizeof(buffer), 1);
|
lus=channel_read(channel,buffer,sizeof(buffer),1);
|
||||||
if(lus==-1){
|
if(lus==-1){
|
||||||
fprintf(stderr, "Error reading channel: %s\n",
|
fprintf(stderr, "Error reading channel: %s\n",
|
||||||
ssh_get_error(session));
|
ssh_get_error(session));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(lus==0){
|
if(lus==0){
|
||||||
ssh_channel_free(channel);
|
ssh_log(session,SSH_LOG_RARE,"EOF received\n");
|
||||||
|
ssh_log(session,SSH_LOG_RARE,"exit-status : %d\n",channel_get_exit_status(channel));
|
||||||
|
channel_free(channel);
|
||||||
channel=channels[0]=NULL;
|
channel=channels[0]=NULL;
|
||||||
} else {
|
} else
|
||||||
ret = write(2, buffer, lus);
|
ret = write(2, buffer, lus);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
fprintf(stderr, "Error writing to stderr: %s",
|
fprintf(stderr, "Error writing to stderr: %s",
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(channel && ssh_channel_is_closed(channel)){
|
if(channel && channel_is_closed(channel)){
|
||||||
ssh_channel_free(channel);
|
channel_free(channel);
|
||||||
channel=NULL;
|
channel=NULL;
|
||||||
}
|
}
|
||||||
} while (ret==EINTR || ret==SSH_EINTR);
|
} while (ret==EINTR || ret==SSH_EINTR);
|
||||||
@@ -177,8 +167,8 @@ static void select_loop(ssh_session session,ssh_channel channel){
|
|||||||
static void forwarding(ssh_session session){
|
static void forwarding(ssh_session session){
|
||||||
ssh_channel channel;
|
ssh_channel channel;
|
||||||
int r;
|
int r;
|
||||||
channel = ssh_channel_new(session);
|
channel=channel_new(session);
|
||||||
r = ssh_channel_open_forward(channel, desthost, atoi(port), "localhost", 22);
|
r=channel_open_forward(channel,desthost,atoi(port),"localhost",22);
|
||||||
if(r<0) {
|
if(r<0) {
|
||||||
printf("error forwarding port : %s\n",ssh_get_error(session));
|
printf("error forwarding port : %s\n",ssh_get_error(session));
|
||||||
return;
|
return;
|
||||||
@@ -212,6 +202,7 @@ static int client(ssh_session session){
|
|||||||
if(auth != SSH_AUTH_SUCCESS){
|
if(auth != SSH_AUTH_SUCCESS){
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
ssh_log(session, SSH_LOG_FUNCTIONS, "Authentication success");
|
||||||
forwarding(session);
|
forwarding(session);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
project(libssh-headers-x C)
|
project(headers C)
|
||||||
|
|
||||||
add_subdirectory(libssh)
|
add_subdirectory(libssh)
|
||||||
|
|||||||