Compare commits
322 Commits
libssh-0.1
...
libssh-0.8
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
789df0b7d0 | ||
|
|
66a222a73c | ||
|
|
09a7638575 | ||
|
|
203818608a | ||
|
|
f8c452cbef | ||
|
|
adeaa69cc5 | ||
|
|
72bce5ece7 | ||
|
|
7819621fc2 | ||
|
|
fcfba0d8aa | ||
|
|
b166ac4749 | ||
|
|
160a416ef6 | ||
|
|
59071bc4c5 | ||
|
|
2ae63251d3 | ||
|
|
eefae820b5 | ||
|
|
0792fb37b0 | ||
|
|
e23c28a82b | ||
|
|
7291b50420 | ||
|
|
c1d61617fb | ||
|
|
488fb47c32 | ||
|
|
721132696c | ||
|
|
ee034e0484 | ||
|
|
d56c8fdfc6 | ||
|
|
4269b62153 | ||
|
|
c6c63030c5 | ||
|
|
afa5dbb8b1 | ||
|
|
bd7e8295e2 | ||
|
|
933d9c6b07 | ||
|
|
0f0eb05e03 | ||
|
|
171a950a80 | ||
|
|
b1b1da0f97 | ||
|
|
7453038d74 | ||
|
|
29ef92a95e | ||
|
|
6650685758 | ||
|
|
bdca6b7efa | ||
|
|
97b2a61d74 | ||
|
|
781ce47dea | ||
|
|
277ee932d6 | ||
|
|
c91f530610 | ||
|
|
69740ea841 | ||
|
|
1bb7895cd9 | ||
|
|
a028b88aed | ||
|
|
8a25f6bb07 | ||
|
|
2db453db16 | ||
|
|
03134c2932 | ||
|
|
95d0c143b3 | ||
|
|
3dcdafa6d7 | ||
|
|
75c446c529 | ||
|
|
4a9c32fc81 | ||
|
|
1634c5a91a | ||
|
|
dfa7593c27 | ||
|
|
034af66338 | ||
|
|
55c7b93a0a | ||
|
|
4818cf5606 | ||
|
|
316a3a42a4 | ||
|
|
546d9da185 | ||
|
|
3b7d997b54 | ||
|
|
129744692c | ||
|
|
83f6ce0928 | ||
|
|
b5c7f07064 | ||
|
|
223ba36d54 | ||
|
|
9141e9d4fe | ||
|
|
ead42db7c8 | ||
|
|
d5a68bedfd | ||
|
|
4307489702 | ||
|
|
f0da1f2e03 | ||
|
|
50477cb80b | ||
|
|
ded4a81ffe | ||
|
|
c2bc4e62dd | ||
|
|
f7ab481b22 | ||
|
|
628b529a91 | ||
|
|
7e25963130 | ||
|
|
91d8f1a256 | ||
|
|
61dcc023b0 | ||
|
|
4468a78ee2 | ||
|
|
8f18063b6d | ||
|
|
a167faee3e | ||
|
|
0e8f6aaee5 | ||
|
|
f0a1b94d0d | ||
|
|
5d1ddf5920 | ||
|
|
152ae623c2 | ||
|
|
e7bd9d02bc | ||
|
|
9196639940 | ||
|
|
786d7e39a3 | ||
|
|
c33710d112 | ||
|
|
a14a80f35f | ||
|
|
0389ff6d9d | ||
|
|
8954fccfdb | ||
|
|
332df98fc9 | ||
|
|
d4cc3f69c6 | ||
|
|
534c58c475 | ||
|
|
84fd910423 | ||
|
|
d51f77c2b1 | ||
|
|
47376cbc77 | ||
|
|
85c3db3e89 | ||
|
|
3f8a522c7f | ||
|
|
eb08802b7c | ||
|
|
dc587045bf | ||
|
|
9b495b72c5 | ||
|
|
2ce6c56609 | ||
|
|
9caef95899 | ||
|
|
66c2630aaf | ||
|
|
b8f63ee2df | ||
|
|
68adb49996 | ||
|
|
12e94bfd18 | ||
|
|
4fc3d7a27f | ||
|
|
466bb332c1 | ||
|
|
ff25b45367 | ||
|
|
df83f4fb57 | ||
|
|
5bda3ab9f6 | ||
|
|
9a057159a2 | ||
|
|
9c0875dd5d | ||
|
|
1fa5a2a504 | ||
|
|
a08a2f52fb | ||
|
|
21d37f8605 | ||
|
|
e43586b4de | ||
|
|
dc7e1bdb39 | ||
|
|
03d559b066 | ||
|
|
3191c1f6be | ||
|
|
d46f01cb7c | ||
|
|
04e290a19b | ||
|
|
bad407f5e2 | ||
|
|
2787756efe | ||
|
|
7b35afdf6b | ||
|
|
dba2903e38 | ||
|
|
965014b035 | ||
|
|
c4ec92f375 | ||
|
|
54cf9d1364 | ||
|
|
23ce6d7156 | ||
|
|
07473976e1 | ||
|
|
51063fe07e | ||
|
|
9cc1af1d53 | ||
|
|
8a83bc0569 | ||
|
|
0181f5b5ed | ||
|
|
eaae8ce086 | ||
|
|
0b2072dd30 | ||
|
|
2e77cf6b34 | ||
|
|
ad3c052e1c | ||
|
|
57d9d97866 | ||
|
|
22747c862a | ||
|
|
fed755eee5 | ||
|
|
804410f8ad | ||
|
|
df57a9a81d | ||
|
|
97076780a5 | ||
|
|
899553f9f7 | ||
|
|
2edff5e69e | ||
|
|
37f451171b | ||
|
|
2efc1721d8 | ||
|
|
e9613e6b52 | ||
|
|
73fbe68ccd | ||
|
|
0cb282df99 | ||
|
|
fdb0c0a29b | ||
|
|
2e56db3b2f | ||
|
|
4eb759bf40 | ||
|
|
c3987a9796 | ||
|
|
a070c942e7 | ||
|
|
113b1872cf | ||
|
|
c7dc2937fc | ||
|
|
075895da40 | ||
|
|
7930086a37 | ||
|
|
3f376f848d | ||
|
|
3cee61a65b | ||
|
|
90321f732e | ||
|
|
c6140b1a4c | ||
|
|
9290d89570 | ||
|
|
da9ab71f88 | ||
|
|
53dfee98d2 | ||
|
|
bb14611f86 | ||
|
|
b1aca92268 | ||
|
|
2b524655ae | ||
|
|
b51594c34a | ||
|
|
b409b7d092 | ||
|
|
4256936fed | ||
|
|
fdb6dc7069 | ||
|
|
6291900234 | ||
|
|
216bd2abd8 | ||
|
|
574f279f00 | ||
|
|
d886870bbf | ||
|
|
f56c93cccd | ||
|
|
bbd17bc97a | ||
|
|
26fa923b55 | ||
|
|
177a082974 | ||
|
|
ce3ee332d4 | ||
|
|
eb95f8fa85 | ||
|
|
8d3db75724 | ||
|
|
e1fbc02209 | ||
|
|
766041d956 | ||
|
|
f880a7728f | ||
|
|
013203301f | ||
|
|
bfb60befa7 | ||
|
|
4d34890624 | ||
|
|
6751c0e2c3 | ||
|
|
a641b6ea79 | ||
|
|
fa3c73016d | ||
|
|
ffabd8c6ed | ||
|
|
219a311925 | ||
|
|
8e3af4d859 | ||
|
|
9fa614a36d | ||
|
|
3d207f72a0 | ||
|
|
f53d2f7511 | ||
|
|
b853d99546 | ||
|
|
a09976e3d6 | ||
|
|
1ba0432524 | ||
|
|
7dcd749ee1 | ||
|
|
30368fb06a | ||
|
|
fd6b7db1ce | ||
|
|
53514b2a40 | ||
|
|
0e20418296 | ||
|
|
92b59ace9e | ||
|
|
af7b5b78ee | ||
|
|
2b67e2d54c | ||
|
|
f44994f1e6 | ||
|
|
97d6eb84a4 | ||
|
|
33f2211cae | ||
|
|
03aff19b80 | ||
|
|
cf660fe27c | ||
|
|
f9d60e1360 | ||
|
|
1098280e43 | ||
|
|
62301834f4 | ||
|
|
3e0ac84001 | ||
|
|
4d26e08789 | ||
|
|
3c4403c400 | ||
|
|
8dcde7a74f | ||
|
|
bb7cd8e22b | ||
|
|
7458e95ee5 | ||
|
|
2f69c5f022 | ||
|
|
efdd567a1b | ||
|
|
cff8f7c0b5 | ||
|
|
fe4a4b1b79 | ||
|
|
8caf653e97 | ||
|
|
88c4d532ab | ||
|
|
e69d063252 | ||
|
|
a35218da74 | ||
|
|
4d8e2cdc8b | ||
|
|
3d0f2977bf | ||
|
|
230929a4b2 | ||
|
|
c847216ca4 | ||
|
|
cacd2fa999 | ||
|
|
0b688e4829 | ||
|
|
27cf0ea06b | ||
|
|
e473108e1b | ||
|
|
c74cc9a606 | ||
|
|
619e60cf0e | ||
|
|
37b3657481 | ||
|
|
c1211a4e1a | ||
|
|
95d34b5937 | ||
|
|
6dc3f666c5 | ||
|
|
8e4491a532 | ||
|
|
492095b2a7 | ||
|
|
d516642980 | ||
|
|
193845ecdd | ||
|
|
598d04d5d9 | ||
|
|
06c5dd9c84 | ||
|
|
6632659907 | ||
|
|
86bf835d50 | ||
|
|
c9d0362a6b | ||
|
|
d2989f28db | ||
|
|
0bab6013d0 | ||
|
|
361d93586c | ||
|
|
0db13661b4 | ||
|
|
c866592d7d | ||
|
|
eb90325bed | ||
|
|
c878545977 | ||
|
|
741021513b | ||
|
|
97e8aba080 | ||
|
|
802d46d040 | ||
|
|
96718df15e | ||
|
|
89bd779e78 | ||
|
|
b5af3e74d7 | ||
|
|
2d3932d988 | ||
|
|
d0c1583ad2 | ||
|
|
59ff4064ba | ||
|
|
00a68c985f | ||
|
|
e862ea556c | ||
|
|
a4704cba0b | ||
|
|
455b3a7865 | ||
|
|
fabaab1540 | ||
|
|
8ac49ff181 | ||
|
|
cdf55a18d2 | ||
|
|
d158ca7101 | ||
|
|
664b7ebfa1 | ||
|
|
163c488e30 | ||
|
|
4b5bfa7a9d | ||
|
|
decbadda45 | ||
|
|
f00d780c16 | ||
|
|
1daa2e4609 | ||
|
|
d84bc3ad8e | ||
|
|
a9350e3205 | ||
|
|
95e3a7e7a3 | ||
|
|
e4cecee7d3 | ||
|
|
8b867b41d3 | ||
|
|
c6bd2fe734 | ||
|
|
d7e52b99bd | ||
|
|
a640d9472a | ||
|
|
b15103ef4e | ||
|
|
95071cd1fe | ||
|
|
18a888f9fb | ||
|
|
bbfc41948a | ||
|
|
c29a8cc084 | ||
|
|
54e7af83e6 | ||
|
|
3483d6327d | ||
|
|
5869345899 | ||
|
|
0cad2778b4 | ||
|
|
24de1fbde8 | ||
|
|
131728a680 | ||
|
|
e949e135b6 | ||
|
|
1510b63d20 | ||
|
|
0db4d9bd46 | ||
|
|
1e17e084bf | ||
|
|
a2c14c5ec5 | ||
|
|
b99849c831 | ||
|
|
c7d4286ca1 | ||
|
|
434e2b7212 | ||
|
|
acf0f0fa6e | ||
|
|
220e6b66e8 | ||
|
|
c4d4731ddf | ||
|
|
139ccaa78c | ||
|
|
c42410b560 | ||
|
|
120f11812d | ||
|
|
500486d501 | ||
|
|
6708debd4c | ||
|
|
852a8b4875 | ||
|
|
9c6b4ecb48 |
@@ -28,6 +28,25 @@ fedora/openssl_1.1.x/x86-64:
|
||||
script:
|
||||
- mkdir -p obj && cd obj && cmake -DCMAKE_BUILD_TYPE=Debug
|
||||
-DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON --DWITH_PCAP=ON
|
||||
-DPICKY_DEVELOPER=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/openssl_1.1.x/x86-64/release:
|
||||
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD
|
||||
script:
|
||||
- mkdir -p obj && cd obj && cmake -DCMAKE_BUILD_TYPE=Release
|
||||
-DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON --DWITH_PCAP=ON
|
||||
-DPICKY_DEVELOPER=ON
|
||||
-DUNIT_TESTING=ON -DCLIENT_TESTING=ON -DSERVER_TESTING=ON .. &&
|
||||
make -j$(nproc) && ctest --output-on-failure
|
||||
tags:
|
||||
@@ -41,14 +60,15 @@ fedora/openssl_1.1.x/x86-64:
|
||||
- obj/
|
||||
|
||||
# Address sanitizer doesn't mix well with LD_PRELOAD used in the testsuite
|
||||
.fedora/address-sanitizer:
|
||||
# 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_C_FLAGS="-O2 -g -fsanitize=address"
|
||||
-DCMAKE_LINK_FLAGS="-fsanitize=address -static-libasan"
|
||||
-DCMAKE_BUILD_TYPE=AddressSanitizer
|
||||
-DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON --DWITH_PCAP=ON
|
||||
-DUNIT_TESTING=ON -DCLIENT_TESTING=ON -DSERVER_TESTING=ON .. &&
|
||||
-DUNIT_TESTING=ON .. &&
|
||||
make -j$(nproc) && ctest --output-on-failure
|
||||
tags:
|
||||
- shared
|
||||
@@ -105,6 +125,7 @@ freebsd/x86-64:
|
||||
script:
|
||||
- mkdir -p obj && cd obj && cmake -DCMAKE_BUILD_TYPE=Debug
|
||||
-DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON --DWITH_PCAP=ON
|
||||
-DPICKY_DEVELOPER=ON
|
||||
-DUNIT_TESTING=ON .. &&
|
||||
make && ctest --output-on-failure
|
||||
tags:
|
||||
@@ -144,6 +165,7 @@ fedora/mbedtls/x86-64:
|
||||
- mkdir -p obj && cd obj && cmake -DCMAKE_BUILD_TYPE=Debug
|
||||
-DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON --DWITH_PCAP=ON
|
||||
-DUNIT_TESTING=ON -DCLIENT_TESTING=ON -DSERVER_TESTING=ON
|
||||
-DPICKY_DEVELOPER=ON
|
||||
-DWITH_MBEDTLS=ON .. &&
|
||||
make -j$(nproc) && ctest --output-on-failure
|
||||
tags:
|
||||
@@ -162,6 +184,7 @@ tumbleweed/openssl_1.1.x/x86-64:
|
||||
- mkdir -p obj && cd obj && cmake -DCMAKE_BUILD_TYPE=Debug
|
||||
-DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON --DWITH_PCAP=ON
|
||||
-DKRB5_CONFIG=/usr/lib/mit/bin/krb5-config
|
||||
-DPICKY_DEVELOPER=ON
|
||||
-DUNIT_TESTING=ON -DCLIENT_TESTING=ON -DSERVER_TESTING=ON .. &&
|
||||
make -j$(nproc) && ctest --output-on-failure
|
||||
tags:
|
||||
@@ -174,11 +197,45 @@ tumbleweed/openssl_1.1.x/x86-64:
|
||||
paths:
|
||||
- obj/
|
||||
|
||||
tumbleweed/openssl_1.1.x/x86-64/release:
|
||||
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$TUMBLEWEED_BUILD
|
||||
script:
|
||||
- mkdir -p obj && cd obj && cmake -DCMAKE_BUILD_TYPE=Release
|
||||
-DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON --DWITH_PCAP=ON
|
||||
-DKRB5_CONFIG=/usr/lib/mit/bin/krb5-config
|
||||
-DPICKY_DEVELOPER=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/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/openssl_1.1.x/x86:
|
||||
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$TUMBLEWEED_BUILD
|
||||
script:
|
||||
- mkdir -p obj && cd obj && cmake -DCMAKE_TOOLCHAIN_FILE=../cmake/Toolchain-cross-m32.cmake
|
||||
-DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON --DWITH_PCAP=ON
|
||||
-DPICKY_DEVELOPER=ON
|
||||
-DUNIT_TESTING=ON .. &&
|
||||
make -j$(nproc) && ctest --output-on-failure
|
||||
tags:
|
||||
@@ -238,6 +295,7 @@ mingw64:
|
||||
- export DISPLAY=:1
|
||||
- mkdir -p obj && cd obj && mingw64-cmake -DCMAKE_BUILD_TYPE=Debug
|
||||
-DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON --DWITH_PCAP=ON
|
||||
-DPICKY_DEVELOPER=ON
|
||||
-DUNIT_TESTING=ON .. &&
|
||||
make -j$(nproc)
|
||||
- export WINEPATH=/usr/x86_64-w64-mingw32/sys-root/mingw/bin
|
||||
@@ -261,6 +319,7 @@ mingw32:
|
||||
- export DISPLAY=:1
|
||||
- mkdir -p obj && cd obj && mingw32-cmake -DCMAKE_BUILD_TYPE=Debug
|
||||
-DWITH_SFTP=ON -DWITH_SERVER=ON -DWITH_ZLIB=ON --DWITH_PCAP=ON
|
||||
-DPICKY_DEVELOPER=ON
|
||||
-DUNIT_TESTING=ON .. &&
|
||||
make -j$(nproc)
|
||||
- export WINEPATH=/usr/i686-w64-mingw32/sys-root/mingw/bin
|
||||
|
||||
@@ -1,7 +1,16 @@
|
||||
cmake_minimum_required(VERSION 3.2.0)
|
||||
cmake_minimum_required(VERSION 3.3.0)
|
||||
cmake_policy(SET CMP0048 NEW)
|
||||
|
||||
project(libssh VERSION 0.8.0 LANGUAGES C)
|
||||
# Specify search path for CMake modules to be loaded by include()
|
||||
# and find_package()
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules")
|
||||
|
||||
# Add defaults for cmake
|
||||
# Those need to be set before the project() call.
|
||||
include(DefineCMakeDefaults)
|
||||
include(DefineCompilerFlags)
|
||||
|
||||
project(libssh VERSION 0.8.4 LANGUAGES C)
|
||||
|
||||
# global needed variable
|
||||
set(APPLICATION_NAME ${PROJECT_NAME})
|
||||
@@ -13,22 +22,19 @@ set(APPLICATION_NAME ${PROJECT_NAME})
|
||||
# Increment AGE. Set REVISION to 0
|
||||
# If the source code was changed, but there were no interface changes:
|
||||
# Increment REVISION.
|
||||
set(LIBRARY_VERSION "4.5.0")
|
||||
set(LIBRARY_VERSION "4.7.1")
|
||||
set(LIBRARY_SOVERSION "4")
|
||||
|
||||
# where to look first for cmake modules, before ${CMAKE_ROOT}/Modules/ is checked
|
||||
set(CMAKE_MODULE_PATH
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules
|
||||
)
|
||||
|
||||
# add definitions
|
||||
include(DefineCMakeDefaults)
|
||||
include(DefinePlatformDefaults)
|
||||
include(DefineCompilerFlags)
|
||||
include(DefineInstallationPaths)
|
||||
include(DefineOptions.cmake)
|
||||
include(CPackConfig.cmake)
|
||||
|
||||
include(CompilerChecks.cmake)
|
||||
|
||||
# disallow in-source build
|
||||
include(MacroEnsureOutOfSourceBuild)
|
||||
macro_ensure_out_of_source_build("${PROJECT_NAME} requires an out of source build. Please create a separate build directory and run 'cmake /path/to/${PROJECT_NAME} [options]' there.")
|
||||
@@ -83,7 +89,7 @@ endif (BSD OR SOLARIS OR OSX)
|
||||
|
||||
# Disable symbol versioning in non UNIX platforms
|
||||
if (UNIX)
|
||||
find_package(ABIMap)
|
||||
find_package(ABIMap 0.3.1)
|
||||
else (UNIX)
|
||||
set(WITH_SYMBOL_VERSIONING OFF)
|
||||
endif (UNIX)
|
||||
@@ -158,13 +164,13 @@ if (WITH_SYMBOL_VERSIONING AND ABIMAP_FOUND)
|
||||
message(STATUS "Library version bumped to ${LIBRARY_VERSION}: Updating ABI")
|
||||
|
||||
# Get the list of header files
|
||||
get_file_list("${PROJECT_NAME}_header_list"
|
||||
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_FILE "${PROJECT_NAME}_header_list"
|
||||
HEADERS_LIST ${PROJECT_NAME}_header_list
|
||||
FILTER_PATTERN "LIBSSH_API"
|
||||
COPY_TO "${CMAKE_SOURCE_DIR}/src/ABI/${PROJECT_NAME}-${LIBRARY_VERSION}.symbols")
|
||||
|
||||
@@ -180,7 +186,7 @@ if (WITH_SYMBOL_VERSIONING AND ABIMAP_FOUND)
|
||||
|
||||
# Generate the symbol version map file
|
||||
generate_map_file(${_SYMBOL_TARGET}
|
||||
SYMBOLS "${PROJECT_NAME}.symbols"
|
||||
SYMBOLS ${PROJECT_NAME}.symbols
|
||||
RELEASE_NAME_VERSION ${PROJECT_NAME}_${LIBRARY_VERSION}
|
||||
CURRENT_MAP ${MAP_PATH}
|
||||
COPY_TO ${MAP_PATH}
|
||||
|
||||
@@ -10,7 +10,7 @@ set(CPACK_PACKAGE_VERSION ${PROJECT_VERSION})
|
||||
|
||||
# SOURCE GENERATOR
|
||||
set(CPACK_SOURCE_GENERATOR "TXZ")
|
||||
set(CPACK_SOURCE_IGNORE_FILES "~$;[.]swp$;/[.]git/;.gitignore;build;obj*;tags;cscope.*")
|
||||
set(CPACK_SOURCE_IGNORE_FILES "~$;[.]swp$;/[.]git/;.gitignore;/build*;/obj*;tags;cscope.*")
|
||||
set(CPACK_SOURCE_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}")
|
||||
|
||||
### NSIS INSTALLER
|
||||
|
||||
37
ChangeLog
@@ -1,6 +1,43 @@
|
||||
ChangeLog
|
||||
==========
|
||||
|
||||
version 0.8.4 (released 2018-10-16)
|
||||
* Fixed CVE-2018-10933
|
||||
* Fixed building without globbing support
|
||||
* Fixed possible memory leaks
|
||||
* Avoid SIGPIPE on sockets
|
||||
|
||||
version 0.8.3 (released 2018-09-21)
|
||||
* Added support for rsa-sha2
|
||||
* Added support to parse private keys in openssh container format
|
||||
(other than ed25519)
|
||||
* Added support for diffie-hellman-group18-sha512 and
|
||||
diffie-hellman-group16-sha512
|
||||
* Added ssh_get_fingerprint_hash()
|
||||
* Added ssh_pki_export_privkey_base64()
|
||||
* Added support for Match keyword in config file
|
||||
* Improved performance and reduced memory footprint for sftp
|
||||
* Fixed ecdsa publickey auth
|
||||
* Fixed reading a closed channel
|
||||
* Added support to announce posix-rename@openssh.com and
|
||||
hardlink@openssh.com in the sftp server
|
||||
|
||||
version 0.8.2 (released 2018-08-30)
|
||||
* Added sha256 fingerprints for pubkeys
|
||||
* Improved compiler flag detection
|
||||
* Fixed race condition in reading sftp messages
|
||||
* Fixed doxygen generation and added modern style
|
||||
* Fixed library initialization on Windows
|
||||
* Fixed __bounded__ attribute detection
|
||||
* Fixed a bug in the options parser
|
||||
* Fixed documentation for new knwon_hosts API
|
||||
|
||||
version 0.8.1 (released 2018-08-13)
|
||||
* Fixed version number in the header
|
||||
* Fixed version number in pkg-config and cmake config
|
||||
* Fixed library initialization
|
||||
* Fixed attribute detection
|
||||
|
||||
version 0.8.0 (released 2018-08-10)
|
||||
* Removed support for deprecated SSHv1 protocol
|
||||
* Added new connector API for clients
|
||||
|
||||
102
CompilerChecks.cmake
Normal file
@@ -0,0 +1,102 @@
|
||||
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
|
||||
add_c_compiler_flag("-Wno-gnu-zero-variadic-macro-arguments" SUPPORTED_COMPILER_FLAGS)
|
||||
|
||||
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")
|
||||
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")
|
||||
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()
|
||||
|
||||
# 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)
|
||||
@@ -4,11 +4,11 @@ include(CheckSymbolExists)
|
||||
include(CheckFunctionExists)
|
||||
include(CheckLibraryExists)
|
||||
include(CheckTypeSize)
|
||||
include(CheckCXXSourceCompiles)
|
||||
include(CheckStructHasMember)
|
||||
include(TestBigEndian)
|
||||
|
||||
set(PACKAGE ${APPLICATION_NAME})
|
||||
set(VERSION ${APPLICATION_VERSION})
|
||||
set(PACKAGE ${PROJECT_NAME})
|
||||
set(VERSION ${PROJECT_VERSION})
|
||||
set(DATADIR ${DATA_INSTALL_DIR})
|
||||
set(LIBDIR ${LIB_INSTALL_DIR})
|
||||
set(PLUGINDIR "${PLUGIN_INSTALL_DIR}-${LIBRARY_SOVERSION}")
|
||||
@@ -150,12 +150,14 @@ endif (NOT WITH_MBEDTLS)
|
||||
|
||||
check_function_exists(isblank HAVE_ISBLANK)
|
||||
check_function_exists(strncpy HAVE_STRNCPY)
|
||||
check_function_exists(strndup HAVE_STRNDUP)
|
||||
check_function_exists(strtoull HAVE_STRTOULL)
|
||||
check_function_exists(explicit_bzero HAVE_EXPLICIT_BZERO)
|
||||
check_function_exists(memset_s HAVE_MEMSET_S)
|
||||
|
||||
if (HAVE_GLOB_H)
|
||||
check_function_exists(glob HAVE_GLOB)
|
||||
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)
|
||||
@@ -267,25 +269,57 @@ int main(void) {
|
||||
return 0;
|
||||
}" HAVE_MSC_THREAD_LOCAL_STORAGE)
|
||||
|
||||
###########################################################
|
||||
# For detecting attributes we need to treat warnings as
|
||||
# errors
|
||||
if (UNIX)
|
||||
# Get warnings for attributs
|
||||
check_c_compiler_flag("-Wattributs" REQUIRED_FLAGS_WERROR)
|
||||
if (REQUIRED_FLAGS_WERROR)
|
||||
set(CMAKE_REQUIRED_FLAGS "-Wattributes")
|
||||
endif()
|
||||
|
||||
# Turn warnings into errors
|
||||
check_c_compiler_flag("-Werror" REQUIRED_FLAGS_WERROR)
|
||||
if (REQUIRED_FLAGS_WERROR)
|
||||
set(CMAKE_REQUIRED_FLAGS "-Werror")
|
||||
endif()
|
||||
endif (UNIX)
|
||||
|
||||
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))
|
||||
|
||||
enum direction_e {
|
||||
UP = 0,
|
||||
DOWN,
|
||||
};
|
||||
|
||||
int main(void) {
|
||||
enum direction_e key = UP;
|
||||
int i = 10;
|
||||
int j = 0;
|
||||
int i = 2;
|
||||
|
||||
switch (key) {
|
||||
case UP:
|
||||
i = 5;
|
||||
switch (i) {
|
||||
case 0:
|
||||
FALL_THROUGH;
|
||||
case DOWN:
|
||||
j = i * 2;
|
||||
case 1:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -332,11 +366,31 @@ int main(void) {
|
||||
return 0;
|
||||
}" HAVE_COMPILER__FUNCTION__)
|
||||
|
||||
|
||||
check_c_source_compiles("
|
||||
void chacha_keysetup(struct chacha_ctx *x, const u_char *k, u_int kbits)
|
||||
__attribute__((__bounded__(__minbytes__, 2, CHACHA_MINKEYLEN)));
|
||||
int main(void) { return 0; }" HAVE_GCC_BOUNDED_ATTRIBUTE)
|
||||
#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)
|
||||
|
||||
# Stop treating warnings as errors
|
||||
unset(CMAKE_REQUIRED_FLAGS)
|
||||
|
||||
# Check for version script support
|
||||
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/conftest.map" "VERS_1 {
|
||||
global: sym;
|
||||
};
|
||||
VERS_2 {
|
||||
global: sym;
|
||||
} VERS_1;
|
||||
")
|
||||
|
||||
set(CMAKE_REQUIRED_FLAGS "-Wl,--version-script=\"${CMAKE_CURRENT_BINARY_DIR}/conftest.map\"")
|
||||
check_c_source_compiles("int main(void) { return 0; }" HAVE_LD_VERSION_SCRIPT)
|
||||
unset(CMAKE_REQUIRED_FLAGS)
|
||||
file(REMOVE "${CMAKE_CURRENT_BINARY_DIR}/conftest.map")
|
||||
|
||||
if (WITH_DEBUG_CRYPTO)
|
||||
set(DEBUG_CRYPTO 1)
|
||||
|
||||
@@ -19,18 +19,25 @@ 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)
|
||||
set(WITH_LIBZ ON)
|
||||
else (WITH_ZLIB)
|
||||
set(WITH_LIBZ OFF)
|
||||
endif (WITH_ZLIB)
|
||||
|
||||
if(WITH_BENCHMARKS)
|
||||
if (WITH_BENCHMARKS)
|
||||
set(UNIT_TESTING ON)
|
||||
endif(WITH_BENCHMARKS)
|
||||
set(CLIENT_TESTING ON)
|
||||
endif()
|
||||
|
||||
if (WITH_STATIC_LIB)
|
||||
set(BUILD_STATIC_LIB ON)
|
||||
endif (WITH_STATIC_LIB)
|
||||
|
||||
if (UNIT_TESTING)
|
||||
set(WITH_STATIC_LIB ON)
|
||||
set(BUILD_STATIC_LIB ON)
|
||||
endif (UNIT_TESTING)
|
||||
|
||||
if (WITH_NACL)
|
||||
|
||||
21
cmake/Modules/AddCCompilerFlag.cmake
Normal file
@@ -0,0 +1,21 @@
|
||||
#
|
||||
# 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,7 +1,7 @@
|
||||
# - ADD_CHECK_TEST(test_name test_source linklib1 ... linklibN)
|
||||
# - add_cmocka_test(test_name test_source linklib1 ... linklibN)
|
||||
|
||||
# Copyright (c) 2007 Daniel Gollub <dgollub@suse.de>
|
||||
# Copyright (c) 2007-2010 Andreas Schneider <asn@cryptomilk.org>
|
||||
# Copyright (c) 2007-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.
|
||||
@@ -9,20 +9,6 @@
|
||||
enable_testing()
|
||||
include(CTest)
|
||||
|
||||
if(CMAKE_COMPILER_IS_GNUCC AND NOT MINGW)
|
||||
# Profiling
|
||||
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")
|
||||
|
||||
# Address Sanitizer
|
||||
set(CMAKE_C_FLAGS_ADDRESSSANITIZER "-g -O1 -fsanitize=address -fno-omit-frame-pointer" CACHE STRING "Address sanitizer compiler flags")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS_ADDRESSSANITIZER "-fsanitize=address" CACHE STRING "Address sanitizer shared linker flags")
|
||||
set(CMAKE_MODULE_LINKER_FLAGS_ADDRESSSANITIZER "-fsanitize=address" CACHE STRING "Address sanitizer module linker flags")
|
||||
set(CMAKE_EXEC_LINKER_FLAGS_ADDRESSSANITIZER "-fsanitize=address" CACHE STRING "Address sanitizer executable linker flags")
|
||||
endif(CMAKE_COMPILER_IS_GNUCC AND NOT MINGW)
|
||||
|
||||
if (CMAKE_CROSSCOMPILING)
|
||||
if (WIN32)
|
||||
find_program(WINE_EXECUTABLE
|
||||
@@ -31,8 +17,10 @@ if (CMAKE_CROSSCOMPILING)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
function (ADD_CMOCKA_TEST _testName _testSource)
|
||||
function(ADD_CMOCKA_TEST _testName _testSource)
|
||||
add_executable(${_testName} ${_testSource})
|
||||
|
||||
target_link_libraries(${_testName} ${ARGN})
|
||||
|
||||
add_test(${_testName} ${TARGET_SYSTEM_EMULATOR} ${CMAKE_CURRENT_BINARY_DIR}/${_testName}${CMAKE_EXECUTABLE_SUFFIX})
|
||||
endfunction (ADD_CMOCKA_TEST)
|
||||
|
||||
@@ -15,12 +15,15 @@
|
||||
# Redistribution and use is allowed according to the terms of the BSD license.
|
||||
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
|
||||
|
||||
|
||||
# Requires cmake 3.10
|
||||
#include_guard(GLOBAL)
|
||||
include(CheckCSourceCompiles)
|
||||
|
||||
function(CHECK_C_COMPILER_FLAG_SSP _FLAG _RESULT)
|
||||
set(SAFE_CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS}")
|
||||
set(CMAKE_REQUIRED_DEFINITIONS "${_FLAG}")
|
||||
macro(CHECK_C_COMPILER_FLAG_SSP _FLAG _RESULT)
|
||||
set(SAFE_CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS}")
|
||||
set(CMAKE_REQUIRED_FLAGS "${_FLAG}")
|
||||
|
||||
check_c_source_compiles("int main(int argc, char **argv) { char buffer[256]; return buffer[argc]=0;}" ${_RESULT})
|
||||
set(CMAKE_REQUIRED_DEFINITIONS "${SAFE_CMAKE_REQUIRED_DEFINITIONS}")
|
||||
endfunction(CHECK_C_COMPILER_FLAG_SSP)
|
||||
|
||||
set(CMAKE_REQUIRED_FLAGS "${SAFE_CMAKE_REQUIRED_FLAGS}")
|
||||
endmacro(CHECK_C_COMPILER_FLAG_SSP)
|
||||
|
||||
@@ -14,17 +14,8 @@ set(CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE ON)
|
||||
# since cmake 2.4.0
|
||||
set(CMAKE_COLOR_MAKEFILE ON)
|
||||
|
||||
# Define the generic version of the libraries here
|
||||
set(GENERIC_LIB_VERSION "0.1.0")
|
||||
set(GENERIC_LIB_SOVERSION "0")
|
||||
|
||||
# Set the default build type to release with debug info
|
||||
if (NOT CMAKE_BUILD_TYPE)
|
||||
set(CMAKE_BUILD_TYPE RelWithDebInfo
|
||||
CACHE STRING
|
||||
"Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel."
|
||||
)
|
||||
endif (NOT CMAKE_BUILD_TYPE)
|
||||
|
||||
# Create the compile command database for clang by default
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||
|
||||
# Always build with -fPIC
|
||||
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||
|
||||
@@ -1,84 +1,25 @@
|
||||
# define system dependent compiler flags
|
||||
|
||||
include(CheckCCompilerFlag)
|
||||
include(CheckCCompilerFlagSSP)
|
||||
|
||||
if (UNIX AND NOT WIN32)
|
||||
#
|
||||
# Define GNUCC compiler flags
|
||||
#
|
||||
if (${CMAKE_C_COMPILER_ID} MATCHES "(GNU|Clang)")
|
||||
|
||||
# add -Wconversion ?
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99 -pedantic -pedantic-errors")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wshadow -Wmissing-prototypes -Wdeclaration-after-statement")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wunused -Wfloat-equal -Wpointer-arith -Wwrite-strings -Wformat-security")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wmissing-format-attribute")
|
||||
|
||||
# with -fPIC
|
||||
check_c_compiler_flag("-fPIC" WITH_FPIC)
|
||||
if (WITH_FPIC)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC")
|
||||
endif (WITH_FPIC)
|
||||
|
||||
check_c_compiler_flag_ssp("-fstack-protector" WITH_STACK_PROTECTOR)
|
||||
if (WITH_STACK_PROTECTOR)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fstack-protector")
|
||||
endif (WITH_STACK_PROTECTOR)
|
||||
|
||||
if (CMAKE_BUILD_TYPE)
|
||||
string(TOLOWER "${CMAKE_BUILD_TYPE}" CMAKE_BUILD_TYPE_LOWER)
|
||||
if (CMAKE_BUILD_TYPE_LOWER MATCHES (release|relwithdebinfo|minsizerel))
|
||||
check_c_compiler_flag("-Wp,-D_FORTIFY_SOURCE=2" WITH_FORTIFY_SOURCE)
|
||||
if (WITH_FORTIFY_SOURCE)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wp,-D_FORTIFY_SOURCE=2")
|
||||
endif (WITH_FORTIFY_SOURCE)
|
||||
endif()
|
||||
endif()
|
||||
endif (${CMAKE_C_COMPILER_ID} MATCHES "(GNU|Clang)")
|
||||
|
||||
#
|
||||
# Check for large filesystem support
|
||||
#
|
||||
if (CMAKE_SIZEOF_VOID_P MATCHES "8")
|
||||
# with large file support
|
||||
execute_process(
|
||||
COMMAND
|
||||
getconf LFS64_CFLAGS
|
||||
OUTPUT_VARIABLE
|
||||
_lfs_CFLAGS
|
||||
ERROR_QUIET
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
else (CMAKE_SIZEOF_VOID_P MATCHES "8")
|
||||
# with large file support
|
||||
execute_process(
|
||||
COMMAND
|
||||
getconf LFS_CFLAGS
|
||||
OUTPUT_VARIABLE
|
||||
_lfs_CFLAGS
|
||||
ERROR_QUIET
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
endif (CMAKE_SIZEOF_VOID_P MATCHES "8")
|
||||
if (_lfs_CFLAGS)
|
||||
string(REGEX REPLACE "[\r\n]" " " "${_lfs_CFLAGS}" "${${_lfs_CFLAGS}}")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${_lfs_CFLAGS}")
|
||||
endif (_lfs_CFLAGS)
|
||||
|
||||
endif (UNIX AND NOT WIN32)
|
||||
|
||||
if (MSVC)
|
||||
# Use secure functions by defaualt and suppress warnings about
|
||||
#"deprecated" functions
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /D _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES=1")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /D _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT=1")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /D _CRT_NONSTDC_NO_WARNINGS=1 /D _CRT_SECURE_NO_WARNINGS=1")
|
||||
endif (MSVC)
|
||||
|
||||
# This removes this annoying warning
|
||||
# "warning: 'BN_CTX_free' is deprecated: first deprecated in OS X 10.7 [-Wdeprecated-declarations]"
|
||||
if (OSX)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-deprecated-declarations")
|
||||
endif (OSX)
|
||||
# Activate with: -DCMAKE_BUILD_TYPE=Profiling
|
||||
set(CMAKE_C_FLAGS_PROFILING "-g -O0 -fprofile-arcs -ftest-coverage"
|
||||
CACHE STRING "Flags used by the C compiler during PROFILING builds.")
|
||||
set(CMAKE_CXX_FLAGS_PROFILING "-g -O0 -fprofile-arcs -ftest-coverage"
|
||||
CACHE STRING "Flags used by the CXX compiler during PROFILING builds.")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS_PROFILING "-fprofile-arcs -ftest-coverage"
|
||||
CACHE STRING "Flags used by the linker during the creation of shared libraries during PROFILING builds.")
|
||||
set(CMAKE_MODULE_LINKER_FLAGS_PROFILING "-fprofile-arcs -ftest-coverage"
|
||||
CACHE STRING "Flags used by the linker during the creation of shared libraries during PROFILING builds.")
|
||||
set(CMAKE_EXEC_LINKER_FLAGS_PROFILING "-fprofile-arcs -ftest-coverage"
|
||||
CACHE STRING "Flags used by the linker during PROFILING builds.")
|
||||
|
||||
# Activate with: -DCMAKE_BUILD_TYPE=AddressSanitizer
|
||||
set(CMAKE_C_FLAGS_ADDRESSSANITIZER "-g -O1 -fsanitize=address -fno-omit-frame-pointer"
|
||||
CACHE STRING "Flags used by the C compiler during ADDRESSSANITIZER builds.")
|
||||
set(CMAKE_CXX_FLAGS_ADDRESSSANITIZER "-g -O1 -fsanitize=address -fno-omit-frame-pointer"
|
||||
CACHE STRING "Flags used by the CXX compiler during ADDRESSSANITIZER builds.")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS_ADDRESSSANITIZER "-fsanitize=address"
|
||||
CACHE STRING "Flags used by the linker during the creation of shared libraries during ADDRESSSANITIZER builds.")
|
||||
set(CMAKE_MODULE_LINKER_FLAGS_ADDRESSSANITIZER "-fsanitize=address"
|
||||
CACHE STRING "Flags used by the linker during the creation of shared libraries during ADDRESSSANITIZER builds.")
|
||||
set(CMAKE_EXEC_LINKER_FLAGS_ADDRESSSANITIZER "-fsanitize=address"
|
||||
CACHE STRING "Flags used by the linker during ADDRESSSANITIZER builds.")
|
||||
endif()
|
||||
|
||||
@@ -85,4 +85,8 @@ endforeach()
|
||||
|
||||
list(REMOVE_DUPLICATES symbols)
|
||||
|
||||
file(WRITE ${OUTPUT_PATH} "${symbols}")
|
||||
list(SORT symbols)
|
||||
|
||||
string(REPLACE ";" "\n" symbols_list "${symbols}")
|
||||
|
||||
file(WRITE ${OUTPUT_PATH} "${symbols_list}")
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
#
|
||||
# generate_map_file(target_name
|
||||
# RELEASE_NAME_VERSION release_name
|
||||
# SYMBOLS symbols_file
|
||||
# SYMBOLS symbols_target
|
||||
# [CURRENT_MAP cur_map]
|
||||
# [FINAL]
|
||||
# [BREAK_ABI]
|
||||
@@ -55,8 +55,9 @@
|
||||
# added to the symbols in the format ``lib_name_1_2_3``.
|
||||
#
|
||||
# ``SYMBOLS``:
|
||||
# Required, expects a file containing the list of symbols to be added to the
|
||||
# symbol version script.
|
||||
# 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
|
||||
@@ -87,9 +88,15 @@
|
||||
# find_package(ABIMap)
|
||||
# generate_map_file("lib.map"
|
||||
# RELEASE_NAME_VERSION "lib_1_0_0"
|
||||
# SYMBOLS "symbol1;symbol2"
|
||||
# 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.
|
||||
#
|
||||
@@ -102,8 +109,8 @@
|
||||
# )
|
||||
#
|
||||
# ``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
|
||||
# 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``:
|
||||
@@ -112,7 +119,7 @@
|
||||
#
|
||||
# ``FILES_PATTERN``:
|
||||
# Required, expects a list of matching expressions to find the files to be
|
||||
# considered.
|
||||
# considered in the directories.
|
||||
#
|
||||
# ``COPY_TO``:
|
||||
# Optional, expects a string containing the path to where the file containing
|
||||
@@ -120,7 +127,9 @@
|
||||
#
|
||||
# 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``.
|
||||
# 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:
|
||||
#
|
||||
@@ -140,10 +149,13 @@
|
||||
#
|
||||
# ``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_FILE headers_list
|
||||
# HEADERS_LIST headers_list_target
|
||||
# [FILTER_PATTERN pattern]
|
||||
# [COPY_TO output]
|
||||
# )
|
||||
@@ -153,9 +165,9 @@
|
||||
# the string given in ``target_name`` will be created in
|
||||
# ``${CMAKE_CURRENT_BINARY_DIR}`` to receive the list of symbols.
|
||||
#
|
||||
# ``HEADERS_LIST_FILE``:
|
||||
# Required, expects a path to a file containing the list of header files to be
|
||||
# parsed.
|
||||
# ``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
|
||||
@@ -170,7 +182,9 @@
|
||||
# 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.
|
||||
# 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:
|
||||
#
|
||||
@@ -178,11 +192,12 @@
|
||||
#
|
||||
# find_package(ABIMap)
|
||||
# extract_symbols("lib.symbols"
|
||||
# HEADERS_LIST_FILE "headers_list"
|
||||
# HEADERS_LIST "headers_target"
|
||||
# FILTER_PATTERN "API_FUNCTION"
|
||||
# )
|
||||
#
|
||||
# Where headers_list contains::
|
||||
# Where ``LIST_FILE`` property in ``headers_target`` points to a file
|
||||
# containing::
|
||||
#
|
||||
# header1.h;header2.h
|
||||
#
|
||||
@@ -196,25 +211,52 @@
|
||||
#
|
||||
# int private_func2(int b);
|
||||
#
|
||||
# Will result in a file ``lib.symbols`` in ``${CMAKE_CURRENT_BINARY_DIR}`` containing::
|
||||
# Will result in a file ``lib.symbols.list`` in ``${CMAKE_CURRENT_BINARY_DIR}``
|
||||
# containing::
|
||||
#
|
||||
# ``exported_func1;exported_func2``
|
||||
# ``exported_func1``
|
||||
# ``exported_func2``
|
||||
#
|
||||
|
||||
# Search for python which is required
|
||||
find_package(PythonInterp REQUIRED)
|
||||
if (ABIMap_FIND_REQURIED)
|
||||
find_package(PythonInterp REQUIRED)
|
||||
else()
|
||||
find_package(PythonInterp)
|
||||
endif()
|
||||
|
||||
# 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`)")
|
||||
else ()
|
||||
set(ABIMAP_FOUND TRUE)
|
||||
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)
|
||||
@@ -224,42 +266,41 @@ set(_GET_FILES_LIST_SCRIPT ${CMAKE_CURRENT_LIST_DIR}/GetFilesList.cmake)
|
||||
function(get_file_list _TARGET_NAME)
|
||||
|
||||
set(one_value_arguments
|
||||
COPY_TO
|
||||
COPY_TO
|
||||
)
|
||||
|
||||
set(multi_value_arguments
|
||||
DIRECTORIES
|
||||
FILES_PATTERNS
|
||||
DIRECTORIES
|
||||
FILES_PATTERNS
|
||||
)
|
||||
|
||||
cmake_parse_arguments(_get_files_list
|
||||
""
|
||||
"${one_value_arguments}"
|
||||
"${multi_value_arguments}"
|
||||
${ARGN}
|
||||
""
|
||||
"${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()
|
||||
" 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."
|
||||
)
|
||||
" of matching patterns for the header files.")
|
||||
endif()
|
||||
|
||||
get_filename_component(_get_files_list_OUTPUT_PATH
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/${_TARGET_NAME}"
|
||||
ABSOLUTE
|
||||
)
|
||||
set(_FILES_LIST_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR}/${_TARGET_NAME}.list)
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${_TARGET_NAME}
|
||||
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}"
|
||||
@@ -271,59 +312,90 @@ function(get_file_list _TARGET_NAME)
|
||||
|
||||
if (DEFINED _get_files_list_COPY_TO)
|
||||
# Copy the generated file back to the COPY_TO
|
||||
add_custom_target(copy_headers_list_${TARGET_NAME} ALL
|
||||
add_custom_target(${_TARGET_NAME} ALL
|
||||
COMMAND
|
||||
${CMAKE_COMMAND} -E copy_if_different ${_TARGET_NAME} ${_get_files_list_COPY_TO}
|
||||
DEPENDS "${_TARGET_NAME}"
|
||||
${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_FILE
|
||||
COPY_TO
|
||||
FILTER_PATTERN
|
||||
HEADERS_LIST
|
||||
COPY_TO
|
||||
)
|
||||
|
||||
set(multi_value_arguments
|
||||
)
|
||||
|
||||
cmake_parse_arguments(_extract_symbols
|
||||
""
|
||||
"${one_value_arguments}"
|
||||
"${multi_value_arguments}"
|
||||
${ARGN}
|
||||
""
|
||||
"${one_value_arguments}"
|
||||
"${multi_value_arguments}"
|
||||
${ARGN}
|
||||
)
|
||||
|
||||
# The HEADERS_LIST_FILE argument is required
|
||||
if (NOT DEFINED _extract_symbols_HEADERS_LIST_FILE)
|
||||
message(FATAL_ERROR "No header files given. Provide a list of header"
|
||||
" files containing exported symbols."
|
||||
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()
|
||||
|
||||
get_filename_component(_extract_symbols_OUTPUT_PATH
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/${_TARGET_NAME}"
|
||||
ABSOLUTE
|
||||
set_target_properties(${_TARGET_NAME}
|
||||
PROPERTIES LIST_FILE ${_SYMBOLS_OUTPUT_PATH}
|
||||
)
|
||||
|
||||
add_custom_target(${_TARGET_NAME}
|
||||
COMMAND ${CMAKE_COMMAND}
|
||||
-DOUTPUT_PATH="${_extract_symbols_OUTPUT_PATH}"
|
||||
-DHEADERS_LIST_FILE="${_extract_symbols_HEADERS_LIST_FILE}"
|
||||
-DFILTER_PATTERN=${_extract_symbols_FILTER_PATTERN}
|
||||
-P ${_EXTRACT_SYMBOLS_SCRIPT}
|
||||
DEPENDS ${_extract_symbols_HEADERS_LIST_FILE}
|
||||
COMMENT "Extracting symbols from headers")
|
||||
|
||||
if (DEFINED _extract_symbols_COPY_TO)
|
||||
file(READ "${CMAKE_CURRENT_BINARY_DIR}/${_TARGET_NAME}" SYMBOL_CONTENT)
|
||||
string(REPLACE ";" "\n" SYMBOL_CONTENT_NEW "${SYMBOL_CONTENT}")
|
||||
file(WRITE "${_extract_symbols_COPY_TO}" "${SYMBOL_CONTENT_NEW}")
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
function(generate_map_file _TARGET_NAME)
|
||||
@@ -344,36 +416,42 @@ function(generate_map_file _TARGET_NAME)
|
||||
)
|
||||
|
||||
cmake_parse_arguments(_generate_map_file
|
||||
"${options}"
|
||||
"${one_value_arguments}"
|
||||
"${multi_value_arguments}"
|
||||
${ARGN}
|
||||
"${options}"
|
||||
"${one_value_arguments}"
|
||||
"${multi_value_arguments}"
|
||||
${ARGN}
|
||||
)
|
||||
|
||||
if (NOT DEFINED _generate_map_file_SYMBOLS)
|
||||
message(FATAL_ERROR "No symbols file provided."
|
||||
)
|
||||
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"
|
||||
)
|
||||
" (e.g. libname_1_0_0)")
|
||||
endif()
|
||||
|
||||
# Set generated map file path
|
||||
get_filename_component(_generate_map_file_OUTPUT_PATH
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/${_TARGET_NAME}"
|
||||
ABSOLUTE
|
||||
|
||||
get_target_property(_SYMBOLS_FILE
|
||||
${_generate_map_file_SYMBOLS}
|
||||
LIST_FILE
|
||||
)
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${_TARGET_NAME}
|
||||
# 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="${_generate_map_file_SYMBOLS}"
|
||||
-DSYMBOLS="${_SYMBOLS_FILE}"
|
||||
-DCURRENT_MAP=${_generate_map_file_CURRENT_MAP}
|
||||
-DOUTPUT_PATH="${_generate_map_file_OUTPUT_PATH}"
|
||||
-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}
|
||||
@@ -382,13 +460,27 @@ function(generate_map_file _TARGET_NAME)
|
||||
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(copy_map_${_TARGET_NAME} ALL
|
||||
add_custom_target(${_TARGET_NAME} ALL
|
||||
COMMAND
|
||||
${CMAKE_COMMAND} -E copy_if_different ${_TARGET_NAME} ${_generate_map_file_COPY_TO}
|
||||
DEPENDS "${_TARGET_NAME}"
|
||||
COMMENT "Copying ${_TARGET_NAME} to ${_generate_map_file_COPY_TO}"
|
||||
${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)
|
||||
|
||||
@@ -21,17 +21,16 @@
|
||||
#
|
||||
|
||||
if (WIN32)
|
||||
set(_NSIS_ROOT_HINTS
|
||||
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\NSIS;Default]")
|
||||
set(_x86 "(x86)")
|
||||
|
||||
set(_NSIS_ROOT_PATHS
|
||||
$ENV{PROGRAMFILES}/NSIS)
|
||||
"$ENV{ProgramFiles}/NSIS"
|
||||
"$ENV{ProgramFiles${_x86}}/NSIS"
|
||||
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\NSIS;Default]")
|
||||
|
||||
find_path(NSIS_ROOT_PATH
|
||||
NAMES
|
||||
Include/Library.nsh
|
||||
HINTS
|
||||
${_NSIS_ROOT_HINTS}
|
||||
PATHS
|
||||
${_NSIS_ROOT_PATHS}
|
||||
)
|
||||
|
||||
@@ -1,140 +0,0 @@
|
||||
# - Run Doxygen
|
||||
#
|
||||
# Adds a doxygen target that runs doxygen to generate the html
|
||||
# and optionally the LaTeX API documentation.
|
||||
# The doxygen target is added to the doc target as a dependency.
|
||||
# i.e.: the API documentation is built with:
|
||||
# make doc
|
||||
#
|
||||
# USAGE: GLOBAL INSTALL
|
||||
#
|
||||
# Install it with:
|
||||
# cmake ./ && sudo make install
|
||||
# Add the following to the CMakeLists.txt of your project:
|
||||
# include(UseDoxygen OPTIONAL)
|
||||
# Optionally copy Doxyfile.in in the directory of CMakeLists.txt and edit it.
|
||||
#
|
||||
# USAGE: INCLUDE IN PROJECT
|
||||
#
|
||||
# set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
# include(UseDoxygen)
|
||||
# Add the Doxyfile.in and UseDoxygen.cmake files to the projects source directory.
|
||||
#
|
||||
#
|
||||
# CONFIGURATION
|
||||
#
|
||||
# To configure Doxygen you can edit Doxyfile.in and set some variables in cmake.
|
||||
# Variables you may define are:
|
||||
# DOXYFILE_SOURCE_DIR - Path where the Doxygen input files are.
|
||||
# Defaults to the current source directory.
|
||||
# DOXYFILE_EXTRA_SOURCES - Additional source diretories/files for Doxygen to scan.
|
||||
# The Paths should be in double quotes and separated by space. e.g.:
|
||||
# "${CMAKE_CURRENT_BINARY_DIR}/foo.c" "${CMAKE_CURRENT_BINARY_DIR}/bar/"
|
||||
#
|
||||
# DOXYFILE_OUTPUT_DIR - Path where the Doxygen output is stored.
|
||||
# Defaults to "${CMAKE_CURRENT_BINARY_DIR}/doc".
|
||||
#
|
||||
# DOXYFILE_LATEX - ON/OFF; Set to "ON" if you want the LaTeX documentation
|
||||
# to be built.
|
||||
# DOXYFILE_LATEX_DIR - Directory relative to DOXYFILE_OUTPUT_DIR where
|
||||
# the Doxygen LaTeX output is stored. Defaults to "latex".
|
||||
#
|
||||
# DOXYFILE_HTML_DIR - Directory relative to DOXYFILE_OUTPUT_DIR where
|
||||
# the Doxygen html output is stored. Defaults to "html".
|
||||
#
|
||||
|
||||
#
|
||||
# Copyright (c) 2009, 2010, 2011 Tobias Rautenkranz <tobias@rautenkranz.ch>
|
||||
#
|
||||
# Redistribution and use is allowed according to the terms of the New
|
||||
# BSD license.
|
||||
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
|
||||
#
|
||||
|
||||
macro(usedoxygen_set_default name value type docstring)
|
||||
if(NOT DEFINED "${name}")
|
||||
set("${name}" "${value}" CACHE "${type}" "${docstring}")
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
find_package(Doxygen)
|
||||
|
||||
if(DOXYGEN_FOUND)
|
||||
find_file(DOXYFILE_IN "Doxyfile.in"
|
||||
PATHS "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_ROOT}/Modules/"
|
||||
NO_DEFAULT_PATH
|
||||
DOC "Path to the doxygen configuration template file")
|
||||
set(DOXYFILE "${CMAKE_CURRENT_BINARY_DIR}/Doxyfile")
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(DOXYFILE_IN DEFAULT_MSG "DOXYFILE_IN")
|
||||
endif()
|
||||
|
||||
if(DOXYGEN_FOUND AND DOXYFILE_IN_FOUND)
|
||||
usedoxygen_set_default(DOXYFILE_OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}/doc"
|
||||
PATH "Doxygen output directory")
|
||||
usedoxygen_set_default(DOXYFILE_HTML_DIR "html"
|
||||
STRING "Doxygen HTML output directory")
|
||||
usedoxygen_set_default(DOXYFILE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||
PATH "Input files source directory")
|
||||
usedoxygen_set_default(DOXYFILE_EXTRA_SOURCE_DIRS ""
|
||||
STRING "Additional source files/directories separated by space")
|
||||
set(DOXYFILE_SOURCE_DIRS "\"${DOXYFILE_SOURCE_DIR}\" ${DOXYFILE_EXTRA_SOURCES}")
|
||||
|
||||
usedoxygen_set_default(DOXYFILE_LATEX YES BOOL "Generate LaTeX API documentation" OFF)
|
||||
usedoxygen_set_default(DOXYFILE_LATEX_DIR "latex" STRING "LaTex output directory")
|
||||
|
||||
mark_as_advanced(DOXYFILE_OUTPUT_DIR DOXYFILE_HTML_DIR DOXYFILE_LATEX_DIR
|
||||
DOXYFILE_SOURCE_DIR DOXYFILE_EXTRA_SOURCE_DIRS DOXYFILE_IN)
|
||||
|
||||
|
||||
set_property(DIRECTORY
|
||||
APPEND PROPERTY
|
||||
ADDITIONAL_MAKE_CLEAN_FILES
|
||||
"${DOXYFILE_OUTPUT_DIR}/${DOXYFILE_HTML_DIR}")
|
||||
|
||||
add_custom_target(doxygen
|
||||
COMMAND "${DOXYGEN_EXECUTABLE}"
|
||||
"${DOXYFILE}"
|
||||
COMMENT "Writing documentation to ${DOXYFILE_OUTPUT_DIR}..."
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
|
||||
set(DOXYFILE_DOT "NO")
|
||||
if(DOXYGEN_DOT_EXECUTABLE)
|
||||
set(DOXYFILE_DOT "YES")
|
||||
endif()
|
||||
|
||||
## LaTeX
|
||||
set(DOXYFILE_PDFLATEX "NO")
|
||||
|
||||
set_property(DIRECTORY APPEND PROPERTY
|
||||
ADDITIONAL_MAKE_CLEAN_FILES
|
||||
"${DOXYFILE_OUTPUT_DIR}/${DOXYFILE_LATEX_DIR}")
|
||||
|
||||
if(DOXYFILE_LATEX STREQUAL "ON")
|
||||
set(DOXYFILE_GENERATE_LATEX "YES")
|
||||
find_package(LATEX)
|
||||
find_program(DOXYFILE_MAKE make)
|
||||
mark_as_advanced(DOXYFILE_MAKE)
|
||||
if(LATEX_COMPILER AND MAKEINDEX_COMPILER AND DOXYFILE_MAKE)
|
||||
if(PDFLATEX_COMPILER)
|
||||
set(DOXYFILE_PDFLATEX "YES")
|
||||
endif()
|
||||
|
||||
add_custom_command(TARGET doxygen
|
||||
POST_BUILD
|
||||
COMMAND "${DOXYFILE_MAKE}"
|
||||
COMMENT "Running LaTeX for Doxygen documentation in ${DOXYFILE_OUTPUT_DIR}/${DOXYFILE_LATEX_DIR}..."
|
||||
WORKING_DIRECTORY "${DOXYFILE_OUTPUT_DIR}/${DOXYFILE_LATEX_DIR}")
|
||||
else()
|
||||
set(DOXYGEN_LATEX "NO")
|
||||
endif()
|
||||
else()
|
||||
set(DOXYFILE_GENERATE_LATEX "NO")
|
||||
endif()
|
||||
|
||||
|
||||
configure_file("${DOXYFILE_IN}" "${DOXYFILE}" @ONLY)
|
||||
|
||||
add_custom_target(doc)
|
||||
add_dependencies(doc doxygen)
|
||||
endif()
|
||||
@@ -1,8 +1,8 @@
|
||||
/* Name of package */
|
||||
#cmakedefine PACKAGE "${APPLICATION_NAME}"
|
||||
#cmakedefine PACKAGE "${PROJECT_NAME}"
|
||||
|
||||
/* Version number of package */
|
||||
#cmakedefine VERSION "${APPLICATION_VERSION}"
|
||||
#cmakedefine VERSION "${PROJECT_VERSION}"
|
||||
|
||||
#cmakedefine LOCALEDIR "${LOCALE_INSTALL_DIR}"
|
||||
#cmakedefine DATADIR "${DATADIR}"
|
||||
@@ -89,6 +89,9 @@
|
||||
/* 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 ***************************/
|
||||
|
||||
/* Define to 1 if you have the `EVP_aes128_ctr' function. */
|
||||
@@ -130,6 +133,9 @@
|
||||
/* Define to 1 if you have the `strncpy' function. */
|
||||
#cmakedefine HAVE_STRNCPY 1
|
||||
|
||||
/* Define to 1 if you have the `strndup' function. */
|
||||
#cmakedefine HAVE_STRNDUP 1
|
||||
|
||||
/* Define to 1 if you have the `cfmakeraw' function. */
|
||||
#cmakedefine HAVE_CFMAKERAW 1
|
||||
|
||||
@@ -193,6 +199,9 @@
|
||||
|
||||
#cmakedefine HAVE_FALLTHROUGH_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
|
||||
|
||||
|
||||
@@ -1,5 +1,46 @@
|
||||
#
|
||||
# Build the documentation
|
||||
#
|
||||
include(UseDoxygen OPTIONAL)
|
||||
if (${CMAKE_VERSION} VERSION_GREATER "3.8.99")
|
||||
|
||||
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
|
||||
|
||||
1917
doc/Doxyfile.in
@@ -20,11 +20,11 @@ the interesting functions as you go.
|
||||
The libssh library provides:
|
||||
|
||||
- <strong>Key Exchange Methods</strong>: <i>curve25519-sha256, curve25519-sha256@libssh.org, ecdh-sha2-nistp256, ecdh-sha2-nistp384, ecdh-sha2-nistp521</i>, diffie-hellman-group1-sha1, diffie-hellman-group14-sha1
|
||||
- <strong>Hostkey Types</strong>: <i>ssh-ed25519, ecdsa-sha2-nistp256, ecdsa-sha2-nistp384, ecdsa-sha2-nistp521</i>, ssh-dss, ssh-rsa
|
||||
- <strong>Public Key Algorithms</strong>: ssh-ed25519, ecdsa-sha2-nistp256, ecdsa-sha2-nistp384, ecdsa-sha2-nistp521, ssh-rsa, rsa-sha2-512, rsa-sha2-256,ssh-dss
|
||||
- <strong>Ciphers</strong>: <i>aes256-ctr, aes192-ctr, aes128-ctr</i>, aes256-cbc (rijndael-cbc@lysator.liu.se), aes192-cbc, aes128-cbc, 3des-cbc, blowfish-cbc, none
|
||||
- <strong>Compression Schemes</strong>: zlib, <i>zlib@openssh.com</i>, none
|
||||
- <strong>MAC hashes</strong>: hmac-sha1, hmac-sha2-256, hmac-sha2-384, hmac-sha2-512, hmac-md5, none
|
||||
- <strong>Authentication</strong>: none, password, public-key, hostbased, keyboard-interactive, <i>gssapi-with-mic</i>
|
||||
- <strong>Authentication</strong>: none, password, public-key, keyboard-interactive, <i>gssapi-with-mic</i>
|
||||
- <strong>Channels</strong>: shell, exec (incl. SCP wrapper), direct-tcpip, subsystem, <i>auth-agent-req@openssh.com</i>
|
||||
- <strong>Global Requests</strong>: tcpip-forward, forwarded-tcpip
|
||||
- <strong>Channel Requests</strong>: x11, pty, <i>exit-status, signal, exit-signal, keepalive@openssh.com, auth-agent-req@openssh.com</i>
|
||||
|
||||
21
doc/that_style/LICENSE
Normal file
@@ -0,0 +1,21 @@
|
||||
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.
|
||||
22
doc/that_style/README.md
Normal file
@@ -0,0 +1,22 @@
|
||||
# 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).
|
||||
56
doc/that_style/header.html
Normal file
@@ -0,0 +1,56 @@
|
||||
<!-- 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 -->
|
||||
97
doc/that_style/img/doc.svg
Normal file
@@ -0,0 +1,97 @@
|
||||
<?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>
|
||||
|
After Width: | Height: | Size: 6.5 KiB |
77
doc/that_style/img/folderclosed.svg
Normal file
@@ -0,0 +1,77 @@
|
||||
<?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>
|
||||
|
After Width: | Height: | Size: 3.4 KiB |
83
doc/that_style/img/folderopen.svg
Normal file
@@ -0,0 +1,83 @@
|
||||
<?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>
|
||||
|
After Width: | Height: | Size: 4.1 KiB |
73
doc/that_style/img/mag_glass.svg
Normal file
@@ -0,0 +1,73 @@
|
||||
<?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>
|
||||
|
After Width: | Height: | Size: 3.8 KiB |
73
doc/that_style/img/nav_edge_inter.svg
Normal file
@@ -0,0 +1,73 @@
|
||||
<?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>
|
||||
|
After Width: | Height: | Size: 3.8 KiB |
73
doc/that_style/img/nav_edge_left.svg
Normal file
@@ -0,0 +1,73 @@
|
||||
<?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>
|
||||
|
After Width: | Height: | Size: 3.1 KiB |
73
doc/that_style/img/nav_edge_right.svg
Normal file
@@ -0,0 +1,73 @@
|
||||
<?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>
|
||||
|
After Width: | Height: | Size: 3.1 KiB |
120
doc/that_style/img/splitbar_handle.svg
Normal file
@@ -0,0 +1,120 @@
|
||||
<?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>
|
||||
|
After Width: | Height: | Size: 7.1 KiB |
BIN
doc/that_style/img/sync_off.png
Normal file
|
After Width: | Height: | Size: 483 B |
BIN
doc/that_style/img/sync_on.png
Normal file
|
After Width: | Height: | Size: 488 B |
32
doc/that_style/js/striped_bg.js
Normal file
@@ -0,0 +1,32 @@
|
||||
// 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);
|
||||
1431
doc/that_style/that_style.css
Normal file
@@ -3,64 +3,50 @@
|
||||
@section threads_with_libssh How to use libssh with threads
|
||||
|
||||
libssh may be used in multithreaded applications, but under several conditions :
|
||||
- Threading must be initialized during the initialization of libssh. This
|
||||
initialization must be done outside of any threading context.
|
||||
- If pthreads is being used by your application (or your framework's backend),
|
||||
you must link with libssh_threads dynamic library and initialize
|
||||
threading with the ssh_threads_pthreads threading object.
|
||||
- If an other threading library is being used by your application, you must
|
||||
implement all the methods of the ssh_threads_callbacks_struct structure
|
||||
and initialize libssh with it.
|
||||
- Your system must support libpthread or, in Windows environment,
|
||||
CriticalSection based mutex control.
|
||||
- Since version 0.8.0, threads initialization is called automatically in the
|
||||
library constructor if libssh is dynamically linked. This means it is no
|
||||
longer necessary to call ssh_init()/ssh_finalize().
|
||||
- If libssh is statically linked, threading must be initialized by calling
|
||||
ssh_init() before using any of libssh provided functions. This initialization
|
||||
must be done outside of any threading context. Don't forget to call
|
||||
ssh_finalize() to avoid memory leak
|
||||
- At all times, you may use different sessions inside threads, make parallel
|
||||
connections, read/write on different sessions and so on. You *cannot* use a
|
||||
single session (or channels for a single session) in several threads at the same
|
||||
time. This will most likely lead to internal state corruption. This limitation is
|
||||
being worked out and will maybe disappear later.
|
||||
|
||||
|
||||
@subsection threads_init Initialization of threads
|
||||
|
||||
To initialize threading, you must first select the threading model you want to
|
||||
use, using ssh_threads_set_callbacks(), then call ssh_init().
|
||||
Since version 0.8.0, it is no longer necessary to call ssh_init()/ssh_finalize()
|
||||
if libssh is dynamically linked.
|
||||
|
||||
@code
|
||||
#include <libssh/callbacks.h>
|
||||
...
|
||||
ssh_threads_set_callbacks(ssh_threads_get_noop());
|
||||
ssh_init();
|
||||
@endcode
|
||||
|
||||
ssh_threads_noop is the threading structure that does nothing. It's the
|
||||
threading callbacks being used by default when you're not using threading.
|
||||
If libssh is statically linked, call ssh_init() before using any of libssh
|
||||
provided functions.
|
||||
|
||||
@subsection threads_pthread Using libpthread with libssh
|
||||
|
||||
If your application is using libpthread, you may simply use the libpthread
|
||||
threading backend:
|
||||
Since version 0.8.0, libpthread is the default threads library used by libssh.
|
||||
|
||||
@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
|
||||
To use libpthread, simply link it to you application.
|
||||
|
||||
If you are using libssh statically linked, don't forget to call ssh_init()
|
||||
before using any of libssh provided functions (and ssh_finalize() in the end).
|
||||
|
||||
@subsection threads_other Using another threading library
|
||||
|
||||
You must find your way in the ssh_threads_callbacks_struct structure. You must
|
||||
implement the following methods :
|
||||
- mutex_lock
|
||||
- mutex_unlock
|
||||
- mutex_init
|
||||
- mutex_destroy
|
||||
- thread_id
|
||||
Since version 0.8.0, libssh does not support custom threading libraries.
|
||||
The change makes sense since the newer versions for libcrypto (OpenSSL) and
|
||||
libgcrypt don't support custom threading libraries.
|
||||
|
||||
The default used threading library is libpthread.
|
||||
Alternatively, in Windows environment, CriticalSection based mutex control can
|
||||
be used.
|
||||
|
||||
If your system does not support libpthread nor CriticalSection based mutex
|
||||
control, unfortunately, you cannot use libssh in multithreaded scenarios.
|
||||
|
||||
libgcrypt 1.6 and bigger backend does not support custom callback. Using anything else than pthreads (ssh_threads_get_pthread()) here will fail.
|
||||
Good luck !
|
||||
*/
|
||||
|
||||
@@ -17,46 +17,57 @@ endif()
|
||||
|
||||
if (UNIX AND NOT WIN32)
|
||||
add_executable(libssh_scp libssh_scp.c ${examples_SRCS})
|
||||
target_compile_options(libssh_scp PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
|
||||
target_link_libraries(libssh_scp ${LIBSSH_SHARED_LIBRARY})
|
||||
|
||||
add_executable(scp_download scp_download.c ${examples_SRCS})
|
||||
target_compile_options(scp_download PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
|
||||
target_link_libraries(scp_download ${LIBSSH_SHARED_LIBRARY})
|
||||
|
||||
add_executable(sshnetcat sshnetcat.c ${examples_SRCS})
|
||||
target_compile_options(sshnetcat PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
|
||||
target_link_libraries(sshnetcat ${LIBSSH_SHARED_LIBRARY})
|
||||
|
||||
if (WITH_SFTP)
|
||||
add_executable(samplesftp samplesftp.c ${examples_SRCS})
|
||||
target_compile_options(samplesftp PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
|
||||
target_link_libraries(samplesftp ${LIBSSH_SHARED_LIBRARY})
|
||||
endif (WITH_SFTP)
|
||||
|
||||
add_executable(ssh-client ssh_client.c ${examples_SRCS})
|
||||
target_compile_options(ssh-client PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
|
||||
target_link_libraries(ssh-client ${LIBSSH_SHARED_LIBRARY})
|
||||
|
||||
if (WITH_SERVER AND (ARGP_LIBRARY OR HAVE_ARGP_H))
|
||||
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})
|
||||
target_compile_options(exec PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
|
||||
target_link_libraries(exec ${LIBSSH_SHARED_LIBRARY})
|
||||
|
||||
add_executable(senddata senddata.c ${examples_SRCS})
|
||||
target_compile_options(senddata PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
|
||||
target_link_libraries(senddata ${LIBSSH_SHARED_LIBRARY})
|
||||
|
||||
add_executable(libsshpp libsshpp.cpp)
|
||||
|
||||
@@ -24,7 +24,8 @@ clients must be made or how a client should react.
|
||||
#include <libssh/libssh.h>
|
||||
#include "examples_common.h"
|
||||
|
||||
int authenticate_kbdint(ssh_session session, const char *password) {
|
||||
int authenticate_kbdint(ssh_session session, const char *password)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = ssh_userauth_kbdint(session, NULL, NULL);
|
||||
@@ -99,78 +100,80 @@ int authenticate_kbdint(ssh_session session, const char *password) {
|
||||
return err;
|
||||
}
|
||||
|
||||
static void error(ssh_session session){
|
||||
fprintf(stderr,"Authentication failed: %s\n",ssh_get_error(session));
|
||||
static void error(ssh_session session)
|
||||
{
|
||||
fprintf(stderr,"Authentication failed: %s\n",ssh_get_error(session));
|
||||
}
|
||||
|
||||
int authenticate_console(ssh_session session){
|
||||
int rc;
|
||||
int method;
|
||||
char password[128] = {0};
|
||||
char *banner;
|
||||
int authenticate_console(ssh_session session)
|
||||
{
|
||||
int rc;
|
||||
int method;
|
||||
char password[128] = {0};
|
||||
char *banner;
|
||||
|
||||
// Try to authenticate
|
||||
rc = ssh_userauth_none(session, NULL);
|
||||
if (rc == SSH_AUTH_ERROR) {
|
||||
error(session);
|
||||
return rc;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -33,7 +33,6 @@ clients must be made or how a client should react.
|
||||
#endif
|
||||
|
||||
int verify_knownhost(ssh_session session){
|
||||
char *hexa;
|
||||
enum ssh_known_hosts_e state;
|
||||
char buf[10];
|
||||
unsigned char *hash = NULL;
|
||||
@@ -47,7 +46,7 @@ int verify_knownhost(ssh_session session){
|
||||
}
|
||||
|
||||
rc = ssh_get_publickey_hash(srv_pubkey,
|
||||
SSH_PUBLICKEY_HASH_SHA1,
|
||||
SSH_PUBLICKEY_HASH_SHA256,
|
||||
&hash,
|
||||
&hlen);
|
||||
ssh_key_free(srv_pubkey);
|
||||
@@ -62,7 +61,7 @@ int verify_knownhost(ssh_session session){
|
||||
break; /* ok */
|
||||
case SSH_KNOWN_HOSTS_CHANGED:
|
||||
fprintf(stderr,"Host key for server changed : server's one is now :\n");
|
||||
ssh_print_hexa("Public key hash",hash, hlen);
|
||||
ssh_print_hash(SSH_PUBLICKEY_HASH_SHA256, hash, hlen);
|
||||
ssh_clean_pubkey_hash(&hash);
|
||||
fprintf(stderr,"For security reason, connection will be stopped\n");
|
||||
return -1;
|
||||
@@ -78,10 +77,10 @@ int verify_knownhost(ssh_session session){
|
||||
/* fallback to SSH_SERVER_NOT_KNOWN behavior */
|
||||
FALL_THROUGH;
|
||||
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);
|
||||
ssh_string_free_char(hexa);
|
||||
fprintf(stderr,
|
||||
"The server is unknown. Do you trust the host key (yes/no)?\n");
|
||||
ssh_print_hash(SSH_PUBLICKEY_HASH_SHA256, hash, hlen);
|
||||
|
||||
if (fgets(buf, sizeof(buf), stdin) == NULL) {
|
||||
ssh_clean_pubkey_hash(&hash);
|
||||
return -1;
|
||||
|
||||
@@ -25,148 +25,230 @@ program.
|
||||
static char **sources;
|
||||
static int nsources;
|
||||
static char *destination;
|
||||
static int verbosity=0;
|
||||
static int verbosity = 0;
|
||||
|
||||
struct location {
|
||||
int is_ssh;
|
||||
char *user;
|
||||
char *host;
|
||||
char *path;
|
||||
ssh_session session;
|
||||
ssh_scp scp;
|
||||
FILE *file;
|
||||
int is_ssh;
|
||||
char *user;
|
||||
char *host;
|
||||
char *path;
|
||||
ssh_session session;
|
||||
ssh_scp scp;
|
||||
FILE *file;
|
||||
};
|
||||
|
||||
enum {
|
||||
READ,
|
||||
WRITE
|
||||
READ,
|
||||
WRITE
|
||||
};
|
||||
|
||||
static void usage(const char *argv0){
|
||||
fprintf(stderr,"Usage : %s [options] [[user@]host1:]file1 ... \n"
|
||||
" [[user@]host2:]destination\n"
|
||||
"sample scp client - libssh-%s\n",
|
||||
// "Options :\n",
|
||||
// " -r : use RSA to verify host public key\n",
|
||||
argv0,
|
||||
ssh_version(0));
|
||||
exit(0);
|
||||
static void usage(const char *argv0) {
|
||||
fprintf(stderr, "Usage : %s [options] [[user@]host1:]file1 ... \n"
|
||||
" [[user@]host2:]destination\n"
|
||||
"sample scp client - libssh-%s\n",
|
||||
// "Options :\n",
|
||||
// " -r : use RSA to verify host public key\n",
|
||||
argv0,
|
||||
ssh_version(0));
|
||||
exit(0);
|
||||
}
|
||||
|
||||
static int opts(int argc, char **argv){
|
||||
int i;
|
||||
while((i=getopt(argc,argv,"v"))!=-1){
|
||||
switch(i){
|
||||
case 'v':
|
||||
verbosity++;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr,"unknown option %c\n",optopt);
|
||||
static int opts(int argc, char **argv) {
|
||||
int i;
|
||||
|
||||
while((i = getopt(argc, argv, "v")) != -1) {
|
||||
switch(i) {
|
||||
case 'v':
|
||||
verbosity++;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "unknown option %c\n", optopt);
|
||||
usage(argv[0]);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
nsources = argc - optind - 1;
|
||||
if (nsources < 1) {
|
||||
usage(argv[0]);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
nsources=argc-optind-1;
|
||||
if(nsources < 1){
|
||||
usage(argv[0]);
|
||||
return -1;
|
||||
}
|
||||
sources=malloc((nsources + 1) * sizeof(char *));
|
||||
if(sources == NULL)
|
||||
return -1;
|
||||
for(i=0;i<nsources;++i){
|
||||
sources[i] = argv[optind];
|
||||
optind++;
|
||||
}
|
||||
sources[i]=NULL;
|
||||
destination=argv[optind];
|
||||
return 0;
|
||||
|
||||
sources = malloc((nsources + 1) * sizeof(char *));
|
||||
if (sources == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
for(i = 0; i < nsources; ++i) {
|
||||
sources[i] = argv[optind];
|
||||
optind++;
|
||||
}
|
||||
|
||||
sources[i] = NULL;
|
||||
destination = argv[optind];
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct location *parse_location(char *loc){
|
||||
struct location *location;
|
||||
char *ptr;
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
location = malloc(sizeof(struct location));
|
||||
if (location == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
memset(location, 0, sizeof(struct location));
|
||||
static struct location *parse_location(char *loc) {
|
||||
struct location *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);
|
||||
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->host=strdup(loc);
|
||||
location->is_ssh = 0;
|
||||
location->path = strdup(loc);
|
||||
}
|
||||
} else {
|
||||
location->is_ssh=0;
|
||||
location->path=strdup(loc);
|
||||
}
|
||||
return location;
|
||||
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;
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
if(ssh_scp_init(loc->scp)==SSH_ERROR){
|
||||
fprintf(stderr,"error : %s\n",ssh_get_error(loc->session));
|
||||
ssh_scp_free(loc->scp);
|
||||
loc->scp = NULL;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
} else if(loc->is_ssh && flag==READ){
|
||||
loc->session=connect_ssh(loc->host, loc->user,verbosity);
|
||||
if(!loc->session){
|
||||
fprintf(stderr,"Couldn't connect to %s\n",loc->host);
|
||||
return -1;
|
||||
}
|
||||
loc->scp=ssh_scp_new(loc->session,SSH_SCP_READ,loc->path);
|
||||
if(!loc->scp){
|
||||
fprintf(stderr,"error : %s\n",ssh_get_error(loc->session));
|
||||
return -1;
|
||||
}
|
||||
if(ssh_scp_init(loc->scp)==SSH_ERROR){
|
||||
fprintf(stderr,"error : %s\n",ssh_get_error(loc->session));
|
||||
ssh_scp_free(loc->scp);
|
||||
loc->scp = NULL;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
} else {
|
||||
loc->file=fopen(loc->path,flag==READ ? "r":"w");
|
||||
if(!loc->file){
|
||||
if(errno==EISDIR){
|
||||
if(chdir(loc->path)){
|
||||
fprintf(stderr,"Error changing directory to %s: %s\n",loc->path,strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
fprintf(stderr,"Error opening %s: %s\n",loc->path,strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/** @brief copies files from source location to destination
|
||||
@@ -174,155 +256,197 @@ static int open_location(struct location *loc, int flag){
|
||||
* @param dest destination location
|
||||
* @param recursive Copy also directories
|
||||
*/
|
||||
static int do_copy(struct location *src, struct location *dest, int recursive){
|
||||
int size;
|
||||
socket_t fd;
|
||||
struct stat s;
|
||||
int w,r;
|
||||
char buffer[16384];
|
||||
int total=0;
|
||||
int mode;
|
||||
char *filename = NULL;
|
||||
/* recursive mode doesn't work yet */
|
||||
(void)recursive;
|
||||
/* Get the file name and size*/
|
||||
if(!src->is_ssh){
|
||||
fd = fileno(src->file);
|
||||
if (fd < 0) {
|
||||
fprintf(stderr, "Invalid file pointer, error: %s\n", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
r = fstat(fd, &s);
|
||||
if (r < 0) {
|
||||
return -1;
|
||||
}
|
||||
size=s.st_size;
|
||||
mode = s.st_mode & ~S_IFMT;
|
||||
filename=ssh_basename(src->path);
|
||||
} else {
|
||||
size=0;
|
||||
do {
|
||||
r=ssh_scp_pull_request(src->scp);
|
||||
if(r==SSH_SCP_REQUEST_NEWDIR){
|
||||
ssh_scp_deny_request(src->scp,"Not in recursive mode");
|
||||
continue;
|
||||
}
|
||||
if(r==SSH_SCP_REQUEST_NEWFILE){
|
||||
size=ssh_scp_request_get_size(src->scp);
|
||||
filename=strdup(ssh_scp_request_get_filename(src->scp));
|
||||
mode=ssh_scp_request_get_permissions(src->scp);
|
||||
//ssh_scp_accept_request(src->scp);
|
||||
break;
|
||||
}
|
||||
if(r==SSH_ERROR){
|
||||
fprintf(stderr,"Error: %s\n",ssh_get_error(src->session));
|
||||
static int do_copy(struct location *src, struct location *dest, int recursive) {
|
||||
int size;
|
||||
socket_t fd;
|
||||
struct stat s;
|
||||
int w, r;
|
||||
char buffer[16384];
|
||||
int total = 0;
|
||||
int mode;
|
||||
char *filename = NULL;
|
||||
/* recursive mode doesn't work yet */
|
||||
(void)recursive;
|
||||
/* Get the file name and size*/
|
||||
if (!src->is_ssh) {
|
||||
fd = fileno(src->file);
|
||||
if (fd < 0) {
|
||||
fprintf(stderr,
|
||||
"Invalid file pointer, error: %s\n",
|
||||
strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
r = fstat(fd, &s);
|
||||
if (r < 0) {
|
||||
return -1;
|
||||
}
|
||||
size = s.st_size;
|
||||
mode = s.st_mode & ~S_IFMT;
|
||||
filename = ssh_basename(src->path);
|
||||
} else {
|
||||
size = 0;
|
||||
do {
|
||||
r = ssh_scp_pull_request(src->scp);
|
||||
if (r == SSH_SCP_REQUEST_NEWDIR) {
|
||||
ssh_scp_deny_request(src->scp, "Not in recursive mode");
|
||||
continue;
|
||||
}
|
||||
if (r == SSH_SCP_REQUEST_NEWFILE) {
|
||||
size = ssh_scp_request_get_size(src->scp);
|
||||
filename = strdup(ssh_scp_request_get_filename(src->scp));
|
||||
mode = ssh_scp_request_get_permissions(src->scp);
|
||||
//ssh_scp_accept_request(src->scp);
|
||||
break;
|
||||
}
|
||||
if (r == SSH_ERROR) {
|
||||
fprintf(stderr,
|
||||
"Error: %s\n",
|
||||
ssh_get_error(src->session));
|
||||
ssh_string_free_char(filename);
|
||||
return -1;
|
||||
}
|
||||
} while(r != SSH_SCP_REQUEST_NEWFILE);
|
||||
}
|
||||
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 {
|
||||
if(src->is_ssh){
|
||||
r=ssh_scp_read(src->scp,buffer,sizeof(buffer));
|
||||
if(r==SSH_ERROR){
|
||||
fprintf(stderr,"Error reading scp: %s\n",ssh_get_error(src->session));
|
||||
ssh_string_free_char(filename);
|
||||
return -1;
|
||||
}
|
||||
if(r==0)
|
||||
break;
|
||||
} else {
|
||||
r=fread(buffer,1,sizeof(buffer),src->file);
|
||||
if(r==0)
|
||||
break;
|
||||
if(r<0){
|
||||
fprintf(stderr,"Error reading file: %s\n",strerror(errno));
|
||||
ssh_string_free_char(filename);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if(dest->is_ssh){
|
||||
w=ssh_scp_write(dest->scp,buffer,r);
|
||||
if(w == SSH_ERROR){
|
||||
fprintf(stderr,"Error writing in scp: %s\n",ssh_get_error(dest->session));
|
||||
ssh_scp_free(dest->scp);
|
||||
dest->scp=NULL;
|
||||
ssh_string_free_char(filename);
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
w=fwrite(buffer,r,1,dest->file);
|
||||
if(w<=0){
|
||||
fprintf(stderr,"Error writing in local file: %s\n",strerror(errno));
|
||||
ssh_string_free_char(filename);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
total+=r;
|
||||
if (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);
|
||||
}
|
||||
}
|
||||
|
||||
} while(total < size);
|
||||
ssh_string_free_char(filename);
|
||||
printf("wrote %d bytes\n",total);
|
||||
return 0;
|
||||
do {
|
||||
if (src->is_ssh) {
|
||||
r = ssh_scp_read(src->scp, buffer, sizeof(buffer));
|
||||
if (r == SSH_ERROR) {
|
||||
fprintf(stderr,
|
||||
"Error reading scp: %s\n",
|
||||
ssh_get_error(src->session));
|
||||
ssh_string_free_char(filename);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (r == 0) {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
r = fread(buffer, 1, sizeof(buffer), src->file);
|
||||
if (r == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (r < 0) {
|
||||
fprintf(stderr,
|
||||
"Error reading file: %s\n",
|
||||
strerror(errno));
|
||||
ssh_string_free_char(filename);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (dest->is_ssh) {
|
||||
w = ssh_scp_write(dest->scp, buffer, r);
|
||||
if (w == SSH_ERROR) {
|
||||
fprintf(stderr,
|
||||
"Error writing in scp: %s\n",
|
||||
ssh_get_error(dest->session));
|
||||
ssh_scp_free(dest->scp);
|
||||
dest->scp = NULL;
|
||||
ssh_string_free_char(filename);
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
w = fwrite(buffer, r, 1, dest->file);
|
||||
if (w <= 0) {
|
||||
fprintf(stderr,
|
||||
"Error writing in local file: %s\n",
|
||||
strerror(errno));
|
||||
ssh_string_free_char(filename);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
total += r;
|
||||
|
||||
} while(total < size);
|
||||
|
||||
ssh_string_free_char(filename);
|
||||
printf("wrote %d bytes\n", total);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv){
|
||||
struct location *dest, *src;
|
||||
int i;
|
||||
int r;
|
||||
if(opts(argc,argv)<0)
|
||||
return EXIT_FAILURE;
|
||||
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;
|
||||
int main(int argc, char **argv) {
|
||||
struct location *dest, *src;
|
||||
int i;
|
||||
int r;
|
||||
if (opts(argc, argv) < 0) {
|
||||
r = EXIT_FAILURE;
|
||||
goto end;
|
||||
}
|
||||
if(do_copy(src,dest,0) < 0){
|
||||
break;
|
||||
|
||||
dest = parse_location(destination);
|
||||
if (dest == NULL) {
|
||||
r = EXIT_FAILURE;
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
if (dest->is_ssh && dest->scp != NULL) {
|
||||
r=ssh_scp_close(dest->scp);
|
||||
if(r == SSH_ERROR){
|
||||
fprintf(stderr,"Error closing scp: %s\n",ssh_get_error(dest->session));
|
||||
ssh_scp_free(dest->scp);
|
||||
dest->scp=NULL;
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
fclose(dest->file);
|
||||
dest->file=NULL;
|
||||
}
|
||||
ssh_disconnect(dest->session);
|
||||
ssh_finalize();
|
||||
return 0;
|
||||
|
||||
if (open_location(dest, WRITE) < 0) {
|
||||
location_free(dest);
|
||||
r = EXIT_FAILURE;
|
||||
goto end;
|
||||
}
|
||||
|
||||
for (i = 0; i < nsources; ++i) {
|
||||
src = parse_location(sources[i]);
|
||||
if (src == NULL) {
|
||||
r = EXIT_FAILURE;
|
||||
goto close_dest;
|
||||
}
|
||||
|
||||
if (open_location(src, READ) < 0) {
|
||||
location_free(src);
|
||||
r = EXIT_FAILURE;
|
||||
goto close_dest;
|
||||
}
|
||||
|
||||
if (do_copy(src, dest, 0) < 0) {
|
||||
close_location(src);
|
||||
location_free(src);
|
||||
break;
|
||||
}
|
||||
|
||||
close_location(src);
|
||||
location_free(src);
|
||||
}
|
||||
|
||||
r = 0;
|
||||
|
||||
close_dest:
|
||||
close_location(dest);
|
||||
location_free(dest);
|
||||
end:
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -33,236 +33,259 @@ static int verbosity;
|
||||
static char *destination;
|
||||
|
||||
#define DATALEN 65536
|
||||
static void do_sftp(ssh_session session){
|
||||
sftp_session sftp=sftp_new(session);
|
||||
|
||||
static void do_sftp(ssh_session session) {
|
||||
sftp_session sftp = sftp_new(session);
|
||||
sftp_dir dir;
|
||||
sftp_attributes file;
|
||||
sftp_statvfs_t sftpstatvfs;
|
||||
struct statvfs sysstatvfs;
|
||||
sftp_file fichier;
|
||||
sftp_file to;
|
||||
int len=1;
|
||||
int len = 1;
|
||||
unsigned int i;
|
||||
char data[DATALEN]={0};
|
||||
char data[DATALEN] = {0};
|
||||
char *lnk;
|
||||
|
||||
unsigned int count;
|
||||
|
||||
if(!sftp){
|
||||
if (!sftp) {
|
||||
fprintf(stderr, "sftp error initialising channel: %s\n",
|
||||
ssh_get_error(session));
|
||||
return;
|
||||
ssh_get_error(session));
|
||||
goto end;
|
||||
}
|
||||
if(sftp_init(sftp)){
|
||||
|
||||
if (sftp_init(sftp)) {
|
||||
fprintf(stderr, "error initialising sftp: %s\n",
|
||||
ssh_get_error(session));
|
||||
return;
|
||||
ssh_get_error(session));
|
||||
goto end;
|
||||
}
|
||||
|
||||
printf("Additional SFTP extensions provided by the server:\n");
|
||||
count = sftp_extensions_get_count(sftp);
|
||||
for (i = 0; i < count; i++) {
|
||||
printf("\t%s, version: %s\n",
|
||||
sftp_extensions_get_name(sftp, i),
|
||||
sftp_extensions_get_data(sftp, i));
|
||||
printf("\t%s, version: %s\n",
|
||||
sftp_extensions_get_name(sftp, i),
|
||||
sftp_extensions_get_data(sftp, i));
|
||||
}
|
||||
|
||||
/* test symlink and readlink */
|
||||
if (sftp_symlink(sftp, "/tmp/this_is_the_link",
|
||||
"/tmp/sftp_symlink_test") < 0) {
|
||||
fprintf(stderr, "Could not create link (%s)\n", ssh_get_error(session));
|
||||
return;
|
||||
"/tmp/sftp_symlink_test") < 0)
|
||||
{
|
||||
fprintf(stderr, "Could not create link (%s)\n",
|
||||
ssh_get_error(session));
|
||||
goto end;
|
||||
}
|
||||
|
||||
lnk = sftp_readlink(sftp, "/tmp/sftp_symlink_test");
|
||||
if (lnk == NULL) {
|
||||
fprintf(stderr, "Could not read link (%s)\n", ssh_get_error(session));
|
||||
return;
|
||||
fprintf(stderr, "Could not read link (%s)\n", ssh_get_error(session));
|
||||
goto end;
|
||||
}
|
||||
printf("readlink /tmp/sftp_symlink_test: %s\n", lnk);
|
||||
|
||||
sftp_unlink(sftp, "/tmp/sftp_symlink_test");
|
||||
|
||||
if (sftp_extension_supported(sftp, "statvfs@openssh.com", "2")) {
|
||||
sftpstatvfs = sftp_statvfs(sftp, "/tmp");
|
||||
if (sftpstatvfs == NULL) {
|
||||
fprintf(stderr, "statvfs failed (%s)\n", ssh_get_error(session));
|
||||
return;
|
||||
}
|
||||
sftpstatvfs = sftp_statvfs(sftp, "/tmp");
|
||||
if (sftpstatvfs == NULL) {
|
||||
fprintf(stderr, "statvfs failed (%s)\n", ssh_get_error(session));
|
||||
goto end;
|
||||
}
|
||||
|
||||
printf("sftp statvfs:\n"
|
||||
"\tfile system block size: %llu\n"
|
||||
"\tfundamental fs block size: %llu\n"
|
||||
"\tnumber of blocks (unit f_frsize): %llu\n"
|
||||
"\tfree blocks in file system: %llu\n"
|
||||
"\tfree blocks for non-root: %llu\n"
|
||||
"\ttotal file inodes: %llu\n"
|
||||
"\tfree file inodes: %llu\n"
|
||||
"\tfree file inodes for to non-root: %llu\n"
|
||||
"\tfile system id: %llu\n"
|
||||
"\tbit mask of f_flag values: %llu\n"
|
||||
"\tmaximum filename length: %llu\n",
|
||||
(unsigned long long) sftpstatvfs->f_bsize,
|
||||
(unsigned long long) sftpstatvfs->f_frsize,
|
||||
(unsigned long long) sftpstatvfs->f_blocks,
|
||||
(unsigned long long) sftpstatvfs->f_bfree,
|
||||
(unsigned long long) sftpstatvfs->f_bavail,
|
||||
(unsigned long long) sftpstatvfs->f_files,
|
||||
(unsigned long long) sftpstatvfs->f_ffree,
|
||||
(unsigned long long) sftpstatvfs->f_favail,
|
||||
(unsigned long long) sftpstatvfs->f_fsid,
|
||||
(unsigned long long) sftpstatvfs->f_flag,
|
||||
(unsigned long long) sftpstatvfs->f_namemax);
|
||||
printf("sftp statvfs:\n"
|
||||
"\tfile system block size: %llu\n"
|
||||
"\tfundamental fs block size: %llu\n"
|
||||
"\tnumber of blocks (unit f_frsize): %llu\n"
|
||||
"\tfree blocks in file system: %llu\n"
|
||||
"\tfree blocks for non-root: %llu\n"
|
||||
"\ttotal file inodes: %llu\n"
|
||||
"\tfree file inodes: %llu\n"
|
||||
"\tfree file inodes for to non-root: %llu\n"
|
||||
"\tfile system id: %llu\n"
|
||||
"\tbit mask of f_flag values: %llu\n"
|
||||
"\tmaximum filename length: %llu\n",
|
||||
(unsigned long long) sftpstatvfs->f_bsize,
|
||||
(unsigned long long) sftpstatvfs->f_frsize,
|
||||
(unsigned long long) sftpstatvfs->f_blocks,
|
||||
(unsigned long long) sftpstatvfs->f_bfree,
|
||||
(unsigned long long) sftpstatvfs->f_bavail,
|
||||
(unsigned long long) sftpstatvfs->f_files,
|
||||
(unsigned long long) sftpstatvfs->f_ffree,
|
||||
(unsigned long long) sftpstatvfs->f_favail,
|
||||
(unsigned long long) sftpstatvfs->f_fsid,
|
||||
(unsigned long long) sftpstatvfs->f_flag,
|
||||
(unsigned long long) sftpstatvfs->f_namemax);
|
||||
|
||||
sftp_statvfs_free(sftpstatvfs);
|
||||
sftp_statvfs_free(sftpstatvfs);
|
||||
|
||||
if (statvfs("/tmp", &sysstatvfs) < 0) {
|
||||
fprintf(stderr, "statvfs failed (%s)\n", strerror(errno));
|
||||
return;
|
||||
}
|
||||
if (statvfs("/tmp", &sysstatvfs) < 0) {
|
||||
fprintf(stderr, "statvfs failed (%s)\n", strerror(errno));
|
||||
goto end;
|
||||
}
|
||||
|
||||
printf("sys statvfs:\n"
|
||||
"\tfile system block size: %llu\n"
|
||||
"\tfundamental fs block size: %llu\n"
|
||||
"\tnumber of blocks (unit f_frsize): %llu\n"
|
||||
"\tfree blocks in file system: %llu\n"
|
||||
"\tfree blocks for non-root: %llu\n"
|
||||
"\ttotal file inodes: %llu\n"
|
||||
"\tfree file inodes: %llu\n"
|
||||
"\tfree file inodes for to non-root: %llu\n"
|
||||
"\tfile system id: %llu\n"
|
||||
"\tbit mask of f_flag values: %llu\n"
|
||||
"\tmaximum filename length: %llu\n",
|
||||
(unsigned long long) sysstatvfs.f_bsize,
|
||||
(unsigned long long) sysstatvfs.f_frsize,
|
||||
(unsigned long long) sysstatvfs.f_blocks,
|
||||
(unsigned long long) sysstatvfs.f_bfree,
|
||||
(unsigned long long) sysstatvfs.f_bavail,
|
||||
(unsigned long long) sysstatvfs.f_files,
|
||||
(unsigned long long) sysstatvfs.f_ffree,
|
||||
(unsigned long long) sysstatvfs.f_favail,
|
||||
(unsigned long long) sysstatvfs.f_fsid,
|
||||
(unsigned long long) sysstatvfs.f_flag,
|
||||
(unsigned long long) sysstatvfs.f_namemax);
|
||||
printf("sys statvfs:\n"
|
||||
"\tfile system block size: %llu\n"
|
||||
"\tfundamental fs block size: %llu\n"
|
||||
"\tnumber of blocks (unit f_frsize): %llu\n"
|
||||
"\tfree blocks in file system: %llu\n"
|
||||
"\tfree blocks for non-root: %llu\n"
|
||||
"\ttotal file inodes: %llu\n"
|
||||
"\tfree file inodes: %llu\n"
|
||||
"\tfree file inodes for to non-root: %llu\n"
|
||||
"\tfile system id: %llu\n"
|
||||
"\tbit mask of f_flag values: %llu\n"
|
||||
"\tmaximum filename length: %llu\n",
|
||||
(unsigned long long) sysstatvfs.f_bsize,
|
||||
(unsigned long long) sysstatvfs.f_frsize,
|
||||
(unsigned long long) sysstatvfs.f_blocks,
|
||||
(unsigned long long) sysstatvfs.f_bfree,
|
||||
(unsigned long long) sysstatvfs.f_bavail,
|
||||
(unsigned long long) sysstatvfs.f_files,
|
||||
(unsigned long long) sysstatvfs.f_ffree,
|
||||
(unsigned long long) sysstatvfs.f_favail,
|
||||
(unsigned long long) sysstatvfs.f_fsid,
|
||||
(unsigned long long) sysstatvfs.f_flag,
|
||||
(unsigned long long) sysstatvfs.f_namemax);
|
||||
}
|
||||
|
||||
/* the connection is made */
|
||||
/* opening a directory */
|
||||
dir=sftp_opendir(sftp,"./");
|
||||
if(!dir) {
|
||||
dir = sftp_opendir(sftp, "./");
|
||||
if (!dir) {
|
||||
fprintf(stderr, "Directory not opened(%s)\n", ssh_get_error(session));
|
||||
return ;
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* reading the whole directory, file by file */
|
||||
while((file=sftp_readdir(sftp,dir))){
|
||||
while ((file = sftp_readdir(sftp, dir))) {
|
||||
fprintf(stderr, "%30s(%.8o) : %s(%.5d) %s(%.5d) : %.10llu bytes\n",
|
||||
file->name,
|
||||
file->permissions,
|
||||
file->owner,
|
||||
file->uid,
|
||||
file->group,
|
||||
file->gid,
|
||||
(long long unsigned int) file->size);
|
||||
file->name,
|
||||
file->permissions,
|
||||
file->owner,
|
||||
file->uid,
|
||||
file->group,
|
||||
file->gid,
|
||||
(long long unsigned int) file->size);
|
||||
sftp_attributes_free(file);
|
||||
}
|
||||
/* when file=NULL, an error has occured OR the directory listing is end of file */
|
||||
if(!sftp_dir_eof(dir)){
|
||||
|
||||
/* when file = NULL, an error has occured OR the directory listing is end of
|
||||
* file */
|
||||
if (!sftp_dir_eof(dir)) {
|
||||
fprintf(stderr, "Error: %s\n", ssh_get_error(session));
|
||||
return;
|
||||
goto end;
|
||||
}
|
||||
if(sftp_closedir(dir)){
|
||||
|
||||
if (sftp_closedir(dir)) {
|
||||
fprintf(stderr, "Error: %s\n", ssh_get_error(session));
|
||||
return;
|
||||
goto end;
|
||||
}
|
||||
/* this will open a file and copy it into your /home directory */
|
||||
/* the small buffer size was intended to stress the library. of course, you can use a buffer till 20kbytes without problem */
|
||||
/* the small buffer size was intended to stress the library. of course, you
|
||||
* can use a buffer till 20kbytes without problem */
|
||||
|
||||
fichier=sftp_open(sftp,"/usr/bin/ssh",O_RDONLY, 0);
|
||||
if(!fichier){
|
||||
fichier = sftp_open(sftp, "/usr/bin/ssh", O_RDONLY, 0);
|
||||
if (!fichier) {
|
||||
fprintf(stderr, "Error opening /usr/bin/ssh: %s\n",
|
||||
ssh_get_error(session));
|
||||
return;
|
||||
ssh_get_error(session));
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* open a file for writing... */
|
||||
to=sftp_open(sftp,"ssh-copy",O_WRONLY | O_CREAT, 0700);
|
||||
if(!to){
|
||||
to = sftp_open(sftp, "ssh-copy", O_WRONLY | O_CREAT, 0700);
|
||||
if (!to) {
|
||||
fprintf(stderr, "Error opening ssh-copy for writing: %s\n",
|
||||
ssh_get_error(session));
|
||||
return;
|
||||
ssh_get_error(session));
|
||||
sftp_close(fichier);
|
||||
goto end;
|
||||
}
|
||||
while((len=sftp_read(fichier,data,4096)) > 0){
|
||||
if(sftp_write(to,data,len)!=len){
|
||||
|
||||
while ((len = sftp_read(fichier, data, 4096)) > 0) {
|
||||
if (sftp_write(to, data, len) != len) {
|
||||
fprintf(stderr, "Error writing %d bytes: %s\n",
|
||||
len, ssh_get_error(session));
|
||||
return;
|
||||
len, ssh_get_error(session));
|
||||
sftp_close(to);
|
||||
sftp_close(fichier);
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
printf("finished\n");
|
||||
if(len<0)
|
||||
if (len < 0) {
|
||||
fprintf(stderr, "Error reading file: %s\n", ssh_get_error(session));
|
||||
}
|
||||
|
||||
sftp_close(fichier);
|
||||
sftp_close(to);
|
||||
printf("fichiers ferm\n");
|
||||
to=sftp_open(sftp,"/tmp/grosfichier",O_WRONLY|O_CREAT, 0644);
|
||||
for(i=0;i<1000;++i){
|
||||
len=sftp_write(to,data,DATALEN);
|
||||
printf("wrote %d bytes\n",len);
|
||||
if(len != DATALEN){
|
||||
printf("chunk %d : %d (%s)\n",i,len,ssh_get_error(session));
|
||||
to = sftp_open(sftp, "/tmp/grosfichier", O_WRONLY|O_CREAT, 0644);
|
||||
|
||||
for (i = 0; i < 1000; ++i) {
|
||||
len = sftp_write(to, data, DATALEN);
|
||||
printf("wrote %d bytes\n", len);
|
||||
if (len != DATALEN) {
|
||||
printf("chunk %d : %d (%s)\n", i, len, ssh_get_error(session));
|
||||
}
|
||||
}
|
||||
sftp_close(to);
|
||||
|
||||
sftp_close(to);
|
||||
end:
|
||||
/* close the sftp session */
|
||||
sftp_free(sftp);
|
||||
printf("sftp session terminated\n");
|
||||
}
|
||||
|
||||
static void usage(const char *argv0){
|
||||
fprintf(stderr,"Usage : %s [-v] remotehost\n"
|
||||
"sample sftp test client - libssh-%s\n"
|
||||
"Options :\n"
|
||||
" -v : increase log verbosity\n",
|
||||
argv0,
|
||||
ssh_version(0));
|
||||
exit(0);
|
||||
static void usage(const char *argv0) {
|
||||
fprintf(stderr, "Usage : %s [-v] remotehost\n"
|
||||
"sample sftp test client - libssh-%s\n"
|
||||
"Options :\n"
|
||||
" -v : increase log verbosity\n",
|
||||
argv0,
|
||||
ssh_version(0));
|
||||
exit(0);
|
||||
}
|
||||
|
||||
static int opts(int argc, char **argv){
|
||||
int i;
|
||||
while((i=getopt(argc,argv,"v"))!=-1){
|
||||
switch(i){
|
||||
case 'v':
|
||||
verbosity++;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr,"unknown option %c\n",optopt);
|
||||
static int opts(int argc, char **argv) {
|
||||
int i;
|
||||
|
||||
while ((i = getopt(argc, argv, "v")) != -1) {
|
||||
switch(i) {
|
||||
case 'v':
|
||||
verbosity++;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "unknown option %c\n", optopt);
|
||||
usage(argv[0]);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
destination = argv[optind];
|
||||
if (destination == NULL) {
|
||||
usage(argv[0]);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
destination=argv[optind];
|
||||
if(destination == NULL){
|
||||
usage(argv[0]);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv){
|
||||
ssh_session session;
|
||||
if(opts(argc,argv)<0)
|
||||
return EXIT_FAILURE;
|
||||
session=connect_ssh(destination,NULL,verbosity);
|
||||
if(session == NULL)
|
||||
return EXIT_FAILURE;
|
||||
do_sftp(session);
|
||||
ssh_disconnect(session);
|
||||
ssh_free(session);
|
||||
return 0;
|
||||
int main(int argc, char **argv) {
|
||||
ssh_session session;
|
||||
|
||||
if (opts(argc, argv) < 0) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
session = connect_ssh(destination, NULL, verbosity);
|
||||
if (session == NULL) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
do_sftp(session);
|
||||
ssh_disconnect(session);
|
||||
ssh_free(session);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -48,12 +48,17 @@ static char *user;
|
||||
static char *cmds[MAXCMD];
|
||||
static struct termios terminal;
|
||||
|
||||
static char *pcap_file=NULL;
|
||||
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) {
|
||||
static int auth_callback(const char *prompt,
|
||||
char *buf,
|
||||
size_t len,
|
||||
int echo,
|
||||
int verify,
|
||||
void *userdata)
|
||||
{
|
||||
(void) verify;
|
||||
(void) userdata;
|
||||
|
||||
@@ -61,11 +66,12 @@ static int auth_callback(const char *prompt, char *buf, size_t len,
|
||||
}
|
||||
|
||||
struct ssh_callbacks_struct cb = {
|
||||
.auth_function=auth_callback,
|
||||
.userdata=NULL
|
||||
.auth_function = auth_callback,
|
||||
.userdata = NULL,
|
||||
};
|
||||
|
||||
static void add_cmd(char *cmd){
|
||||
static void add_cmd(char *cmd)
|
||||
{
|
||||
int n;
|
||||
|
||||
for (n = 0; (n < MAXCMD) && cmds[n] != NULL; n++);
|
||||
@@ -73,7 +79,8 @@ static void add_cmd(char *cmd){
|
||||
if (n == MAXCMD) {
|
||||
return;
|
||||
}
|
||||
cmds[n]=strdup(cmd);
|
||||
|
||||
cmds[n] = strdup(cmd);
|
||||
}
|
||||
|
||||
static void usage(void)
|
||||
@@ -98,37 +105,43 @@ static void usage(void)
|
||||
exit(0);
|
||||
}
|
||||
|
||||
static int opts(int argc, char **argv){
|
||||
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){
|
||||
|
||||
while((i = getopt(argc,argv,"T:P:")) != -1) {
|
||||
switch(i){
|
||||
case 'P':
|
||||
pcap_file=optarg;
|
||||
break;
|
||||
case 'P':
|
||||
pcap_file = optarg;
|
||||
break;
|
||||
#ifndef _WIN32
|
||||
case 'T':
|
||||
proxycommand=optarg;
|
||||
case 'T':
|
||||
proxycommand = optarg;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
fprintf(stderr,"unknown option %c\n",optopt);
|
||||
usage();
|
||||
default:
|
||||
fprintf(stderr, "Unknown option %c\n", optopt);
|
||||
usage();
|
||||
}
|
||||
}
|
||||
if(optind < argc)
|
||||
host=argv[optind++];
|
||||
while(optind < argc)
|
||||
if (optind < argc) {
|
||||
host = argv[optind++];
|
||||
}
|
||||
|
||||
while(optind < argc) {
|
||||
add_cmd(argv[optind++]);
|
||||
if(host==NULL)
|
||||
}
|
||||
|
||||
if (host == NULL) {
|
||||
usage();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef HAVE_CFMAKERAW
|
||||
static void cfmakeraw(struct termios *termios_p){
|
||||
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);
|
||||
@@ -138,44 +151,53 @@ static void cfmakeraw(struct termios *termios_p){
|
||||
#endif
|
||||
|
||||
|
||||
static void do_cleanup(int i) {
|
||||
static void do_cleanup(int i)
|
||||
{
|
||||
/* unused variable */
|
||||
(void) i;
|
||||
|
||||
tcsetattr(0,TCSANOW,&terminal);
|
||||
tcsetattr(0, TCSANOW, &terminal);
|
||||
}
|
||||
|
||||
static void do_exit(int i) {
|
||||
/* unused variable */
|
||||
(void) i;
|
||||
static void do_exit(int i)
|
||||
{
|
||||
/* unused variable */
|
||||
(void) i;
|
||||
|
||||
do_cleanup(0);
|
||||
exit(0);
|
||||
do_cleanup(0);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
ssh_channel chan;
|
||||
int signal_delayed=0;
|
||||
static ssh_channel chan;
|
||||
static int signal_delayed = 0;
|
||||
|
||||
static void sigwindowchanged(int i){
|
||||
(void) i;
|
||||
signal_delayed=1;
|
||||
static void sigwindowchanged(int i)
|
||||
{
|
||||
(void) i;
|
||||
signal_delayed = 1;
|
||||
}
|
||||
|
||||
static void setsignal(void){
|
||||
static void setsignal(void)
|
||||
{
|
||||
signal(SIGWINCH, sigwindowchanged);
|
||||
signal_delayed=0;
|
||||
signal_delayed = 0;
|
||||
}
|
||||
|
||||
static void sizechanged(void){
|
||||
struct winsize win = { 0, 0, 0, 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);
|
||||
// printf("Changed pty size\n");
|
||||
setsignal();
|
||||
}
|
||||
|
||||
static void select_loop(ssh_session session,ssh_channel channel){
|
||||
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 */
|
||||
@@ -196,9 +218,10 @@ static void select_loop(ssh_session session,ssh_channel channel){
|
||||
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)
|
||||
while (ssh_channel_is_open(channel)) {
|
||||
if (signal_delayed) {
|
||||
sizechanged();
|
||||
}
|
||||
ssh_event_dopoll(event, 60000);
|
||||
}
|
||||
ssh_event_remove_connector(event, connector_in);
|
||||
@@ -213,121 +236,148 @@ static void select_loop(ssh_session session,ssh_channel channel){
|
||||
ssh_channel_free(channel);
|
||||
}
|
||||
|
||||
static void shell(ssh_session session){
|
||||
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 (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));
|
||||
|
||||
if (ssh_channel_open_session(channel)) {
|
||||
printf("Error opening channel : %s\n", ssh_get_error(session));
|
||||
return;
|
||||
}
|
||||
chan=channel;
|
||||
if(interactive){
|
||||
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));
|
||||
|
||||
if (ssh_channel_request_shell(channel)) {
|
||||
printf("Requesting shell : %s\n", ssh_get_error(session));
|
||||
return;
|
||||
}
|
||||
if(interactive){
|
||||
|
||||
if (interactive) {
|
||||
cfmakeraw(&terminal_local);
|
||||
tcsetattr(0,TCSANOW,&terminal_local);
|
||||
tcsetattr(0, TCSANOW, &terminal_local);
|
||||
setsignal();
|
||||
}
|
||||
signal(SIGTERM,do_cleanup);
|
||||
select_loop(session,channel);
|
||||
if(interactive)
|
||||
do_cleanup(0);
|
||||
signal(SIGTERM, do_cleanup);
|
||||
select_loop(session, channel);
|
||||
if (interactive) {
|
||||
do_cleanup(0);
|
||||
}
|
||||
}
|
||||
|
||||
static void batch_shell(ssh_session session){
|
||||
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);
|
||||
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));
|
||||
if (ssh_channel_request_exec(channel, buffer)) {
|
||||
printf("Error executing '%s' : %s\n", buffer, ssh_get_error(session));
|
||||
return;
|
||||
}
|
||||
select_loop(session,channel);
|
||||
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);
|
||||
static int client(ssh_session session)
|
||||
{
|
||||
int auth = 0;
|
||||
char *banner;
|
||||
int state;
|
||||
|
||||
if(ssh_connect(session)){
|
||||
fprintf(stderr,"Connection failed : %s\n",ssh_get_error(session));
|
||||
return -1;
|
||||
}
|
||||
state=verify_knownhost(session);
|
||||
if (state != 0)
|
||||
return -1;
|
||||
ssh_userauth_none(session, NULL);
|
||||
banner=ssh_get_issue_banner(session);
|
||||
if(banner){
|
||||
printf("%s\n",banner);
|
||||
free(banner);
|
||||
}
|
||||
auth=authenticate_console(session);
|
||||
if(auth != SSH_AUTH_SUCCESS){
|
||||
return -1;
|
||||
}
|
||||
if(!cmds[0])
|
||||
shell(session);
|
||||
else
|
||||
batch_shell(session);
|
||||
return 0;
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
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);
|
||||
}
|
||||
|
||||
void cleanup_pcap(void);
|
||||
void cleanup_pcap(){
|
||||
if(pcap)
|
||||
ssh_pcap_file_free(pcap);
|
||||
pcap=NULL;
|
||||
static void cleanup_pcap(void)
|
||||
{
|
||||
if (pcap != NULL) {
|
||||
ssh_pcap_file_free(pcap);
|
||||
}
|
||||
pcap = NULL;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv){
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
ssh_session session;
|
||||
|
||||
session = ssh_new();
|
||||
@@ -335,12 +385,13 @@ int main(int argc, char **argv){
|
||||
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();
|
||||
if (ssh_options_getopt(session, &argc, argv)) {
|
||||
fprintf(stderr,
|
||||
"Error parsing command line: %s\n",
|
||||
ssh_get_error(session));
|
||||
usage();
|
||||
}
|
||||
opts(argc,argv);
|
||||
opts(argc, argv);
|
||||
signal(SIGTERM, do_exit);
|
||||
|
||||
set_pcap(session);
|
||||
|
||||
@@ -43,7 +43,8 @@ const char *port="22";
|
||||
char *pcap_file=NULL;
|
||||
#endif
|
||||
|
||||
static void usage(){
|
||||
static void usage(void)
|
||||
{
|
||||
fprintf(stderr,"Usage : sshnetcat [user@]host forwarded_host forwarded_port\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@@ -66,6 +66,9 @@
|
||||
#define SSH_COM_AGENT2_FAILURE 102
|
||||
|
||||
#define SSH_AGENT_OLD_SIGNATURE 0x01
|
||||
/* Signature flags from draft-miller-ssh-agent-02 */
|
||||
#define SSH_AGENT_RSA_SHA2_256 0x02
|
||||
#define SSH_AGENT_RSA_SHA2_512 0x04
|
||||
|
||||
struct ssh_agent_struct {
|
||||
struct ssh_socket_struct *sock;
|
||||
|
||||
@@ -76,6 +76,14 @@ enum ssh_auth_state_e {
|
||||
SSH_AUTH_STATE_GSSAPI_TOKEN,
|
||||
/** We have sent the MIC and expecting to be authenticated */
|
||||
SSH_AUTH_STATE_GSSAPI_MIC_SENT,
|
||||
/** We have offered a pubkey to check if it is supported */
|
||||
SSH_AUTH_STATE_PUBKEY_OFFER_SENT,
|
||||
/** We have sent pubkey and signature expecting to be authenticated */
|
||||
SSH_AUTH_STATE_PUBKEY_AUTH_SENT,
|
||||
/** We have sent a password expecting to be authenticated */
|
||||
SSH_AUTH_STATE_PASSWORD_AUTH_SENT,
|
||||
/** We have sent a request without auth information (method 'none') */
|
||||
SSH_AUTH_STATE_AUTH_NONE_SENT,
|
||||
};
|
||||
|
||||
/** @internal
|
||||
|
||||
@@ -24,20 +24,6 @@
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "libssh/libssh.h"
|
||||
/*
|
||||
* Describes a buffer state
|
||||
* [XXXXXXXXXXXXDATA PAYLOAD XXXXXXXXXXXXXXXXXXXXXXXX]
|
||||
* ^ ^ ^ ^]
|
||||
* \_data points\_pos points here \_used points here | /
|
||||
* here Allocated
|
||||
*/
|
||||
struct ssh_buffer_struct {
|
||||
char *data;
|
||||
uint32_t used;
|
||||
uint32_t allocated;
|
||||
uint32_t pos;
|
||||
int secure;
|
||||
};
|
||||
|
||||
#define SSH_BUFFER_PACK_END ((uint32_t) 0x4f65feb3)
|
||||
|
||||
|
||||
@@ -92,7 +92,6 @@ SSH_PACKET_CALLBACK(channel_rcv_close);
|
||||
SSH_PACKET_CALLBACK(channel_rcv_request);
|
||||
SSH_PACKET_CALLBACK(channel_rcv_data);
|
||||
|
||||
ssh_channel ssh_channel_new(ssh_session session);
|
||||
int channel_default_bufferize(ssh_channel channel, void *data, int len,
|
||||
int is_stderr);
|
||||
int ssh_channel_flush(ssh_channel channel);
|
||||
|
||||
@@ -62,7 +62,11 @@ enum ssh_key_exchange_e {
|
||||
/* curve25519-sha256@libssh.org */
|
||||
SSH_KEX_CURVE25519_SHA256_LIBSSH_ORG,
|
||||
/* curve25519-sha256 */
|
||||
SSH_KEX_CURVE25519_SHA256
|
||||
SSH_KEX_CURVE25519_SHA256,
|
||||
/* diffie-hellman-group16-sha512 */
|
||||
SSH_KEX_DH_GROUP16_SHA512,
|
||||
/* diffie-hellman-group18-sha512 */
|
||||
SSH_KEX_DH_GROUP18_SHA512,
|
||||
};
|
||||
|
||||
enum ssh_cipher_e {
|
||||
|
||||
@@ -43,6 +43,7 @@ char **ssh_space_tokenize(const char *chain);
|
||||
int ssh_get_kex1(ssh_session session);
|
||||
char *ssh_find_matching(const char *in_d, const char *what_d);
|
||||
const char *ssh_kex_get_supported_method(uint32_t algo);
|
||||
const char *ssh_kex_get_default_methods(uint32_t algo);
|
||||
const char *ssh_kex_get_description(uint32_t algo);
|
||||
|
||||
#endif /* KEX_H_ */
|
||||
|
||||
@@ -101,8 +101,7 @@ int ssh_mbedcry_is_bit_set(bignum num, size_t pos);
|
||||
mbedtls_mpi_size(num))
|
||||
#define bignum_cmp(num1, num2) mbedtls_mpi_cmp_mpi(num1, num2)
|
||||
|
||||
mbedtls_entropy_context ssh_mbedtls_entropy;
|
||||
mbedtls_ctr_drbg_context ssh_mbedtls_ctr_drbg;
|
||||
mbedtls_ctr_drbg_context *ssh_get_mbedtls_ctr_drbg_context(void);
|
||||
|
||||
int ssh_mbedtls_random(void *where, int len, int strong);
|
||||
|
||||
|
||||
@@ -78,8 +78,8 @@
|
||||
|
||||
/* libssh version */
|
||||
#define LIBSSH_VERSION_MAJOR 0
|
||||
#define LIBSSH_VERSION_MINOR 7
|
||||
#define LIBSSH_VERSION_MICRO 90
|
||||
#define LIBSSH_VERSION_MINOR 8
|
||||
#define LIBSSH_VERSION_MICRO 4
|
||||
|
||||
#define LIBSSH_VERSION_INT SSH_VERSION_INT(LIBSSH_VERSION_MAJOR, \
|
||||
LIBSSH_VERSION_MINOR, \
|
||||
@@ -239,11 +239,39 @@ enum ssh_server_known_e {
|
||||
};
|
||||
|
||||
enum ssh_known_hosts_e {
|
||||
/**
|
||||
* There had been an error checking the host.
|
||||
*/
|
||||
SSH_KNOWN_HOSTS_ERROR = -2,
|
||||
|
||||
/**
|
||||
* The known host file does not exist. The host is thus unknown. File will
|
||||
* be created if host key is accepted.
|
||||
*/
|
||||
SSH_KNOWN_HOSTS_NOT_FOUND = -1,
|
||||
|
||||
/**
|
||||
* The server is unknown. User should confirm the public key hash is
|
||||
* correct.
|
||||
*/
|
||||
SSH_KNOWN_HOSTS_UNKNOWN = 0,
|
||||
|
||||
/**
|
||||
* The server is known and has not changed.
|
||||
*/
|
||||
SSH_KNOWN_HOSTS_OK,
|
||||
|
||||
/**
|
||||
* The server key has changed. Either you are under attack or the
|
||||
* administrator changed the key. You HAVE to warn the user about a
|
||||
* possible attack.
|
||||
*/
|
||||
SSH_KNOWN_HOSTS_CHANGED,
|
||||
|
||||
/**
|
||||
* The server gave use a key of a type while we had an other type recorded.
|
||||
* It is a possible attack.
|
||||
*/
|
||||
SSH_KNOWN_HOSTS_OTHER,
|
||||
};
|
||||
|
||||
@@ -376,6 +404,7 @@ enum ssh_options_e {
|
||||
SSH_OPTIONS_GSSAPI_AUTH,
|
||||
SSH_OPTIONS_GLOBAL_KNOWNHOSTS,
|
||||
SSH_OPTIONS_NODELAY,
|
||||
SSH_OPTIONS_PUBLICKEY_ACCEPTED_TYPES,
|
||||
};
|
||||
|
||||
enum {
|
||||
@@ -500,7 +529,8 @@ LIBSSH_API int ssh_get_server_publickey(ssh_session session, ssh_key *key);
|
||||
|
||||
enum ssh_publickey_hash_type {
|
||||
SSH_PUBLICKEY_HASH_SHA1,
|
||||
SSH_PUBLICKEY_HASH_MD5
|
||||
SSH_PUBLICKEY_HASH_MD5,
|
||||
SSH_PUBLICKEY_HASH_SHA256
|
||||
};
|
||||
LIBSSH_API int ssh_get_publickey_hash(const ssh_key key,
|
||||
enum ssh_publickey_hash_type type,
|
||||
@@ -600,6 +630,8 @@ typedef int (*ssh_auth_callback) (const char *prompt, char *buf, size_t len,
|
||||
int echo, int verify, void *userdata);
|
||||
|
||||
LIBSSH_API ssh_key ssh_key_new(void);
|
||||
#define SSH_KEY_FREE(x) \
|
||||
do { if ((x) != NULL) { ssh_key_free(x); x = NULL; } } while(0)
|
||||
LIBSSH_API void ssh_key_free (ssh_key key);
|
||||
LIBSSH_API enum ssh_keytypes_e ssh_key_type(const ssh_key key);
|
||||
LIBSSH_API const char *ssh_key_type_to_char(enum ssh_keytypes_e type);
|
||||
@@ -617,6 +649,11 @@ LIBSSH_API int ssh_pki_import_privkey_base64(const char *b64_key,
|
||||
ssh_auth_callback auth_fn,
|
||||
void *auth_data,
|
||||
ssh_key *pkey);
|
||||
LIBSSH_API int ssh_pki_export_privkey_base64(const ssh_key privkey,
|
||||
const char *passphrase,
|
||||
ssh_auth_callback auth_fn,
|
||||
void *auth_data,
|
||||
char **b64_key);
|
||||
LIBSSH_API int ssh_pki_import_privkey_file(const char *filename,
|
||||
const char *passphrase,
|
||||
ssh_auth_callback auth_fn,
|
||||
@@ -652,6 +689,10 @@ LIBSSH_API int ssh_pki_export_pubkey_file(const ssh_key key,
|
||||
|
||||
LIBSSH_API const char *ssh_pki_key_ecdsa_name(const ssh_key key);
|
||||
|
||||
LIBSSH_API char *ssh_get_fingerprint_hash(enum ssh_publickey_hash_type type,
|
||||
unsigned char *hash,
|
||||
size_t len);
|
||||
LIBSSH_API void ssh_print_hash(enum ssh_publickey_hash_type type, unsigned char *hash, size_t len);
|
||||
LIBSSH_API void ssh_print_hexa(const char *descr, const unsigned char *what, size_t len);
|
||||
LIBSSH_API int ssh_send_ignore (ssh_session session, const char *data);
|
||||
LIBSSH_API int ssh_send_debug (ssh_session session, const char *message, int always_display);
|
||||
@@ -726,12 +767,16 @@ LIBSSH_API void ssh_string_burn(ssh_string str);
|
||||
LIBSSH_API ssh_string ssh_string_copy(ssh_string str);
|
||||
LIBSSH_API void *ssh_string_data(ssh_string str);
|
||||
LIBSSH_API int ssh_string_fill(ssh_string str, const void *data, size_t len);
|
||||
#define SSH_STRING_FREE(x) \
|
||||
do { if ((x) != NULL) { ssh_string_free(x); x = NULL; } } while(0)
|
||||
LIBSSH_API void ssh_string_free(ssh_string str);
|
||||
LIBSSH_API ssh_string ssh_string_from_char(const char *what);
|
||||
LIBSSH_API size_t ssh_string_len(ssh_string str);
|
||||
LIBSSH_API ssh_string ssh_string_new(size_t size);
|
||||
LIBSSH_API const char *ssh_string_get_char(ssh_string str);
|
||||
LIBSSH_API char *ssh_string_to_char(ssh_string str);
|
||||
#define SSH_STRING_FREE_CHAR(x) \
|
||||
do { if ((x) != NULL) { ssh_string_free_char(x); x = NULL; } } while(0)
|
||||
LIBSSH_API void ssh_string_free_char(char *s);
|
||||
|
||||
LIBSSH_API int ssh_getpass(const char *prompt, char *buf, size_t len, int echo,
|
||||
@@ -760,6 +805,8 @@ LIBSSH_API const char* ssh_get_hmac_out(ssh_session session);
|
||||
|
||||
LIBSSH_API ssh_buffer ssh_buffer_new(void);
|
||||
LIBSSH_API void ssh_buffer_free(ssh_buffer buffer);
|
||||
#define SSH_BUFFER_FREE(x) \
|
||||
do { if ((x) != NULL) { ssh_buffer_free(x); x = NULL; } } while(0)
|
||||
LIBSSH_API int ssh_buffer_reinit(ssh_buffer buffer);
|
||||
LIBSSH_API int ssh_buffer_add_data(ssh_buffer buffer, const void *data, uint32_t len);
|
||||
LIBSSH_API uint32_t ssh_buffer_get_data(ssh_buffer buffer, void *data, uint32_t requestedlen);
|
||||
|
||||
@@ -195,11 +195,20 @@ public:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** @brief Authenticate through the "keyboard-interactive" method.
|
||||
* @param[in] The username to authenticate. You can specify NULL if ssh_option_set_username() has been used. You cannot try two different logins in a row.
|
||||
* @param[in] Undocumented. Set it to NULL.
|
||||
/**
|
||||
* @brief Authenticate through the "keyboard-interactive" method.
|
||||
*
|
||||
* @param[in] username The username to authenticate. You can specify NULL if
|
||||
* ssh_option_set_username() has been used. You cannot
|
||||
* try two different logins in a row.
|
||||
*
|
||||
* @param[in] submethods Undocumented. Set it to NULL.
|
||||
*
|
||||
* @throws SshException on error
|
||||
* @returns SSH_AUTH_SUCCESS, SSH_AUTH_PARTIAL, SSH_AUTH_DENIED, SSH_AUTH_ERROR, SSH_AUTH_INFO, SSH_AUTH_AGAIN
|
||||
*
|
||||
* @returns SSH_AUTH_SUCCESS, SSH_AUTH_PARTIAL, SSH_AUTH_DENIED,
|
||||
* SSH_AUTH_ERROR, SSH_AUTH_INFO, SSH_AUTH_AGAIN
|
||||
*
|
||||
* @see ssh_userauth_kbdint
|
||||
*/
|
||||
int userauthKbdint(const char* username, const char* submethods){
|
||||
@@ -216,15 +225,25 @@ public:
|
||||
return ssh_userauth_kbdint_getnprompts(c_session);
|
||||
}
|
||||
|
||||
/** @brief Set the answer for a question from a message block..
|
||||
* @param[in] index The number of the ith prompt.
|
||||
* @param[in] The answer to give to the server. The answer MUST be encoded UTF-8. It is up to the server how to interpret the value and validate it. However, if you read the answer in some other encoding, you MUST convert it to UTF-8.
|
||||
/**
|
||||
* @brief Set the answer for a question from a message block.
|
||||
*
|
||||
* @param[in] index The index number of the prompt.
|
||||
* @param[in] answer The answer to give to the server. The answer MUST be
|
||||
* encoded UTF-8. It is up to the server how to interpret
|
||||
* the value and validate it. However, if you read the
|
||||
* answer in some other encoding, you MUST convert it to
|
||||
* UTF-8.
|
||||
*
|
||||
* @throws SshException on error
|
||||
*
|
||||
* @returns 0 on success, < 0 on error
|
||||
*
|
||||
* @see ssh_userauth_kbdint_setanswer
|
||||
*/
|
||||
int userauthKbdintSetAnswer(unsigned int i, const char* answer){
|
||||
int ret=ssh_userauth_kbdint_setanswer(c_session, i, answer);
|
||||
int userauthKbdintSetAnswer(unsigned int index, const char *answer)
|
||||
{
|
||||
int ret = ssh_userauth_kbdint_setanswer(c_session, index, answer);
|
||||
ssh_throw(ret);
|
||||
return ret;
|
||||
}
|
||||
@@ -316,11 +335,10 @@ public:
|
||||
* @see ssh_get_issue_banner
|
||||
*/
|
||||
std::string getIssueBanner(){
|
||||
char *banner=ssh_get_issue_banner(c_session);
|
||||
std::string ret;
|
||||
if (banner)
|
||||
{
|
||||
ret= std::string(banner);
|
||||
char *banner = ssh_get_issue_banner(c_session);
|
||||
std::string ret = "";
|
||||
if (banner != NULL) {
|
||||
ret = std::string(banner);
|
||||
::free(banner);
|
||||
}
|
||||
return ret;
|
||||
@@ -438,9 +456,9 @@ private:
|
||||
class Channel {
|
||||
friend class Session;
|
||||
public:
|
||||
Channel(Session &session){
|
||||
channel=ssh_channel_new(session.getCSession());
|
||||
this->session=&session;
|
||||
Channel(Session &ssh_session){
|
||||
channel = ssh_channel_new(ssh_session.getCSession());
|
||||
this->session = &ssh_session;
|
||||
}
|
||||
~Channel(){
|
||||
ssh_channel_free(channel);
|
||||
@@ -641,9 +659,9 @@ protected:
|
||||
ssh_channel channel;
|
||||
|
||||
private:
|
||||
Channel (Session &session, ssh_channel c_channel){
|
||||
Channel (Session &ssh_session, ssh_channel c_channel){
|
||||
this->channel=c_channel;
|
||||
this->session=&session;
|
||||
this->session = &ssh_session;
|
||||
}
|
||||
/* No copy and no = operator */
|
||||
Channel(const Channel &);
|
||||
|
||||
@@ -43,6 +43,12 @@ enum ssh_packet_state_e {
|
||||
PACKET_STATE_PROCESSING
|
||||
};
|
||||
|
||||
enum ssh_packet_filter_result_e {
|
||||
SSH_PACKET_UNKNOWN,
|
||||
SSH_PACKET_ALLOWED,
|
||||
SSH_PACKET_DENIED
|
||||
};
|
||||
|
||||
int ssh_packet_send(ssh_session session);
|
||||
|
||||
SSH_PACKET_CALLBACK(ssh_packet_unimplemented);
|
||||
@@ -51,6 +57,7 @@ SSH_PACKET_CALLBACK(ssh_packet_ignore_callback);
|
||||
SSH_PACKET_CALLBACK(ssh_packet_dh_reply);
|
||||
SSH_PACKET_CALLBACK(ssh_packet_newkeys);
|
||||
SSH_PACKET_CALLBACK(ssh_packet_service_accept);
|
||||
SSH_PACKET_CALLBACK(ssh_packet_ext_info);
|
||||
|
||||
#ifdef WITH_SERVER
|
||||
SSH_PACKET_CALLBACK(ssh_packet_kexdh_init);
|
||||
|
||||
@@ -69,6 +69,7 @@ struct ssh_key_struct {
|
||||
|
||||
struct ssh_signature_struct {
|
||||
enum ssh_keytypes_e type;
|
||||
enum ssh_digest_e hash_type;
|
||||
const char *type_c;
|
||||
#ifdef HAVE_LIBGCRYPT
|
||||
gcry_sexp_t dsa_sig;
|
||||
@@ -95,6 +96,11 @@ typedef struct ssh_signature_struct *ssh_signature;
|
||||
ssh_key ssh_key_dup(const ssh_key key);
|
||||
void ssh_key_clean (ssh_key key);
|
||||
|
||||
const char *
|
||||
ssh_key_get_signature_algorithm(ssh_session session,
|
||||
enum ssh_keytypes_e type);
|
||||
enum ssh_keytypes_e ssh_key_type_from_signature_name(const char *name);
|
||||
|
||||
/* SSH Signature Functions */
|
||||
ssh_signature ssh_signature_new(void);
|
||||
void ssh_signature_free(ssh_signature sign);
|
||||
@@ -133,4 +139,5 @@ ssh_string ssh_srv_pki_do_sign_sessionid(ssh_session session,
|
||||
ssh_public_key ssh_pki_convert_key_to_publickey(const ssh_key key);
|
||||
ssh_private_key ssh_pki_convert_key_to_privatekey(const ssh_key key);
|
||||
|
||||
int ssh_key_algorithm_allowed(ssh_session session, const char *type);
|
||||
#endif /* PKI_H_ */
|
||||
|
||||
@@ -45,6 +45,10 @@ int bcrypt_pbkdf(const char *pass,
|
||||
|
||||
int pki_key_ecdsa_nid_from_name(const char *name);
|
||||
const char *pki_key_ecdsa_nid_to_name(int nid);
|
||||
const char *ssh_key_signature_to_char(enum ssh_keytypes_e type,
|
||||
enum ssh_digest_e hash_type);
|
||||
enum ssh_digest_e ssh_key_type_to_hash(ssh_session session,
|
||||
enum ssh_keytypes_e type);
|
||||
|
||||
/* SSH Key Functions */
|
||||
ssh_key pki_key_dup(const ssh_key key, int demote);
|
||||
@@ -68,6 +72,9 @@ ssh_string pki_private_key_to_pem(const ssh_key key,
|
||||
const char *passphrase,
|
||||
ssh_auth_callback auth_fn,
|
||||
void *auth_data);
|
||||
int pki_import_privkey_buffer(enum ssh_keytypes_e type,
|
||||
ssh_buffer buffer,
|
||||
ssh_key *pkey);
|
||||
|
||||
/* SSH Public Key Functions */
|
||||
int pki_pubkey_build_dss(ssh_key key,
|
||||
@@ -81,11 +88,32 @@ int pki_pubkey_build_rsa(ssh_key key,
|
||||
int pki_pubkey_build_ecdsa(ssh_key key, int nid, ssh_string e);
|
||||
ssh_string pki_publickey_to_blob(const ssh_key key);
|
||||
|
||||
/* SSH Private Key Functions */
|
||||
int pki_privkey_build_dss(ssh_key key,
|
||||
ssh_string p,
|
||||
ssh_string q,
|
||||
ssh_string g,
|
||||
ssh_string pubkey,
|
||||
ssh_string privkey);
|
||||
int pki_privkey_build_rsa(ssh_key key,
|
||||
ssh_string n,
|
||||
ssh_string e,
|
||||
ssh_string d,
|
||||
ssh_string iqmp,
|
||||
ssh_string p,
|
||||
ssh_string q);
|
||||
int pki_privkey_build_ecdsa(ssh_key key,
|
||||
int nid,
|
||||
ssh_string e,
|
||||
ssh_string exp);
|
||||
ssh_string pki_publickey_to_blob(const ssh_key key);
|
||||
|
||||
/* SSH Signature Functions */
|
||||
ssh_string pki_signature_to_blob(const ssh_signature sign);
|
||||
ssh_signature pki_signature_from_blob(const ssh_key pubkey,
|
||||
const ssh_string sig_blob,
|
||||
enum ssh_keytypes_e type);
|
||||
enum ssh_keytypes_e type,
|
||||
enum ssh_digest_e hash_type);
|
||||
int pki_signature_verify(ssh_session session,
|
||||
const ssh_signature sig,
|
||||
const ssh_key key,
|
||||
@@ -93,12 +121,18 @@ int pki_signature_verify(ssh_session session,
|
||||
size_t hlen);
|
||||
|
||||
/* SSH Signing Functions */
|
||||
ssh_signature pki_do_sign(const ssh_key privkey,
|
||||
const unsigned char *hash,
|
||||
size_t hlen);
|
||||
ssh_signature pki_do_sign_sessionid(const ssh_key key,
|
||||
const unsigned char *hash,
|
||||
size_t hlen);
|
||||
#define pki_do_sign(key, hash, hlen) \
|
||||
pki_do_sign_hash(key, hash, hlen, SSH_DIGEST_AUTO)
|
||||
ssh_signature pki_do_sign_hash(const ssh_key privkey,
|
||||
const unsigned char *hash,
|
||||
size_t hlen,
|
||||
enum ssh_digest_e hash_type);
|
||||
#define pki_do_sign_sessionid(key, hash, hlen) \
|
||||
pki_do_sign_sessionid_hash(key, hash, hlen, SSH_DIGEST_AUTO)
|
||||
ssh_signature pki_do_sign_sessionid_hash(const ssh_key key,
|
||||
const unsigned char *hash,
|
||||
size_t hlen,
|
||||
enum ssh_digest_e hash_type);
|
||||
int pki_ed25519_sign(const ssh_key privkey, ssh_signature sig,
|
||||
const unsigned char *hash, size_t hlen);
|
||||
int pki_ed25519_verify(const ssh_key pubkey, ssh_signature sig,
|
||||
@@ -110,8 +144,12 @@ int pki_ed25519_key_dup(ssh_key new, const ssh_key key);
|
||||
int pki_ed25519_public_key_to_blob(ssh_buffer buffer, ssh_key key);
|
||||
ssh_string pki_ed25519_sig_to_blob(ssh_signature sig);
|
||||
int pki_ed25519_sig_from_blob(ssh_signature sig, ssh_string sig_blob);
|
||||
int pki_privkey_build_ed25519(ssh_key key,
|
||||
ssh_string pubkey,
|
||||
ssh_string privkey);
|
||||
|
||||
/* PKI Container OpenSSH */
|
||||
ssh_key ssh_pki_openssh_pubkey_import(const char *text_key);
|
||||
ssh_key ssh_pki_openssh_privkey_import(const char *text_key,
|
||||
const char *passphrase, ssh_auth_callback auth_fn, void *auth_data);
|
||||
ssh_string ssh_pki_openssh_privkey_export(const ssh_key privkey,
|
||||
|
||||
@@ -44,6 +44,10 @@
|
||||
# endif
|
||||
#endif /* !defined(HAVE_STRTOULL) */
|
||||
|
||||
#if !defined(HAVE_STRNDUP)
|
||||
char *strndup(const char *s, size_t n);
|
||||
#endif /* ! HAVE_STRNDUP */
|
||||
|
||||
#ifdef HAVE_BYTESWAP_H
|
||||
#include <byteswap.h>
|
||||
#endif
|
||||
@@ -232,6 +236,7 @@ void _ssh_set_error_oom(void *error, const char *function);
|
||||
_ssh_set_error_invalid(error, __func__)
|
||||
void _ssh_set_error_invalid(void *error, const char *function);
|
||||
|
||||
void ssh_reset_error(void *error);
|
||||
|
||||
/* server.c */
|
||||
#ifdef WITH_SERVER
|
||||
@@ -257,6 +262,8 @@ int compress_buffer(ssh_session session,ssh_buffer buf);
|
||||
int decompress_buffer(ssh_session session,ssh_buffer buf, size_t maxlen);
|
||||
|
||||
/* match.c */
|
||||
int match_pattern_list(const char *string, const char *pattern,
|
||||
unsigned int len, int dolower);
|
||||
int match_hostname(const char *host, const char *pattern, unsigned int len);
|
||||
|
||||
/* connector.c */
|
||||
|
||||
@@ -86,6 +86,12 @@ enum ssh_pending_call_e {
|
||||
#define SSH_OPT_FLAG_KBDINT_AUTH 0x4
|
||||
#define SSH_OPT_FLAG_GSSAPI_AUTH 0x8
|
||||
|
||||
/* extensions flags */
|
||||
/* server-sig-algs extension */
|
||||
#define SSH_EXT_SIG_RSA_SHA256 0x01
|
||||
#define SSH_EXT_SIG_RSA_SHA512 0x02
|
||||
#define SSH_EXT_ALL SSH_EXT_SIG_RSA_SHA256 | SSH_EXT_SIG_RSA_SHA512
|
||||
|
||||
/* members that are common to ssh_session and ssh_bind */
|
||||
struct ssh_common_struct {
|
||||
struct error_struct error;
|
||||
@@ -114,6 +120,9 @@ struct ssh_session_struct {
|
||||
/* session flags (SSH_SESSION_FLAG_*) */
|
||||
int flags;
|
||||
|
||||
/* Extensions negotiated using RFC 8308 */
|
||||
uint32_t extensions;
|
||||
|
||||
ssh_string banner; /* that's the issue banner from
|
||||
the server */
|
||||
char *discon_msg; /* disconnect message from
|
||||
@@ -128,11 +137,16 @@ struct ssh_session_struct {
|
||||
enum ssh_session_state_e session_state;
|
||||
int packet_state;
|
||||
enum ssh_dh_state_e dh_handshake_state;
|
||||
enum ssh_auth_service_state_e auth_service_state;
|
||||
enum ssh_auth_state_e auth_state;
|
||||
enum ssh_channel_request_state_e global_req_state;
|
||||
struct ssh_agent_state_struct *agent_state;
|
||||
struct ssh_auth_auto_state_struct *auth_auto_state;
|
||||
|
||||
struct {
|
||||
struct ssh_auth_auto_state_struct *auto_state;
|
||||
enum ssh_auth_service_state_e service_state;
|
||||
enum ssh_auth_state_e state;
|
||||
uint32_t supported_methods;
|
||||
uint32_t current_method;
|
||||
} auth;
|
||||
|
||||
/*
|
||||
* RFC 4253, 7.1: if the first_kex_packet_follows flag was set in
|
||||
@@ -167,8 +181,8 @@ struct ssh_session_struct {
|
||||
/* The type of host key wanted by client */
|
||||
enum ssh_keytypes_e hostkey;
|
||||
} srv;
|
||||
|
||||
/* auths accepted by server */
|
||||
int auth_methods;
|
||||
struct ssh_list *ssh_message_list; /* list of delayed SSH messages */
|
||||
int (*ssh_message_callback)( struct ssh_session_struct *session, ssh_message msg, void *userdata);
|
||||
void *ssh_message_callback_data;
|
||||
@@ -191,6 +205,7 @@ struct ssh_session_struct {
|
||||
char *knownhosts;
|
||||
char *global_knownhosts;
|
||||
char *wanted_methods[10];
|
||||
char *pubkey_accepted_types;
|
||||
char *ProxyCommand;
|
||||
char *custombanner;
|
||||
unsigned long timeout; /* seconds */
|
||||
|
||||
@@ -84,6 +84,7 @@ struct sftp_session_struct {
|
||||
int errnum;
|
||||
void **handles;
|
||||
sftp_ext ext;
|
||||
sftp_packet read_packet;
|
||||
};
|
||||
|
||||
struct sftp_packet_struct {
|
||||
@@ -134,6 +135,7 @@ struct sftp_client_message_struct {
|
||||
ssh_string data; /* can be newpath of rename() */
|
||||
ssh_buffer complete_message; /* complete message in case of retransmission*/
|
||||
char *str_data; /* cstring version of data */
|
||||
char *submessage; /* for extended messages */
|
||||
};
|
||||
|
||||
struct sftp_request_queue_struct {
|
||||
@@ -862,6 +864,7 @@ LIBSSH_API const char *sftp_client_message_get_filename(sftp_client_message msg)
|
||||
LIBSSH_API void sftp_client_message_set_filename(sftp_client_message msg, const char *newname);
|
||||
LIBSSH_API const char *sftp_client_message_get_data(sftp_client_message msg);
|
||||
LIBSSH_API uint32_t sftp_client_message_get_flags(sftp_client_message msg);
|
||||
LIBSSH_API const char *sftp_client_message_get_submessage(sftp_client_message msg);
|
||||
LIBSSH_API int sftp_send_client_message(sftp_session sftp, sftp_client_message msg);
|
||||
LIBSSH_API int sftp_reply_name(sftp_client_message msg, const char *name,
|
||||
sftp_attributes attr);
|
||||
@@ -1011,6 +1014,7 @@ LIBSSH_API void sftp_handle_remove(sftp_session sftp, void *handle);
|
||||
#define SFTP_RENAME SSH_FXP_RENAME
|
||||
#define SFTP_READLINK SSH_FXP_READLINK
|
||||
#define SFTP_SYMLINK SSH_FXP_SYMLINK
|
||||
#define SFTP_EXTENDED SSH_FXP_EXTENDED
|
||||
|
||||
/* openssh flags */
|
||||
#define SSH_FXE_STATVFS_ST_RDONLY 0x1 /* read-only */
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#define SSH2_MSG_DEBUG 4
|
||||
#define SSH2_MSG_SERVICE_REQUEST 5
|
||||
#define SSH2_MSG_SERVICE_ACCEPT 6
|
||||
#define SSH2_MSG_EXT_INFO 7
|
||||
|
||||
#define SSH2_MSG_KEXINIT 20
|
||||
#define SSH2_MSG_NEWKEYS 21
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
#include <pthread.h>
|
||||
#define SSH_MUTEX pthread_mutex_t
|
||||
|
||||
#if defined _GNU_SOURCE
|
||||
#if defined(PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP)
|
||||
#define SSH_MUTEX_STATIC_INIT PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP
|
||||
#else
|
||||
#define SSH_MUTEX_STATIC_INIT PTHREAD_MUTEX_INITIALIZER
|
||||
|
||||
@@ -27,6 +27,13 @@
|
||||
#include "libssh/libgcrypt.h"
|
||||
#include "libssh/libmbedcrypto.h"
|
||||
|
||||
enum ssh_digest_e {
|
||||
SSH_DIGEST_AUTO=0,
|
||||
SSH_DIGEST_SHA1=1,
|
||||
SSH_DIGEST_SHA256,
|
||||
SSH_DIGEST_SHA512
|
||||
};
|
||||
|
||||
enum ssh_mac_e {
|
||||
SSH_MAC_SHA1=1,
|
||||
SSH_MAC_SHA256,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
set(PACKAGE_VERSION @APPLICATION_VERSION@)
|
||||
set(PACKAGE_VERSION @PROJECT_VERSION@)
|
||||
|
||||
# Check whether the requested PACKAGE_FIND_VERSION is compatible
|
||||
if("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}")
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
Name: ${APPLICATION_NAME}
|
||||
Name: ${PROJECT_NAME}
|
||||
Description: The SSH Library
|
||||
Version: ${APPLICATION_VERSION}
|
||||
Version: ${PROJECT_VERSION}
|
||||
Libs: -L${LIB_INSTALL_DIR} -lssh
|
||||
Cflags: -I${INCLUDE_INSTALL_DIR}
|
||||
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
Name: ${APPLICATION_NAME}_threads
|
||||
Description: The SSH Library Thread Extension
|
||||
Version: ${APPLICATION_VERSION}
|
||||
Libs: -L${LIB_INSTALL_DIR} -lssh_threads
|
||||
Cflags: -I${INCLUDE_INSTALL_DIR}
|
||||
|
||||
@@ -1 +1 @@
|
||||
4.5.0
|
||||
4.7.1
|
||||
0
src/ABI/libssh-4.5.1.symbols
Normal file
412
src/ABI/libssh-4.6.0.symbols
Normal file
@@ -0,0 +1,412 @@
|
||||
_ssh_log
|
||||
buffer_free
|
||||
buffer_get
|
||||
buffer_get_len
|
||||
buffer_new
|
||||
channel_accept_x11
|
||||
channel_change_pty_size
|
||||
channel_close
|
||||
channel_forward_accept
|
||||
channel_forward_cancel
|
||||
channel_forward_listen
|
||||
channel_free
|
||||
channel_get_exit_status
|
||||
channel_get_session
|
||||
channel_is_closed
|
||||
channel_is_eof
|
||||
channel_is_open
|
||||
channel_new
|
||||
channel_open_forward
|
||||
channel_open_session
|
||||
channel_poll
|
||||
channel_read
|
||||
channel_read_buffer
|
||||
channel_read_nonblocking
|
||||
channel_request_env
|
||||
channel_request_exec
|
||||
channel_request_pty
|
||||
channel_request_pty_size
|
||||
channel_request_send_signal
|
||||
channel_request_sftp
|
||||
channel_request_shell
|
||||
channel_request_subsystem
|
||||
channel_request_x11
|
||||
channel_select
|
||||
channel_send_eof
|
||||
channel_set_blocking
|
||||
channel_write
|
||||
channel_write_stderr
|
||||
privatekey_free
|
||||
privatekey_from_file
|
||||
publickey_free
|
||||
publickey_from_file
|
||||
publickey_from_privatekey
|
||||
publickey_to_string
|
||||
sftp_async_read
|
||||
sftp_async_read_begin
|
||||
sftp_attributes_free
|
||||
sftp_canonicalize_path
|
||||
sftp_chmod
|
||||
sftp_chown
|
||||
sftp_client_message_free
|
||||
sftp_client_message_get_data
|
||||
sftp_client_message_get_filename
|
||||
sftp_client_message_get_flags
|
||||
sftp_client_message_get_type
|
||||
sftp_client_message_set_filename
|
||||
sftp_close
|
||||
sftp_closedir
|
||||
sftp_dir_eof
|
||||
sftp_extension_supported
|
||||
sftp_extensions_get_count
|
||||
sftp_extensions_get_data
|
||||
sftp_extensions_get_name
|
||||
sftp_file_set_blocking
|
||||
sftp_file_set_nonblocking
|
||||
sftp_free
|
||||
sftp_fstat
|
||||
sftp_fstatvfs
|
||||
sftp_fsync
|
||||
sftp_get_client_message
|
||||
sftp_get_error
|
||||
sftp_handle
|
||||
sftp_handle_alloc
|
||||
sftp_handle_remove
|
||||
sftp_init
|
||||
sftp_lstat
|
||||
sftp_mkdir
|
||||
sftp_new
|
||||
sftp_new_channel
|
||||
sftp_open
|
||||
sftp_opendir
|
||||
sftp_read
|
||||
sftp_readdir
|
||||
sftp_readlink
|
||||
sftp_rename
|
||||
sftp_reply_attr
|
||||
sftp_reply_data
|
||||
sftp_reply_handle
|
||||
sftp_reply_name
|
||||
sftp_reply_names
|
||||
sftp_reply_names_add
|
||||
sftp_reply_status
|
||||
sftp_rewind
|
||||
sftp_rmdir
|
||||
sftp_seek
|
||||
sftp_seek64
|
||||
sftp_send_client_message
|
||||
sftp_server_init
|
||||
sftp_server_new
|
||||
sftp_server_version
|
||||
sftp_setstat
|
||||
sftp_stat
|
||||
sftp_statvfs
|
||||
sftp_statvfs_free
|
||||
sftp_symlink
|
||||
sftp_tell
|
||||
sftp_tell64
|
||||
sftp_unlink
|
||||
sftp_utimes
|
||||
sftp_write
|
||||
ssh_accept
|
||||
ssh_add_channel_callbacks
|
||||
ssh_auth_list
|
||||
ssh_basename
|
||||
ssh_bind_accept
|
||||
ssh_bind_accept_fd
|
||||
ssh_bind_fd_toaccept
|
||||
ssh_bind_free
|
||||
ssh_bind_get_fd
|
||||
ssh_bind_listen
|
||||
ssh_bind_new
|
||||
ssh_bind_options_set
|
||||
ssh_bind_set_blocking
|
||||
ssh_bind_set_callbacks
|
||||
ssh_bind_set_fd
|
||||
ssh_blocking_flush
|
||||
ssh_buffer_add_data
|
||||
ssh_buffer_free
|
||||
ssh_buffer_get
|
||||
ssh_buffer_get_data
|
||||
ssh_buffer_get_len
|
||||
ssh_buffer_new
|
||||
ssh_buffer_reinit
|
||||
ssh_channel_accept_forward
|
||||
ssh_channel_accept_x11
|
||||
ssh_channel_cancel_forward
|
||||
ssh_channel_change_pty_size
|
||||
ssh_channel_close
|
||||
ssh_channel_free
|
||||
ssh_channel_get_exit_status
|
||||
ssh_channel_get_session
|
||||
ssh_channel_is_closed
|
||||
ssh_channel_is_eof
|
||||
ssh_channel_is_open
|
||||
ssh_channel_listen_forward
|
||||
ssh_channel_new
|
||||
ssh_channel_open_auth_agent
|
||||
ssh_channel_open_forward
|
||||
ssh_channel_open_reverse_forward
|
||||
ssh_channel_open_session
|
||||
ssh_channel_open_x11
|
||||
ssh_channel_poll
|
||||
ssh_channel_poll_timeout
|
||||
ssh_channel_read
|
||||
ssh_channel_read_nonblocking
|
||||
ssh_channel_read_timeout
|
||||
ssh_channel_request_auth_agent
|
||||
ssh_channel_request_env
|
||||
ssh_channel_request_exec
|
||||
ssh_channel_request_pty
|
||||
ssh_channel_request_pty_size
|
||||
ssh_channel_request_send_break
|
||||
ssh_channel_request_send_exit_signal
|
||||
ssh_channel_request_send_exit_status
|
||||
ssh_channel_request_send_signal
|
||||
ssh_channel_request_sftp
|
||||
ssh_channel_request_shell
|
||||
ssh_channel_request_subsystem
|
||||
ssh_channel_request_x11
|
||||
ssh_channel_select
|
||||
ssh_channel_send_eof
|
||||
ssh_channel_set_blocking
|
||||
ssh_channel_set_counter
|
||||
ssh_channel_window_size
|
||||
ssh_channel_write
|
||||
ssh_channel_write_stderr
|
||||
ssh_clean_pubkey_hash
|
||||
ssh_connect
|
||||
ssh_connector_free
|
||||
ssh_connector_new
|
||||
ssh_connector_set_in_channel
|
||||
ssh_connector_set_in_fd
|
||||
ssh_connector_set_out_channel
|
||||
ssh_connector_set_out_fd
|
||||
ssh_copyright
|
||||
ssh_dirname
|
||||
ssh_disconnect
|
||||
ssh_dump_knownhost
|
||||
ssh_event_add_connector
|
||||
ssh_event_add_fd
|
||||
ssh_event_add_session
|
||||
ssh_event_dopoll
|
||||
ssh_event_free
|
||||
ssh_event_new
|
||||
ssh_event_remove_connector
|
||||
ssh_event_remove_fd
|
||||
ssh_event_remove_session
|
||||
ssh_execute_message_callbacks
|
||||
ssh_finalize
|
||||
ssh_forward_accept
|
||||
ssh_forward_cancel
|
||||
ssh_forward_listen
|
||||
ssh_free
|
||||
ssh_get_cipher_in
|
||||
ssh_get_cipher_out
|
||||
ssh_get_clientbanner
|
||||
ssh_get_disconnect_message
|
||||
ssh_get_error
|
||||
ssh_get_error_code
|
||||
ssh_get_fd
|
||||
ssh_get_hexa
|
||||
ssh_get_hmac_in
|
||||
ssh_get_hmac_out
|
||||
ssh_get_issue_banner
|
||||
ssh_get_kex_algo
|
||||
ssh_get_log_callback
|
||||
ssh_get_log_level
|
||||
ssh_get_log_userdata
|
||||
ssh_get_openssh_version
|
||||
ssh_get_poll_flags
|
||||
ssh_get_pubkey
|
||||
ssh_get_pubkey_hash
|
||||
ssh_get_publickey
|
||||
ssh_get_publickey_hash
|
||||
ssh_get_random
|
||||
ssh_get_server_publickey
|
||||
ssh_get_serverbanner
|
||||
ssh_get_status
|
||||
ssh_get_version
|
||||
ssh_getpass
|
||||
ssh_gssapi_get_creds
|
||||
ssh_gssapi_set_creds
|
||||
ssh_handle_key_exchange
|
||||
ssh_init
|
||||
ssh_is_blocking
|
||||
ssh_is_connected
|
||||
ssh_is_server_known
|
||||
ssh_key_cmp
|
||||
ssh_key_free
|
||||
ssh_key_is_private
|
||||
ssh_key_is_public
|
||||
ssh_key_new
|
||||
ssh_key_type
|
||||
ssh_key_type_from_name
|
||||
ssh_key_type_to_char
|
||||
ssh_known_hosts_parse_line
|
||||
ssh_knownhosts_entry_free
|
||||
ssh_log
|
||||
ssh_message_auth_interactive_request
|
||||
ssh_message_auth_kbdint_is_response
|
||||
ssh_message_auth_password
|
||||
ssh_message_auth_pubkey
|
||||
ssh_message_auth_publickey
|
||||
ssh_message_auth_publickey_state
|
||||
ssh_message_auth_reply_pk_ok
|
||||
ssh_message_auth_reply_pk_ok_simple
|
||||
ssh_message_auth_reply_success
|
||||
ssh_message_auth_set_methods
|
||||
ssh_message_auth_user
|
||||
ssh_message_channel_request_channel
|
||||
ssh_message_channel_request_command
|
||||
ssh_message_channel_request_env_name
|
||||
ssh_message_channel_request_env_value
|
||||
ssh_message_channel_request_open_destination
|
||||
ssh_message_channel_request_open_destination_port
|
||||
ssh_message_channel_request_open_originator
|
||||
ssh_message_channel_request_open_originator_port
|
||||
ssh_message_channel_request_open_reply_accept
|
||||
ssh_message_channel_request_pty_height
|
||||
ssh_message_channel_request_pty_pxheight
|
||||
ssh_message_channel_request_pty_pxwidth
|
||||
ssh_message_channel_request_pty_term
|
||||
ssh_message_channel_request_pty_width
|
||||
ssh_message_channel_request_reply_success
|
||||
ssh_message_channel_request_subsystem
|
||||
ssh_message_channel_request_x11_auth_cookie
|
||||
ssh_message_channel_request_x11_auth_protocol
|
||||
ssh_message_channel_request_x11_screen_number
|
||||
ssh_message_channel_request_x11_single_connection
|
||||
ssh_message_free
|
||||
ssh_message_get
|
||||
ssh_message_global_request_address
|
||||
ssh_message_global_request_port
|
||||
ssh_message_global_request_reply_success
|
||||
ssh_message_reply_default
|
||||
ssh_message_retrieve
|
||||
ssh_message_service_reply_success
|
||||
ssh_message_service_service
|
||||
ssh_message_subtype
|
||||
ssh_message_type
|
||||
ssh_mkdir
|
||||
ssh_new
|
||||
ssh_options_copy
|
||||
ssh_options_get
|
||||
ssh_options_get_port
|
||||
ssh_options_getopt
|
||||
ssh_options_parse_config
|
||||
ssh_options_set
|
||||
ssh_pcap_file_close
|
||||
ssh_pcap_file_free
|
||||
ssh_pcap_file_new
|
||||
ssh_pcap_file_open
|
||||
ssh_pki_copy_cert_to_privkey
|
||||
ssh_pki_export_privkey_file
|
||||
ssh_pki_export_privkey_to_pubkey
|
||||
ssh_pki_export_pubkey_base64
|
||||
ssh_pki_export_pubkey_file
|
||||
ssh_pki_generate
|
||||
ssh_pki_import_cert_base64
|
||||
ssh_pki_import_cert_file
|
||||
ssh_pki_import_privkey_base64
|
||||
ssh_pki_import_privkey_file
|
||||
ssh_pki_import_pubkey_base64
|
||||
ssh_pki_import_pubkey_file
|
||||
ssh_pki_key_ecdsa_name
|
||||
ssh_print_hash
|
||||
ssh_print_hexa
|
||||
ssh_privatekey_type
|
||||
ssh_publickey_to_file
|
||||
ssh_remove_channel_callbacks
|
||||
ssh_scp_accept_request
|
||||
ssh_scp_close
|
||||
ssh_scp_deny_request
|
||||
ssh_scp_free
|
||||
ssh_scp_init
|
||||
ssh_scp_leave_directory
|
||||
ssh_scp_new
|
||||
ssh_scp_pull_request
|
||||
ssh_scp_push_directory
|
||||
ssh_scp_push_file
|
||||
ssh_scp_push_file64
|
||||
ssh_scp_read
|
||||
ssh_scp_request_get_filename
|
||||
ssh_scp_request_get_permissions
|
||||
ssh_scp_request_get_size
|
||||
ssh_scp_request_get_size64
|
||||
ssh_scp_request_get_warning
|
||||
ssh_scp_write
|
||||
ssh_select
|
||||
ssh_send_debug
|
||||
ssh_send_ignore
|
||||
ssh_send_keepalive
|
||||
ssh_server_init_kex
|
||||
ssh_service_request
|
||||
ssh_session_export_known_hosts_entry
|
||||
ssh_session_has_known_hosts_entry
|
||||
ssh_session_is_known_server
|
||||
ssh_session_update_known_hosts
|
||||
ssh_set_agent_channel
|
||||
ssh_set_agent_socket
|
||||
ssh_set_auth_methods
|
||||
ssh_set_blocking
|
||||
ssh_set_callbacks
|
||||
ssh_set_channel_callbacks
|
||||
ssh_set_counters
|
||||
ssh_set_fd_except
|
||||
ssh_set_fd_toread
|
||||
ssh_set_fd_towrite
|
||||
ssh_set_log_callback
|
||||
ssh_set_log_level
|
||||
ssh_set_log_userdata
|
||||
ssh_set_message_callback
|
||||
ssh_set_pcap_file
|
||||
ssh_set_server_callbacks
|
||||
ssh_silent_disconnect
|
||||
ssh_string_burn
|
||||
ssh_string_copy
|
||||
ssh_string_data
|
||||
ssh_string_fill
|
||||
ssh_string_free
|
||||
ssh_string_free_char
|
||||
ssh_string_from_char
|
||||
ssh_string_get_char
|
||||
ssh_string_len
|
||||
ssh_string_new
|
||||
ssh_string_to_char
|
||||
ssh_threads_get_noop
|
||||
ssh_threads_get_pthread
|
||||
ssh_threads_set_callbacks
|
||||
ssh_try_publickey_from_file
|
||||
ssh_userauth_agent
|
||||
ssh_userauth_agent_pubkey
|
||||
ssh_userauth_autopubkey
|
||||
ssh_userauth_gssapi
|
||||
ssh_userauth_kbdint
|
||||
ssh_userauth_kbdint_getanswer
|
||||
ssh_userauth_kbdint_getinstruction
|
||||
ssh_userauth_kbdint_getname
|
||||
ssh_userauth_kbdint_getnanswers
|
||||
ssh_userauth_kbdint_getnprompts
|
||||
ssh_userauth_kbdint_getprompt
|
||||
ssh_userauth_kbdint_setanswer
|
||||
ssh_userauth_list
|
||||
ssh_userauth_none
|
||||
ssh_userauth_offer_pubkey
|
||||
ssh_userauth_password
|
||||
ssh_userauth_privatekey_file
|
||||
ssh_userauth_pubkey
|
||||
ssh_userauth_publickey
|
||||
ssh_userauth_publickey_auto
|
||||
ssh_userauth_try_publickey
|
||||
ssh_version
|
||||
ssh_write_knownhost
|
||||
string_burn
|
||||
string_copy
|
||||
string_data
|
||||
string_fill
|
||||
string_free
|
||||
string_from_char
|
||||
string_len
|
||||
string_new
|
||||
string_to_char
|
||||
415
src/ABI/libssh-4.7.0.symbols
Normal file
@@ -0,0 +1,415 @@
|
||||
_ssh_log
|
||||
buffer_free
|
||||
buffer_get
|
||||
buffer_get_len
|
||||
buffer_new
|
||||
channel_accept_x11
|
||||
channel_change_pty_size
|
||||
channel_close
|
||||
channel_forward_accept
|
||||
channel_forward_cancel
|
||||
channel_forward_listen
|
||||
channel_free
|
||||
channel_get_exit_status
|
||||
channel_get_session
|
||||
channel_is_closed
|
||||
channel_is_eof
|
||||
channel_is_open
|
||||
channel_new
|
||||
channel_open_forward
|
||||
channel_open_session
|
||||
channel_poll
|
||||
channel_read
|
||||
channel_read_buffer
|
||||
channel_read_nonblocking
|
||||
channel_request_env
|
||||
channel_request_exec
|
||||
channel_request_pty
|
||||
channel_request_pty_size
|
||||
channel_request_send_signal
|
||||
channel_request_sftp
|
||||
channel_request_shell
|
||||
channel_request_subsystem
|
||||
channel_request_x11
|
||||
channel_select
|
||||
channel_send_eof
|
||||
channel_set_blocking
|
||||
channel_write
|
||||
channel_write_stderr
|
||||
privatekey_free
|
||||
privatekey_from_file
|
||||
publickey_free
|
||||
publickey_from_file
|
||||
publickey_from_privatekey
|
||||
publickey_to_string
|
||||
sftp_async_read
|
||||
sftp_async_read_begin
|
||||
sftp_attributes_free
|
||||
sftp_canonicalize_path
|
||||
sftp_chmod
|
||||
sftp_chown
|
||||
sftp_client_message_free
|
||||
sftp_client_message_get_data
|
||||
sftp_client_message_get_filename
|
||||
sftp_client_message_get_flags
|
||||
sftp_client_message_get_submessage
|
||||
sftp_client_message_get_type
|
||||
sftp_client_message_set_filename
|
||||
sftp_close
|
||||
sftp_closedir
|
||||
sftp_dir_eof
|
||||
sftp_extension_supported
|
||||
sftp_extensions_get_count
|
||||
sftp_extensions_get_data
|
||||
sftp_extensions_get_name
|
||||
sftp_file_set_blocking
|
||||
sftp_file_set_nonblocking
|
||||
sftp_free
|
||||
sftp_fstat
|
||||
sftp_fstatvfs
|
||||
sftp_fsync
|
||||
sftp_get_client_message
|
||||
sftp_get_error
|
||||
sftp_handle
|
||||
sftp_handle_alloc
|
||||
sftp_handle_remove
|
||||
sftp_init
|
||||
sftp_lstat
|
||||
sftp_mkdir
|
||||
sftp_new
|
||||
sftp_new_channel
|
||||
sftp_open
|
||||
sftp_opendir
|
||||
sftp_read
|
||||
sftp_readdir
|
||||
sftp_readlink
|
||||
sftp_rename
|
||||
sftp_reply_attr
|
||||
sftp_reply_data
|
||||
sftp_reply_handle
|
||||
sftp_reply_name
|
||||
sftp_reply_names
|
||||
sftp_reply_names_add
|
||||
sftp_reply_status
|
||||
sftp_rewind
|
||||
sftp_rmdir
|
||||
sftp_seek
|
||||
sftp_seek64
|
||||
sftp_send_client_message
|
||||
sftp_server_init
|
||||
sftp_server_new
|
||||
sftp_server_version
|
||||
sftp_setstat
|
||||
sftp_stat
|
||||
sftp_statvfs
|
||||
sftp_statvfs_free
|
||||
sftp_symlink
|
||||
sftp_tell
|
||||
sftp_tell64
|
||||
sftp_unlink
|
||||
sftp_utimes
|
||||
sftp_write
|
||||
ssh_accept
|
||||
ssh_add_channel_callbacks
|
||||
ssh_auth_list
|
||||
ssh_basename
|
||||
ssh_bind_accept
|
||||
ssh_bind_accept_fd
|
||||
ssh_bind_fd_toaccept
|
||||
ssh_bind_free
|
||||
ssh_bind_get_fd
|
||||
ssh_bind_listen
|
||||
ssh_bind_new
|
||||
ssh_bind_options_set
|
||||
ssh_bind_set_blocking
|
||||
ssh_bind_set_callbacks
|
||||
ssh_bind_set_fd
|
||||
ssh_blocking_flush
|
||||
ssh_buffer_add_data
|
||||
ssh_buffer_free
|
||||
ssh_buffer_get
|
||||
ssh_buffer_get_data
|
||||
ssh_buffer_get_len
|
||||
ssh_buffer_new
|
||||
ssh_buffer_reinit
|
||||
ssh_channel_accept_forward
|
||||
ssh_channel_accept_x11
|
||||
ssh_channel_cancel_forward
|
||||
ssh_channel_change_pty_size
|
||||
ssh_channel_close
|
||||
ssh_channel_free
|
||||
ssh_channel_get_exit_status
|
||||
ssh_channel_get_session
|
||||
ssh_channel_is_closed
|
||||
ssh_channel_is_eof
|
||||
ssh_channel_is_open
|
||||
ssh_channel_listen_forward
|
||||
ssh_channel_new
|
||||
ssh_channel_open_auth_agent
|
||||
ssh_channel_open_forward
|
||||
ssh_channel_open_reverse_forward
|
||||
ssh_channel_open_session
|
||||
ssh_channel_open_x11
|
||||
ssh_channel_poll
|
||||
ssh_channel_poll_timeout
|
||||
ssh_channel_read
|
||||
ssh_channel_read_nonblocking
|
||||
ssh_channel_read_timeout
|
||||
ssh_channel_request_auth_agent
|
||||
ssh_channel_request_env
|
||||
ssh_channel_request_exec
|
||||
ssh_channel_request_pty
|
||||
ssh_channel_request_pty_size
|
||||
ssh_channel_request_send_break
|
||||
ssh_channel_request_send_exit_signal
|
||||
ssh_channel_request_send_exit_status
|
||||
ssh_channel_request_send_signal
|
||||
ssh_channel_request_sftp
|
||||
ssh_channel_request_shell
|
||||
ssh_channel_request_subsystem
|
||||
ssh_channel_request_x11
|
||||
ssh_channel_select
|
||||
ssh_channel_send_eof
|
||||
ssh_channel_set_blocking
|
||||
ssh_channel_set_counter
|
||||
ssh_channel_window_size
|
||||
ssh_channel_write
|
||||
ssh_channel_write_stderr
|
||||
ssh_clean_pubkey_hash
|
||||
ssh_connect
|
||||
ssh_connector_free
|
||||
ssh_connector_new
|
||||
ssh_connector_set_in_channel
|
||||
ssh_connector_set_in_fd
|
||||
ssh_connector_set_out_channel
|
||||
ssh_connector_set_out_fd
|
||||
ssh_copyright
|
||||
ssh_dirname
|
||||
ssh_disconnect
|
||||
ssh_dump_knownhost
|
||||
ssh_event_add_connector
|
||||
ssh_event_add_fd
|
||||
ssh_event_add_session
|
||||
ssh_event_dopoll
|
||||
ssh_event_free
|
||||
ssh_event_new
|
||||
ssh_event_remove_connector
|
||||
ssh_event_remove_fd
|
||||
ssh_event_remove_session
|
||||
ssh_execute_message_callbacks
|
||||
ssh_finalize
|
||||
ssh_forward_accept
|
||||
ssh_forward_cancel
|
||||
ssh_forward_listen
|
||||
ssh_free
|
||||
ssh_get_cipher_in
|
||||
ssh_get_cipher_out
|
||||
ssh_get_clientbanner
|
||||
ssh_get_disconnect_message
|
||||
ssh_get_error
|
||||
ssh_get_error_code
|
||||
ssh_get_fd
|
||||
ssh_get_fingerprint_hash
|
||||
ssh_get_hexa
|
||||
ssh_get_hmac_in
|
||||
ssh_get_hmac_out
|
||||
ssh_get_issue_banner
|
||||
ssh_get_kex_algo
|
||||
ssh_get_log_callback
|
||||
ssh_get_log_level
|
||||
ssh_get_log_userdata
|
||||
ssh_get_openssh_version
|
||||
ssh_get_poll_flags
|
||||
ssh_get_pubkey
|
||||
ssh_get_pubkey_hash
|
||||
ssh_get_publickey
|
||||
ssh_get_publickey_hash
|
||||
ssh_get_random
|
||||
ssh_get_server_publickey
|
||||
ssh_get_serverbanner
|
||||
ssh_get_status
|
||||
ssh_get_version
|
||||
ssh_getpass
|
||||
ssh_gssapi_get_creds
|
||||
ssh_gssapi_set_creds
|
||||
ssh_handle_key_exchange
|
||||
ssh_init
|
||||
ssh_is_blocking
|
||||
ssh_is_connected
|
||||
ssh_is_server_known
|
||||
ssh_key_cmp
|
||||
ssh_key_free
|
||||
ssh_key_is_private
|
||||
ssh_key_is_public
|
||||
ssh_key_new
|
||||
ssh_key_type
|
||||
ssh_key_type_from_name
|
||||
ssh_key_type_to_char
|
||||
ssh_known_hosts_parse_line
|
||||
ssh_knownhosts_entry_free
|
||||
ssh_log
|
||||
ssh_message_auth_interactive_request
|
||||
ssh_message_auth_kbdint_is_response
|
||||
ssh_message_auth_password
|
||||
ssh_message_auth_pubkey
|
||||
ssh_message_auth_publickey
|
||||
ssh_message_auth_publickey_state
|
||||
ssh_message_auth_reply_pk_ok
|
||||
ssh_message_auth_reply_pk_ok_simple
|
||||
ssh_message_auth_reply_success
|
||||
ssh_message_auth_set_methods
|
||||
ssh_message_auth_user
|
||||
ssh_message_channel_request_channel
|
||||
ssh_message_channel_request_command
|
||||
ssh_message_channel_request_env_name
|
||||
ssh_message_channel_request_env_value
|
||||
ssh_message_channel_request_open_destination
|
||||
ssh_message_channel_request_open_destination_port
|
||||
ssh_message_channel_request_open_originator
|
||||
ssh_message_channel_request_open_originator_port
|
||||
ssh_message_channel_request_open_reply_accept
|
||||
ssh_message_channel_request_pty_height
|
||||
ssh_message_channel_request_pty_pxheight
|
||||
ssh_message_channel_request_pty_pxwidth
|
||||
ssh_message_channel_request_pty_term
|
||||
ssh_message_channel_request_pty_width
|
||||
ssh_message_channel_request_reply_success
|
||||
ssh_message_channel_request_subsystem
|
||||
ssh_message_channel_request_x11_auth_cookie
|
||||
ssh_message_channel_request_x11_auth_protocol
|
||||
ssh_message_channel_request_x11_screen_number
|
||||
ssh_message_channel_request_x11_single_connection
|
||||
ssh_message_free
|
||||
ssh_message_get
|
||||
ssh_message_global_request_address
|
||||
ssh_message_global_request_port
|
||||
ssh_message_global_request_reply_success
|
||||
ssh_message_reply_default
|
||||
ssh_message_retrieve
|
||||
ssh_message_service_reply_success
|
||||
ssh_message_service_service
|
||||
ssh_message_subtype
|
||||
ssh_message_type
|
||||
ssh_mkdir
|
||||
ssh_new
|
||||
ssh_options_copy
|
||||
ssh_options_get
|
||||
ssh_options_get_port
|
||||
ssh_options_getopt
|
||||
ssh_options_parse_config
|
||||
ssh_options_set
|
||||
ssh_pcap_file_close
|
||||
ssh_pcap_file_free
|
||||
ssh_pcap_file_new
|
||||
ssh_pcap_file_open
|
||||
ssh_pki_copy_cert_to_privkey
|
||||
ssh_pki_export_privkey_base64
|
||||
ssh_pki_export_privkey_file
|
||||
ssh_pki_export_privkey_to_pubkey
|
||||
ssh_pki_export_pubkey_base64
|
||||
ssh_pki_export_pubkey_file
|
||||
ssh_pki_generate
|
||||
ssh_pki_import_cert_base64
|
||||
ssh_pki_import_cert_file
|
||||
ssh_pki_import_privkey_base64
|
||||
ssh_pki_import_privkey_file
|
||||
ssh_pki_import_pubkey_base64
|
||||
ssh_pki_import_pubkey_file
|
||||
ssh_pki_key_ecdsa_name
|
||||
ssh_print_hash
|
||||
ssh_print_hexa
|
||||
ssh_privatekey_type
|
||||
ssh_publickey_to_file
|
||||
ssh_remove_channel_callbacks
|
||||
ssh_scp_accept_request
|
||||
ssh_scp_close
|
||||
ssh_scp_deny_request
|
||||
ssh_scp_free
|
||||
ssh_scp_init
|
||||
ssh_scp_leave_directory
|
||||
ssh_scp_new
|
||||
ssh_scp_pull_request
|
||||
ssh_scp_push_directory
|
||||
ssh_scp_push_file
|
||||
ssh_scp_push_file64
|
||||
ssh_scp_read
|
||||
ssh_scp_request_get_filename
|
||||
ssh_scp_request_get_permissions
|
||||
ssh_scp_request_get_size
|
||||
ssh_scp_request_get_size64
|
||||
ssh_scp_request_get_warning
|
||||
ssh_scp_write
|
||||
ssh_select
|
||||
ssh_send_debug
|
||||
ssh_send_ignore
|
||||
ssh_send_keepalive
|
||||
ssh_server_init_kex
|
||||
ssh_service_request
|
||||
ssh_session_export_known_hosts_entry
|
||||
ssh_session_has_known_hosts_entry
|
||||
ssh_session_is_known_server
|
||||
ssh_session_update_known_hosts
|
||||
ssh_set_agent_channel
|
||||
ssh_set_agent_socket
|
||||
ssh_set_auth_methods
|
||||
ssh_set_blocking
|
||||
ssh_set_callbacks
|
||||
ssh_set_channel_callbacks
|
||||
ssh_set_counters
|
||||
ssh_set_fd_except
|
||||
ssh_set_fd_toread
|
||||
ssh_set_fd_towrite
|
||||
ssh_set_log_callback
|
||||
ssh_set_log_level
|
||||
ssh_set_log_userdata
|
||||
ssh_set_message_callback
|
||||
ssh_set_pcap_file
|
||||
ssh_set_server_callbacks
|
||||
ssh_silent_disconnect
|
||||
ssh_string_burn
|
||||
ssh_string_copy
|
||||
ssh_string_data
|
||||
ssh_string_fill
|
||||
ssh_string_free
|
||||
ssh_string_free_char
|
||||
ssh_string_from_char
|
||||
ssh_string_get_char
|
||||
ssh_string_len
|
||||
ssh_string_new
|
||||
ssh_string_to_char
|
||||
ssh_threads_get_noop
|
||||
ssh_threads_get_pthread
|
||||
ssh_threads_set_callbacks
|
||||
ssh_try_publickey_from_file
|
||||
ssh_userauth_agent
|
||||
ssh_userauth_agent_pubkey
|
||||
ssh_userauth_autopubkey
|
||||
ssh_userauth_gssapi
|
||||
ssh_userauth_kbdint
|
||||
ssh_userauth_kbdint_getanswer
|
||||
ssh_userauth_kbdint_getinstruction
|
||||
ssh_userauth_kbdint_getname
|
||||
ssh_userauth_kbdint_getnanswers
|
||||
ssh_userauth_kbdint_getnprompts
|
||||
ssh_userauth_kbdint_getprompt
|
||||
ssh_userauth_kbdint_setanswer
|
||||
ssh_userauth_list
|
||||
ssh_userauth_none
|
||||
ssh_userauth_offer_pubkey
|
||||
ssh_userauth_password
|
||||
ssh_userauth_privatekey_file
|
||||
ssh_userauth_pubkey
|
||||
ssh_userauth_publickey
|
||||
ssh_userauth_publickey_auto
|
||||
ssh_userauth_try_publickey
|
||||
ssh_version
|
||||
ssh_write_knownhost
|
||||
string_burn
|
||||
string_copy
|
||||
string_data
|
||||
string_fill
|
||||
string_free
|
||||
string_from_char
|
||||
string_len
|
||||
string_new
|
||||
string_to_char
|
||||
415
src/ABI/libssh-4.7.1.symbols
Normal file
@@ -0,0 +1,415 @@
|
||||
_ssh_log
|
||||
buffer_free
|
||||
buffer_get
|
||||
buffer_get_len
|
||||
buffer_new
|
||||
channel_accept_x11
|
||||
channel_change_pty_size
|
||||
channel_close
|
||||
channel_forward_accept
|
||||
channel_forward_cancel
|
||||
channel_forward_listen
|
||||
channel_free
|
||||
channel_get_exit_status
|
||||
channel_get_session
|
||||
channel_is_closed
|
||||
channel_is_eof
|
||||
channel_is_open
|
||||
channel_new
|
||||
channel_open_forward
|
||||
channel_open_session
|
||||
channel_poll
|
||||
channel_read
|
||||
channel_read_buffer
|
||||
channel_read_nonblocking
|
||||
channel_request_env
|
||||
channel_request_exec
|
||||
channel_request_pty
|
||||
channel_request_pty_size
|
||||
channel_request_send_signal
|
||||
channel_request_sftp
|
||||
channel_request_shell
|
||||
channel_request_subsystem
|
||||
channel_request_x11
|
||||
channel_select
|
||||
channel_send_eof
|
||||
channel_set_blocking
|
||||
channel_write
|
||||
channel_write_stderr
|
||||
privatekey_free
|
||||
privatekey_from_file
|
||||
publickey_free
|
||||
publickey_from_file
|
||||
publickey_from_privatekey
|
||||
publickey_to_string
|
||||
sftp_async_read
|
||||
sftp_async_read_begin
|
||||
sftp_attributes_free
|
||||
sftp_canonicalize_path
|
||||
sftp_chmod
|
||||
sftp_chown
|
||||
sftp_client_message_free
|
||||
sftp_client_message_get_data
|
||||
sftp_client_message_get_filename
|
||||
sftp_client_message_get_flags
|
||||
sftp_client_message_get_submessage
|
||||
sftp_client_message_get_type
|
||||
sftp_client_message_set_filename
|
||||
sftp_close
|
||||
sftp_closedir
|
||||
sftp_dir_eof
|
||||
sftp_extension_supported
|
||||
sftp_extensions_get_count
|
||||
sftp_extensions_get_data
|
||||
sftp_extensions_get_name
|
||||
sftp_file_set_blocking
|
||||
sftp_file_set_nonblocking
|
||||
sftp_free
|
||||
sftp_fstat
|
||||
sftp_fstatvfs
|
||||
sftp_fsync
|
||||
sftp_get_client_message
|
||||
sftp_get_error
|
||||
sftp_handle
|
||||
sftp_handle_alloc
|
||||
sftp_handle_remove
|
||||
sftp_init
|
||||
sftp_lstat
|
||||
sftp_mkdir
|
||||
sftp_new
|
||||
sftp_new_channel
|
||||
sftp_open
|
||||
sftp_opendir
|
||||
sftp_read
|
||||
sftp_readdir
|
||||
sftp_readlink
|
||||
sftp_rename
|
||||
sftp_reply_attr
|
||||
sftp_reply_data
|
||||
sftp_reply_handle
|
||||
sftp_reply_name
|
||||
sftp_reply_names
|
||||
sftp_reply_names_add
|
||||
sftp_reply_status
|
||||
sftp_rewind
|
||||
sftp_rmdir
|
||||
sftp_seek
|
||||
sftp_seek64
|
||||
sftp_send_client_message
|
||||
sftp_server_init
|
||||
sftp_server_new
|
||||
sftp_server_version
|
||||
sftp_setstat
|
||||
sftp_stat
|
||||
sftp_statvfs
|
||||
sftp_statvfs_free
|
||||
sftp_symlink
|
||||
sftp_tell
|
||||
sftp_tell64
|
||||
sftp_unlink
|
||||
sftp_utimes
|
||||
sftp_write
|
||||
ssh_accept
|
||||
ssh_add_channel_callbacks
|
||||
ssh_auth_list
|
||||
ssh_basename
|
||||
ssh_bind_accept
|
||||
ssh_bind_accept_fd
|
||||
ssh_bind_fd_toaccept
|
||||
ssh_bind_free
|
||||
ssh_bind_get_fd
|
||||
ssh_bind_listen
|
||||
ssh_bind_new
|
||||
ssh_bind_options_set
|
||||
ssh_bind_set_blocking
|
||||
ssh_bind_set_callbacks
|
||||
ssh_bind_set_fd
|
||||
ssh_blocking_flush
|
||||
ssh_buffer_add_data
|
||||
ssh_buffer_free
|
||||
ssh_buffer_get
|
||||
ssh_buffer_get_data
|
||||
ssh_buffer_get_len
|
||||
ssh_buffer_new
|
||||
ssh_buffer_reinit
|
||||
ssh_channel_accept_forward
|
||||
ssh_channel_accept_x11
|
||||
ssh_channel_cancel_forward
|
||||
ssh_channel_change_pty_size
|
||||
ssh_channel_close
|
||||
ssh_channel_free
|
||||
ssh_channel_get_exit_status
|
||||
ssh_channel_get_session
|
||||
ssh_channel_is_closed
|
||||
ssh_channel_is_eof
|
||||
ssh_channel_is_open
|
||||
ssh_channel_listen_forward
|
||||
ssh_channel_new
|
||||
ssh_channel_open_auth_agent
|
||||
ssh_channel_open_forward
|
||||
ssh_channel_open_reverse_forward
|
||||
ssh_channel_open_session
|
||||
ssh_channel_open_x11
|
||||
ssh_channel_poll
|
||||
ssh_channel_poll_timeout
|
||||
ssh_channel_read
|
||||
ssh_channel_read_nonblocking
|
||||
ssh_channel_read_timeout
|
||||
ssh_channel_request_auth_agent
|
||||
ssh_channel_request_env
|
||||
ssh_channel_request_exec
|
||||
ssh_channel_request_pty
|
||||
ssh_channel_request_pty_size
|
||||
ssh_channel_request_send_break
|
||||
ssh_channel_request_send_exit_signal
|
||||
ssh_channel_request_send_exit_status
|
||||
ssh_channel_request_send_signal
|
||||
ssh_channel_request_sftp
|
||||
ssh_channel_request_shell
|
||||
ssh_channel_request_subsystem
|
||||
ssh_channel_request_x11
|
||||
ssh_channel_select
|
||||
ssh_channel_send_eof
|
||||
ssh_channel_set_blocking
|
||||
ssh_channel_set_counter
|
||||
ssh_channel_window_size
|
||||
ssh_channel_write
|
||||
ssh_channel_write_stderr
|
||||
ssh_clean_pubkey_hash
|
||||
ssh_connect
|
||||
ssh_connector_free
|
||||
ssh_connector_new
|
||||
ssh_connector_set_in_channel
|
||||
ssh_connector_set_in_fd
|
||||
ssh_connector_set_out_channel
|
||||
ssh_connector_set_out_fd
|
||||
ssh_copyright
|
||||
ssh_dirname
|
||||
ssh_disconnect
|
||||
ssh_dump_knownhost
|
||||
ssh_event_add_connector
|
||||
ssh_event_add_fd
|
||||
ssh_event_add_session
|
||||
ssh_event_dopoll
|
||||
ssh_event_free
|
||||
ssh_event_new
|
||||
ssh_event_remove_connector
|
||||
ssh_event_remove_fd
|
||||
ssh_event_remove_session
|
||||
ssh_execute_message_callbacks
|
||||
ssh_finalize
|
||||
ssh_forward_accept
|
||||
ssh_forward_cancel
|
||||
ssh_forward_listen
|
||||
ssh_free
|
||||
ssh_get_cipher_in
|
||||
ssh_get_cipher_out
|
||||
ssh_get_clientbanner
|
||||
ssh_get_disconnect_message
|
||||
ssh_get_error
|
||||
ssh_get_error_code
|
||||
ssh_get_fd
|
||||
ssh_get_fingerprint_hash
|
||||
ssh_get_hexa
|
||||
ssh_get_hmac_in
|
||||
ssh_get_hmac_out
|
||||
ssh_get_issue_banner
|
||||
ssh_get_kex_algo
|
||||
ssh_get_log_callback
|
||||
ssh_get_log_level
|
||||
ssh_get_log_userdata
|
||||
ssh_get_openssh_version
|
||||
ssh_get_poll_flags
|
||||
ssh_get_pubkey
|
||||
ssh_get_pubkey_hash
|
||||
ssh_get_publickey
|
||||
ssh_get_publickey_hash
|
||||
ssh_get_random
|
||||
ssh_get_server_publickey
|
||||
ssh_get_serverbanner
|
||||
ssh_get_status
|
||||
ssh_get_version
|
||||
ssh_getpass
|
||||
ssh_gssapi_get_creds
|
||||
ssh_gssapi_set_creds
|
||||
ssh_handle_key_exchange
|
||||
ssh_init
|
||||
ssh_is_blocking
|
||||
ssh_is_connected
|
||||
ssh_is_server_known
|
||||
ssh_key_cmp
|
||||
ssh_key_free
|
||||
ssh_key_is_private
|
||||
ssh_key_is_public
|
||||
ssh_key_new
|
||||
ssh_key_type
|
||||
ssh_key_type_from_name
|
||||
ssh_key_type_to_char
|
||||
ssh_known_hosts_parse_line
|
||||
ssh_knownhosts_entry_free
|
||||
ssh_log
|
||||
ssh_message_auth_interactive_request
|
||||
ssh_message_auth_kbdint_is_response
|
||||
ssh_message_auth_password
|
||||
ssh_message_auth_pubkey
|
||||
ssh_message_auth_publickey
|
||||
ssh_message_auth_publickey_state
|
||||
ssh_message_auth_reply_pk_ok
|
||||
ssh_message_auth_reply_pk_ok_simple
|
||||
ssh_message_auth_reply_success
|
||||
ssh_message_auth_set_methods
|
||||
ssh_message_auth_user
|
||||
ssh_message_channel_request_channel
|
||||
ssh_message_channel_request_command
|
||||
ssh_message_channel_request_env_name
|
||||
ssh_message_channel_request_env_value
|
||||
ssh_message_channel_request_open_destination
|
||||
ssh_message_channel_request_open_destination_port
|
||||
ssh_message_channel_request_open_originator
|
||||
ssh_message_channel_request_open_originator_port
|
||||
ssh_message_channel_request_open_reply_accept
|
||||
ssh_message_channel_request_pty_height
|
||||
ssh_message_channel_request_pty_pxheight
|
||||
ssh_message_channel_request_pty_pxwidth
|
||||
ssh_message_channel_request_pty_term
|
||||
ssh_message_channel_request_pty_width
|
||||
ssh_message_channel_request_reply_success
|
||||
ssh_message_channel_request_subsystem
|
||||
ssh_message_channel_request_x11_auth_cookie
|
||||
ssh_message_channel_request_x11_auth_protocol
|
||||
ssh_message_channel_request_x11_screen_number
|
||||
ssh_message_channel_request_x11_single_connection
|
||||
ssh_message_free
|
||||
ssh_message_get
|
||||
ssh_message_global_request_address
|
||||
ssh_message_global_request_port
|
||||
ssh_message_global_request_reply_success
|
||||
ssh_message_reply_default
|
||||
ssh_message_retrieve
|
||||
ssh_message_service_reply_success
|
||||
ssh_message_service_service
|
||||
ssh_message_subtype
|
||||
ssh_message_type
|
||||
ssh_mkdir
|
||||
ssh_new
|
||||
ssh_options_copy
|
||||
ssh_options_get
|
||||
ssh_options_get_port
|
||||
ssh_options_getopt
|
||||
ssh_options_parse_config
|
||||
ssh_options_set
|
||||
ssh_pcap_file_close
|
||||
ssh_pcap_file_free
|
||||
ssh_pcap_file_new
|
||||
ssh_pcap_file_open
|
||||
ssh_pki_copy_cert_to_privkey
|
||||
ssh_pki_export_privkey_base64
|
||||
ssh_pki_export_privkey_file
|
||||
ssh_pki_export_privkey_to_pubkey
|
||||
ssh_pki_export_pubkey_base64
|
||||
ssh_pki_export_pubkey_file
|
||||
ssh_pki_generate
|
||||
ssh_pki_import_cert_base64
|
||||
ssh_pki_import_cert_file
|
||||
ssh_pki_import_privkey_base64
|
||||
ssh_pki_import_privkey_file
|
||||
ssh_pki_import_pubkey_base64
|
||||
ssh_pki_import_pubkey_file
|
||||
ssh_pki_key_ecdsa_name
|
||||
ssh_print_hash
|
||||
ssh_print_hexa
|
||||
ssh_privatekey_type
|
||||
ssh_publickey_to_file
|
||||
ssh_remove_channel_callbacks
|
||||
ssh_scp_accept_request
|
||||
ssh_scp_close
|
||||
ssh_scp_deny_request
|
||||
ssh_scp_free
|
||||
ssh_scp_init
|
||||
ssh_scp_leave_directory
|
||||
ssh_scp_new
|
||||
ssh_scp_pull_request
|
||||
ssh_scp_push_directory
|
||||
ssh_scp_push_file
|
||||
ssh_scp_push_file64
|
||||
ssh_scp_read
|
||||
ssh_scp_request_get_filename
|
||||
ssh_scp_request_get_permissions
|
||||
ssh_scp_request_get_size
|
||||
ssh_scp_request_get_size64
|
||||
ssh_scp_request_get_warning
|
||||
ssh_scp_write
|
||||
ssh_select
|
||||
ssh_send_debug
|
||||
ssh_send_ignore
|
||||
ssh_send_keepalive
|
||||
ssh_server_init_kex
|
||||
ssh_service_request
|
||||
ssh_session_export_known_hosts_entry
|
||||
ssh_session_has_known_hosts_entry
|
||||
ssh_session_is_known_server
|
||||
ssh_session_update_known_hosts
|
||||
ssh_set_agent_channel
|
||||
ssh_set_agent_socket
|
||||
ssh_set_auth_methods
|
||||
ssh_set_blocking
|
||||
ssh_set_callbacks
|
||||
ssh_set_channel_callbacks
|
||||
ssh_set_counters
|
||||
ssh_set_fd_except
|
||||
ssh_set_fd_toread
|
||||
ssh_set_fd_towrite
|
||||
ssh_set_log_callback
|
||||
ssh_set_log_level
|
||||
ssh_set_log_userdata
|
||||
ssh_set_message_callback
|
||||
ssh_set_pcap_file
|
||||
ssh_set_server_callbacks
|
||||
ssh_silent_disconnect
|
||||
ssh_string_burn
|
||||
ssh_string_copy
|
||||
ssh_string_data
|
||||
ssh_string_fill
|
||||
ssh_string_free
|
||||
ssh_string_free_char
|
||||
ssh_string_from_char
|
||||
ssh_string_get_char
|
||||
ssh_string_len
|
||||
ssh_string_new
|
||||
ssh_string_to_char
|
||||
ssh_threads_get_noop
|
||||
ssh_threads_get_pthread
|
||||
ssh_threads_set_callbacks
|
||||
ssh_try_publickey_from_file
|
||||
ssh_userauth_agent
|
||||
ssh_userauth_agent_pubkey
|
||||
ssh_userauth_autopubkey
|
||||
ssh_userauth_gssapi
|
||||
ssh_userauth_kbdint
|
||||
ssh_userauth_kbdint_getanswer
|
||||
ssh_userauth_kbdint_getinstruction
|
||||
ssh_userauth_kbdint_getname
|
||||
ssh_userauth_kbdint_getnanswers
|
||||
ssh_userauth_kbdint_getnprompts
|
||||
ssh_userauth_kbdint_getprompt
|
||||
ssh_userauth_kbdint_setanswer
|
||||
ssh_userauth_list
|
||||
ssh_userauth_none
|
||||
ssh_userauth_offer_pubkey
|
||||
ssh_userauth_password
|
||||
ssh_userauth_privatekey_file
|
||||
ssh_userauth_pubkey
|
||||
ssh_userauth_publickey
|
||||
ssh_userauth_publickey_auto
|
||||
ssh_userauth_try_publickey
|
||||
ssh_version
|
||||
ssh_write_knownhost
|
||||
string_burn
|
||||
string_copy
|
||||
string_data
|
||||
string_fill
|
||||
string_free
|
||||
string_from_char
|
||||
string_len
|
||||
string_new
|
||||
string_to_char
|
||||
@@ -106,12 +106,12 @@ set(LIBSSH_SHARED_LIBRARY
|
||||
CACHE INTERNAL "libssh shared library"
|
||||
)
|
||||
|
||||
if (WITH_STATIC_LIB)
|
||||
if (BUILD_STATIC_LIB)
|
||||
set(LIBSSH_STATIC_LIBRARY
|
||||
ssh_static
|
||||
CACHE INTERNAL "libssh static library"
|
||||
)
|
||||
endif (WITH_STATIC_LIB)
|
||||
endif (BUILD_STATIC_LIB)
|
||||
|
||||
set(libssh_SRCS
|
||||
agent.c
|
||||
@@ -266,15 +266,15 @@ include_directories(
|
||||
# Set the path to the default map file
|
||||
set(MAP_PATH "${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}.map")
|
||||
|
||||
if (WITH_SYMBOL_VERSIONING AND ABIMAP_FOUND)
|
||||
if (WITH_SYMBOL_VERSIONING AND HAVE_LD_VERSION_SCRIPT AND ABIMAP_FOUND)
|
||||
# Get the list of header files
|
||||
get_file_list("dev_header_list"
|
||||
get_file_list(dev_header_list
|
||||
DIRECTORIES "${LIBSSH_PUBLIC_INCLUDE_DIRS}/libssh"
|
||||
FILES_PATTERNS "*.h")
|
||||
|
||||
# Extract the symbols marked as "LIBSSH_API" from the header files
|
||||
extract_symbols("${PROJECT_NAME}_dev.symbols"
|
||||
HEADERS_LIST_FILE "dev_header_list"
|
||||
HEADERS_LIST dev_header_list
|
||||
FILTER_PATTERN "LIBSSH_API")
|
||||
|
||||
if (WITH_ABI_BREAK)
|
||||
@@ -292,13 +292,14 @@ if (WITH_SYMBOL_VERSIONING AND ABIMAP_FOUND)
|
||||
${libssh_SRCS}
|
||||
${PROJECT_NAME}_dev.map
|
||||
)
|
||||
endif (WITH_SYMBOL_VERSIONING AND ABIMAP_FOUND)
|
||||
endif (WITH_SYMBOL_VERSIONING AND HAVE_LD_VERSION_SCRIPT AND ABIMAP_FOUND)
|
||||
|
||||
add_library(${LIBSSH_SHARED_LIBRARY} SHARED ${libssh_SRCS})
|
||||
target_compile_options(${LIBSSH_SHARED_LIBRARY} PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
|
||||
|
||||
target_link_libraries(${LIBSSH_SHARED_LIBRARY} ${LIBSSH_LINK_LIBRARIES})
|
||||
|
||||
if (WITH_SYMBOL_VERSIONING)
|
||||
if (WITH_SYMBOL_VERSIONING AND HAVE_LD_VERSION_SCRIPT)
|
||||
if (ABIMAP_FOUND)
|
||||
# Change path to devel map file
|
||||
set(MAP_PATH "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}_dev.map")
|
||||
@@ -307,7 +308,7 @@ if (WITH_SYMBOL_VERSIONING)
|
||||
set_target_properties(${LIBSSH_SHARED_LIBRARY}
|
||||
PROPERTIES LINK_FLAGS
|
||||
"-Wl,--version-script,\"${MAP_PATH}\"")
|
||||
endif (WITH_SYMBOL_VERSIONING)
|
||||
endif (WITH_SYMBOL_VERSIONING AND HAVE_LD_VERSION_SCRIPT)
|
||||
|
||||
set_target_properties(
|
||||
${LIBSSH_SHARED_LIBRARY}
|
||||
@@ -340,8 +341,9 @@ install(
|
||||
COMPONENT libraries
|
||||
)
|
||||
|
||||
if (WITH_STATIC_LIB)
|
||||
if (BUILD_STATIC_LIB)
|
||||
add_library(${LIBSSH_STATIC_LIBRARY} STATIC ${libssh_SRCS})
|
||||
target_compile_options(${LIBSSH_STATIC_LIBRARY} PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
|
||||
|
||||
if (MSVC)
|
||||
set(OUTPUT_SUFFIX static)
|
||||
@@ -370,14 +372,14 @@ if (WITH_STATIC_LIB)
|
||||
)
|
||||
endif (WIN32)
|
||||
|
||||
install(
|
||||
TARGETS
|
||||
${LIBSSH_STATIC_LIBRARY}
|
||||
DESTINATION
|
||||
${LIB_INSTALL_DIR}/${OUTPUT_SUFFIX}
|
||||
COMPONENT
|
||||
libraries
|
||||
)
|
||||
endif (WITH_STATIC_LIB)
|
||||
if (WITH_STATIC_LIB)
|
||||
install(TARGETS
|
||||
${LIBSSH_STATIC_LIBRARY}
|
||||
DESTINATION
|
||||
${LIB_INSTALL_DIR}/${OUTPUT_SUFFIX}
|
||||
COMPONENT
|
||||
libraries)
|
||||
endif (WITH_STATIC_LIB)
|
||||
endif (BUILD_STATIC_LIB)
|
||||
|
||||
message(STATUS "Threads_FOUND=${Threads_FOUND}")
|
||||
|
||||
10
src/agent.c
@@ -331,7 +331,7 @@ int ssh_agent_get_ident_count(struct ssh_session_struct *session) {
|
||||
ssh_buffer request = NULL;
|
||||
ssh_buffer reply = NULL;
|
||||
unsigned int type = 0;
|
||||
uint8_t buf[4] = {0};
|
||||
uint32_t buf[1] = {0};
|
||||
int rc;
|
||||
|
||||
/* send message to the agent requesting the list of identities */
|
||||
@@ -548,6 +548,14 @@ ssh_string ssh_agent_sign_data(ssh_session session,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Add Flags: SHA2 extension (RFC 8332) if negotiated */
|
||||
if (pubkey->type == SSH_KEYTYPE_RSA) {
|
||||
if (session->extensions & SSH_EXT_SIG_RSA_SHA512) {
|
||||
flags |= SSH_AGENT_RSA_SHA2_512;
|
||||
} else if (session->extensions & SSH_EXT_SIG_RSA_SHA256) {
|
||||
flags |= SSH_AGENT_RSA_SHA2_256;
|
||||
}
|
||||
}
|
||||
if (ssh_buffer_add_u32(request, htonl(flags)) < 0) {
|
||||
ssh_buffer_free(request);
|
||||
return NULL;
|
||||
|
||||
293
src/auth.c
@@ -79,18 +79,52 @@ static int ssh_userauth_request_service(ssh_session session) {
|
||||
|
||||
static int ssh_auth_response_termination(void *user) {
|
||||
ssh_session session = (ssh_session)user;
|
||||
switch (session->auth_state) {
|
||||
switch (session->auth.state) {
|
||||
case SSH_AUTH_STATE_NONE:
|
||||
case SSH_AUTH_STATE_KBDINT_SENT:
|
||||
case SSH_AUTH_STATE_GSSAPI_REQUEST_SENT:
|
||||
case SSH_AUTH_STATE_GSSAPI_TOKEN:
|
||||
case SSH_AUTH_STATE_GSSAPI_MIC_SENT:
|
||||
case SSH_AUTH_STATE_PUBKEY_AUTH_SENT:
|
||||
case SSH_AUTH_STATE_PUBKEY_OFFER_SENT:
|
||||
case SSH_AUTH_STATE_PASSWORD_AUTH_SENT:
|
||||
case SSH_AUTH_STATE_AUTH_NONE_SENT:
|
||||
return 0;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
static const char *ssh_auth_get_current_method(ssh_session session)
|
||||
{
|
||||
const char *method = "unknown";
|
||||
|
||||
switch (session->auth.current_method) {
|
||||
case SSH_AUTH_METHOD_NONE:
|
||||
method = "none";
|
||||
break;
|
||||
case SSH_AUTH_METHOD_PASSWORD:
|
||||
method = "password";
|
||||
break;
|
||||
case SSH_AUTH_METHOD_PUBLICKEY:
|
||||
method = "publickey";
|
||||
break;
|
||||
case SSH_AUTH_METHOD_HOSTBASED:
|
||||
method = "hostbased";
|
||||
break;
|
||||
case SSH_AUTH_METHOD_INTERACTIVE:
|
||||
method = "keyboard interactive";
|
||||
break;
|
||||
case SSH_AUTH_METHOD_GSSAPI_MIC:
|
||||
method = "gssapi";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return method;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* @brief Wait for a response of an authentication function.
|
||||
@@ -116,7 +150,7 @@ static int ssh_userauth_get_response(ssh_session session) {
|
||||
return SSH_AUTH_AGAIN;
|
||||
}
|
||||
|
||||
switch(session->auth_state) {
|
||||
switch(session->auth.state) {
|
||||
case SSH_AUTH_STATE_ERROR:
|
||||
rc = SSH_AUTH_ERROR;
|
||||
break;
|
||||
@@ -137,6 +171,10 @@ static int ssh_userauth_get_response(ssh_session session) {
|
||||
case SSH_AUTH_STATE_GSSAPI_REQUEST_SENT:
|
||||
case SSH_AUTH_STATE_GSSAPI_TOKEN:
|
||||
case SSH_AUTH_STATE_GSSAPI_MIC_SENT:
|
||||
case SSH_AUTH_STATE_PUBKEY_OFFER_SENT:
|
||||
case SSH_AUTH_STATE_PUBKEY_AUTH_SENT:
|
||||
case SSH_AUTH_STATE_PASSWORD_AUTH_SENT:
|
||||
case SSH_AUTH_STATE_AUTH_NONE_SENT:
|
||||
case SSH_AUTH_STATE_NONE:
|
||||
/* not reached */
|
||||
rc = SSH_AUTH_ERROR;
|
||||
@@ -181,6 +219,7 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_banner) {
|
||||
* This handles the complete or partial authentication failure.
|
||||
*/
|
||||
SSH_PACKET_CALLBACK(ssh_packet_userauth_failure) {
|
||||
const char *current_method = ssh_auth_get_current_method(session);
|
||||
char *auth_methods = NULL;
|
||||
uint8_t partial = 0;
|
||||
int rc;
|
||||
@@ -191,43 +230,46 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_failure) {
|
||||
if (rc != SSH_OK) {
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
"Invalid SSH_MSG_USERAUTH_FAILURE message");
|
||||
session->auth_state=SSH_AUTH_STATE_ERROR;
|
||||
session->auth.state = SSH_AUTH_STATE_ERROR;
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (partial) {
|
||||
session->auth_state=SSH_AUTH_STATE_PARTIAL;
|
||||
session->auth.state = SSH_AUTH_STATE_PARTIAL;
|
||||
SSH_LOG(SSH_LOG_INFO,
|
||||
"Partial success. Authentication that can continue: %s",
|
||||
"Partial success for '%s'. Authentication that can continue: %s",
|
||||
current_method,
|
||||
auth_methods);
|
||||
} else {
|
||||
session->auth_state=SSH_AUTH_STATE_FAILED;
|
||||
SSH_LOG(SSH_LOG_INFO,
|
||||
"Access denied. Authentication that can continue: %s",
|
||||
auth_methods);
|
||||
session->auth.state = SSH_AUTH_STATE_FAILED;
|
||||
ssh_set_error(session, SSH_REQUEST_DENIED,
|
||||
"Access denied. Authentication that can continue: %s",
|
||||
auth_methods);
|
||||
"Access denied for '%s'. Authentication that can continue: %s",
|
||||
current_method,
|
||||
auth_methods);
|
||||
SSH_LOG(SSH_LOG_INFO,
|
||||
"%s",
|
||||
ssh_get_error(session));
|
||||
|
||||
}
|
||||
session->auth_methods = 0;
|
||||
session->auth.supported_methods = 0;
|
||||
if (strstr(auth_methods, "password") != NULL) {
|
||||
session->auth_methods |= SSH_AUTH_METHOD_PASSWORD;
|
||||
session->auth.supported_methods |= SSH_AUTH_METHOD_PASSWORD;
|
||||
}
|
||||
if (strstr(auth_methods, "keyboard-interactive") != NULL) {
|
||||
session->auth_methods |= SSH_AUTH_METHOD_INTERACTIVE;
|
||||
session->auth.supported_methods |= SSH_AUTH_METHOD_INTERACTIVE;
|
||||
}
|
||||
if (strstr(auth_methods, "publickey") != NULL) {
|
||||
session->auth_methods |= SSH_AUTH_METHOD_PUBLICKEY;
|
||||
session->auth.supported_methods |= SSH_AUTH_METHOD_PUBLICKEY;
|
||||
}
|
||||
if (strstr(auth_methods, "hostbased") != NULL) {
|
||||
session->auth_methods |= SSH_AUTH_METHOD_HOSTBASED;
|
||||
session->auth.supported_methods |= SSH_AUTH_METHOD_HOSTBASED;
|
||||
}
|
||||
if (strstr(auth_methods, "gssapi-with-mic") != NULL) {
|
||||
session->auth_methods |= SSH_AUTH_METHOD_GSSAPI_MIC;
|
||||
session->auth.supported_methods |= SSH_AUTH_METHOD_GSSAPI_MIC;
|
||||
}
|
||||
|
||||
end:
|
||||
session->auth.current_method = SSH_AUTH_METHOD_UNKNOWN;
|
||||
SAFE_FREE(auth_methods);
|
||||
|
||||
return SSH_PACKET_USED;
|
||||
@@ -248,7 +290,7 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_success) {
|
||||
SSH_LOG(SSH_LOG_DEBUG, "Authentication successful");
|
||||
SSH_LOG(SSH_LOG_TRACE, "Received SSH_USERAUTH_SUCCESS");
|
||||
|
||||
session->auth_state = SSH_AUTH_STATE_SUCCESS;
|
||||
session->auth.state = SSH_AUTH_STATE_SUCCESS;
|
||||
session->session_state = SSH_SESSION_STATE_AUTHENTICATED;
|
||||
session->flags |= SSH_SESSION_FLAG_AUTHENTICATED;
|
||||
|
||||
@@ -261,6 +303,9 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_success) {
|
||||
session->current_crypto->do_compress_in = 1;
|
||||
}
|
||||
|
||||
/* Reset errors by previous authentication methods. */
|
||||
ssh_reset_error(session);
|
||||
session->auth.current_method = SSH_AUTH_METHOD_UNKNOWN;
|
||||
return SSH_PACKET_USED;
|
||||
}
|
||||
|
||||
@@ -275,24 +320,30 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_success) {
|
||||
SSH_PACKET_CALLBACK(ssh_packet_userauth_pk_ok) {
|
||||
int rc;
|
||||
|
||||
SSH_LOG(SSH_LOG_TRACE, "Received SSH_USERAUTH_PK_OK/INFO_REQUEST/GSSAPI_RESPONSE");
|
||||
|
||||
if (session->auth_state==SSH_AUTH_STATE_KBDINT_SENT) {
|
||||
/* Assuming we are in keyboard-interactive context */
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"keyboard-interactive context, assuming SSH_USERAUTH_INFO_REQUEST");
|
||||
rc = ssh_packet_userauth_info_request(session,type,packet,user);
|
||||
#ifdef WITH_GSSAPI
|
||||
} else if (session->auth_state == SSH_AUTH_STATE_GSSAPI_REQUEST_SENT) {
|
||||
rc = ssh_packet_userauth_gssapi_response(session, type, packet, user);
|
||||
#endif
|
||||
} else {
|
||||
session->auth_state = SSH_AUTH_STATE_PK_OK;
|
||||
SSH_LOG(SSH_LOG_TRACE, "Assuming SSH_USERAUTH_PK_OK");
|
||||
rc = SSH_PACKET_USED;
|
||||
}
|
||||
"Received SSH_USERAUTH_PK_OK/INFO_REQUEST/GSSAPI_RESPONSE");
|
||||
|
||||
return rc;
|
||||
if (session->auth.state == SSH_AUTH_STATE_KBDINT_SENT) {
|
||||
/* Assuming we are in keyboard-interactive context */
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"keyboard-interactive context, "
|
||||
"assuming SSH_USERAUTH_INFO_REQUEST");
|
||||
rc = ssh_packet_userauth_info_request(session,type,packet,user);
|
||||
#ifdef WITH_GSSAPI
|
||||
} else if (session->auth.state == SSH_AUTH_STATE_GSSAPI_REQUEST_SENT) {
|
||||
rc = ssh_packet_userauth_gssapi_response(session, type, packet, user);
|
||||
#endif
|
||||
} else if (session->auth.state == SSH_AUTH_STATE_PUBKEY_OFFER_SENT) {
|
||||
session->auth.state = SSH_AUTH_STATE_PK_OK;
|
||||
SSH_LOG(SSH_LOG_TRACE, "Assuming SSH_USERAUTH_PK_OK");
|
||||
rc = SSH_PACKET_USED;
|
||||
} else {
|
||||
session->auth.state = SSH_AUTH_STATE_ERROR;
|
||||
SSH_LOG(SSH_LOG_TRACE, "SSH_USERAUTH_PK_OK received in wrong state");
|
||||
rc = SSH_PACKET_USED;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -323,7 +374,7 @@ int ssh_userauth_list(ssh_session session, const char *username)
|
||||
return 0;
|
||||
}
|
||||
|
||||
return session->auth_methods;
|
||||
return session->auth.supported_methods;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -378,7 +429,8 @@ int ssh_userauth_none(ssh_session session, const char *username) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
session->auth_state = SSH_AUTH_STATE_NONE;
|
||||
session->auth.current_method = SSH_AUTH_METHOD_NONE;
|
||||
session->auth.state = SSH_AUTH_STATE_AUTH_NONE_SENT;
|
||||
session->pending_call_state = SSH_PENDING_CALL_AUTH_NONE;
|
||||
rc = ssh_packet_send(session);
|
||||
if (rc == SSH_ERROR) {
|
||||
@@ -432,6 +484,7 @@ int ssh_userauth_try_publickey(ssh_session session,
|
||||
const ssh_key pubkey)
|
||||
{
|
||||
ssh_string pubkey_s = NULL;
|
||||
const char *sig_type_c = NULL;
|
||||
int rc;
|
||||
|
||||
if (session == NULL) {
|
||||
@@ -456,6 +509,34 @@ int ssh_userauth_try_publickey(ssh_session session,
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
switch (pubkey->type) {
|
||||
case SSH_KEYTYPE_UNKNOWN:
|
||||
ssh_set_error(session,
|
||||
SSH_REQUEST_DENIED,
|
||||
"Invalid key type (unknown)");
|
||||
return SSH_AUTH_DENIED;
|
||||
case SSH_KEYTYPE_ECDSA:
|
||||
sig_type_c = ssh_pki_key_ecdsa_name(pubkey);
|
||||
break;
|
||||
case SSH_KEYTYPE_DSS:
|
||||
case SSH_KEYTYPE_RSA:
|
||||
case SSH_KEYTYPE_RSA1:
|
||||
case SSH_KEYTYPE_ED25519:
|
||||
case SSH_KEYTYPE_DSS_CERT01:
|
||||
case SSH_KEYTYPE_RSA_CERT01:
|
||||
sig_type_c = ssh_key_get_signature_algorithm(session, pubkey->type);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Check if the given public key algorithm is allowed */
|
||||
if (!ssh_key_algorithm_allowed(session, sig_type_c)) {
|
||||
ssh_set_error(session, SSH_REQUEST_DENIED,
|
||||
"The key algorithm '%s' is not allowed to be used by"
|
||||
" PUBLICKEY_ACCEPTED_TYPES configuration option",
|
||||
sig_type_c);
|
||||
return SSH_AUTH_DENIED;
|
||||
}
|
||||
|
||||
rc = ssh_userauth_request_service(session);
|
||||
if (rc == SSH_AGAIN) {
|
||||
return SSH_AUTH_AGAIN;
|
||||
@@ -476,7 +557,7 @@ int ssh_userauth_try_publickey(ssh_session session,
|
||||
"ssh-connection",
|
||||
"publickey",
|
||||
0, /* private key ? */
|
||||
pubkey->type_c, /* algo */
|
||||
sig_type_c, /* algo */
|
||||
pubkey_s /* public key */
|
||||
);
|
||||
if (rc < 0) {
|
||||
@@ -485,7 +566,8 @@ int ssh_userauth_try_publickey(ssh_session session,
|
||||
|
||||
ssh_string_free(pubkey_s);
|
||||
|
||||
session->auth_state = SSH_AUTH_STATE_NONE;
|
||||
session->auth.current_method = SSH_AUTH_METHOD_PUBLICKEY;
|
||||
session->auth.state = SSH_AUTH_STATE_PUBKEY_OFFER_SENT;
|
||||
session->pending_call_state = SSH_PENDING_CALL_AUTH_OFFER_PUBKEY;
|
||||
rc = ssh_packet_send(session);
|
||||
if (rc == SSH_ERROR) {
|
||||
@@ -536,7 +618,7 @@ int ssh_userauth_publickey(ssh_session session,
|
||||
{
|
||||
ssh_string str = NULL;
|
||||
int rc;
|
||||
const char *type_c;
|
||||
const char *sig_type_c = NULL;
|
||||
enum ssh_keytypes_e key_type;
|
||||
|
||||
if (session == NULL) {
|
||||
@@ -560,6 +642,37 @@ int ssh_userauth_publickey(ssh_session session,
|
||||
return SSH_AUTH_ERROR;
|
||||
}
|
||||
|
||||
/* Cert auth requires presenting the cert type name (*-cert@openssh.com) */
|
||||
key_type = privkey->cert != NULL ? privkey->cert_type : privkey->type;
|
||||
|
||||
switch (key_type) {
|
||||
case SSH_KEYTYPE_UNKNOWN:
|
||||
ssh_set_error(session,
|
||||
SSH_REQUEST_DENIED,
|
||||
"Invalid key type (unknown)");
|
||||
return SSH_AUTH_DENIED;
|
||||
case SSH_KEYTYPE_ECDSA:
|
||||
sig_type_c = ssh_pki_key_ecdsa_name(privkey);
|
||||
break;
|
||||
case SSH_KEYTYPE_DSS:
|
||||
case SSH_KEYTYPE_RSA:
|
||||
case SSH_KEYTYPE_RSA1:
|
||||
case SSH_KEYTYPE_ED25519:
|
||||
case SSH_KEYTYPE_DSS_CERT01:
|
||||
case SSH_KEYTYPE_RSA_CERT01:
|
||||
sig_type_c = ssh_key_get_signature_algorithm(session, key_type);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Check if the given public key algorithm is allowed */
|
||||
if (!ssh_key_algorithm_allowed(session, sig_type_c)) {
|
||||
ssh_set_error(session, SSH_REQUEST_DENIED,
|
||||
"The key algorithm '%s' is not allowed to be used by"
|
||||
" PUBLICKEY_ACCEPTED_TYPES configuration option",
|
||||
sig_type_c);
|
||||
return SSH_AUTH_DENIED;
|
||||
}
|
||||
|
||||
rc = ssh_userauth_request_service(session);
|
||||
if (rc == SSH_AGAIN) {
|
||||
return SSH_AUTH_AGAIN;
|
||||
@@ -567,10 +680,6 @@ int ssh_userauth_publickey(ssh_session session,
|
||||
return SSH_AUTH_ERROR;
|
||||
}
|
||||
|
||||
/* Cert auth requires presenting the cert type name (*-cert@openssh.com) */
|
||||
key_type = privkey->cert != NULL ? privkey->cert_type : privkey->type;
|
||||
type_c = ssh_key_type_to_char(key_type);
|
||||
|
||||
/* get public key or cert */
|
||||
rc = ssh_pki_export_pubkey_blob(privkey, &str);
|
||||
if (rc < 0) {
|
||||
@@ -584,7 +693,7 @@ int ssh_userauth_publickey(ssh_session session,
|
||||
"ssh-connection",
|
||||
"publickey",
|
||||
1, /* private key */
|
||||
type_c, /* algo */
|
||||
sig_type_c, /* algo */
|
||||
str /* public key or cert */
|
||||
);
|
||||
if (rc < 0) {
|
||||
@@ -605,7 +714,8 @@ int ssh_userauth_publickey(ssh_session session,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
session->auth_state = SSH_AUTH_STATE_NONE;
|
||||
session->auth.current_method = SSH_AUTH_METHOD_PUBLICKEY;
|
||||
session->auth.state = SSH_AUTH_STATE_PUBKEY_AUTH_SENT;
|
||||
session->pending_call_state = SSH_PENDING_CALL_AUTH_PUBKEY;
|
||||
rc = ssh_packet_send(session);
|
||||
if (rc == SSH_ERROR) {
|
||||
@@ -632,7 +742,9 @@ static int ssh_userauth_agent_publickey(ssh_session session,
|
||||
const char *username,
|
||||
ssh_key pubkey)
|
||||
{
|
||||
ssh_string str = NULL;
|
||||
ssh_string pubkey_s = NULL;
|
||||
ssh_string sig_blob = NULL;
|
||||
const char *sig_type_c = NULL;
|
||||
int rc;
|
||||
|
||||
switch(session->pending_call_state) {
|
||||
@@ -654,12 +766,22 @@ static int ssh_userauth_agent_publickey(ssh_session session,
|
||||
return SSH_AUTH_ERROR;
|
||||
}
|
||||
|
||||
|
||||
/* public key */
|
||||
rc = ssh_pki_export_pubkey_blob(pubkey, &str);
|
||||
rc = ssh_pki_export_pubkey_blob(pubkey, &pubkey_s);
|
||||
if (rc < 0) {
|
||||
goto fail;
|
||||
}
|
||||
sig_type_c = ssh_key_get_signature_algorithm(session, pubkey->type);
|
||||
|
||||
/* Check if the given public key algorithm is allowed */
|
||||
if (!ssh_key_algorithm_allowed(session, sig_type_c)) {
|
||||
ssh_set_error(session, SSH_REQUEST_DENIED,
|
||||
"The key algorithm '%s' is not allowed to be used by"
|
||||
" PUBLICKEY_ACCEPTED_TYPES configuration option",
|
||||
sig_type_c);
|
||||
SSH_STRING_FREE(pubkey_s);
|
||||
return SSH_AUTH_DENIED;
|
||||
}
|
||||
|
||||
/* request */
|
||||
rc = ssh_buffer_pack(session->out_buffer, "bsssbsS",
|
||||
@@ -668,29 +790,28 @@ static int ssh_userauth_agent_publickey(ssh_session session,
|
||||
"ssh-connection",
|
||||
"publickey",
|
||||
1, /* private key */
|
||||
pubkey->type_c, /* algo */
|
||||
str /* public key */
|
||||
sig_type_c, /* algo */
|
||||
pubkey_s /* public key */
|
||||
);
|
||||
SSH_STRING_FREE(pubkey_s);
|
||||
if (rc < 0) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ssh_string_free(str);
|
||||
|
||||
/* sign the buffer with the private key */
|
||||
str = ssh_pki_do_sign_agent(session, session->out_buffer, pubkey);
|
||||
if (str == NULL) {
|
||||
sig_blob = ssh_pki_do_sign_agent(session, session->out_buffer, pubkey);
|
||||
if (sig_blob == NULL) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
rc = ssh_buffer_add_ssh_string(session->out_buffer, str);
|
||||
ssh_string_free(str);
|
||||
str = NULL;
|
||||
rc = ssh_buffer_add_ssh_string(session->out_buffer, sig_blob);
|
||||
SSH_STRING_FREE(sig_blob);
|
||||
if (rc < 0) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
session->auth_state = SSH_AUTH_STATE_NONE;
|
||||
session->auth.current_method = SSH_AUTH_METHOD_PUBLICKEY;
|
||||
session->auth.state = SSH_AUTH_STATE_PUBKEY_AUTH_SENT;
|
||||
session->pending_call_state = SSH_PENDING_CALL_AUTH_AGENT;
|
||||
rc = ssh_packet_send(session);
|
||||
if (rc == SSH_ERROR) {
|
||||
@@ -707,7 +828,7 @@ pending:
|
||||
fail:
|
||||
ssh_set_error_oom(session);
|
||||
ssh_buffer_reinit(session->out_buffer);
|
||||
ssh_string_free(str);
|
||||
SSH_STRING_FREE(pubkey_s);
|
||||
|
||||
return SSH_AUTH_ERROR;
|
||||
}
|
||||
@@ -905,23 +1026,22 @@ int ssh_userauth_publickey_auto(ssh_session session,
|
||||
return SSH_AUTH_ERROR;
|
||||
}
|
||||
if (! (session->opts.flags & SSH_OPT_FLAG_PUBKEY_AUTH)) {
|
||||
session->auth_methods &= ~SSH_AUTH_METHOD_PUBLICKEY;
|
||||
session->auth.supported_methods &= ~SSH_AUTH_METHOD_PUBLICKEY;
|
||||
return SSH_AUTH_DENIED;
|
||||
}
|
||||
if (session->common.callbacks) {
|
||||
auth_fn = session->common.callbacks->auth_function;
|
||||
auth_data = session->common.callbacks->userdata;
|
||||
}
|
||||
if (!session->auth_auto_state) {
|
||||
session->auth_auto_state =
|
||||
malloc(sizeof(struct ssh_auth_auto_state_struct));
|
||||
if (!session->auth_auto_state) {
|
||||
if (!session->auth.auto_state) {
|
||||
session->auth.auto_state =
|
||||
calloc(1, sizeof(struct ssh_auth_auto_state_struct));
|
||||
if (!session->auth.auto_state) {
|
||||
ssh_set_error_oom(session);
|
||||
return SSH_AUTH_ERROR;
|
||||
}
|
||||
ZERO_STRUCTP(session->auth_auto_state);
|
||||
}
|
||||
state = session->auth_auto_state;
|
||||
state = session->auth.auto_state;
|
||||
if (state->state == SSH_AUTH_AUTO_STATE_NONE) {
|
||||
#ifndef _WIN32
|
||||
/* Try authentication with ssh-agent first */
|
||||
@@ -954,7 +1074,7 @@ int ssh_userauth_publickey_auto(ssh_session session,
|
||||
SSH_FATAL,
|
||||
"Failed to import public key: %s",
|
||||
pubkey_file);
|
||||
SAFE_FREE(session->auth_auto_state);
|
||||
SAFE_FREE(session->auth.auto_state);
|
||||
return SSH_AUTH_ERROR;
|
||||
} else if (rc == SSH_EOF) {
|
||||
/* Read the private key and save the public key to file */
|
||||
@@ -982,7 +1102,7 @@ int ssh_userauth_publickey_auto(ssh_session session,
|
||||
rc = ssh_pki_export_privkey_to_pubkey(state->privkey, &state->pubkey);
|
||||
if (rc == SSH_ERROR) {
|
||||
ssh_key_free(state->privkey);
|
||||
SAFE_FREE(session->auth_auto_state);
|
||||
SAFE_FREE(session->auth.auto_state);
|
||||
return SSH_AUTH_ERROR;
|
||||
}
|
||||
|
||||
@@ -1003,7 +1123,7 @@ int ssh_userauth_publickey_auto(ssh_session session,
|
||||
privkey_file);
|
||||
ssh_key_free(state->privkey);
|
||||
ssh_key_free(state->pubkey);
|
||||
SAFE_FREE(session->auth_auto_state);
|
||||
SAFE_FREE(session->auth.auto_state);
|
||||
return rc;
|
||||
} else if (rc == SSH_AUTH_AGAIN) {
|
||||
return rc;
|
||||
@@ -1056,7 +1176,7 @@ int ssh_userauth_publickey_auto(ssh_session session,
|
||||
if (rc != SSH_AUTH_AGAIN && rc != SSH_AUTH_DENIED) {
|
||||
ssh_key_free(state->privkey);
|
||||
ssh_key_free(state->pubkey);
|
||||
SAFE_FREE(session->auth_auto_state);
|
||||
SAFE_FREE(session->auth.auto_state);
|
||||
if (rc == SSH_AUTH_SUCCESS) {
|
||||
SSH_LOG(SSH_LOG_INFO,
|
||||
"Successfully authenticated using %s",
|
||||
@@ -1077,7 +1197,7 @@ int ssh_userauth_publickey_auto(ssh_session session,
|
||||
}
|
||||
SSH_LOG(SSH_LOG_INFO,
|
||||
"Tried every public key, none matched");
|
||||
SAFE_FREE(session->auth_auto_state);
|
||||
SAFE_FREE(session->auth.auto_state);
|
||||
return SSH_AUTH_DENIED;
|
||||
}
|
||||
|
||||
@@ -1121,7 +1241,7 @@ int ssh_userauth_password(ssh_session session,
|
||||
switch(session->pending_call_state) {
|
||||
case SSH_PENDING_CALL_NONE:
|
||||
break;
|
||||
case SSH_PENDING_CALL_AUTH_OFFER_PUBKEY:
|
||||
case SSH_PENDING_CALL_AUTH_PASSWORD:
|
||||
goto pending;
|
||||
default:
|
||||
ssh_set_error(session,
|
||||
@@ -1151,8 +1271,9 @@ int ssh_userauth_password(ssh_session session,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
session->auth_state = SSH_AUTH_STATE_NONE;
|
||||
session->pending_call_state = SSH_PENDING_CALL_AUTH_OFFER_PUBKEY;
|
||||
session->auth.current_method = SSH_AUTH_METHOD_PASSWORD;
|
||||
session->auth.state = SSH_AUTH_STATE_PASSWORD_AUTH_SENT;
|
||||
session->pending_call_state = SSH_PENDING_CALL_AUTH_PASSWORD;
|
||||
rc = ssh_packet_send(session);
|
||||
if (rc == SSH_ERROR) {
|
||||
return SSH_AUTH_ERROR;
|
||||
@@ -1228,7 +1349,9 @@ void ssh_kbdint_free(ssh_kbdint kbd) {
|
||||
n = kbd->nprompts;
|
||||
if (kbd->prompts) {
|
||||
for (i = 0; i < n; i++) {
|
||||
explicit_bzero(kbd->prompts[i], strlen(kbd->prompts[i]));
|
||||
if (kbd->prompts[i] != NULL) {
|
||||
explicit_bzero(kbd->prompts[i], strlen(kbd->prompts[i]));
|
||||
}
|
||||
SAFE_FREE(kbd->prompts[i]);
|
||||
}
|
||||
SAFE_FREE(kbd->prompts);
|
||||
@@ -1237,7 +1360,9 @@ void ssh_kbdint_free(ssh_kbdint kbd) {
|
||||
n = kbd->nanswers;
|
||||
if (kbd->answers) {
|
||||
for (i = 0; i < n; i++) {
|
||||
explicit_bzero(kbd->answers[i], strlen(kbd->answers[i]));
|
||||
if (kbd->answers[i] != NULL) {
|
||||
explicit_bzero(kbd->answers[i], strlen(kbd->answers[i]));
|
||||
}
|
||||
SAFE_FREE(kbd->answers[i]);
|
||||
}
|
||||
SAFE_FREE(kbd->answers);
|
||||
@@ -1319,7 +1444,7 @@ static int ssh_userauth_kbdint_init(ssh_session session,
|
||||
}
|
||||
|
||||
|
||||
session->auth_state = SSH_AUTH_STATE_KBDINT_SENT;
|
||||
session->auth.state = SSH_AUTH_STATE_KBDINT_SENT;
|
||||
session->pending_call_state = SSH_PENDING_CALL_AUTH_KBDINT_INIT;
|
||||
|
||||
SSH_LOG(SSH_LOG_DEBUG,
|
||||
@@ -1378,7 +1503,8 @@ static int ssh_userauth_kbdint_send(ssh_session session)
|
||||
}
|
||||
}
|
||||
|
||||
session->auth_state = SSH_AUTH_STATE_KBDINT_SENT;
|
||||
session->auth.current_method = SSH_AUTH_METHOD_INTERACTIVE;
|
||||
session->auth.state = SSH_AUTH_STATE_KBDINT_SENT;
|
||||
session->pending_call_state = SSH_PENDING_CALL_AUTH_KBDINT_SEND;
|
||||
ssh_kbdint_free(session->kbdint);
|
||||
session->kbdint = NULL;
|
||||
@@ -1468,7 +1594,7 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_info_request) {
|
||||
return SSH_PACKET_USED;
|
||||
}
|
||||
|
||||
session->kbdint->echo = malloc(nprompts);
|
||||
session->kbdint->echo = calloc(nprompts, sizeof(unsigned char));
|
||||
if (session->kbdint->echo == NULL) {
|
||||
session->kbdint->nprompts = 0;
|
||||
ssh_set_error_oom(session);
|
||||
@@ -1477,7 +1603,6 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_info_request) {
|
||||
|
||||
return SSH_PACKET_USED;
|
||||
}
|
||||
memset(session->kbdint->echo, 0, nprompts);
|
||||
|
||||
for (i = 0; i < nprompts; i++) {
|
||||
rc = ssh_buffer_unpack(packet, "sb",
|
||||
@@ -1491,7 +1616,7 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_info_request) {
|
||||
return SSH_PACKET_USED;
|
||||
}
|
||||
}
|
||||
session->auth_state=SSH_AUTH_STATE_INFO;
|
||||
session->auth.state=SSH_AUTH_STATE_INFO;
|
||||
|
||||
return SSH_PACKET_USED;
|
||||
}
|
||||
@@ -1791,12 +1916,14 @@ int ssh_userauth_gssapi(ssh_session session) {
|
||||
return SSH_AUTH_ERROR;
|
||||
}
|
||||
SSH_LOG(SSH_LOG_PROTOCOL, "Authenticating with gssapi-with-mic");
|
||||
session->auth_state = SSH_AUTH_STATE_NONE;
|
||||
|
||||
session->auth.current_method = SSH_AUTH_METHOD_GSSAPI_MIC;
|
||||
session->auth.state = SSH_AUTH_STATE_NONE;
|
||||
session->pending_call_state = SSH_PENDING_CALL_AUTH_GSSAPI_MIC;
|
||||
rc = ssh_gssapi_auth_mic(session);
|
||||
|
||||
if (rc == SSH_AUTH_ERROR || rc == SSH_AUTH_DENIED) {
|
||||
session->auth_state = SSH_AUTH_STATE_NONE;
|
||||
session->auth.state = SSH_AUTH_STATE_NONE;
|
||||
session->pending_call_state = SSH_PENDING_CALL_NONE;
|
||||
return rc;
|
||||
}
|
||||
|
||||
431
src/buffer.c
@@ -25,6 +25,7 @@
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <netinet/in.h>
|
||||
@@ -36,6 +37,24 @@
|
||||
#include "libssh/misc.h"
|
||||
#include "libssh/bignum.h"
|
||||
|
||||
/*
|
||||
* Describes a buffer state
|
||||
* [XXXXXXXXXXXXDATA PAYLOAD XXXXXXXXXXXXXXXXXXXXXXXX]
|
||||
* ^ ^ ^ ^]
|
||||
* \_data points\_pos points here \_used points here | /
|
||||
* here Allocated
|
||||
*/
|
||||
struct ssh_buffer_struct {
|
||||
bool secure;
|
||||
size_t used;
|
||||
size_t allocated;
|
||||
size_t pos;
|
||||
uint8_t *data;
|
||||
};
|
||||
|
||||
/* Buffer size maximum is 256M */
|
||||
#define BUFFER_SIZE_MAX 0x10000000
|
||||
|
||||
/**
|
||||
* @defgroup libssh_buffer The SSH buffer functions.
|
||||
* @ingroup libssh
|
||||
@@ -54,24 +73,38 @@
|
||||
*
|
||||
* @param[in] buf The buffer to check.
|
||||
*/
|
||||
static void buffer_verify(ssh_buffer buf){
|
||||
int doabort=0;
|
||||
if(buf->data == NULL)
|
||||
return;
|
||||
if(buf->used > buf->allocated){
|
||||
fprintf(stderr,"Buffer error : allocated %u, used %u\n",buf->allocated, buf->used);
|
||||
doabort=1;
|
||||
}
|
||||
if(buf->pos > buf->used){
|
||||
fprintf(stderr,"Buffer error : position %u, used %u\n",buf->pos, buf->used);
|
||||
doabort=1;
|
||||
}
|
||||
if(buf->pos > buf->allocated){
|
||||
fprintf(stderr,"Buffer error : position %u, allocated %u\n",buf->pos, buf->allocated);
|
||||
doabort=1;
|
||||
}
|
||||
if(doabort)
|
||||
abort();
|
||||
static void buffer_verify(ssh_buffer buf)
|
||||
{
|
||||
bool do_abort = false;
|
||||
|
||||
if (buf->data == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (buf->used > buf->allocated) {
|
||||
fprintf(stderr,
|
||||
"BUFFER ERROR: allocated %zu, used %zu\n",
|
||||
buf->allocated,
|
||||
buf->used);
|
||||
do_abort = true;
|
||||
}
|
||||
if (buf->pos > buf->used) {
|
||||
fprintf(stderr,
|
||||
"BUFFER ERROR: position %zu, used %zu\n",
|
||||
buf->pos,
|
||||
buf->used);
|
||||
do_abort = true;
|
||||
}
|
||||
if (buf->pos > buf->allocated) {
|
||||
fprintf(stderr,
|
||||
"BUFFER ERROR: position %zu, allocated %zu\n",
|
||||
buf->pos,
|
||||
buf->allocated);
|
||||
do_abort = true;
|
||||
}
|
||||
if (do_abort) {
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
@@ -83,15 +116,29 @@ static void buffer_verify(ssh_buffer buf){
|
||||
*
|
||||
* @return A newly initialized SSH buffer, NULL on error.
|
||||
*/
|
||||
struct ssh_buffer_struct *ssh_buffer_new(void) {
|
||||
struct ssh_buffer_struct *buf =
|
||||
calloc(1, sizeof(struct ssh_buffer_struct));
|
||||
if (buf == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
struct ssh_buffer_struct *ssh_buffer_new(void)
|
||||
{
|
||||
struct ssh_buffer_struct *buf = NULL;
|
||||
int rc;
|
||||
|
||||
buffer_verify(buf);
|
||||
return buf;
|
||||
buf = calloc(1, sizeof(struct ssh_buffer_struct));
|
||||
if (buf == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Always preallocate 64 bytes.
|
||||
*
|
||||
* -1 for ralloc_buffer magic.
|
||||
*/
|
||||
rc = ssh_buffer_allocate_size(buf, 64 - 1);
|
||||
if (rc != 0) {
|
||||
SAFE_FREE(buf);
|
||||
return NULL;
|
||||
}
|
||||
buffer_verify(buf);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -99,19 +146,23 @@ struct ssh_buffer_struct *ssh_buffer_new(void) {
|
||||
*
|
||||
* \param[in] buffer The buffer to free.
|
||||
*/
|
||||
void ssh_buffer_free(struct ssh_buffer_struct *buffer) {
|
||||
if (buffer == NULL) {
|
||||
return;
|
||||
}
|
||||
buffer_verify(buffer);
|
||||
void ssh_buffer_free(struct ssh_buffer_struct *buffer)
|
||||
{
|
||||
if (buffer == NULL) {
|
||||
return;
|
||||
}
|
||||
buffer_verify(buffer);
|
||||
|
||||
if (buffer->data) {
|
||||
/* burn the data */
|
||||
explicit_bzero(buffer->data, buffer->allocated);
|
||||
SAFE_FREE(buffer->data);
|
||||
}
|
||||
explicit_bzero(buffer, sizeof(struct ssh_buffer_struct));
|
||||
SAFE_FREE(buffer);
|
||||
if (buffer->secure && buffer->allocated > 0) {
|
||||
/* burn the data */
|
||||
explicit_bzero(buffer->data, buffer->allocated);
|
||||
SAFE_FREE(buffer->data);
|
||||
|
||||
explicit_bzero(buffer, sizeof(struct ssh_buffer_struct));
|
||||
} else {
|
||||
SAFE_FREE(buffer->data);
|
||||
}
|
||||
SAFE_FREE(buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -122,13 +173,15 @@ void ssh_buffer_free(struct ssh_buffer_struct *buffer) {
|
||||
*
|
||||
* @param[in] buffer buffer to set secure.
|
||||
*/
|
||||
void ssh_buffer_set_secure(ssh_buffer buffer){
|
||||
buffer->secure = 1;
|
||||
void ssh_buffer_set_secure(ssh_buffer buffer)
|
||||
{
|
||||
buffer->secure = true;
|
||||
}
|
||||
|
||||
static int realloc_buffer(struct ssh_buffer_struct *buffer, size_t needed) {
|
||||
static int realloc_buffer(struct ssh_buffer_struct *buffer, size_t needed)
|
||||
{
|
||||
size_t smallest = 1;
|
||||
char *new;
|
||||
uint8_t *new = NULL;
|
||||
|
||||
buffer_verify(buffer);
|
||||
|
||||
@@ -140,25 +193,28 @@ static int realloc_buffer(struct ssh_buffer_struct *buffer, size_t needed) {
|
||||
smallest <<= 1;
|
||||
}
|
||||
needed = smallest;
|
||||
if (buffer->secure){
|
||||
|
||||
if (needed > BUFFER_SIZE_MAX) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (buffer->secure) {
|
||||
new = malloc(needed);
|
||||
if (new == NULL) {
|
||||
return -1;
|
||||
}
|
||||
if (buffer->used > 0) {
|
||||
memcpy(new, buffer->data,buffer->used);
|
||||
explicit_bzero(buffer->data, buffer->used);
|
||||
SAFE_FREE(buffer->data);
|
||||
}
|
||||
memcpy(new, buffer->data, buffer->used);
|
||||
explicit_bzero(buffer->data, buffer->used);
|
||||
SAFE_FREE(buffer->data);
|
||||
} else {
|
||||
new = realloc(buffer->data, needed);
|
||||
if (new == NULL) {
|
||||
buffer->data = NULL;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
buffer->data = new;
|
||||
buffer->allocated = needed;
|
||||
|
||||
buffer_verify(buffer);
|
||||
return 0;
|
||||
}
|
||||
@@ -167,45 +223,64 @@ static int realloc_buffer(struct ssh_buffer_struct *buffer, size_t needed) {
|
||||
* @brief shifts a buffer to remove unused data in the beginning
|
||||
* @param buffer SSH buffer
|
||||
*/
|
||||
static void buffer_shift(ssh_buffer buffer){
|
||||
uint32_t burn_pos = buffer->pos;
|
||||
static void buffer_shift(ssh_buffer buffer)
|
||||
{
|
||||
size_t burn_pos = buffer->pos;
|
||||
|
||||
buffer_verify(buffer);
|
||||
if(buffer->pos==0)
|
||||
return;
|
||||
memmove(buffer->data, buffer->data + buffer->pos, buffer->used - buffer->pos);
|
||||
buffer->used -= buffer->pos;
|
||||
buffer->pos=0;
|
||||
buffer_verify(buffer);
|
||||
|
||||
if (buffer->secure){
|
||||
void *ptr = buffer->data + buffer->used;
|
||||
explicit_bzero(ptr, burn_pos);
|
||||
}
|
||||
if (buffer->pos == 0) {
|
||||
return;
|
||||
}
|
||||
memmove(buffer->data,
|
||||
buffer->data + buffer->pos,
|
||||
buffer->used - buffer->pos);
|
||||
buffer->used -= buffer->pos;
|
||||
buffer->pos = 0;
|
||||
|
||||
buffer_verify(buffer);
|
||||
if (buffer->secure) {
|
||||
void *ptr = buffer->data + buffer->used;
|
||||
explicit_bzero(ptr, burn_pos);
|
||||
}
|
||||
|
||||
buffer_verify(buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reinitialize a SSH buffer.
|
||||
*
|
||||
* In case the buffer has exceeded 64K in size, the buffer will be reallocated
|
||||
* to 64K.
|
||||
*
|
||||
* @param[in] buffer The buffer to reinitialize.
|
||||
*
|
||||
* @return 0 on success, < 0 on error.
|
||||
*/
|
||||
int ssh_buffer_reinit(struct ssh_buffer_struct *buffer)
|
||||
{
|
||||
if (buffer == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
buffer_verify(buffer);
|
||||
if (buffer->used > 0) {
|
||||
explicit_bzero(buffer->data, buffer->used);
|
||||
|
||||
if (buffer->secure && buffer->allocated > 0) {
|
||||
explicit_bzero(buffer->data, buffer->allocated);
|
||||
}
|
||||
buffer->used = 0;
|
||||
buffer->pos = 0;
|
||||
|
||||
if (buffer->allocated > 127) {
|
||||
if (realloc_buffer(buffer, 127) < 0) {
|
||||
/* If the buffer is bigger then 64K, reset it to 64K */
|
||||
if (buffer->allocated > 65536) {
|
||||
int rc;
|
||||
|
||||
/* -1 for realloc_buffer magic */
|
||||
rc = realloc_buffer(buffer, 65536 - 1);
|
||||
if (rc != 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
buffer_verify(buffer);
|
||||
|
||||
return 0;
|
||||
@@ -683,32 +758,153 @@ int ssh_buffer_validate_length(struct ssh_buffer_struct *buffer, size_t len)
|
||||
*
|
||||
* @returns The SSH String, NULL on error.
|
||||
*/
|
||||
struct ssh_string_struct *ssh_buffer_get_ssh_string(struct ssh_buffer_struct *buffer) {
|
||||
uint32_t stringlen;
|
||||
uint32_t hostlen;
|
||||
struct ssh_string_struct *str = NULL;
|
||||
int rc;
|
||||
struct ssh_string_struct *
|
||||
ssh_buffer_get_ssh_string(struct ssh_buffer_struct *buffer)
|
||||
{
|
||||
uint32_t stringlen;
|
||||
uint32_t hostlen;
|
||||
struct ssh_string_struct *str = NULL;
|
||||
int rc;
|
||||
|
||||
if (ssh_buffer_get_u32(buffer, &stringlen) == 0) {
|
||||
return NULL;
|
||||
}
|
||||
hostlen = ntohl(stringlen);
|
||||
/* verify if there is enough space in buffer to get it */
|
||||
rc = ssh_buffer_validate_length(buffer, hostlen);
|
||||
if (rc != SSH_OK) {
|
||||
return NULL; /* it is indeed */
|
||||
}
|
||||
str = ssh_string_new(hostlen);
|
||||
if (str == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
if (ssh_buffer_get_data(buffer, ssh_string_data(str), hostlen) != hostlen) {
|
||||
/* should never happen */
|
||||
SAFE_FREE(str);
|
||||
return NULL;
|
||||
}
|
||||
rc = ssh_buffer_get_u32(buffer, &stringlen);
|
||||
if (rc == 0) {
|
||||
return NULL;
|
||||
}
|
||||
hostlen = ntohl(stringlen);
|
||||
/* verify if there is enough space in buffer to get it */
|
||||
rc = ssh_buffer_validate_length(buffer, hostlen);
|
||||
if (rc != SSH_OK) {
|
||||
return NULL; /* it is indeed */
|
||||
}
|
||||
str = ssh_string_new(hostlen);
|
||||
if (str == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return str;
|
||||
stringlen = ssh_buffer_get_data(buffer, ssh_string_data(str), hostlen);
|
||||
if (stringlen != hostlen) {
|
||||
/* should never happen */
|
||||
SAFE_FREE(str);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Pre-calculate the size we need for packing the buffer.
|
||||
*
|
||||
* This makes sure that enough memory is allocated for packing the buffer and
|
||||
* we only have to do one memory allocation.
|
||||
*
|
||||
* @param[in] buffer The buffer to allocate
|
||||
*
|
||||
* @param[in] format A format string of arguments.
|
||||
*
|
||||
* @param[in] argc The number of arguments.
|
||||
*
|
||||
* @param[in] ap The va_list of arguments.
|
||||
*
|
||||
* @return SSH_OK on success, SSH_ERROR on error.
|
||||
*/
|
||||
static int ssh_buffer_pack_allocate_va(struct ssh_buffer_struct *buffer,
|
||||
const char *format,
|
||||
int argc,
|
||||
va_list ap)
|
||||
{
|
||||
const char *p = NULL;
|
||||
ssh_string string = NULL;
|
||||
char *cstring = NULL;
|
||||
size_t needed_size = 0;
|
||||
size_t count;
|
||||
size_t len;
|
||||
int rc = SSH_OK;
|
||||
|
||||
for (p = format, count = 0; *p != '\0'; p++, count++) {
|
||||
/* Invalid number of arguments passed */
|
||||
if (argc != -1 && count > argc) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
switch(*p) {
|
||||
case 'b':
|
||||
va_arg(ap, unsigned int);
|
||||
needed_size += sizeof(uint8_t);
|
||||
break;
|
||||
case 'w':
|
||||
va_arg(ap, unsigned int);
|
||||
needed_size += sizeof(uint16_t);
|
||||
break;
|
||||
case 'd':
|
||||
va_arg(ap, uint32_t);
|
||||
needed_size += sizeof(uint32_t);
|
||||
break;
|
||||
case 'q':
|
||||
va_arg(ap, uint64_t);
|
||||
needed_size += sizeof(uint64_t);
|
||||
break;
|
||||
case 'S':
|
||||
string = va_arg(ap, ssh_string);
|
||||
needed_size += 4 + ssh_string_len(string);
|
||||
string = NULL;
|
||||
break;
|
||||
case 's':
|
||||
cstring = va_arg(ap, char *);
|
||||
needed_size += sizeof(uint32_t) + strlen(cstring);
|
||||
cstring = NULL;
|
||||
break;
|
||||
case 'P':
|
||||
len = va_arg(ap, size_t);
|
||||
needed_size += len;
|
||||
va_arg(ap, void *);
|
||||
count++; /* increase argument count */
|
||||
break;
|
||||
case 'B':
|
||||
va_arg(ap, bignum);
|
||||
/*
|
||||
* Use a fixed size for a bignum
|
||||
* (they should normaly be around 32)
|
||||
*/
|
||||
needed_size += 64;
|
||||
break;
|
||||
case 't':
|
||||
cstring = va_arg(ap, char *);
|
||||
needed_size += strlen(cstring);
|
||||
cstring = NULL;
|
||||
break;
|
||||
default:
|
||||
SSH_LOG(SSH_LOG_WARN, "Invalid buffer format %c", *p);
|
||||
rc = SSH_ERROR;
|
||||
}
|
||||
if (rc != SSH_OK){
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (argc != -1 && argc != count) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
if (rc != SSH_ERROR){
|
||||
/*
|
||||
* Check if our canary is intact, if not, something really bad happened.
|
||||
*/
|
||||
uint32_t canary = va_arg(ap, uint32_t);
|
||||
if (canary != SSH_BUFFER_PACK_END) {
|
||||
if (argc == -1){
|
||||
return SSH_ERROR;
|
||||
} else {
|
||||
abort();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rc = ssh_buffer_allocate_size(buffer, needed_size);
|
||||
if (rc != 0) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
return SSH_OK;
|
||||
}
|
||||
|
||||
/** @internal
|
||||
@@ -860,9 +1056,18 @@ int _ssh_buffer_pack(struct ssh_buffer_struct *buffer,
|
||||
va_list ap;
|
||||
int rc;
|
||||
|
||||
va_start(ap, argc);
|
||||
rc = ssh_buffer_pack_allocate_va(buffer, format, argc, ap);
|
||||
va_end(ap);
|
||||
|
||||
if (rc != SSH_OK) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
va_start(ap, argc);
|
||||
rc = ssh_buffer_pack_va(buffer, format, argc, ap);
|
||||
va_end(ap);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -903,8 +1108,8 @@ int ssh_buffer_unpack_va(struct ssh_buffer_struct *buffer,
|
||||
for (p = format, count = 0; *p != '\0'; p++, count++) {
|
||||
/* Invalid number of arguments passed */
|
||||
if (argc != -1 && count > argc) {
|
||||
va_end(ap_copy);
|
||||
return SSH_ERROR;
|
||||
rc = SSH_ERROR;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
switch (*p) {
|
||||
@@ -1016,8 +1221,9 @@ int ssh_buffer_unpack_va(struct ssh_buffer_struct *buffer,
|
||||
rc = SSH_ERROR;
|
||||
}
|
||||
|
||||
cleanup:
|
||||
if (rc != SSH_ERROR){
|
||||
/* Check if our canary is intact, if not somthing really bad happened */
|
||||
/* Check if our canary is intact, if not something really bad happened */
|
||||
uint32_t canary = va_arg(ap, uint32_t);
|
||||
if (canary != SSH_BUFFER_PACK_END){
|
||||
if (argc == -1){
|
||||
@@ -1034,22 +1240,53 @@ int ssh_buffer_unpack_va(struct ssh_buffer_struct *buffer,
|
||||
for(p=format;p<last;++p){
|
||||
switch(*p){
|
||||
case 'b':
|
||||
o.byte = va_arg(ap_copy, uint8_t *);
|
||||
if (buffer->secure) {
|
||||
explicit_bzero(o.byte, sizeof(uint8_t));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 'w':
|
||||
o.word = va_arg(ap_copy, uint16_t *);
|
||||
if (buffer->secure) {
|
||||
explicit_bzero(o.word, sizeof(uint16_t));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 'd':
|
||||
o.dword = va_arg(ap_copy, uint32_t *);
|
||||
if (buffer->secure) {
|
||||
explicit_bzero(o.dword, sizeof(uint32_t));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 'q':
|
||||
(void)va_arg(ap_copy, void *);
|
||||
o.qword = va_arg(ap_copy, uint64_t *);
|
||||
if (buffer->secure) {
|
||||
explicit_bzero(o.qword, sizeof(uint64_t));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 'S':
|
||||
o.string=va_arg(ap_copy, ssh_string *);
|
||||
o.string = va_arg(ap_copy, ssh_string *);
|
||||
if (buffer->secure) {
|
||||
ssh_string_burn(*o.string);
|
||||
}
|
||||
SAFE_FREE(*o.string);
|
||||
break;
|
||||
case 's':
|
||||
o.cstring=va_arg(ap_copy, char **);
|
||||
o.cstring = va_arg(ap_copy, char **);
|
||||
if (buffer->secure) {
|
||||
explicit_bzero(*o.cstring, strlen(*o.cstring));
|
||||
}
|
||||
SAFE_FREE(*o.cstring);
|
||||
break;
|
||||
case 'P':
|
||||
(void)va_arg(ap_copy, size_t);
|
||||
len = va_arg(ap_copy, size_t);
|
||||
o.data = va_arg(ap_copy, void **);
|
||||
if (buffer->secure) {
|
||||
explicit_bzero(*o.data, len);
|
||||
}
|
||||
SAFE_FREE(*o.data);
|
||||
break;
|
||||
default:
|
||||
|
||||
140
src/channels.c
@@ -76,44 +76,46 @@ static ssh_channel channel_from_msg(ssh_session session, ssh_buffer packet);
|
||||
*
|
||||
* @return A pointer to a newly allocated channel, NULL on error.
|
||||
*/
|
||||
ssh_channel ssh_channel_new(ssh_session session) {
|
||||
ssh_channel channel = NULL;
|
||||
ssh_channel ssh_channel_new(ssh_session session)
|
||||
{
|
||||
ssh_channel channel = NULL;
|
||||
|
||||
if(session == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
if (session == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
channel = malloc(sizeof(struct ssh_channel_struct));
|
||||
if (channel == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
return NULL;
|
||||
}
|
||||
memset(channel,0,sizeof(struct ssh_channel_struct));
|
||||
channel = calloc(1, sizeof(struct ssh_channel_struct));
|
||||
if (channel == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
channel->stdout_buffer = ssh_buffer_new();
|
||||
if (channel->stdout_buffer == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
SAFE_FREE(channel);
|
||||
return NULL;
|
||||
}
|
||||
channel->stdout_buffer = ssh_buffer_new();
|
||||
if (channel->stdout_buffer == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
SAFE_FREE(channel);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
channel->stderr_buffer = ssh_buffer_new();
|
||||
if (channel->stderr_buffer == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
ssh_buffer_free(channel->stdout_buffer);
|
||||
SAFE_FREE(channel);
|
||||
return NULL;
|
||||
}
|
||||
channel->stderr_buffer = ssh_buffer_new();
|
||||
if (channel->stderr_buffer == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
ssh_buffer_free(channel->stdout_buffer);
|
||||
SAFE_FREE(channel);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
channel->session = session;
|
||||
channel->exit_status = -1;
|
||||
channel->flags = SSH_CHANNEL_FLAG_NOT_BOUND;
|
||||
channel->session = session;
|
||||
channel->exit_status = -1;
|
||||
channel->flags = SSH_CHANNEL_FLAG_NOT_BOUND;
|
||||
|
||||
if(session->channels == NULL) {
|
||||
session->channels = ssh_list_new();
|
||||
}
|
||||
ssh_list_prepend(session->channels, channel);
|
||||
return channel;
|
||||
if (session->channels == NULL) {
|
||||
session->channels = ssh_list_new();
|
||||
}
|
||||
|
||||
ssh_list_prepend(session->channels, channel);
|
||||
|
||||
return channel;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -169,6 +171,15 @@ SSH_PACKET_CALLBACK(ssh_packet_channel_open_conf){
|
||||
"Received a CHANNEL_OPEN_CONFIRMATION for channel %d:%d",
|
||||
channel->local_channel,
|
||||
channel->remote_channel);
|
||||
|
||||
if (channel->state != SSH_CHANNEL_STATE_OPENING) {
|
||||
SSH_LOG(SSH_LOG_RARE,
|
||||
"SSH2_MSG_CHANNEL_OPEN_CONFIRMATION received in incorrect "
|
||||
"channel state %d",
|
||||
channel->state);
|
||||
goto error;
|
||||
}
|
||||
|
||||
SSH_LOG(SSH_LOG_PROTOCOL,
|
||||
"Remote window : %lu, maxpacket : %lu",
|
||||
(long unsigned int) channel->remote_window,
|
||||
@@ -209,6 +220,14 @@ SSH_PACKET_CALLBACK(ssh_packet_channel_open_fail){
|
||||
return SSH_PACKET_USED;
|
||||
}
|
||||
|
||||
if (channel->state != SSH_CHANNEL_STATE_OPENING) {
|
||||
SSH_LOG(SSH_LOG_RARE,
|
||||
"SSH2_MSG_CHANNEL_OPEN_FAILURE received in incorrect channel "
|
||||
"state %d",
|
||||
channel->state);
|
||||
goto error;
|
||||
}
|
||||
|
||||
ssh_set_error(session, SSH_REQUEST_DENIED,
|
||||
"Channel opening failure: channel %u error (%lu) %s",
|
||||
channel->local_channel,
|
||||
@@ -217,6 +236,10 @@ SSH_PACKET_CALLBACK(ssh_packet_channel_open_fail){
|
||||
SAFE_FREE(error);
|
||||
channel->state=SSH_CHANNEL_STATE_OPEN_DENIED;
|
||||
return SSH_PACKET_USED;
|
||||
|
||||
error:
|
||||
ssh_set_error(session, SSH_FATAL, "Invalid packet");
|
||||
return SSH_PACKET_USED;
|
||||
}
|
||||
|
||||
static int ssh_channel_open_termination(void *c){
|
||||
@@ -1005,22 +1028,24 @@ void ssh_channel_free(ssh_channel channel) {
|
||||
* @brief Effectively free a channel, without caring about flags
|
||||
*/
|
||||
|
||||
void ssh_channel_do_free(ssh_channel channel){
|
||||
struct ssh_iterator *it;
|
||||
ssh_session session = channel->session;
|
||||
it = ssh_list_find(session->channels, channel);
|
||||
if(it != NULL){
|
||||
ssh_list_remove(session->channels, it);
|
||||
}
|
||||
ssh_buffer_free(channel->stdout_buffer);
|
||||
ssh_buffer_free(channel->stderr_buffer);
|
||||
if (channel->callbacks != NULL){
|
||||
ssh_list_free(channel->callbacks);
|
||||
}
|
||||
void ssh_channel_do_free(ssh_channel channel)
|
||||
{
|
||||
struct ssh_iterator *it = NULL;
|
||||
ssh_session session = channel->session;
|
||||
|
||||
/* debug trick to catch use after frees */
|
||||
memset(channel, 'X', sizeof(struct ssh_channel_struct));
|
||||
SAFE_FREE(channel);
|
||||
it = ssh_list_find(session->channels, channel);
|
||||
if (it != NULL) {
|
||||
ssh_list_remove(session->channels, it);
|
||||
}
|
||||
|
||||
ssh_buffer_free(channel->stdout_buffer);
|
||||
ssh_buffer_free(channel->stderr_buffer);
|
||||
|
||||
if (channel->callbacks != NULL) {
|
||||
ssh_list_free(channel->callbacks);
|
||||
}
|
||||
|
||||
SAFE_FREE(channel);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2631,7 +2656,11 @@ static int ssh_channel_read_termination(void *s){
|
||||
*/
|
||||
int ssh_channel_read(ssh_channel channel, void *dest, uint32_t count, int is_stderr)
|
||||
{
|
||||
return ssh_channel_read_timeout(channel, dest, count, is_stderr, -1);
|
||||
return ssh_channel_read_timeout(channel,
|
||||
dest,
|
||||
count,
|
||||
is_stderr,
|
||||
SSH_TIMEOUT_DEFAULT);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2661,7 +2690,7 @@ int ssh_channel_read_timeout(ssh_channel channel,
|
||||
void *dest,
|
||||
uint32_t count,
|
||||
int is_stderr,
|
||||
int timeout)
|
||||
int timeout_ms)
|
||||
{
|
||||
ssh_session session;
|
||||
ssh_buffer stdbuf;
|
||||
@@ -2711,18 +2740,23 @@ int ssh_channel_read_timeout(ssh_channel channel,
|
||||
ctx.buffer = stdbuf;
|
||||
ctx.count = 1;
|
||||
|
||||
if (timeout < 0) {
|
||||
timeout = SSH_TIMEOUT_DEFAULT;
|
||||
if (timeout_ms < 0) {
|
||||
timeout_ms = SSH_TIMEOUT_INFINITE;
|
||||
}
|
||||
|
||||
rc = ssh_handle_packets_termination(session,
|
||||
timeout,
|
||||
timeout_ms,
|
||||
ssh_channel_read_termination,
|
||||
&ctx);
|
||||
if (rc == SSH_ERROR){
|
||||
return rc;
|
||||
}
|
||||
if (session->session_state == SSH_SESSION_STATE_ERROR){
|
||||
|
||||
/*
|
||||
* If the channel is closed or in an error state, reading from it is an error
|
||||
*/
|
||||
if (session->session_state == SSH_SESSION_STATE_ERROR ||
|
||||
channel->state == SSH_CHANNEL_STATE_CLOSED) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
if (channel->remote_eof && ssh_buffer_get_len(stdbuf) == 0) {
|
||||
|
||||
12
src/client.c
@@ -250,6 +250,8 @@ static int dh_handshake(ssh_session session) {
|
||||
switch(session->next_crypto->kex_type){
|
||||
case SSH_KEX_DH_GROUP1_SHA1:
|
||||
case SSH_KEX_DH_GROUP14_SHA1:
|
||||
case SSH_KEX_DH_GROUP16_SHA512:
|
||||
case SSH_KEX_DH_GROUP18_SHA512:
|
||||
rc = ssh_client_dh_init(session);
|
||||
break;
|
||||
#ifdef HAVE_ECDH
|
||||
@@ -295,7 +297,7 @@ static int dh_handshake(ssh_session session) {
|
||||
static int ssh_service_request_termination(void *s){
|
||||
ssh_session session = (ssh_session)s;
|
||||
if(session->session_state == SSH_SESSION_STATE_ERROR ||
|
||||
session->auth_service_state != SSH_AUTH_SERVICE_SENT)
|
||||
session->auth.service_state != SSH_AUTH_SERVICE_SENT)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
@@ -319,7 +321,7 @@ static int ssh_service_request_termination(void *s){
|
||||
int ssh_service_request(ssh_session session, const char *service) {
|
||||
int rc=SSH_ERROR;
|
||||
|
||||
if(session->auth_service_state != SSH_AUTH_SERVICE_NONE)
|
||||
if(session->auth.service_state != SSH_AUTH_SERVICE_NONE)
|
||||
goto pending;
|
||||
|
||||
rc = ssh_buffer_pack(session->out_buffer,
|
||||
@@ -330,7 +332,7 @@ int ssh_service_request(ssh_session session, const char *service) {
|
||||
ssh_set_error_oom(session);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
session->auth_service_state=SSH_AUTH_SERVICE_SENT;
|
||||
session->auth.service_state = SSH_AUTH_SERVICE_SENT;
|
||||
if (ssh_packet_send(session) == SSH_ERROR) {
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
"Sending SSH2_MSG_SERVICE_REQUEST failed.");
|
||||
@@ -345,7 +347,7 @@ pending:
|
||||
if (rc == SSH_ERROR) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
switch(session->auth_service_state){
|
||||
switch(session->auth.service_state) {
|
||||
case SSH_AUTH_SERVICE_DENIED:
|
||||
ssh_set_error(session,SSH_FATAL,"ssh_auth_service request denied");
|
||||
break;
|
||||
@@ -700,7 +702,7 @@ error:
|
||||
if (session->out_hashbuf) {
|
||||
ssh_buffer_reinit(session->out_hashbuf);
|
||||
}
|
||||
session->auth_methods = 0;
|
||||
session->auth.supported_methods = 0;
|
||||
SAFE_FREE(session->serverbanner);
|
||||
SAFE_FREE(session->clientbanner);
|
||||
|
||||
|
||||
195
src/config.c
@@ -30,6 +30,7 @@
|
||||
#ifdef HAVE_GLOB_H
|
||||
# include <glob.h>
|
||||
#endif
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "libssh/priv.h"
|
||||
#include "libssh/session.h"
|
||||
@@ -72,6 +73,7 @@ enum ssh_config_opcode_e {
|
||||
SOC_KBDINTERACTIVEAUTHENTICATION,
|
||||
SOC_PASSWORDAUTHENTICATION,
|
||||
SOC_PUBKEYAUTHENTICATION,
|
||||
SOC_PUBKEYACCEPTEDTYPES,
|
||||
|
||||
SOC_END /* Keep this one last in the list */
|
||||
};
|
||||
@@ -144,7 +146,7 @@ static struct ssh_config_keyword_table_s ssh_config_keyword_table[] = {
|
||||
{ "preferredauthentications", SOC_UNSUPPORTED},
|
||||
{ "proxyjump", SOC_UNSUPPORTED},
|
||||
{ "proxyusefdpass", SOC_UNSUPPORTED},
|
||||
{ "pubkeyacceptedtypes", SOC_UNSUPPORTED},
|
||||
{ "pubkeyacceptedtypes", SOC_PUBKEYACCEPTEDTYPES},
|
||||
{ "rekeylimit", SOC_UNSUPPORTED},
|
||||
{ "remotecommand", SOC_UNSUPPORTED},
|
||||
{ "revokedhostkeys", SOC_UNSUPPORTED},
|
||||
@@ -184,6 +186,32 @@ static struct ssh_config_keyword_table_s ssh_config_keyword_table[] = {
|
||||
{ NULL, SOC_UNKNOWN }
|
||||
};
|
||||
|
||||
enum ssh_config_match_e {
|
||||
MATCH_UNKNOWN = -1,
|
||||
MATCH_ALL,
|
||||
MATCH_CANONICAL,
|
||||
MATCH_EXEC,
|
||||
MATCH_HOST,
|
||||
MATCH_ORIGINALHOST,
|
||||
MATCH_USER,
|
||||
MATCH_LOCALUSER
|
||||
};
|
||||
|
||||
struct ssh_config_match_keyword_table_s {
|
||||
const char *name;
|
||||
enum ssh_config_match_e opcode;
|
||||
};
|
||||
|
||||
static struct ssh_config_match_keyword_table_s ssh_config_match_keyword_table[] = {
|
||||
{ "all", MATCH_ALL },
|
||||
{ "canonical", MATCH_CANONICAL },
|
||||
{ "exec", MATCH_EXEC },
|
||||
{ "host", MATCH_HOST },
|
||||
{ "originalhost", MATCH_ORIGINALHOST },
|
||||
{ "user", MATCH_USER },
|
||||
{ "localuser", MATCH_LOCALUSER },
|
||||
};
|
||||
|
||||
static int ssh_config_parse_line(ssh_session session, const char *line,
|
||||
unsigned int count, int *parsing, int seen[]);
|
||||
|
||||
@@ -319,7 +347,7 @@ static void local_parse_file(ssh_session session, const char *filename, int *par
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef HAVE_GLOB
|
||||
#if defined(HAVE_GLOB) && defined(HAVE_GLOB_GL_FLAGS_MEMBER)
|
||||
static void local_parse_glob(ssh_session session,
|
||||
const char *fileglob,
|
||||
int *parsing,
|
||||
@@ -348,7 +376,41 @@ static void local_parse_glob(ssh_session session,
|
||||
|
||||
globfree(&globbuf);
|
||||
}
|
||||
#endif /* HAVE_GLOB */
|
||||
#endif /* HAVE_GLOB HAVE_GLOB_GL_FLAGS_MEMBER */
|
||||
|
||||
static enum ssh_config_match_e
|
||||
ssh_config_get_match_opcode(const char *keyword)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; ssh_config_match_keyword_table[i].name != NULL; i++) {
|
||||
if (strcasecmp(keyword, ssh_config_match_keyword_table[i].name) == 0) {
|
||||
return ssh_config_match_keyword_table[i].opcode;
|
||||
}
|
||||
}
|
||||
|
||||
return MATCH_UNKNOWN;
|
||||
}
|
||||
|
||||
static int
|
||||
ssh_config_match(char *value, const char *pattern, bool negate)
|
||||
{
|
||||
int ok, result = 0;
|
||||
char *lowervalue;
|
||||
|
||||
lowervalue = (value) ? ssh_lowercase(value) : NULL;
|
||||
ok = match_pattern_list(lowervalue, pattern, strlen(pattern), 0);
|
||||
if (ok <= 0 && negate == true) {
|
||||
result = 1;
|
||||
} else if (ok > 0 && negate == false) {
|
||||
result = 1;
|
||||
}
|
||||
SSH_LOG(SSH_LOG_TRACE, "%s '%s' against pattern '%s'%s (ok=%d)",
|
||||
result == 1 ? "Matched" : "Not matched", value, pattern,
|
||||
negate == true ? " (negated)" : "", ok);
|
||||
SAFE_FREE(lowervalue);
|
||||
return result;
|
||||
}
|
||||
|
||||
static int ssh_config_parse_line(ssh_session session, const char *line,
|
||||
unsigned int count, int *parsing, int seen[]) {
|
||||
@@ -383,7 +445,11 @@ static int ssh_config_parse_line(ssh_session session, const char *line,
|
||||
}
|
||||
|
||||
opcode = ssh_config_get_opcode(keyword);
|
||||
if (*parsing == 1 && opcode != SOC_HOST && opcode != SOC_UNSUPPORTED && opcode != SOC_INCLUDE) {
|
||||
if (*parsing == 1 &&
|
||||
opcode != SOC_HOST &&
|
||||
opcode != SOC_MATCH &&
|
||||
opcode != SOC_INCLUDE &&
|
||||
opcode > SOC_UNSUPPORTED) { /* Ignore all unknown types here */
|
||||
if (seen[opcode] != 0) {
|
||||
SAFE_FREE(x);
|
||||
return 0;
|
||||
@@ -396,15 +462,115 @@ static int ssh_config_parse_line(ssh_session session, const char *line,
|
||||
|
||||
p = ssh_config_get_str_tok(&s, NULL);
|
||||
if (p && *parsing) {
|
||||
#ifdef HAVE_GLOB
|
||||
#if defined(HAVE_GLOB) && defined(HAVE_GLOB_GL_FLAGS_MEMBER)
|
||||
local_parse_glob(session, p, parsing, seen);
|
||||
#else
|
||||
local_parse_file(session, p, parsing, seen);
|
||||
#endif /* HAVE_GLOB */
|
||||
}
|
||||
break;
|
||||
|
||||
case SOC_MATCH: {
|
||||
bool negate;
|
||||
int result = 1;
|
||||
size_t args = 0;
|
||||
enum ssh_config_match_e opt;
|
||||
|
||||
*parsing = 0;
|
||||
do {
|
||||
p = ssh_config_get_str_tok(&s, NULL);
|
||||
if (p == NULL || p[0] == '\0') {
|
||||
break;
|
||||
}
|
||||
args++;
|
||||
SSH_LOG(SSH_LOG_TRACE, "line %d: Processing Match keyword '%s'",
|
||||
count, p);
|
||||
|
||||
/* If the option is prefixed with ! the result should be negated */
|
||||
negate = false;
|
||||
if (p[0] == '!') {
|
||||
negate = true;
|
||||
p++;
|
||||
}
|
||||
|
||||
opt = ssh_config_get_match_opcode(p);
|
||||
switch (opt) {
|
||||
case MATCH_ALL:
|
||||
p = ssh_config_get_str_tok(&s, NULL);
|
||||
if (args == 1 && (p == NULL || p[0] == '\0')) {
|
||||
/* The first argument and end of line */
|
||||
if (negate == true) {
|
||||
result = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
"line %d: ERROR - Match all can not be combined with "
|
||||
"other Match attributes", count);
|
||||
SAFE_FREE(x);
|
||||
return -1;
|
||||
|
||||
case MATCH_EXEC:
|
||||
case MATCH_ORIGINALHOST:
|
||||
case MATCH_LOCALUSER:
|
||||
/* Skip one argument */
|
||||
p = ssh_config_get_str_tok(&s, NULL);
|
||||
args++;
|
||||
FALL_THROUGH;
|
||||
case MATCH_CANONICAL:
|
||||
SSH_LOG(SSH_LOG_WARN, "line: %d: Unsupported Match keyword "
|
||||
"'%s', Ignoring\n", count, p);
|
||||
result = 0;
|
||||
break;
|
||||
|
||||
case MATCH_HOST:
|
||||
/* Here we match only one argument */
|
||||
p = ssh_config_get_str_tok(&s, NULL);
|
||||
if (p == NULL || p[0] == '\0') {
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
"line %d: ERROR - Match host keyword "
|
||||
"requires argument", count);
|
||||
SAFE_FREE(x);
|
||||
return -1;
|
||||
}
|
||||
result &= ssh_config_match(session->opts.host, p, negate);
|
||||
args++;
|
||||
break;
|
||||
|
||||
case MATCH_USER:
|
||||
/* Here we match only one argument */
|
||||
p = ssh_config_get_str_tok(&s, NULL);
|
||||
if (p == NULL || p[0] == '\0') {
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
"line %d: ERROR - Match user keyword "
|
||||
"requires argument", count);
|
||||
SAFE_FREE(x);
|
||||
return -1;
|
||||
}
|
||||
result &= ssh_config_match(session->opts.username, p, negate);
|
||||
args++;
|
||||
break;
|
||||
|
||||
case MATCH_UNKNOWN:
|
||||
default:
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
"ERROR - Unknown argument '%s' for Match keyword", p);
|
||||
SAFE_FREE(x);
|
||||
return -1;
|
||||
}
|
||||
} while (p != NULL && p[0] != '\0');
|
||||
if (args == 0) {
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
"ERROR - Match keyword requires an argument");
|
||||
SAFE_FREE(x);
|
||||
return -1;
|
||||
}
|
||||
*parsing = result;
|
||||
break;
|
||||
}
|
||||
case SOC_HOST: {
|
||||
int ok = 0;
|
||||
int ok = 0, result = -1;
|
||||
|
||||
*parsing = 0;
|
||||
lowerhost = (session->opts.host) ? ssh_lowercase(session->opts.host) : NULL;
|
||||
@@ -413,14 +579,17 @@ static int ssh_config_parse_line(ssh_session session, const char *line,
|
||||
p = ssh_config_get_str_tok(&s, NULL)) {
|
||||
if (ok >= 0) {
|
||||
ok = match_hostname(lowerhost, p, strlen(p));
|
||||
if (ok < 0) {
|
||||
*parsing = 0;
|
||||
} else if (ok > 0) {
|
||||
*parsing = 1;
|
||||
if (result == -1 && ok < 0) {
|
||||
result = 0;
|
||||
} else if (result == -1 && ok > 0) {
|
||||
result = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
SAFE_FREE(lowerhost);
|
||||
if (result != -1) {
|
||||
*parsing = result;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SOC_HOSTNAME:
|
||||
@@ -591,6 +760,12 @@ static int ssh_config_parse_line(ssh_session session, const char *line,
|
||||
ssh_options_set(session, SSH_OPTIONS_HOSTKEYS, p);
|
||||
}
|
||||
break;
|
||||
case SOC_PUBKEYACCEPTEDTYPES:
|
||||
p = ssh_config_get_str_tok(&s, NULL);
|
||||
if (p && *parsing) {
|
||||
ssh_options_set(session, SSH_OPTIONS_PUBLICKEY_ACCEPTED_TYPES, p);
|
||||
}
|
||||
break;
|
||||
case SOC_KEXALGORITHMS:
|
||||
p = ssh_config_get_str_tok(&s, NULL);
|
||||
if (p && *parsing) {
|
||||
|
||||
@@ -220,7 +220,12 @@ static int ssh_connect_ai_timeout(ssh_session session, const char *host,
|
||||
static int set_tcp_nodelay(socket_t socket)
|
||||
{
|
||||
int opt = 1;
|
||||
return setsockopt(socket, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt));
|
||||
|
||||
return setsockopt(socket,
|
||||
IPPROTO_TCP,
|
||||
TCP_NODELAY,
|
||||
(void *)&opt,
|
||||
sizeof(opt));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
127
src/connector.c
@@ -26,6 +26,10 @@
|
||||
#include "libssh/callbacks.h"
|
||||
#include "libssh/session.h"
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <stdbool.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#define CHUNKSIZE 4096
|
||||
|
||||
#ifdef _WIN32
|
||||
@@ -40,6 +44,9 @@
|
||||
# undef unlink
|
||||
# define unlink _unlink
|
||||
# endif /* HAVE_IO_H */
|
||||
#else
|
||||
# include <sys/types.h>
|
||||
# include <sys/socket.h>
|
||||
#endif
|
||||
|
||||
struct ssh_connector_struct {
|
||||
@@ -51,6 +58,8 @@ struct ssh_connector_struct {
|
||||
socket_t in_fd;
|
||||
socket_t out_fd;
|
||||
|
||||
bool fd_is_socket;
|
||||
|
||||
ssh_poll_handle in_poll;
|
||||
ssh_poll_handle out_poll;
|
||||
|
||||
@@ -76,6 +85,13 @@ static int ssh_connector_channel_write_wontblock_cb(ssh_session session,
|
||||
ssh_channel channel,
|
||||
size_t bytes,
|
||||
void *userdata);
|
||||
static ssize_t ssh_connector_fd_read(ssh_connector connector,
|
||||
void *buffer,
|
||||
uint32_t len);
|
||||
static ssize_t ssh_connector_fd_write(ssh_connector connector,
|
||||
const void *buffer,
|
||||
uint32_t len);
|
||||
static bool ssh_connector_fd_is_socket(socket_t socket);
|
||||
|
||||
ssh_connector ssh_connector_new(ssh_session session)
|
||||
{
|
||||
@@ -91,6 +107,8 @@ ssh_connector ssh_connector_new(ssh_session session)
|
||||
connector->in_fd = SSH_INVALID_SOCKET;
|
||||
connector->out_fd = SSH_INVALID_SOCKET;
|
||||
|
||||
connector->fd_is_socket = false;
|
||||
|
||||
ssh_callbacks_init(&connector->in_channel_cb);
|
||||
ssh_callbacks_init(&connector->out_channel_cb);
|
||||
|
||||
@@ -167,12 +185,14 @@ int ssh_connector_set_out_channel(ssh_connector connector,
|
||||
void ssh_connector_set_in_fd(ssh_connector connector, socket_t fd)
|
||||
{
|
||||
connector->in_fd = fd;
|
||||
connector->fd_is_socket = ssh_connector_fd_is_socket(fd);
|
||||
connector->in_channel = NULL;
|
||||
}
|
||||
|
||||
void ssh_connector_set_out_fd(ssh_connector connector, socket_t fd)
|
||||
{
|
||||
connector->out_fd = fd;
|
||||
connector->fd_is_socket = ssh_connector_fd_is_socket(fd);
|
||||
connector->out_channel = NULL;
|
||||
}
|
||||
|
||||
@@ -223,9 +243,9 @@ static void ssh_connector_reset_pollevents(ssh_connector connector)
|
||||
static void ssh_connector_fd_in_cb(ssh_connector connector)
|
||||
{
|
||||
unsigned char buffer[CHUNKSIZE];
|
||||
int r;
|
||||
int toread = CHUNKSIZE;
|
||||
int w;
|
||||
uint32_t toread = CHUNKSIZE;
|
||||
ssize_t r;
|
||||
ssize_t w;
|
||||
int total = 0;
|
||||
int rc;
|
||||
|
||||
@@ -239,7 +259,7 @@ static void ssh_connector_fd_in_cb(ssh_connector connector)
|
||||
toread = MIN(size, CHUNKSIZE);
|
||||
}
|
||||
|
||||
r = read(connector->in_fd, buffer, toread);
|
||||
r = ssh_connector_fd_read(connector, buffer, toread);
|
||||
if (r < 0) {
|
||||
ssh_connector_except(connector, connector->in_fd);
|
||||
return;
|
||||
@@ -277,7 +297,7 @@ static void ssh_connector_fd_in_cb(ssh_connector connector)
|
||||
* bytes
|
||||
*/
|
||||
while (total != r) {
|
||||
w = write(connector->out_fd, buffer + total, r - total);
|
||||
w = ssh_connector_fd_write(connector, buffer + total, r - total);
|
||||
if (w < 0){
|
||||
ssh_connector_except(connector, connector->out_fd);
|
||||
return;
|
||||
@@ -319,7 +339,7 @@ static void ssh_connector_fd_out_cb(ssh_connector connector){
|
||||
} else if(r>0) {
|
||||
/* loop around write in case the write blocks even for CHUNKSIZE bytes */
|
||||
while (total != r){
|
||||
w = write(connector->out_fd, buffer + total, r - total);
|
||||
w = ssh_connector_fd_write(connector, buffer + total, r - total);
|
||||
if (w < 0){
|
||||
ssh_connector_except(connector, connector->out_fd);
|
||||
return;
|
||||
@@ -451,7 +471,7 @@ static int ssh_connector_channel_data_cb(ssh_session session,
|
||||
ssh_connector_except_channel(connector, connector->out_channel);
|
||||
}
|
||||
} else if (connector->out_fd != SSH_INVALID_SOCKET) {
|
||||
w = write(connector->out_fd, data, len);
|
||||
w = ssh_connector_fd_write(connector, data, len);
|
||||
if (w < 0)
|
||||
ssh_connector_except(connector, connector->out_fd);
|
||||
} else {
|
||||
@@ -634,3 +654,96 @@ int ssh_connector_remove_event(ssh_connector connector) {
|
||||
|
||||
return SSH_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
* @brief Check the file descriptor to check if it is a Windows socket handle.
|
||||
*
|
||||
*/
|
||||
static bool ssh_connector_fd_is_socket(socket_t s)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
struct sockaddr_storage ss;
|
||||
int len = sizeof(struct sockaddr_storage);
|
||||
int rc;
|
||||
|
||||
rc = getsockname(s, (struct sockaddr *)&ss, &len);
|
||||
if (rc == 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"Error %i in getsockname() for fd %d",
|
||||
WSAGetLastError(),
|
||||
s);
|
||||
|
||||
return false;
|
||||
#else
|
||||
struct stat sb;
|
||||
int rc;
|
||||
|
||||
rc = fstat(s, &sb);
|
||||
if (rc != 0) {
|
||||
SSH_LOG(SSH_LOG_TRACE,
|
||||
"error %i in fstat() for fd %d",
|
||||
errno,
|
||||
s);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* The descriptor is a socket */
|
||||
if (S_ISSOCK(sb.st_mode)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
#endif /* _WIN32 */
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
* @brief read len bytes from socket into buffer
|
||||
*
|
||||
*/
|
||||
static ssize_t ssh_connector_fd_read(ssh_connector connector,
|
||||
void *buffer,
|
||||
uint32_t len)
|
||||
{
|
||||
ssize_t nread = -1;
|
||||
|
||||
if (connector->fd_is_socket) {
|
||||
nread = recv(connector->in_fd,buffer, len, 0);
|
||||
} else {
|
||||
nread = read(connector->in_fd,buffer, len);
|
||||
}
|
||||
|
||||
return nread;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
* @brief brief writes len bytes from buffer to socket
|
||||
*
|
||||
*/
|
||||
static ssize_t ssh_connector_fd_write(ssh_connector connector,
|
||||
const void *buffer,
|
||||
uint32_t len)
|
||||
{
|
||||
ssize_t bwritten = -1;
|
||||
int flags = 0;
|
||||
|
||||
#ifdef MSG_NOSIGNAL
|
||||
flags |= MSG_NOSIGNAL;
|
||||
#endif
|
||||
|
||||
if (connector->fd_is_socket) {
|
||||
bwritten = send(connector->out_fd,buffer, len, flags);
|
||||
} else {
|
||||
bwritten = write(connector->out_fd, buffer, len);
|
||||
}
|
||||
|
||||
return bwritten;
|
||||
}
|
||||
|
||||
473
src/dh.c
@@ -112,14 +112,164 @@ static unsigned char p_group14_value[] = {
|
||||
|
||||
#define P_GROUP14_LEN 256 /* Size in bytes of the p number for group 14 */
|
||||
|
||||
static unsigned char p_group16_value[] = {
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2,
|
||||
0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
|
||||
0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6,
|
||||
0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
|
||||
0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D,
|
||||
0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
|
||||
0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9,
|
||||
0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
|
||||
0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11,
|
||||
0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
|
||||
0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36,
|
||||
0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
|
||||
0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56,
|
||||
0x20, 0x85, 0x52, 0xBB, 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
|
||||
0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, 0xF1, 0x74, 0x6C, 0x08,
|
||||
0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
|
||||
0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2,
|
||||
0xEC, 0x07, 0xA2, 0x8F, 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9,
|
||||
0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, 0x39, 0x95, 0x49, 0x7C,
|
||||
0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
|
||||
0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, 0xAD, 0x33, 0x17, 0x0D,
|
||||
0x04, 0x50, 0x7A, 0x33, 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64,
|
||||
0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, 0x8A, 0xEA, 0x71, 0x57,
|
||||
0x5D, 0x06, 0x0C, 0x7D, 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7,
|
||||
0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, 0x1E, 0x8C, 0x94, 0xE0,
|
||||
0x4A, 0x25, 0x61, 0x9D, 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B,
|
||||
0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, 0xD8, 0x76, 0x02, 0x73,
|
||||
0x3E, 0xC8, 0x6A, 0x64, 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C,
|
||||
0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, 0x77, 0x09, 0x88, 0xC0,
|
||||
0xBA, 0xD9, 0x46, 0xE2, 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31,
|
||||
0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, 0x4B, 0x82, 0xD1, 0x20,
|
||||
0xA9, 0x21, 0x08, 0x01, 0x1A, 0x72, 0x3C, 0x12, 0xA7, 0x87, 0xE6, 0xD7,
|
||||
0x88, 0x71, 0x9A, 0x10, 0xBD, 0xBA, 0x5B, 0x26, 0x99, 0xC3, 0x27, 0x18,
|
||||
0x6A, 0xF4, 0xE2, 0x3C, 0x1A, 0x94, 0x68, 0x34, 0xB6, 0x15, 0x0B, 0xDA,
|
||||
0x25, 0x83, 0xE9, 0xCA, 0x2A, 0xD4, 0x4C, 0xE8, 0xDB, 0xBB, 0xC2, 0xDB,
|
||||
0x04, 0xDE, 0x8E, 0xF9, 0x2E, 0x8E, 0xFC, 0x14, 0x1F, 0xBE, 0xCA, 0xA6,
|
||||
0x28, 0x7C, 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D, 0x99, 0xB2, 0x96, 0x4F,
|
||||
0xA0, 0x90, 0xC3, 0xA2, 0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7, 0xED,
|
||||
0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, 0xD7, 0xAF, 0xB8, 0x1B, 0xDD, 0x76,
|
||||
0x21, 0x70, 0x48, 0x1C, 0xD0, 0x06, 0x91, 0x27, 0xD5, 0xB0, 0x5A, 0xA9,
|
||||
0x93, 0xB4, 0xEA, 0x98, 0x8D, 0x8F, 0xDD, 0xC1, 0x86, 0xFF, 0xB7, 0xDC,
|
||||
0x90, 0xA6, 0xC0, 0x8F, 0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x06, 0x31, 0x99,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
|
||||
|
||||
#define P_GROUP16_LEN 512 /* Size in bytes of the p number for group 16 */
|
||||
|
||||
static unsigned char p_group18_value[] = {
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2,
|
||||
0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
|
||||
0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6,
|
||||
0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
|
||||
0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D,
|
||||
0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
|
||||
0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9,
|
||||
0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
|
||||
0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11,
|
||||
0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
|
||||
0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36,
|
||||
0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
|
||||
0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56,
|
||||
0x20, 0x85, 0x52, 0xBB, 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
|
||||
0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, 0xF1, 0x74, 0x6C, 0x08,
|
||||
0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
|
||||
0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2,
|
||||
0xEC, 0x07, 0xA2, 0x8F, 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9,
|
||||
0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, 0x39, 0x95, 0x49, 0x7C,
|
||||
0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
|
||||
0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D, 0xAD, 0x33, 0x17, 0x0D,
|
||||
0x04, 0x50, 0x7A, 0x33, 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64,
|
||||
0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A, 0x8A, 0xEA, 0x71, 0x57,
|
||||
0x5D, 0x06, 0x0C, 0x7D, 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7,
|
||||
0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7, 0x1E, 0x8C, 0x94, 0xE0,
|
||||
0x4A, 0x25, 0x61, 0x9D, 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B,
|
||||
0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64, 0xD8, 0x76, 0x02, 0x73,
|
||||
0x3E, 0xC8, 0x6A, 0x64, 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C,
|
||||
0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C, 0x77, 0x09, 0x88, 0xC0,
|
||||
0xBA, 0xD9, 0x46, 0xE2, 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31,
|
||||
0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E, 0x4B, 0x82, 0xD1, 0x20,
|
||||
0xA9, 0x21, 0x08, 0x01, 0x1A, 0x72, 0x3C, 0x12, 0xA7, 0x87, 0xE6, 0xD7,
|
||||
0x88, 0x71, 0x9A, 0x10, 0xBD, 0xBA, 0x5B, 0x26, 0x99, 0xC3, 0x27, 0x18,
|
||||
0x6A, 0xF4, 0xE2, 0x3C, 0x1A, 0x94, 0x68, 0x34, 0xB6, 0x15, 0x0B, 0xDA,
|
||||
0x25, 0x83, 0xE9, 0xCA, 0x2A, 0xD4, 0x4C, 0xE8, 0xDB, 0xBB, 0xC2, 0xDB,
|
||||
0x04, 0xDE, 0x8E, 0xF9, 0x2E, 0x8E, 0xFC, 0x14, 0x1F, 0xBE, 0xCA, 0xA6,
|
||||
0x28, 0x7C, 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D, 0x99, 0xB2, 0x96, 0x4F,
|
||||
0xA0, 0x90, 0xC3, 0xA2, 0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7, 0xED,
|
||||
0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, 0xD7, 0xAF, 0xB8, 0x1B, 0xDD, 0x76,
|
||||
0x21, 0x70, 0x48, 0x1C, 0xD0, 0x06, 0x91, 0x27, 0xD5, 0xB0, 0x5A, 0xA9,
|
||||
0x93, 0xB4, 0xEA, 0x98, 0x8D, 0x8F, 0xDD, 0xC1, 0x86, 0xFF, 0xB7, 0xDC,
|
||||
0x90, 0xA6, 0xC0, 0x8F, 0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x02, 0x84, 0x92,
|
||||
0x36, 0xC3, 0xFA, 0xB4, 0xD2, 0x7C, 0x70, 0x26, 0xC1, 0xD4, 0xDC, 0xB2,
|
||||
0x60, 0x26, 0x46, 0xDE, 0xC9, 0x75, 0x1E, 0x76, 0x3D, 0xBA, 0x37, 0xBD,
|
||||
0xF8, 0xFF, 0x94, 0x06, 0xAD, 0x9E, 0x53, 0x0E, 0xE5, 0xDB, 0x38, 0x2F,
|
||||
0x41, 0x30, 0x01, 0xAE, 0xB0, 0x6A, 0x53, 0xED, 0x90, 0x27, 0xD8, 0x31,
|
||||
0x17, 0x97, 0x27, 0xB0, 0x86, 0x5A, 0x89, 0x18, 0xDA, 0x3E, 0xDB, 0xEB,
|
||||
0xCF, 0x9B, 0x14, 0xED, 0x44, 0xCE, 0x6C, 0xBA, 0xCE, 0xD4, 0xBB, 0x1B,
|
||||
0xDB, 0x7F, 0x14, 0x47, 0xE6, 0xCC, 0x25, 0x4B, 0x33, 0x20, 0x51, 0x51,
|
||||
0x2B, 0xD7, 0xAF, 0x42, 0x6F, 0xB8, 0xF4, 0x01, 0x37, 0x8C, 0xD2, 0xBF,
|
||||
0x59, 0x83, 0xCA, 0x01, 0xC6, 0x4B, 0x92, 0xEC, 0xF0, 0x32, 0xEA, 0x15,
|
||||
0xD1, 0x72, 0x1D, 0x03, 0xF4, 0x82, 0xD7, 0xCE, 0x6E, 0x74, 0xFE, 0xF6,
|
||||
0xD5, 0x5E, 0x70, 0x2F, 0x46, 0x98, 0x0C, 0x82, 0xB5, 0xA8, 0x40, 0x31,
|
||||
0x90, 0x0B, 0x1C, 0x9E, 0x59, 0xE7, 0xC9, 0x7F, 0xBE, 0xC7, 0xE8, 0xF3,
|
||||
0x23, 0xA9, 0x7A, 0x7E, 0x36, 0xCC, 0x88, 0xBE, 0x0F, 0x1D, 0x45, 0xB7,
|
||||
0xFF, 0x58, 0x5A, 0xC5, 0x4B, 0xD4, 0x07, 0xB2, 0x2B, 0x41, 0x54, 0xAA,
|
||||
0xCC, 0x8F, 0x6D, 0x7E, 0xBF, 0x48, 0xE1, 0xD8, 0x14, 0xCC, 0x5E, 0xD2,
|
||||
0x0F, 0x80, 0x37, 0xE0, 0xA7, 0x97, 0x15, 0xEE, 0xF2, 0x9B, 0xE3, 0x28,
|
||||
0x06, 0xA1, 0xD5, 0x8B, 0xB7, 0xC5, 0xDA, 0x76, 0xF5, 0x50, 0xAA, 0x3D,
|
||||
0x8A, 0x1F, 0xBF, 0xF0, 0xEB, 0x19, 0xCC, 0xB1, 0xA3, 0x13, 0xD5, 0x5C,
|
||||
0xDA, 0x56, 0xC9, 0xEC, 0x2E, 0xF2, 0x96, 0x32, 0x38, 0x7F, 0xE8, 0xD7,
|
||||
0x6E, 0x3C, 0x04, 0x68, 0x04, 0x3E, 0x8F, 0x66, 0x3F, 0x48, 0x60, 0xEE,
|
||||
0x12, 0xBF, 0x2D, 0x5B, 0x0B, 0x74, 0x74, 0xD6, 0xE6, 0x94, 0xF9, 0x1E,
|
||||
0x6D, 0xBE, 0x11, 0x59, 0x74, 0xA3, 0x92, 0x6F, 0x12, 0xFE, 0xE5, 0xE4,
|
||||
0x38, 0x77, 0x7C, 0xB6, 0xA9, 0x32, 0xDF, 0x8C, 0xD8, 0xBE, 0xC4, 0xD0,
|
||||
0x73, 0xB9, 0x31, 0xBA, 0x3B, 0xC8, 0x32, 0xB6, 0x8D, 0x9D, 0xD3, 0x00,
|
||||
0x74, 0x1F, 0xA7, 0xBF, 0x8A, 0xFC, 0x47, 0xED, 0x25, 0x76, 0xF6, 0x93,
|
||||
0x6B, 0xA4, 0x24, 0x66, 0x3A, 0xAB, 0x63, 0x9C, 0x5A, 0xE4, 0xF5, 0x68,
|
||||
0x34, 0x23, 0xB4, 0x74, 0x2B, 0xF1, 0xC9, 0x78, 0x23, 0x8F, 0x16, 0xCB,
|
||||
0xE3, 0x9D, 0x65, 0x2D, 0xE3, 0xFD, 0xB8, 0xBE, 0xFC, 0x84, 0x8A, 0xD9,
|
||||
0x22, 0x22, 0x2E, 0x04, 0xA4, 0x03, 0x7C, 0x07, 0x13, 0xEB, 0x57, 0xA8,
|
||||
0x1A, 0x23, 0xF0, 0xC7, 0x34, 0x73, 0xFC, 0x64, 0x6C, 0xEA, 0x30, 0x6B,
|
||||
0x4B, 0xCB, 0xC8, 0x86, 0x2F, 0x83, 0x85, 0xDD, 0xFA, 0x9D, 0x4B, 0x7F,
|
||||
0xA2, 0xC0, 0x87, 0xE8, 0x79, 0x68, 0x33, 0x03, 0xED, 0x5B, 0xDD, 0x3A,
|
||||
0x06, 0x2B, 0x3C, 0xF5, 0xB3, 0xA2, 0x78, 0xA6, 0x6D, 0x2A, 0x13, 0xF8,
|
||||
0x3F, 0x44, 0xF8, 0x2D, 0xDF, 0x31, 0x0E, 0xE0, 0x74, 0xAB, 0x6A, 0x36,
|
||||
0x45, 0x97, 0xE8, 0x99, 0xA0, 0x25, 0x5D, 0xC1, 0x64, 0xF3, 0x1C, 0xC5,
|
||||
0x08, 0x46, 0x85, 0x1D, 0xF9, 0xAB, 0x48, 0x19, 0x5D, 0xED, 0x7E, 0xA1,
|
||||
0xB1, 0xD5, 0x10, 0xBD, 0x7E, 0xE7, 0x4D, 0x73, 0xFA, 0xF3, 0x6B, 0xC3,
|
||||
0x1E, 0xCF, 0xA2, 0x68, 0x35, 0x90, 0x46, 0xF4, 0xEB, 0x87, 0x9F, 0x92,
|
||||
0x40, 0x09, 0x43, 0x8B, 0x48, 0x1C, 0x6C, 0xD7, 0x88, 0x9A, 0x00, 0x2E,
|
||||
0xD5, 0xEE, 0x38, 0x2B, 0xC9, 0x19, 0x0D, 0xA6, 0xFC, 0x02, 0x6E, 0x47,
|
||||
0x95, 0x58, 0xE4, 0x47, 0x56, 0x77, 0xE9, 0xAA, 0x9E, 0x30, 0x50, 0xE2,
|
||||
0x76, 0x56, 0x94, 0xDF, 0xC8, 0x1F, 0x56, 0xE8, 0x80, 0xB9, 0x6E, 0x71,
|
||||
0x60, 0xC9, 0x80, 0xDD, 0x98, 0xED, 0xD3, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF};
|
||||
|
||||
#define P_GROUP18_LEN 1024 /* Size in bytes of the p number for group 18 */
|
||||
|
||||
static unsigned long g_int = 2 ; /* G is defined as 2 by the ssh2 standards */
|
||||
static bignum g;
|
||||
static bignum p_group1;
|
||||
static bignum p_group14;
|
||||
static bignum p_group16;
|
||||
static bignum p_group18;
|
||||
static int dh_crypto_initialized;
|
||||
|
||||
static bignum select_p(enum ssh_key_exchange_e type) {
|
||||
return type == SSH_KEX_DH_GROUP14_SHA1 ? p_group14 : p_group1;
|
||||
switch(type) {
|
||||
case SSH_KEX_DH_GROUP1_SHA1:
|
||||
return p_group1;
|
||||
case SSH_KEX_DH_GROUP14_SHA1:
|
||||
return p_group14;
|
||||
case SSH_KEX_DH_GROUP16_SHA512:
|
||||
return p_group16;
|
||||
case SSH_KEX_DH_GROUP18_SHA512:
|
||||
return p_group18;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -151,6 +301,23 @@ int ssh_dh_init(void)
|
||||
bignum_safe_free(g);
|
||||
bignum_safe_free(p_group1);
|
||||
|
||||
return SSH_ERROR;
|
||||
}
|
||||
bignum_bin2bn(p_group16_value, P_GROUP16_LEN, &p_group16);
|
||||
if (p_group16 == NULL) {
|
||||
bignum_safe_free(g);
|
||||
bignum_safe_free(p_group1);
|
||||
bignum_safe_free(p_group14);
|
||||
|
||||
return SSH_ERROR;
|
||||
}
|
||||
bignum_bin2bn(p_group18_value, P_GROUP18_LEN, &p_group18);
|
||||
if (p_group18 == NULL) {
|
||||
bignum_safe_free(g);
|
||||
bignum_safe_free(p_group1);
|
||||
bignum_safe_free(p_group14);
|
||||
bignum_safe_free(p_group16);
|
||||
|
||||
return SSH_ERROR;
|
||||
}
|
||||
#elif defined(HAVE_LIBCRYPTO)
|
||||
@@ -170,12 +337,39 @@ int ssh_dh_init(void)
|
||||
return SSH_ERROR;
|
||||
}
|
||||
bignum_bin2bn(p_group14_value, P_GROUP14_LEN, p_group14);
|
||||
|
||||
p_group16 = bignum_new();
|
||||
if (p_group16 == NULL) {
|
||||
bignum_safe_free(g);
|
||||
bignum_safe_free(p_group1);
|
||||
bignum_safe_free(p_group14);
|
||||
|
||||
return SSH_ERROR;
|
||||
}
|
||||
bignum_bin2bn(p_group16_value, P_GROUP16_LEN, p_group16);
|
||||
|
||||
p_group18 = bignum_new();
|
||||
if (p_group18 == NULL) {
|
||||
bignum_safe_free(g);
|
||||
bignum_safe_free(p_group1);
|
||||
bignum_safe_free(p_group14);
|
||||
bignum_safe_free(p_group16);
|
||||
|
||||
return SSH_ERROR;
|
||||
}
|
||||
bignum_bin2bn(p_group18_value, P_GROUP18_LEN, p_group18);
|
||||
#elif defined(HAVE_LIBMBEDCRYPTO)
|
||||
p_group1 = bignum_new();
|
||||
bignum_bin2bn(p_group1_value, P_GROUP1_LEN, p_group1);
|
||||
|
||||
p_group14 = bignum_new();
|
||||
bignum_bin2bn(p_group14_value, P_GROUP14_LEN, p_group14);
|
||||
|
||||
p_group16 = bignum_new();
|
||||
bignum_bin2bn(p_group16_value, P_GROUP16_LEN, p_group16);
|
||||
|
||||
p_group18 = bignum_new();
|
||||
bignum_bin2bn(p_group18_value, P_GROUP18_LEN, p_group18);
|
||||
#endif
|
||||
dh_crypto_initialized = 1;
|
||||
|
||||
@@ -195,53 +389,83 @@ void ssh_dh_finalize(void)
|
||||
bignum_safe_free(g);
|
||||
bignum_safe_free(p_group1);
|
||||
bignum_safe_free(p_group14);
|
||||
bignum_safe_free(p_group16);
|
||||
bignum_safe_free(p_group18);
|
||||
|
||||
dh_crypto_initialized = 0;
|
||||
}
|
||||
|
||||
int ssh_dh_generate_x(ssh_session session) {
|
||||
int keysize;
|
||||
if (session->next_crypto->kex_type == SSH_KEX_DH_GROUP1_SHA1) {
|
||||
keysize = 1023;
|
||||
} else {
|
||||
keysize = 2047;
|
||||
}
|
||||
session->next_crypto->x = bignum_new();
|
||||
if (session->next_crypto->x == NULL) {
|
||||
return -1;
|
||||
}
|
||||
int ssh_dh_generate_x(ssh_session session)
|
||||
{
|
||||
size_t keysize;
|
||||
|
||||
bignum_rand(session->next_crypto->x, keysize);
|
||||
switch(session->next_crypto->kex_type) {
|
||||
case SSH_KEX_DH_GROUP1_SHA1:
|
||||
keysize = 1023;
|
||||
break;
|
||||
case SSH_KEX_DH_GROUP14_SHA1:
|
||||
keysize = 2047;
|
||||
break;
|
||||
case SSH_KEX_DH_GROUP16_SHA512:
|
||||
keysize = 4095;
|
||||
break;
|
||||
case SSH_KEX_DH_GROUP18_SHA512:
|
||||
keysize = 8191;
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* not harder than this */
|
||||
session->next_crypto->x = bignum_new();
|
||||
if (session->next_crypto->x == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
bignum_rand(session->next_crypto->x, keysize);
|
||||
|
||||
/* not harder than this */
|
||||
#ifdef DEBUG_CRYPTO
|
||||
ssh_print_bignum("x", session->next_crypto->x);
|
||||
ssh_print_bignum("x", session->next_crypto->x);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* used by server */
|
||||
int ssh_dh_generate_y(ssh_session session) {
|
||||
int keysize;
|
||||
if (session->next_crypto->kex_type == SSH_KEX_DH_GROUP1_SHA1) {
|
||||
keysize = 1023;
|
||||
} else {
|
||||
keysize = 2047;
|
||||
}
|
||||
session->next_crypto->y = bignum_new();
|
||||
if (session->next_crypto->y == NULL) {
|
||||
return -1;
|
||||
}
|
||||
int ssh_dh_generate_y(ssh_session session)
|
||||
{
|
||||
size_t keysize;
|
||||
|
||||
bignum_rand(session->next_crypto->y, keysize);
|
||||
switch(session->next_crypto->kex_type) {
|
||||
case SSH_KEX_DH_GROUP1_SHA1:
|
||||
keysize = 1023;
|
||||
break;
|
||||
case SSH_KEX_DH_GROUP14_SHA1:
|
||||
keysize = 2047;
|
||||
break;
|
||||
case SSH_KEX_DH_GROUP16_SHA512:
|
||||
keysize = 4095;
|
||||
break;
|
||||
case SSH_KEX_DH_GROUP18_SHA512:
|
||||
keysize = 8191;
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* not harder than this */
|
||||
session->next_crypto->y = bignum_new();
|
||||
if (session->next_crypto->y == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
bignum_rand(session->next_crypto->y, keysize);
|
||||
|
||||
/* not harder than this */
|
||||
#ifdef DEBUG_CRYPTO
|
||||
ssh_print_bignum("y", session->next_crypto->y);
|
||||
ssh_print_bignum("y", session->next_crypto->y);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* used by server */
|
||||
@@ -597,8 +821,11 @@ int ssh_make_sessionid(ssh_session session) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (session->next_crypto->kex_type == SSH_KEX_DH_GROUP1_SHA1 ||
|
||||
session->next_crypto->kex_type == SSH_KEX_DH_GROUP14_SHA1) {
|
||||
switch(session->next_crypto->kex_type) {
|
||||
case SSH_KEX_DH_GROUP1_SHA1:
|
||||
case SSH_KEX_DH_GROUP14_SHA1:
|
||||
case SSH_KEX_DH_GROUP16_SHA512:
|
||||
case SSH_KEX_DH_GROUP18_SHA512:
|
||||
rc = ssh_buffer_pack(buf,
|
||||
"BB",
|
||||
session->next_crypto->e,
|
||||
@@ -606,11 +833,11 @@ int ssh_make_sessionid(ssh_session session) {
|
||||
if (rc != SSH_OK) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
break;
|
||||
#ifdef HAVE_ECDH
|
||||
} else if ((session->next_crypto->kex_type == SSH_KEX_ECDH_SHA2_NISTP256) ||
|
||||
(session->next_crypto->kex_type == SSH_KEX_ECDH_SHA2_NISTP384) ||
|
||||
(session->next_crypto->kex_type == SSH_KEX_ECDH_SHA2_NISTP521)) {
|
||||
case SSH_KEX_ECDH_SHA2_NISTP256:
|
||||
case SSH_KEX_ECDH_SHA2_NISTP384:
|
||||
case SSH_KEX_ECDH_SHA2_NISTP521:
|
||||
if (session->next_crypto->ecdh_client_pubkey == NULL ||
|
||||
session->next_crypto->ecdh_server_pubkey == NULL) {
|
||||
SSH_LOG(SSH_LOG_WARNING, "ECDH parameted missing");
|
||||
@@ -623,10 +850,11 @@ int ssh_make_sessionid(ssh_session session) {
|
||||
if (rc != SSH_OK) {
|
||||
goto error;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
#ifdef HAVE_CURVE25519
|
||||
} else if ((session->next_crypto->kex_type == SSH_KEX_CURVE25519_SHA256) ||
|
||||
(session->next_crypto->kex_type == SSH_KEX_CURVE25519_SHA256_LIBSSH_ORG)) {
|
||||
case SSH_KEX_CURVE25519_SHA256:
|
||||
case SSH_KEX_CURVE25519_SHA256_LIBSSH_ORG:
|
||||
rc = ssh_buffer_pack(buf,
|
||||
"dPdP",
|
||||
CURVE25519_PUBKEY_SIZE,
|
||||
@@ -637,6 +865,7 @@ int ssh_make_sessionid(ssh_session session) {
|
||||
if (rc != SSH_OK) {
|
||||
goto error;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
rc = ssh_buffer_pack(buf, "B", session->next_crypto->k);
|
||||
@@ -685,6 +914,8 @@ int ssh_make_sessionid(ssh_session session) {
|
||||
sha384(ssh_buffer_get(buf), ssh_buffer_get_len(buf),
|
||||
session->next_crypto->secret_hash);
|
||||
break;
|
||||
case SSH_KEX_DH_GROUP16_SHA512:
|
||||
case SSH_KEX_DH_GROUP18_SHA512:
|
||||
case SSH_KEX_ECDH_SHA2_NISTP521:
|
||||
session->next_crypto->digest_len = SHA512_DIGEST_LENGTH;
|
||||
session->next_crypto->mac_type = SSH_MAC_SHA512;
|
||||
@@ -693,8 +924,9 @@ int ssh_make_sessionid(ssh_session session) {
|
||||
ssh_set_error_oom(session);
|
||||
goto error;
|
||||
}
|
||||
sha512(ssh_buffer_get(buf), ssh_buffer_get_len(buf),
|
||||
session->next_crypto->secret_hash);
|
||||
sha512(ssh_buffer_get(buf),
|
||||
ssh_buffer_get_len(buf),
|
||||
session->next_crypto->secret_hash);
|
||||
break;
|
||||
}
|
||||
/* During the first kex, secret hash and session ID are equal. However, after
|
||||
@@ -1142,6 +1374,29 @@ int ssh_get_publickey_hash(const ssh_key key,
|
||||
*hlen = SHA_DIGEST_LEN;
|
||||
}
|
||||
break;
|
||||
case SSH_PUBLICKEY_HASH_SHA256:
|
||||
{
|
||||
SHA256CTX ctx;
|
||||
|
||||
h = malloc(SHA256_DIGEST_LEN);
|
||||
if (h == NULL) {
|
||||
rc = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ctx = sha256_init();
|
||||
if (ctx == NULL) {
|
||||
free(h);
|
||||
rc = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
sha256_update(ctx, ssh_string_data(blob), ssh_string_len(blob));
|
||||
sha256_final(h, ctx);
|
||||
|
||||
*hlen = SHA256_DIGEST_LEN;
|
||||
}
|
||||
break;
|
||||
case SSH_PUBLICKEY_HASH_MD5:
|
||||
{
|
||||
MD5CTX ctx;
|
||||
@@ -1177,6 +1432,38 @@ out:
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
* @brief Convert a buffer into an unpadded base64 string.
|
||||
* The caller has to free the memory.
|
||||
*
|
||||
* @param hash What should be converted to a base64 string.
|
||||
*
|
||||
* @param len Length of the buffer to convert.
|
||||
*
|
||||
* @return The base64 string or NULL on error.
|
||||
*
|
||||
* @see ssh_string_free_char()
|
||||
*/
|
||||
static char *ssh_get_b64_unpadded(const unsigned char *hash, size_t len)
|
||||
{
|
||||
char *b64_padded = NULL;
|
||||
char *b64_unpadded = NULL;
|
||||
size_t k;
|
||||
|
||||
b64_padded = (char *)bin_to_base64(hash, (int)len);
|
||||
if (b64_padded == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
for (k = strlen(b64_padded); k != 0 && b64_padded[k-1] == '='; k--);
|
||||
|
||||
b64_unpadded = strndup(b64_padded, k);
|
||||
SAFE_FREE(b64_padded);
|
||||
|
||||
return b64_unpadded;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Convert a buffer into a colon separated hex string.
|
||||
* The caller has to free the memory.
|
||||
@@ -1214,6 +1501,110 @@ char *ssh_get_hexa(const unsigned char *what, size_t len) {
|
||||
return hexa;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get a hash as a human-readable hex- or base64-string.
|
||||
*
|
||||
* This gets an allocated fingerprint hash. It is a hex strings if the given
|
||||
* hash is a md5 sum. If it is a SHA sum, it will return an unpadded base64
|
||||
* strings. Either way, the output is prepended by the hash-type.
|
||||
*
|
||||
* @param type Which sort of hash is given.
|
||||
*
|
||||
* @param hash What should be converted to a base64 string.
|
||||
*
|
||||
* @param len Length of the buffer to convert.
|
||||
*
|
||||
* @return Returns the allocated fingerprint hash or NULL on error.
|
||||
*
|
||||
* @see ssh_string_free_char()
|
||||
*/
|
||||
char *ssh_get_fingerprint_hash(enum ssh_publickey_hash_type type,
|
||||
unsigned char *hash,
|
||||
size_t len)
|
||||
{
|
||||
const char *prefix = "UNKNOWN";
|
||||
char *fingerprint = NULL;
|
||||
char *str = NULL;
|
||||
size_t str_len;
|
||||
int rc;
|
||||
|
||||
switch (type) {
|
||||
case SSH_PUBLICKEY_HASH_SHA1:
|
||||
case SSH_PUBLICKEY_HASH_SHA256:
|
||||
fingerprint = ssh_get_b64_unpadded(hash, len);
|
||||
break;
|
||||
case SSH_PUBLICKEY_HASH_MD5:
|
||||
fingerprint = ssh_get_hexa(hash, len);
|
||||
break;
|
||||
}
|
||||
if (fingerprint == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case SSH_PUBLICKEY_HASH_MD5:
|
||||
prefix = "MD5";
|
||||
break;
|
||||
case SSH_PUBLICKEY_HASH_SHA1:
|
||||
prefix = "SHA1";
|
||||
break;
|
||||
case SSH_PUBLICKEY_HASH_SHA256:
|
||||
prefix = "SHA256";
|
||||
break;
|
||||
}
|
||||
|
||||
str_len = strlen(prefix);
|
||||
if (str_len + 1 + strlen(fingerprint) + 1 < str_len) {
|
||||
SAFE_FREE(fingerprint);
|
||||
return NULL;
|
||||
}
|
||||
str_len += 1 + strlen(fingerprint) + 1;
|
||||
|
||||
str = malloc(str_len);
|
||||
if (str == NULL) {
|
||||
SAFE_FREE(fingerprint);
|
||||
return NULL;
|
||||
}
|
||||
rc = snprintf(str, str_len, "%s:%s", prefix, fingerprint);
|
||||
SAFE_FREE(fingerprint);
|
||||
if (rc < 0 || rc < (int)(str_len - 1)) {
|
||||
SAFE_FREE(str);
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Print a hash as a human-readable hex- or base64-string.
|
||||
*
|
||||
* This function prints hex strings if the given hash is a md5 sum.
|
||||
* But prints unpadded base64 strings for sha sums.
|
||||
* Either way, the output is prepended by the hash-type.
|
||||
*
|
||||
* @param type Which sort of hash is given.
|
||||
*
|
||||
* @param hash What should be converted to a base64 string.
|
||||
*
|
||||
* @param len Length of the buffer to convert.
|
||||
*/
|
||||
void ssh_print_hash(enum ssh_publickey_hash_type type,
|
||||
unsigned char *hash,
|
||||
size_t len)
|
||||
{
|
||||
char *fingerprint = NULL;
|
||||
|
||||
fingerprint = ssh_get_fingerprint_hash(type,
|
||||
hash,
|
||||
len);
|
||||
if (fingerprint == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
fprintf(stderr, "%s\n", fingerprint);
|
||||
|
||||
SAFE_FREE(fingerprint);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Print a buffer as colon separated hex string.
|
||||
*
|
||||
|
||||
@@ -79,9 +79,11 @@ int ssh_client_ecdh_init(ssh_session session)
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = mbedtls_ecp_gen_keypair(&grp, &session->next_crypto->ecdh_privkey->d,
|
||||
&session->next_crypto->ecdh_privkey->Q, mbedtls_ctr_drbg_random,
|
||||
&ssh_mbedtls_ctr_drbg);
|
||||
rc = mbedtls_ecp_gen_keypair(&grp,
|
||||
&session->next_crypto->ecdh_privkey->d,
|
||||
&session->next_crypto->ecdh_privkey->Q,
|
||||
mbedtls_ctr_drbg_random,
|
||||
ssh_get_mbedtls_ctr_drbg_context());
|
||||
|
||||
if (rc != 0) {
|
||||
rc = SSH_ERROR;
|
||||
@@ -157,9 +159,12 @@ int ecdh_build_k(ssh_session session)
|
||||
|
||||
mbedtls_mpi_init(session->next_crypto->k);
|
||||
|
||||
rc = mbedtls_ecdh_compute_shared(&grp, session->next_crypto->k, &pubkey,
|
||||
&session->next_crypto->ecdh_privkey->d, mbedtls_ctr_drbg_random,
|
||||
&ssh_mbedtls_ctr_drbg);
|
||||
rc = mbedtls_ecdh_compute_shared(&grp,
|
||||
session->next_crypto->k,
|
||||
&pubkey,
|
||||
&session->next_crypto->ecdh_privkey->d,
|
||||
mbedtls_ctr_drbg_random,
|
||||
ssh_get_mbedtls_ctr_drbg_context());
|
||||
if (rc != 0) {
|
||||
rc = SSH_ERROR;
|
||||
goto out;
|
||||
@@ -213,9 +218,11 @@ int ssh_server_ecdh_init(ssh_session session, ssh_buffer packet)
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = mbedtls_ecp_gen_keypair(&grp, &session->next_crypto->ecdh_privkey->d,
|
||||
&session->next_crypto->ecdh_privkey->Q, mbedtls_ctr_drbg_random,
|
||||
&ssh_mbedtls_ctr_drbg);
|
||||
rc = mbedtls_ecp_gen_keypair(&grp,
|
||||
&session->next_crypto->ecdh_privkey->d,
|
||||
&session->next_crypto->ecdh_privkey->Q,
|
||||
mbedtls_ctr_drbg_random,
|
||||
ssh_get_mbedtls_ctr_drbg_context());
|
||||
if (rc != 0) {
|
||||
rc = SSH_ERROR;
|
||||
goto out;
|
||||
|
||||
15
src/error.c
@@ -103,6 +103,21 @@ void _ssh_set_error_invalid(void *error, const char *function)
|
||||
"Invalid argument in %s", function);
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
* @brief Reset the error code and message
|
||||
*
|
||||
* @param error The place to reset the error.
|
||||
*/
|
||||
void ssh_reset_error(void *error)
|
||||
{
|
||||
struct ssh_common_struct *err = error;
|
||||
|
||||
ZERO_STRUCT(err->error.error_buffer);
|
||||
err->error.error_code = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Retrieve the error text message from the last error.
|
||||
*
|
||||
|
||||
2
src/external/chacha.c
vendored
@@ -10,8 +10,6 @@ Public domain.
|
||||
|
||||
#include "libssh/chacha.h"
|
||||
|
||||
typedef unsigned int uint32_t;
|
||||
|
||||
typedef struct chacha_ctx chacha_ctx;
|
||||
|
||||
#define U8C(v) (v##U)
|
||||
|
||||
@@ -49,11 +49,10 @@ static int ssh_gets(const char *prompt, char *buf, size_t len, int verify) {
|
||||
char *ptr = NULL;
|
||||
int ok = 0;
|
||||
|
||||
tmp = malloc(len);
|
||||
tmp = calloc(1, len);
|
||||
if (tmp == NULL) {
|
||||
return 0;
|
||||
}
|
||||
memset(tmp,'\0',len);
|
||||
|
||||
/* read the password */
|
||||
while (!ok) {
|
||||
@@ -80,16 +79,15 @@ static int ssh_gets(const char *prompt, char *buf, size_t len, int verify) {
|
||||
if (verify) {
|
||||
char *key_string;
|
||||
|
||||
key_string = malloc(len);
|
||||
key_string = calloc(1, len);
|
||||
if (key_string == NULL) {
|
||||
break;
|
||||
}
|
||||
memset(key_string, '\0', len);
|
||||
|
||||
fprintf(stdout, "\nVerifying, please re-enter. %s", prompt);
|
||||
fflush(stdout);
|
||||
if (! fgets(key_string, len, stdin)) {
|
||||
memset(key_string, '\0', len);
|
||||
explicit_bzero(key_string, len);
|
||||
SAFE_FREE(key_string);
|
||||
clearerr(stdin);
|
||||
continue;
|
||||
@@ -100,17 +98,17 @@ static int ssh_gets(const char *prompt, char *buf, size_t len, int verify) {
|
||||
fprintf(stdout, "\n");
|
||||
if (strcmp(buf, key_string)) {
|
||||
printf("\n\07\07Mismatch - try again\n");
|
||||
memset(key_string, '\0', len);
|
||||
explicit_bzero(key_string, len);
|
||||
SAFE_FREE(key_string);
|
||||
fflush(stdout);
|
||||
continue;
|
||||
}
|
||||
memset(key_string, '\0', len);
|
||||
explicit_bzero(key_string, len);
|
||||
SAFE_FREE(key_string);
|
||||
}
|
||||
ok = 1;
|
||||
}
|
||||
memset(tmp, '\0', len);
|
||||
explicit_bzero(tmp, len);
|
||||
free(tmp);
|
||||
|
||||
return ok;
|
||||
@@ -152,7 +150,7 @@ int ssh_getpass(const char *prompt,
|
||||
SetConsoleMode(h, mode);
|
||||
|
||||
if (!ok) {
|
||||
memset (buf, '\0', len);
|
||||
explicit_bzero(buf, len);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -273,7 +271,7 @@ int ssh_getpass(const char *prompt,
|
||||
}
|
||||
|
||||
if (!ok) {
|
||||
memset (buf, '\0', len);
|
||||
explicit_bzero(buf, len);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
22
src/gssapi.c
@@ -188,13 +188,13 @@ int ssh_gssapi_handle_userauth(ssh_session session, const char *user, uint32_t n
|
||||
gss_buffer_desc name_buf;
|
||||
gss_name_t server_name; /* local server fqdn */
|
||||
OM_uint32 maj_stat, min_stat;
|
||||
unsigned int i;
|
||||
size_t i;
|
||||
char *ptr;
|
||||
gss_OID_set supported; /* oids supported by server */
|
||||
gss_OID_set both_supported; /* oids supported by both client and server */
|
||||
gss_OID_set selected; /* oid selected for authentication */
|
||||
int present=0;
|
||||
int oid_count=0;
|
||||
size_t oid_count=0;
|
||||
struct gss_OID_desc_struct oid;
|
||||
int rc;
|
||||
|
||||
@@ -218,7 +218,7 @@ int ssh_gssapi_handle_userauth(ssh_session session, const char *user, uint32_t n
|
||||
maj_stat = gss_indicate_mechs(&min_stat, &supported);
|
||||
for (i=0; i < supported->count; ++i){
|
||||
ptr = ssh_get_hexa(supported->elements[i].elements, supported->elements[i].length);
|
||||
SSH_LOG(SSH_LOG_DEBUG, "Supported mech %d: %s", i, ptr);
|
||||
SSH_LOG(SSH_LOG_DEBUG, "Supported mech %zu: %s", i, ptr);
|
||||
free(ptr);
|
||||
}
|
||||
|
||||
@@ -291,7 +291,7 @@ int ssh_gssapi_handle_userauth(ssh_session session, const char *user, uint32_t n
|
||||
oid.length = len - 2;
|
||||
gss_test_oid_set_member(&min_stat,&oid,selected,&present);
|
||||
if(present){
|
||||
SSH_LOG(SSH_LOG_PACKET, "Selected oid %d", i);
|
||||
SSH_LOG(SSH_LOG_PACKET, "Selected oid %zu", i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -598,7 +598,7 @@ static int ssh_gssapi_send_auth_mic(ssh_session session, ssh_string *oid_set, in
|
||||
}
|
||||
}
|
||||
|
||||
session->auth_state = SSH_AUTH_STATE_GSSAPI_REQUEST_SENT;
|
||||
session->auth.state = SSH_AUTH_STATE_GSSAPI_REQUEST_SENT;
|
||||
return ssh_packet_send(session);
|
||||
fail:
|
||||
ssh_buffer_reinit(session->out_buffer);
|
||||
@@ -797,7 +797,7 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_gssapi_response){
|
||||
(void)user;
|
||||
|
||||
SSH_LOG(SSH_LOG_PACKET, "Received SSH_USERAUTH_GSSAPI_RESPONSE");
|
||||
if (session->auth_state != SSH_AUTH_STATE_GSSAPI_REQUEST_SENT){
|
||||
if (session->auth.state != SSH_AUTH_STATE_GSSAPI_REQUEST_SENT){
|
||||
ssh_set_error(session, SSH_FATAL, "Invalid state in ssh_packet_userauth_gssapi_response");
|
||||
goto error;
|
||||
}
|
||||
@@ -845,12 +845,12 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_gssapi_response){
|
||||
output_token.length,
|
||||
(size_t)output_token.length, output_token.value);
|
||||
ssh_packet_send(session);
|
||||
session->auth_state = SSH_AUTH_STATE_GSSAPI_TOKEN;
|
||||
session->auth.state = SSH_AUTH_STATE_GSSAPI_TOKEN;
|
||||
}
|
||||
return SSH_PACKET_USED;
|
||||
|
||||
error:
|
||||
session->auth_state = SSH_AUTH_STATE_ERROR;
|
||||
session->auth.state = SSH_AUTH_STATE_ERROR;
|
||||
ssh_gssapi_free(session);
|
||||
session->gssapi = NULL;
|
||||
return SSH_PACKET_USED;
|
||||
@@ -907,7 +907,7 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_gssapi_token_client){
|
||||
(void)type;
|
||||
|
||||
SSH_LOG(SSH_LOG_PACKET,"Received SSH_MSG_USERAUTH_GSSAPI_TOKEN");
|
||||
if (!session->gssapi || session->auth_state != SSH_AUTH_STATE_GSSAPI_TOKEN) {
|
||||
if (!session->gssapi || session->auth.state != SSH_AUTH_STATE_GSSAPI_TOKEN) {
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
"Received SSH_MSG_USERAUTH_GSSAPI_TOKEN in invalid state");
|
||||
goto error;
|
||||
@@ -960,14 +960,14 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_gssapi_token_client){
|
||||
}
|
||||
|
||||
if (maj_stat == GSS_S_COMPLETE) {
|
||||
session->auth_state = SSH_AUTH_STATE_NONE;
|
||||
ssh_gssapi_send_mic(session);
|
||||
session->auth.state = SSH_AUTH_STATE_GSSAPI_MIC_SENT;
|
||||
}
|
||||
|
||||
return SSH_PACKET_USED;
|
||||
|
||||
error:
|
||||
session->auth_state = SSH_AUTH_STATE_ERROR;
|
||||
session->auth.state = SSH_AUTH_STATE_ERROR;
|
||||
ssh_gssapi_free(session);
|
||||
session->gssapi = NULL;
|
||||
return SSH_PACKET_USED;
|
||||
|
||||
@@ -39,11 +39,10 @@ static z_stream *initcompress(ssh_session session, int level) {
|
||||
z_stream *stream = NULL;
|
||||
int status;
|
||||
|
||||
stream = malloc(sizeof(z_stream));
|
||||
stream = calloc(1, sizeof(z_stream));
|
||||
if (stream == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
memset(stream, 0, sizeof(z_stream));
|
||||
|
||||
status = deflateInit(stream, level);
|
||||
if (status != Z_OK) {
|
||||
@@ -128,11 +127,10 @@ static z_stream *initdecompress(ssh_session session) {
|
||||
z_stream *stream = NULL;
|
||||
int status;
|
||||
|
||||
stream = malloc(sizeof(z_stream));
|
||||
stream = calloc(1, sizeof(z_stream));
|
||||
if (stream == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
memset(stream,0,sizeof(z_stream));
|
||||
|
||||
status = inflateInit(stream);
|
||||
if (status != Z_OK) {
|
||||
|
||||
80
src/init.c
@@ -32,8 +32,17 @@
|
||||
#include <winsock2.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_CONSTRUCTOR_ATTRIBUTE
|
||||
#define CONSTRUCTOR_ATTRIBUTE __attribute__((constructor))
|
||||
#else
|
||||
#define CONSTRUCTOR_ATTRIBUTE
|
||||
#endif /* HAVE_CONSTRUCTOR_ATTRIBUTE */
|
||||
|
||||
#ifdef HAVE_DESTRUCTOR_ATTRIBUTE
|
||||
#define DESTRUCTOR_ATTRIBUTE __attribute__((destructor))
|
||||
#else
|
||||
#define DESTRUCTOR_ATTRIBUTE
|
||||
#endif /* HAVE_DESTRUCTOR_ATTRIBUTE */
|
||||
|
||||
/* Declare static mutex */
|
||||
static SSH_MUTEX ssh_init_mutex = SSH_MUTEX_STATIC_INIT;
|
||||
@@ -144,29 +153,29 @@ static int _ssh_finalize(unsigned destructor) {
|
||||
|
||||
if (!destructor) {
|
||||
ssh_mutex_lock(&ssh_init_mutex);
|
||||
}
|
||||
|
||||
if (_ssh_initialized == 1) {
|
||||
_ssh_initialized = 0;
|
||||
|
||||
if (_ssh_init_ret < 0) {
|
||||
if (_ssh_initialized > 1) {
|
||||
_ssh_initialized--;
|
||||
goto _ret;
|
||||
}
|
||||
|
||||
ssh_dh_finalize();
|
||||
ssh_crypto_finalize();
|
||||
ssh_socket_cleanup();
|
||||
/* It is important to finalize threading after CRYPTO because
|
||||
* it still depends on it */
|
||||
ssh_threads_finalize();
|
||||
|
||||
}
|
||||
else {
|
||||
if (_ssh_initialized > 0) {
|
||||
_ssh_initialized--;
|
||||
if (_ssh_initialized == 1) {
|
||||
if (_ssh_init_ret < 0) {
|
||||
goto _ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* If the counter reaches zero or it is the destructor calling, finalize */
|
||||
ssh_dh_finalize();
|
||||
ssh_crypto_finalize();
|
||||
ssh_socket_cleanup();
|
||||
/* It is important to finalize threading after CRYPTO because
|
||||
* it still depends on it */
|
||||
ssh_threads_finalize();
|
||||
|
||||
_ssh_initialized = 0;
|
||||
|
||||
_ret:
|
||||
if (!destructor) {
|
||||
ssh_mutex_unlock(&ssh_init_mutex);
|
||||
@@ -191,14 +200,6 @@ void libssh_destructor(void)
|
||||
if (rc < 0) {
|
||||
fprintf(stderr, "Error in libssh_destructor()\n");
|
||||
}
|
||||
|
||||
/* Detect if ssh_init() was called without matching ssh_finalize() */
|
||||
if (_ssh_initialized > 0) {
|
||||
fprintf(stderr,
|
||||
"Warning: ssh still initialized; probably ssh_init() "
|
||||
"was called more than once (init count: %d)\n",
|
||||
_ssh_initialized);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -221,4 +222,35 @@ int ssh_finalize(void) {
|
||||
return _ssh_finalize(0);
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#if defined(_MSC_VER) && !defined(LIBSSH_STATIC)
|
||||
/* Library constructor and destructor */
|
||||
BOOL WINAPI DllMain(HINSTANCE hinstDLL,
|
||||
DWORD fdwReason,
|
||||
LPVOID lpvReserved)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
switch(fdwReason) {
|
||||
case DLL_PROCESS_ATTACH:
|
||||
rc = _ssh_init(1);
|
||||
if (rc != 0) {
|
||||
fprintf(stderr, "DllMain: ssh_init failed!");
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
case DLL_PROCESS_DETACH:
|
||||
_ssh_finalize(1);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
#endif /* _MSC_VER && !LIBSSH_STATIC */
|
||||
|
||||
#endif /* _WIN32 */
|
||||
|
||||
/** @} */
|
||||
|
||||
88
src/kex.c
@@ -86,25 +86,28 @@
|
||||
|
||||
#ifdef HAVE_ECDH
|
||||
#define ECDH "ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,"
|
||||
#define HOSTKEYS "ssh-ed25519,ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,ssh-rsa,ssh-dss"
|
||||
#define PUBLIC_KEY_ALGORITHMS "ssh-ed25519,ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,ssh-rsa,rsa-sha2-512,rsa-sha2-256,ssh-dss"
|
||||
#else
|
||||
#ifdef HAVE_DSA
|
||||
#define HOSTKEYS "ssh-ed25519,ssh-rsa,ssh-dss"
|
||||
#define PUBLIC_KEY_ALGORITHMS "ssh-ed25519,ssh-rsa,rsa-sha2-512,rsa-sha2-256,ssh-dss"
|
||||
#else
|
||||
#define HOSTKEYS "ssh-ed25519,ssh-rsa"
|
||||
#define PUBLIC_KEY_ALGORITHMS "ssh-ed25519,ssh-rsa,rsa-sha2-512,rsa-sha2-256"
|
||||
#endif
|
||||
#define ECDH ""
|
||||
#endif
|
||||
|
||||
#define CHACHA20 "chacha20-poly1305@openssh.com,"
|
||||
|
||||
#define KEY_EXCHANGE CURVE25519 ECDH "diffie-hellman-group14-sha1,diffie-hellman-group1-sha1"
|
||||
#define KEY_EXCHANGE CURVE25519 ECDH "diffie-hellman-group16-sha512,diffie-hellman-group18-sha512,diffie-hellman-group14-sha1,diffie-hellman-group1-sha1"
|
||||
#define KEX_METHODS_SIZE 10
|
||||
|
||||
/* RFC 8308 */
|
||||
#define KEX_EXTENSION_CLIENT "ext-info-c"
|
||||
|
||||
/* NOTE: This is a fixed API and the index is defined by ssh_kex_types_e */
|
||||
static const char *default_methods[] = {
|
||||
KEY_EXCHANGE,
|
||||
HOSTKEYS,
|
||||
PUBLIC_KEY_ALGORITHMS,
|
||||
AES BLOWFISH DES,
|
||||
AES BLOWFISH DES,
|
||||
"hmac-sha2-256,hmac-sha2-512,hmac-sha1",
|
||||
@@ -119,7 +122,7 @@ static const char *default_methods[] = {
|
||||
/* NOTE: This is a fixed API and the index is defined by ssh_kex_types_e */
|
||||
static const char *supported_methods[] = {
|
||||
KEY_EXCHANGE,
|
||||
HOSTKEYS,
|
||||
PUBLIC_KEY_ALGORITHMS,
|
||||
CHACHA20 AES BLOWFISH DES_SUPPORTED,
|
||||
CHACHA20 AES BLOWFISH DES_SUPPORTED,
|
||||
"hmac-sha2-256,hmac-sha2-512,hmac-sha1",
|
||||
@@ -149,8 +152,8 @@ static const char *ssh_kex_descriptions[] = {
|
||||
/* tokenize will return a token of strings delimited by ",". the first element has to be freed */
|
||||
static char **tokenize(const char *chain){
|
||||
char **tokens;
|
||||
int n=1;
|
||||
int i=0;
|
||||
size_t n=1;
|
||||
size_t i=0;
|
||||
char *tmp;
|
||||
char *ptr;
|
||||
|
||||
@@ -187,8 +190,8 @@ static char **tokenize(const char *chain){
|
||||
/* TODO FIXME rewrite me! */
|
||||
char **ssh_space_tokenize(const char *chain){
|
||||
char **tokens;
|
||||
int n=1;
|
||||
int i=0;
|
||||
size_t n=1;
|
||||
size_t i=0;
|
||||
char *tmp;
|
||||
char *ptr;
|
||||
|
||||
@@ -232,6 +235,15 @@ char **ssh_space_tokenize(const char *chain){
|
||||
return tokens;
|
||||
}
|
||||
|
||||
const char *ssh_kex_get_default_methods(uint32_t algo)
|
||||
{
|
||||
if (algo >= KEX_METHODS_SIZE) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return default_methods[algo];
|
||||
}
|
||||
|
||||
const char *ssh_kex_get_supported_method(uint32_t algo) {
|
||||
if (algo >= KEX_METHODS_SIZE) {
|
||||
return NULL;
|
||||
@@ -403,10 +415,10 @@ out:
|
||||
}
|
||||
|
||||
SSH_PACKET_CALLBACK(ssh_packet_kexinit){
|
||||
int i;
|
||||
int i, ok;
|
||||
int server_kex=session->server;
|
||||
ssh_string str = NULL;
|
||||
char *strings[KEX_METHODS_SIZE];
|
||||
char *strings[KEX_METHODS_SIZE] = {0};
|
||||
int rc = SSH_ERROR;
|
||||
|
||||
uint8_t first_kex_packet_follows = 0;
|
||||
@@ -415,7 +427,6 @@ SSH_PACKET_CALLBACK(ssh_packet_kexinit){
|
||||
(void)type;
|
||||
(void)user;
|
||||
|
||||
memset(strings, 0, sizeof(strings));
|
||||
if (session->session_state == SSH_SESSION_STATE_AUTHENTICATED){
|
||||
SSH_LOG(SSH_LOG_WARNING, "Other side initiating key re-exchange");
|
||||
} else if(session->session_state != SSH_SESSION_STATE_INITIAL_KEX){
|
||||
@@ -507,6 +518,22 @@ SSH_PACKET_CALLBACK(ssh_packet_kexinit){
|
||||
goto error;
|
||||
}
|
||||
|
||||
/*
|
||||
* If client sent a ext-info-c message in the kex list, it supports
|
||||
* RFC 8308 extension negotiation.
|
||||
*/
|
||||
ok = ssh_match_group(session->next_crypto->client_kex.methods[SSH_KEX],
|
||||
KEX_EXTENSION_CLIENT);
|
||||
if (ok) {
|
||||
/*
|
||||
* Enable all the supported extensions and when the time comes
|
||||
* (after NEWKEYS) send them to the client.
|
||||
*/
|
||||
SSH_LOG(SSH_LOG_DEBUG, "The client supports extension "
|
||||
"negotiation: enabling all extensions");
|
||||
session->extensions = SSH_EXT_ALL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Remember whether 'first_kex_packet_follows' was set and the client
|
||||
* guess was wrong: in this case the next SSH_MSG_KEXDH_INIT message
|
||||
@@ -642,11 +669,15 @@ static char *ssh_client_select_hostkeys(ssh_session session)
|
||||
* @brief sets the key exchange parameters to be sent to the server,
|
||||
* in function of the options and available methods.
|
||||
*/
|
||||
int ssh_set_client_kex(ssh_session session){
|
||||
int ssh_set_client_kex(ssh_session session)
|
||||
{
|
||||
struct ssh_kex_struct *client= &session->next_crypto->client_kex;
|
||||
const char *wanted;
|
||||
char *kex = NULL;
|
||||
char *kex_tmp = NULL;
|
||||
int ok;
|
||||
int i;
|
||||
size_t kex_len, len;
|
||||
|
||||
ok = ssh_get_random(client->cookie, 16, 0);
|
||||
if (!ok) {
|
||||
@@ -673,6 +704,23 @@ int ssh_set_client_kex(ssh_session session){
|
||||
}
|
||||
}
|
||||
|
||||
/* Here we append ext-info-c to the list of kex algorithms */
|
||||
kex = client->methods[SSH_KEX];
|
||||
len = strlen(kex);
|
||||
if (len + strlen(KEX_EXTENSION_CLIENT) + 2 < len) {
|
||||
/* Overflow */
|
||||
return SSH_ERROR;
|
||||
}
|
||||
kex_len = len + strlen(KEX_EXTENSION_CLIENT) + 2; /* comma, NULL */
|
||||
kex_tmp = realloc(kex, kex_len);
|
||||
if (kex_tmp == NULL) {
|
||||
free(kex);
|
||||
ssh_set_error_oom(session);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
snprintf(kex_tmp + len, kex_len - len, ",%s", KEX_EXTENSION_CLIENT);
|
||||
client->methods[SSH_KEX] = kex_tmp;
|
||||
|
||||
return SSH_OK;
|
||||
}
|
||||
|
||||
@@ -682,8 +730,16 @@ int ssh_set_client_kex(ssh_session session){
|
||||
int ssh_kex_select_methods (ssh_session session){
|
||||
struct ssh_kex_struct *server = &session->next_crypto->server_kex;
|
||||
struct ssh_kex_struct *client = &session->next_crypto->client_kex;
|
||||
char *ext_start = NULL;
|
||||
int i;
|
||||
|
||||
/* Here we should drop the ext-info-c from the list so we avoid matching.
|
||||
* it. We added it to the end, so we can just truncate the string here */
|
||||
ext_start = strstr(client->methods[SSH_KEX], ","KEX_EXTENSION_CLIENT);
|
||||
if (ext_start != NULL) {
|
||||
ext_start[0] = '\0';
|
||||
}
|
||||
|
||||
for (i = 0; i < KEX_METHODS_SIZE; i++) {
|
||||
session->next_crypto->kex_methods[i]=ssh_find_matching(server->methods[i],client->methods[i]);
|
||||
if(session->next_crypto->kex_methods[i] == NULL && i < SSH_LANG_C_S){
|
||||
@@ -699,6 +755,10 @@ int ssh_kex_select_methods (ssh_session session){
|
||||
session->next_crypto->kex_type=SSH_KEX_DH_GROUP1_SHA1;
|
||||
} else if(strcmp(session->next_crypto->kex_methods[SSH_KEX], "diffie-hellman-group14-sha1") == 0){
|
||||
session->next_crypto->kex_type=SSH_KEX_DH_GROUP14_SHA1;
|
||||
} else if(strcmp(session->next_crypto->kex_methods[SSH_KEX], "diffie-hellman-group16-sha512") == 0){
|
||||
session->next_crypto->kex_type=SSH_KEX_DH_GROUP16_SHA512;
|
||||
} else if(strcmp(session->next_crypto->kex_methods[SSH_KEX], "diffie-hellman-group18-sha512") == 0){
|
||||
session->next_crypto->kex_type=SSH_KEX_DH_GROUP18_SHA512;
|
||||
} else if(strcmp(session->next_crypto->kex_methods[SSH_KEX], "ecdh-sha2-nistp256") == 0){
|
||||
session->next_crypto->kex_type=SSH_KEX_ECDH_SHA2_NISTP256;
|
||||
} else if(strcmp(session->next_crypto->kex_methods[SSH_KEX], "ecdh-sha2-nistp384") == 0){
|
||||
|
||||
@@ -131,17 +131,13 @@ static char **ssh_get_knownhost_line(FILE **file, const char *filename,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(!tokens[0] || !tokens[1] || !tokens[2]) {
|
||||
if(tokens[0] == NULL || tokens[1] == NULL || tokens[2] == NULL) {
|
||||
/* it should have at least 3 tokens */
|
||||
tokens_free(tokens);
|
||||
continue;
|
||||
}
|
||||
|
||||
*found_type = tokens[1];
|
||||
if (tokens[3] || tokens[4]) {
|
||||
tokens_free(tokens);
|
||||
continue;
|
||||
}
|
||||
|
||||
return tokens;
|
||||
}
|
||||
@@ -154,6 +150,8 @@ static char **ssh_get_knownhost_line(FILE **file, const char *filename,
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
* @brief Check the public key in the known host line matches the public key of
|
||||
* the currently connected server.
|
||||
*
|
||||
@@ -206,6 +204,7 @@ static int check_public_key(ssh_session session, char **tokens) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* @brief Check if a hostname matches a openssh-style hashed known host.
|
||||
*
|
||||
* @param[in] host The host to check.
|
||||
@@ -441,14 +440,8 @@ int ssh_is_server_known(ssh_session session) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Output the current server as a known host line.
|
||||
*
|
||||
* This could be placed in a known hosts file after user confirmation.
|
||||
* The return value should be passed to free() after the caller is done with it.
|
||||
*
|
||||
* @param[in] session The ssh session to use.
|
||||
*
|
||||
* @return string on success, NULL on error.
|
||||
* @deprecated Please use ssh_session_export_known_hosts_entry()
|
||||
* @brief This function is deprecated.
|
||||
*/
|
||||
char * ssh_dump_knownhost(ssh_session session) {
|
||||
ssh_key server_pubkey = NULL;
|
||||
@@ -516,14 +509,8 @@ char * ssh_dump_knownhost(ssh_session session) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Write the current server as known in the known hosts file.
|
||||
*
|
||||
* This will create the known hosts file if it does not exist. You generaly use
|
||||
* it when ssh_is_server_known() answered SSH_SERVER_NOT_KNOWN.
|
||||
*
|
||||
* @param[in] session The ssh session to use.
|
||||
*
|
||||
* @return SSH_OK on success, SSH_ERROR on error.
|
||||
* @deprecated Please use ssh_session_update_known_hosts()
|
||||
* @brief This function is deprecated
|
||||
*/
|
||||
int ssh_write_knownhost(ssh_session session) {
|
||||
FILE *file;
|
||||
|
||||
@@ -43,6 +43,12 @@
|
||||
#include "libssh/dh.h"
|
||||
#include "libssh/knownhosts.h"
|
||||
|
||||
/**
|
||||
* @addtogroup libssh_session
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
static int hash_hostname(const char *name,
|
||||
unsigned char *salt,
|
||||
unsigned int salt_size,
|
||||
@@ -523,7 +529,7 @@ out:
|
||||
*
|
||||
* @param[in] session The session with with the values set to check.
|
||||
*
|
||||
* @return A @ssh_known_hosts_e return value.
|
||||
* @return A ssh_known_hosts_e return value.
|
||||
*/
|
||||
enum ssh_known_hosts_e ssh_session_has_known_hosts_entry(ssh_session session)
|
||||
{
|
||||
@@ -878,9 +884,11 @@ ssh_session_get_known_hosts_entry(ssh_session session,
|
||||
* SSH_KNOWN_HOSTS_NOT_FOUND: The known host file does not exist. The
|
||||
* host is thus unknown. File will be
|
||||
* created if host key is accepted.\n
|
||||
* SSH_KNOWN_HOSTS_ERROR: There had been an eror checking the host.
|
||||
* SSH_KNOWN_HOSTS_ERROR: There had been an error checking the host.
|
||||
*/
|
||||
enum ssh_known_hosts_e ssh_session_is_known_server(ssh_session session)
|
||||
{
|
||||
return ssh_session_get_known_hosts_entry(session, NULL);
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
@@ -30,6 +30,9 @@
|
||||
#ifdef HAVE_LIBMBEDCRYPTO
|
||||
#include <mbedtls/md.h>
|
||||
|
||||
static mbedtls_entropy_context ssh_mbedtls_entropy;
|
||||
static mbedtls_ctr_drbg_context ssh_mbedtls_ctr_drbg;
|
||||
|
||||
struct ssh_mac_ctx_struct {
|
||||
enum ssh_mac_e mac_type;
|
||||
mbedtls_md_context_t ctx;
|
||||
@@ -169,7 +172,7 @@ void evp_update(EVPCTX ctx, const void *data, unsigned long len)
|
||||
void evp_final(EVPCTX ctx, unsigned char *md, unsigned int *mdlen)
|
||||
{
|
||||
*mdlen = mbedtls_md_get_size(ctx->md_info);
|
||||
mbedtls_md_hmac_finish(ctx, md);
|
||||
mbedtls_md_finish(ctx, md);
|
||||
mbedtls_md_free(ctx);
|
||||
SAFE_FREE(ctx);
|
||||
}
|
||||
@@ -999,6 +1002,11 @@ int ssh_mbedtls_random(void *where, int len, int strong)
|
||||
return !rc;
|
||||
}
|
||||
|
||||
mbedtls_ctr_drbg_context *ssh_get_mbedtls_ctr_drbg_context(void)
|
||||
{
|
||||
return &ssh_mbedtls_ctr_drbg;
|
||||
}
|
||||
|
||||
void ssh_crypto_finalize(void)
|
||||
{
|
||||
if (!libmbedcrypto_initialized) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# This map file was created with abimap-0.3.0
|
||||
# This map file was updated with abimap-0.3.1
|
||||
|
||||
LIBSSH_4_5_0 # Released
|
||||
{
|
||||
@@ -418,3 +418,16 @@ LIBSSH_4_5_0 # Released
|
||||
*;
|
||||
} ;
|
||||
|
||||
LIBSSH_4_6_0 # Released
|
||||
{
|
||||
global:
|
||||
ssh_print_hash;
|
||||
} LIBSSH_4_5_0;
|
||||
|
||||
LIBSSH_4_7_0 # Released
|
||||
{
|
||||
global:
|
||||
sftp_client_message_get_submessage;
|
||||
ssh_get_fingerprint_hash;
|
||||
ssh_pki_export_privkey_base64;
|
||||
} LIBSSH_4_6_0;
|
||||
|
||||
@@ -81,7 +81,7 @@ static void ssh_log_stderr(int verbosity,
|
||||
const char *function,
|
||||
const char *buffer)
|
||||
{
|
||||
char date[64] = {0};
|
||||
char date[128] = {0};
|
||||
int rc;
|
||||
|
||||
rc = current_timestring(1, date, sizeof(date));
|
||||
|
||||
@@ -119,7 +119,7 @@ static int match_pattern(const char *s, const char *pattern) {
|
||||
* Returns -1 if negation matches, 1 if there is a positive match, 0 if there is
|
||||
* no match at all.
|
||||
*/
|
||||
static int match_pattern_list(const char *string, const char *pattern,
|
||||
int match_pattern_list(const char *string, const char *pattern,
|
||||
unsigned int len, int dolower) {
|
||||
char sub[1024];
|
||||
int negated;
|
||||
|
||||
@@ -81,8 +81,10 @@ int ssh_mbedcry_rand(bignum rnd, int bits, int top, int bottom)
|
||||
}
|
||||
|
||||
len = bits / 8 + 1;
|
||||
rc = mbedtls_mpi_fill_random(rnd, len, mbedtls_ctr_drbg_random,
|
||||
&ssh_mbedtls_ctr_drbg);
|
||||
rc = mbedtls_mpi_fill_random(rnd,
|
||||
len,
|
||||
mbedtls_ctr_drbg_random,
|
||||
ssh_get_mbedtls_ctr_drbg_context());
|
||||
if (rc != 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -430,6 +430,13 @@ void ssh_message_queue(ssh_session session, ssh_message message){
|
||||
}
|
||||
if (session->ssh_message_list != NULL) {
|
||||
ssh_list_append(session->ssh_message_list, message);
|
||||
} else {
|
||||
/* If the message list couldn't be allocated, the message can't be
|
||||
* enqueued */
|
||||
ssh_message_reply_default(message);
|
||||
ssh_set_error_oom(session);
|
||||
ssh_message_free(message);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -645,7 +652,8 @@ error:
|
||||
*/
|
||||
static ssh_buffer ssh_msg_userauth_build_digest(ssh_session session,
|
||||
ssh_message msg,
|
||||
const char *service)
|
||||
const char *service,
|
||||
ssh_string algo)
|
||||
{
|
||||
struct ssh_crypto_struct *crypto =
|
||||
session->current_crypto ? session->current_crypto :
|
||||
@@ -673,7 +681,7 @@ static ssh_buffer ssh_msg_userauth_build_digest(ssh_session session,
|
||||
service,
|
||||
"publickey", /* method */
|
||||
1, /* has to be signed (true) */
|
||||
msg->auth_request.pubkey->type_c, /* pubkey algorithm */
|
||||
ssh_string_get_char(algo), /* pubkey algorithm */
|
||||
str); /* public key as a blob */
|
||||
|
||||
ssh_string_free(str);
|
||||
@@ -785,13 +793,13 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_request){
|
||||
if (rc != SSH_OK) {
|
||||
goto error;
|
||||
}
|
||||
ssh_string_free(algo);
|
||||
algo = NULL;
|
||||
|
||||
rc = ssh_pki_import_pubkey_blob(pubkey_blob, &msg->auth_request.pubkey);
|
||||
ssh_string_free(pubkey_blob);
|
||||
pubkey_blob = NULL;
|
||||
if (rc < 0) {
|
||||
ssh_string_free(algo);
|
||||
algo = NULL;
|
||||
goto error;
|
||||
}
|
||||
msg->auth_request.signature_state = SSH_PUBLICKEY_STATE_NONE;
|
||||
@@ -804,10 +812,14 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_request){
|
||||
if(sig_blob == NULL) {
|
||||
SSH_LOG(SSH_LOG_PACKET, "Invalid signature packet from peer");
|
||||
msg->auth_request.signature_state = SSH_PUBLICKEY_STATE_ERROR;
|
||||
ssh_string_free(algo);
|
||||
algo = NULL;
|
||||
goto error;
|
||||
}
|
||||
|
||||
digest = ssh_msg_userauth_build_digest(session, msg, service);
|
||||
digest = ssh_msg_userauth_build_digest(session, msg, service, algo);
|
||||
ssh_string_free(algo);
|
||||
algo = NULL;
|
||||
if (digest == NULL) {
|
||||
ssh_string_free(sig_blob);
|
||||
SSH_LOG(SSH_LOG_PACKET, "Failed to get digest");
|
||||
@@ -834,6 +846,7 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_request){
|
||||
|
||||
msg->auth_request.signature_state = SSH_PUBLICKEY_STATE_VALID;
|
||||
}
|
||||
ssh_string_free(algo);
|
||||
goto end;
|
||||
}
|
||||
#ifdef WITH_GSSAPI
|
||||
|
||||
29
src/misc.c
@@ -217,7 +217,7 @@ char *ssh_get_user_home_dir(void) {
|
||||
char *szPath = NULL;
|
||||
struct passwd pwd;
|
||||
struct passwd *pwdbuf;
|
||||
char buf[NSS_BUFLEN_PASSWD];
|
||||
char buf[NSS_BUFLEN_PASSWD] = {0};
|
||||
int rc;
|
||||
|
||||
rc = getpwuid_r(getuid(), &pwd, buf, NSS_BUFLEN_PASSWD, &pwdbuf);
|
||||
@@ -226,7 +226,6 @@ char *ssh_get_user_home_dir(void) {
|
||||
if (szPath == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
memset(buf, 0, sizeof(buf));
|
||||
snprintf(buf, sizeof(buf), "%s", szPath);
|
||||
|
||||
return strdup(buf);
|
||||
@@ -778,7 +777,10 @@ char *ssh_path_expand_escape(ssh_session session, const char *s) {
|
||||
if (session->opts.port < 65536) {
|
||||
char tmp[6];
|
||||
|
||||
snprintf(tmp, sizeof(tmp), "%u", session->opts.port);
|
||||
snprintf(tmp,
|
||||
sizeof(tmp),
|
||||
"%u",
|
||||
session->opts.port > 0 ? session->opts.port : 22);
|
||||
x = strdup(tmp);
|
||||
}
|
||||
break;
|
||||
@@ -1082,4 +1084,25 @@ void explicit_bzero(void *s, size_t n)
|
||||
}
|
||||
#endif /* !HAVE_EXPLICIT_BZERO */
|
||||
|
||||
#if !defined(HAVE_STRNDUP)
|
||||
char *strndup(const char *s, size_t n)
|
||||
{
|
||||
char *x = NULL;
|
||||
|
||||
if (n + 1 < n) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
x = malloc(n + 1);
|
||||
if (x == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memcpy(x, s, n);
|
||||
x[n] = '\0';
|
||||
|
||||
return x;
|
||||
}
|
||||
#endif /* ! HAVE_STRNDUP */
|
||||
|
||||
/** @} */
|
||||
|
||||
310
src/options.c
@@ -147,6 +147,14 @@ int ssh_options_copy(ssh_session src, ssh_session *dest) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (src->opts.pubkey_accepted_types != NULL) {
|
||||
new->opts.pubkey_accepted_types = strdup(src->opts.pubkey_accepted_types);
|
||||
if (new->opts.pubkey_accepted_types == NULL) {
|
||||
ssh_free(new);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
new->opts.fd = src->opts.fd;
|
||||
new->opts.port = src->opts.port;
|
||||
new->opts.timeout = src->opts.timeout;
|
||||
@@ -343,6 +351,11 @@ int ssh_options_set_algo(ssh_session session,
|
||||
* comma-separated list). ex:
|
||||
* "ssh-rsa,ssh-dss,ecdh-sha2-nistp256"
|
||||
*
|
||||
* - SSH_OPTIONS_PUBLICKEY_ACCEPTED_TYPES:
|
||||
* Set the preferred public key algorithms to be used for
|
||||
* authentication (const char *, comma-separated list). ex:
|
||||
* "ssh-rsa,rsa-sha2-256,ssh-dss,ecdh-sha2-nistp256"
|
||||
*
|
||||
* - SSH_OPTIONS_COMPRESSION_C_S:
|
||||
* Set the compression to use for client to server
|
||||
* communication (const char *, "yes", "no" or a specific
|
||||
@@ -743,6 +756,24 @@ int ssh_options_set(ssh_session session, enum ssh_options_e type,
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case SSH_OPTIONS_PUBLICKEY_ACCEPTED_TYPES:
|
||||
v = value;
|
||||
if (v == NULL || v[0] == '\0') {
|
||||
ssh_set_error_invalid(session);
|
||||
return -1;
|
||||
} else {
|
||||
p = ssh_keep_known_algos(SSH_HOSTKEYS, v);
|
||||
if (p == NULL) {
|
||||
ssh_set_error(session, SSH_REQUEST_DENIED,
|
||||
"Setting method: no known public key algorithm (%s)",
|
||||
v);
|
||||
return -1;
|
||||
}
|
||||
|
||||
SAFE_FREE(session->opts.pubkey_accepted_types);
|
||||
session->opts.pubkey_accepted_types = p;
|
||||
}
|
||||
break;
|
||||
case SSH_OPTIONS_HMAC_C_S:
|
||||
v = value;
|
||||
if (v == NULL || v[0] == '\0') {
|
||||
@@ -1070,164 +1101,169 @@ int ssh_options_get(ssh_session session, enum ssh_options_e type, char** value)
|
||||
*
|
||||
* @see ssh_session_new()
|
||||
*/
|
||||
int ssh_options_getopt(ssh_session session, int *argcptr, char **argv) {
|
||||
char *user = NULL;
|
||||
char *cipher = NULL;
|
||||
char *identity = NULL;
|
||||
char *port = NULL;
|
||||
char **save = NULL;
|
||||
char **tmp = NULL;
|
||||
int i = 0;
|
||||
int argc = *argcptr;
|
||||
int debuglevel = 0;
|
||||
int usersa = 0;
|
||||
int usedss = 0;
|
||||
int compress = 0;
|
||||
int cont = 1;
|
||||
int current = 0;
|
||||
int ssh_options_getopt(ssh_session session, int *argcptr, char **argv)
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
(void)session;
|
||||
(void)argcptr;
|
||||
(void)argv;
|
||||
/* Not supported with a Microsoft compiler */
|
||||
return -1;
|
||||
#else
|
||||
int saveoptind = optind; /* need to save 'em */
|
||||
int saveopterr = opterr;
|
||||
char *user = NULL;
|
||||
char *cipher = NULL;
|
||||
char *identity = NULL;
|
||||
char *port = NULL;
|
||||
char **save = NULL;
|
||||
char **tmp = NULL;
|
||||
size_t i = 0;
|
||||
int argc = *argcptr;
|
||||
int debuglevel = 0;
|
||||
int usersa = 0;
|
||||
int usedss = 0;
|
||||
int compress = 0;
|
||||
int cont = 1;
|
||||
size_t current = 0;
|
||||
int saveoptind = optind; /* need to save 'em */
|
||||
int saveopterr = opterr;
|
||||
int opt;
|
||||
|
||||
opterr = 0; /* shut up getopt */
|
||||
while(cont && ((i = getopt(argc, argv, "c:i:Cl:p:vb:rd12")) != -1)) {
|
||||
switch(i) {
|
||||
case 'l':
|
||||
user = optarg;
|
||||
break;
|
||||
case 'p':
|
||||
port = optarg;
|
||||
break;
|
||||
case 'v':
|
||||
debuglevel++;
|
||||
break;
|
||||
case 'r':
|
||||
usersa++;
|
||||
break;
|
||||
case 'd':
|
||||
usedss++;
|
||||
break;
|
||||
case 'c':
|
||||
cipher = optarg;
|
||||
break;
|
||||
case 'i':
|
||||
identity = optarg;
|
||||
break;
|
||||
case 'C':
|
||||
compress++;
|
||||
break;
|
||||
case '2':
|
||||
break;
|
||||
case '1':
|
||||
break;
|
||||
default:
|
||||
{
|
||||
char opt[3]="- ";
|
||||
opt[1] = optopt;
|
||||
tmp = realloc(save, (current + 1) * sizeof(char*));
|
||||
if (tmp == NULL) {
|
||||
opterr = 0; /* shut up getopt */
|
||||
while((opt = getopt(argc, argv, "c:i:Cl:p:vb:rd12")) != -1) {
|
||||
switch(opt) {
|
||||
case 'l':
|
||||
user = optarg;
|
||||
break;
|
||||
case 'p':
|
||||
port = optarg;
|
||||
break;
|
||||
case 'v':
|
||||
debuglevel++;
|
||||
break;
|
||||
case 'r':
|
||||
usersa++;
|
||||
break;
|
||||
case 'd':
|
||||
usedss++;
|
||||
break;
|
||||
case 'c':
|
||||
cipher = optarg;
|
||||
break;
|
||||
case 'i':
|
||||
identity = optarg;
|
||||
break;
|
||||
case 'C':
|
||||
compress++;
|
||||
break;
|
||||
case '2':
|
||||
break;
|
||||
case '1':
|
||||
break;
|
||||
default:
|
||||
{
|
||||
char optv[3] = "- ";
|
||||
optv[1] = optopt;
|
||||
tmp = realloc(save, (current + 1) * sizeof(char*));
|
||||
if (tmp == NULL) {
|
||||
SAFE_FREE(save);
|
||||
ssh_set_error_oom(session);
|
||||
return -1;
|
||||
}
|
||||
save = tmp;
|
||||
save[current] = strdup(optv);
|
||||
if (save[current] == NULL) {
|
||||
SAFE_FREE(save);
|
||||
ssh_set_error_oom(session);
|
||||
return -1;
|
||||
}
|
||||
current++;
|
||||
if (optarg) {
|
||||
save[current++] = argv[optind + 1];
|
||||
}
|
||||
}
|
||||
} /* switch */
|
||||
} /* while */
|
||||
opterr = saveopterr;
|
||||
tmp = realloc(save, (current + (argc - optind)) * sizeof(char*));
|
||||
if (tmp == NULL) {
|
||||
SAFE_FREE(save);
|
||||
ssh_set_error_oom(session);
|
||||
return -1;
|
||||
}
|
||||
save = tmp;
|
||||
while (optind < argc) {
|
||||
tmp = realloc(save, (current + 1) * sizeof(char*));
|
||||
if (tmp == NULL) {
|
||||
SAFE_FREE(save);
|
||||
ssh_set_error_oom(session);
|
||||
return -1;
|
||||
}
|
||||
save = tmp;
|
||||
save[current] = strdup(opt);
|
||||
if (save[current] == NULL) {
|
||||
SAFE_FREE(save);
|
||||
ssh_set_error_oom(session);
|
||||
return -1;
|
||||
}
|
||||
current++;
|
||||
if (optarg) {
|
||||
save[current++] = argv[optind + 1];
|
||||
}
|
||||
}
|
||||
} /* switch */
|
||||
} /* while */
|
||||
opterr = saveopterr;
|
||||
tmp = realloc(save, (current + (argc - optind)) * sizeof(char*));
|
||||
if (tmp == NULL) {
|
||||
save = tmp;
|
||||
save[current] = argv[optind];
|
||||
current++;
|
||||
optind++;
|
||||
}
|
||||
|
||||
if (usersa && usedss) {
|
||||
ssh_set_error(session, SSH_FATAL, "Either RSA or DSS must be chosen");
|
||||
cont = 0;
|
||||
}
|
||||
|
||||
ssh_set_log_level(debuglevel);
|
||||
|
||||
optind = saveoptind;
|
||||
|
||||
if(!cont) {
|
||||
SAFE_FREE(save);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* first recopy the save vector into the original's */
|
||||
for (i = 0; i < current; i++) {
|
||||
/* don't erase argv[0] */
|
||||
argv[ i + 1] = save[i];
|
||||
}
|
||||
argv[current + 1] = NULL;
|
||||
*argcptr = current + 1;
|
||||
SAFE_FREE(save);
|
||||
ssh_set_error_oom(session);
|
||||
return -1;
|
||||
}
|
||||
save = tmp;
|
||||
while (optind < argc) {
|
||||
tmp = realloc(save, (current + 1) * sizeof(char*));
|
||||
if (tmp == NULL) {
|
||||
SAFE_FREE(save);
|
||||
ssh_set_error_oom(session);
|
||||
return -1;
|
||||
}
|
||||
save = tmp;
|
||||
save[current] = argv[optind];
|
||||
current++;
|
||||
optind++;
|
||||
}
|
||||
|
||||
if (usersa && usedss) {
|
||||
ssh_set_error(session, SSH_FATAL, "Either RSA or DSS must be chosen");
|
||||
cont = 0;
|
||||
}
|
||||
|
||||
ssh_set_log_level(debuglevel);
|
||||
|
||||
optind = saveoptind;
|
||||
|
||||
if(!cont) {
|
||||
SAFE_FREE(save);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* first recopy the save vector into the original's */
|
||||
for (i = 0; i < current; i++) {
|
||||
/* don't erase argv[0] */
|
||||
argv[ i + 1] = save[i];
|
||||
}
|
||||
argv[current + 1] = NULL;
|
||||
*argcptr = current + 1;
|
||||
SAFE_FREE(save);
|
||||
|
||||
/* set a new option struct */
|
||||
if (compress) {
|
||||
if (ssh_options_set(session, SSH_OPTIONS_COMPRESSION, "yes") < 0) {
|
||||
cont = 0;
|
||||
/* set a new option struct */
|
||||
if (compress) {
|
||||
if (ssh_options_set(session, SSH_OPTIONS_COMPRESSION, "yes") < 0) {
|
||||
cont = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (cont && cipher) {
|
||||
if (ssh_options_set(session, SSH_OPTIONS_CIPHERS_C_S, cipher) < 0) {
|
||||
cont = 0;
|
||||
if (cont && cipher) {
|
||||
if (ssh_options_set(session, SSH_OPTIONS_CIPHERS_C_S, cipher) < 0) {
|
||||
cont = 0;
|
||||
}
|
||||
if (cont && ssh_options_set(session, SSH_OPTIONS_CIPHERS_S_C, cipher) < 0) {
|
||||
cont = 0;
|
||||
}
|
||||
}
|
||||
if (cont && ssh_options_set(session, SSH_OPTIONS_CIPHERS_S_C, cipher) < 0) {
|
||||
cont = 0;
|
||||
|
||||
if (cont && user) {
|
||||
if (ssh_options_set(session, SSH_OPTIONS_USER, user) < 0) {
|
||||
cont = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (cont && user) {
|
||||
if (ssh_options_set(session, SSH_OPTIONS_USER, user) < 0) {
|
||||
cont = 0;
|
||||
if (cont && identity) {
|
||||
if (ssh_options_set(session, SSH_OPTIONS_IDENTITY, identity) < 0) {
|
||||
cont = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (cont && identity) {
|
||||
if (ssh_options_set(session, SSH_OPTIONS_IDENTITY, identity) < 0) {
|
||||
cont = 0;
|
||||
if (port != NULL) {
|
||||
ssh_options_set(session, SSH_OPTIONS_PORT_STR, port);
|
||||
}
|
||||
}
|
||||
|
||||
if (port != NULL) {
|
||||
ssh_options_set(session, SSH_OPTIONS_PORT_STR, port);
|
||||
}
|
||||
if (!cont) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
if (!cont) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
return SSH_OK;
|
||||
return SSH_OK;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
844
src/packet.c
@@ -59,8 +59,9 @@ static ssh_packet_callback default_packet_handlers[]= {
|
||||
NULL,
|
||||
#endif
|
||||
ssh_packet_service_accept, // SSH2_MSG_SERVICE_ACCEPT 6
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, // 7-19
|
||||
ssh_packet_ext_info, // SSH2_MSG_EXT_INFO 7
|
||||
NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, // 8-19
|
||||
ssh_packet_kexinit, // SSH2_MSG_KEXINIT 20
|
||||
ssh_packet_newkeys, // SSH2_MSG_NEWKEYS 21
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
@@ -127,6 +128,797 @@ static ssh_packet_callback default_packet_handlers[]= {
|
||||
ssh_packet_channel_failure, // SSH2_MSG_CHANNEL_FAILURE 100
|
||||
};
|
||||
|
||||
/** @internal
|
||||
* @brief check if the received packet is allowed for the current session state
|
||||
* @param session current ssh_session
|
||||
* @returns SSH_PACKET_ALLOWED if the packet is allowed; SSH_PACKET_DENIED
|
||||
* if the packet arrived in wrong state; SSH_PACKET_UNKNOWN if the packet type
|
||||
* is unknown
|
||||
*/
|
||||
static enum ssh_packet_filter_result_e ssh_packet_incoming_filter(ssh_session session)
|
||||
{
|
||||
enum ssh_packet_filter_result_e rc;
|
||||
|
||||
#ifdef DEBUG_PACKET
|
||||
SSH_LOG(SSH_LOG_PACKET, "Filtering packet type %d",
|
||||
session->in_packet.type);
|
||||
#endif
|
||||
|
||||
switch(session->in_packet.type) {
|
||||
case SSH2_MSG_DISCONNECT: // 1
|
||||
/*
|
||||
* States required:
|
||||
* - None
|
||||
*
|
||||
* Transitions:
|
||||
* - session->socket->state = SSH_SOCKET_CLOSED
|
||||
* - session->session_state = SSH_SESSION_STATE_ERROR
|
||||
* */
|
||||
|
||||
/* Always allowed */
|
||||
rc = SSH_PACKET_ALLOWED;
|
||||
break;
|
||||
case SSH2_MSG_IGNORE: // 2
|
||||
/*
|
||||
* States required:
|
||||
* - None
|
||||
*
|
||||
* Transitions:
|
||||
* - None
|
||||
* */
|
||||
|
||||
/* Always allowed */
|
||||
rc = SSH_PACKET_ALLOWED;
|
||||
break;
|
||||
case SSH2_MSG_UNIMPLEMENTED: // 3
|
||||
/*
|
||||
* States required:
|
||||
* - None
|
||||
*
|
||||
* Transitions:
|
||||
* - None
|
||||
* */
|
||||
|
||||
/* Always allowed */
|
||||
rc = SSH_PACKET_ALLOWED;
|
||||
break;
|
||||
case SSH2_MSG_DEBUG: // 4
|
||||
/*
|
||||
* States required:
|
||||
* - None
|
||||
*
|
||||
* Transitions:
|
||||
* - None
|
||||
* */
|
||||
|
||||
/* Always allowed */
|
||||
rc = SSH_PACKET_ALLOWED;
|
||||
break;
|
||||
case SSH2_MSG_SERVICE_REQUEST: // 5
|
||||
/* Server only */
|
||||
|
||||
/*
|
||||
* States required:
|
||||
* - session->session_state == SSH_SESSION_STATE_AUTHENTICATING
|
||||
* or session->session_state == SSH_SESSION_STATE_AUTHENTICATED
|
||||
* - session->dh_handshake_state == DH_STATE_FINISHED
|
||||
*
|
||||
* Transitions:
|
||||
* - None
|
||||
* */
|
||||
|
||||
/* If this is a client, reject the message */
|
||||
if (session->client) {
|
||||
rc = SSH_PACKET_DENIED;
|
||||
break;
|
||||
}
|
||||
|
||||
if ((session->session_state != SSH_SESSION_STATE_AUTHENTICATING) &&
|
||||
(session->session_state != SSH_SESSION_STATE_AUTHENTICATED))
|
||||
{
|
||||
rc = SSH_PACKET_DENIED;
|
||||
break;
|
||||
}
|
||||
|
||||
if (session->dh_handshake_state != DH_STATE_FINISHED) {
|
||||
rc = SSH_PACKET_DENIED;
|
||||
break;
|
||||
}
|
||||
|
||||
rc = SSH_PACKET_ALLOWED;
|
||||
break;
|
||||
case SSH2_MSG_SERVICE_ACCEPT: // 6
|
||||
/*
|
||||
* States required:
|
||||
* - session->session_state == SSH_SESSION_STATE_AUTHENTICATING
|
||||
* or session->session_state == SSH_SESSION_STATE_AUTHENTICATED
|
||||
* - session->dh_handshake_state == DH_STATE_FINISHED
|
||||
* - session->auth.service_state == SSH_AUTH_SERVICE_SENT
|
||||
*
|
||||
* Transitions:
|
||||
* - auth.service_state = SSH_AUTH_SERVICE_ACCEPTED
|
||||
* */
|
||||
|
||||
if ((session->session_state != SSH_SESSION_STATE_AUTHENTICATING) &&
|
||||
(session->session_state != SSH_SESSION_STATE_AUTHENTICATED))
|
||||
{
|
||||
rc = SSH_PACKET_DENIED;
|
||||
break;
|
||||
}
|
||||
|
||||
if (session->dh_handshake_state != DH_STATE_FINISHED) {
|
||||
rc = SSH_PACKET_DENIED;
|
||||
break;
|
||||
}
|
||||
|
||||
/* TODO check if only auth service can be requested */
|
||||
if (session->auth.service_state != SSH_AUTH_SERVICE_SENT) {
|
||||
rc = SSH_PACKET_DENIED;
|
||||
break;
|
||||
}
|
||||
|
||||
rc = SSH_PACKET_ALLOWED;
|
||||
break;
|
||||
case SSH2_MSG_EXT_INFO: // 7
|
||||
/*
|
||||
* States required:
|
||||
* - session_state == SSH_SESSION_STATE_AUTHENTICATING
|
||||
* - dh_handshake_state == DH_STATE_FINISHED
|
||||
*
|
||||
* Transitions:
|
||||
* - None
|
||||
* */
|
||||
|
||||
if (session->session_state != SSH_SESSION_STATE_AUTHENTICATING) {
|
||||
rc = SSH_PACKET_DENIED;
|
||||
break;
|
||||
}
|
||||
|
||||
if (session->dh_handshake_state != DH_STATE_FINISHED) {
|
||||
rc = SSH_PACKET_DENIED;
|
||||
break;
|
||||
}
|
||||
|
||||
rc = SSH_PACKET_ALLOWED;
|
||||
break;
|
||||
case SSH2_MSG_KEXINIT: // 20
|
||||
/*
|
||||
* States required:
|
||||
* - session_state == SSH_SESSION_STATE_AUTHENTICATED
|
||||
* or session_state == SSH_SESSION_STATE_INITIAL_KEX
|
||||
* - dh_handshake_state == DH_STATE_INIT
|
||||
* or dh_handshake_state == DH_STATE_FINISHED (re-exchange)
|
||||
*
|
||||
* Transitions:
|
||||
* - session->dh_handshake_state = DH_STATE_INIT
|
||||
* - session->session_state = SSH_SESSION_STATE_KEXINIT_RECEIVED
|
||||
*
|
||||
* On server:
|
||||
* - session->session_state = SSH_SESSION_STATE_DH
|
||||
* */
|
||||
|
||||
if ((session->session_state != SSH_SESSION_STATE_AUTHENTICATED) &&
|
||||
(session->session_state != SSH_SESSION_STATE_INITIAL_KEX))
|
||||
{
|
||||
rc = SSH_PACKET_DENIED;
|
||||
break;
|
||||
}
|
||||
|
||||
if ((session->dh_handshake_state != DH_STATE_INIT) &&
|
||||
(session->dh_handshake_state != DH_STATE_FINISHED))
|
||||
{
|
||||
rc = SSH_PACKET_DENIED;
|
||||
}
|
||||
|
||||
rc = SSH_PACKET_ALLOWED;
|
||||
break;
|
||||
case SSH2_MSG_NEWKEYS: // 21
|
||||
/*
|
||||
* States required:
|
||||
* - session_state == SSH_SESSION_STATE_DH
|
||||
* - dh_handshake_state == DH_STATE_NEWKEYS_SENT
|
||||
*
|
||||
* Transitions:
|
||||
* - session->dh_handshake_state = DH_STATE_FINISHED
|
||||
* - session->session_state = SSH_SESSION_STATE_AUTHENTICATING
|
||||
* if session->flags & SSH_SESSION_FLAG_AUTHENTICATED
|
||||
* - session->session_state = SSH_SESSION_STATE_AUTHENTICATED
|
||||
* */
|
||||
|
||||
/* If DH has not been started, reject message */
|
||||
if (session->session_state != SSH_SESSION_STATE_DH) {
|
||||
rc = SSH_PACKET_DENIED;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Only allowed if dh_handshake_state is in NEWKEYS_SENT state */
|
||||
if (session->dh_handshake_state != DH_STATE_NEWKEYS_SENT) {
|
||||
rc = SSH_PACKET_DENIED;
|
||||
break;
|
||||
}
|
||||
|
||||
rc = SSH_PACKET_ALLOWED;
|
||||
break;
|
||||
case SSH2_MSG_KEXDH_INIT: // 30
|
||||
// SSH2_MSG_KEX_ECDH_INIT: // 30
|
||||
// SSH2_MSG_ECMQV_INIT: // 30
|
||||
// SSH2_MSG_KEX_DH_GEX_REQUEST_OLD: // 30
|
||||
|
||||
/* Server only */
|
||||
|
||||
/*
|
||||
* States required:
|
||||
* - session_state == SSH_SESSION_STATE_DH
|
||||
* - dh_handshake_state == DH_STATE_INIT
|
||||
*
|
||||
* Transitions:
|
||||
* - session->dh_handshake_state = DH_STATE_INIT_SENT
|
||||
* then calls dh_handshake_server which triggers:
|
||||
* - session->dh_handhsake_state = DH_STATE_NEWKEYS_SENT
|
||||
* */
|
||||
|
||||
if (session->session_state != SSH_SESSION_STATE_DH) {
|
||||
rc = SSH_PACKET_DENIED;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Only allowed if dh_handshake_state is in initial state */
|
||||
if (session->dh_handshake_state != DH_STATE_INIT) {
|
||||
rc = SSH_PACKET_DENIED;
|
||||
break;
|
||||
}
|
||||
|
||||
rc = SSH_PACKET_ALLOWED;
|
||||
break;
|
||||
case SSH2_MSG_KEXDH_REPLY: // 31
|
||||
// SSH2_MSG_KEX_ECDH_REPLY: // 31
|
||||
// SSH2_MSG_ECMQV_REPLY: // 31
|
||||
// SSH2_MSG_KEX_DH_GEX_GROUP: // 31
|
||||
|
||||
/*
|
||||
* States required:
|
||||
* - session_state == SSH_SESSION_STATE_DH
|
||||
* - dh_handshake_state == DH_STATE_INIT_SENT
|
||||
*
|
||||
* Transitions:
|
||||
* - session->dh_handhsake_state = DH_STATE_NEWKEYS_SENT
|
||||
* */
|
||||
|
||||
if (session->session_state != SSH_SESSION_STATE_DH) {
|
||||
rc = SSH_PACKET_DENIED;
|
||||
break;
|
||||
}
|
||||
|
||||
if (session->dh_handshake_state != DH_STATE_INIT_SENT) {
|
||||
rc = SSH_PACKET_DENIED;
|
||||
break;
|
||||
}
|
||||
|
||||
rc = SSH_PACKET_ALLOWED;
|
||||
break;
|
||||
case SSH2_MSG_KEX_DH_GEX_INIT: // 32
|
||||
/* TODO Not filtered */
|
||||
rc = SSH_PACKET_ALLOWED;
|
||||
break;
|
||||
case SSH2_MSG_KEX_DH_GEX_REPLY: // 33
|
||||
/* TODO Not filtered */
|
||||
rc = SSH_PACKET_ALLOWED;
|
||||
break;
|
||||
case SSH2_MSG_KEX_DH_GEX_REQUEST: // 34
|
||||
/* TODO Not filtered */
|
||||
rc = SSH_PACKET_ALLOWED;
|
||||
break;
|
||||
case SSH2_MSG_USERAUTH_REQUEST: // 50
|
||||
/* Server only */
|
||||
|
||||
/*
|
||||
* States required:
|
||||
* - session_state == SSH_SESSION_STATE_AUTHENTICATING
|
||||
* - dh_hanshake_state == DH_STATE_FINISHED
|
||||
*
|
||||
* Transitions:
|
||||
* - if authentication was successful:
|
||||
* - session_state = SSH_SESSION_STATE_AUTHENTICATED
|
||||
* */
|
||||
|
||||
/* If this is a client, reject the message */
|
||||
if (session->client) {
|
||||
rc = SSH_PACKET_DENIED;
|
||||
break;
|
||||
}
|
||||
|
||||
if (session->dh_handshake_state != DH_STATE_FINISHED) {
|
||||
rc = SSH_PACKET_DENIED;
|
||||
break;
|
||||
}
|
||||
|
||||
if (session->session_state != SSH_SESSION_STATE_AUTHENTICATING) {
|
||||
rc = SSH_PACKET_DENIED;
|
||||
break;
|
||||
}
|
||||
|
||||
rc = SSH_PACKET_ALLOWED;
|
||||
break;
|
||||
case SSH2_MSG_USERAUTH_FAILURE: // 51
|
||||
/*
|
||||
* States required:
|
||||
* - session_state == SSH_SESSION_STATE_AUTHENTICATING
|
||||
* - dh_hanshake_state == DH_STATE_FINISHED
|
||||
* - session->auth.state == SSH_AUTH_STATE_KBDINT_SENT
|
||||
* or session->auth.state == SSH_AUTH_STATE_PUBKEY_OFFER_SENT
|
||||
* or session->auth.state == SSH_AUTH_STATE_PUBKEY_AUTH_SENT
|
||||
* or session->auth.state == SSH_AUTH_STATE_PASSWORD_AUTH_SENT
|
||||
* or session->auth.state == SSH_AUTH_STATE_GSSAPI_MIC_SENT
|
||||
*
|
||||
* Transitions:
|
||||
* - if unpacking failed:
|
||||
* - session->auth.state = SSH_AUTH_ERROR
|
||||
* - if failure was partial:
|
||||
* - session->auth.state = SSH_AUTH_PARTIAL
|
||||
* - else:
|
||||
* - session->auth.state = SSH_AUTH_STATE_FAILED
|
||||
* */
|
||||
|
||||
/* If this is a server, reject the message */
|
||||
if (session->server) {
|
||||
rc = SSH_PACKET_DENIED;
|
||||
break;
|
||||
}
|
||||
|
||||
if (session->dh_handshake_state != DH_STATE_FINISHED) {
|
||||
rc = SSH_PACKET_DENIED;
|
||||
break;
|
||||
}
|
||||
|
||||
if (session->session_state != SSH_SESSION_STATE_AUTHENTICATING) {
|
||||
rc = SSH_PACKET_DENIED;
|
||||
break;
|
||||
}
|
||||
|
||||
rc = SSH_PACKET_ALLOWED;
|
||||
break;
|
||||
case SSH2_MSG_USERAUTH_SUCCESS: // 52
|
||||
/*
|
||||
* States required:
|
||||
* - session_state == SSH_SESSION_STATE_AUTHENTICATING
|
||||
* - dh_hanshake_state == DH_STATE_FINISHED
|
||||
* - session->auth.state == SSH_AUTH_STATE_KBDINT_SENT
|
||||
* or session->auth.state == SSH_AUTH_STATE_PUBKEY_AUTH_SENT
|
||||
* or session->auth.state == SSH_AUTH_STATE_PASSWORD_AUTH_SENT
|
||||
* or session->auth.state == SSH_AUTH_STATE_GSSAPI_MIC_SENT
|
||||
* or session->auth.state == SSH_AUTH_STATE_AUTH_NONE_SENT
|
||||
*
|
||||
* Transitions:
|
||||
* - session->auth.state = SSH_AUTH_STATE_SUCCESS
|
||||
* - session->session_state = SSH_SESSION_STATE_AUTHENTICATED
|
||||
* - session->flags |= SSH_SESSION_FLAG_AUTHENTICATED
|
||||
* - sessions->auth.current_method = SSH_AUTH_METHOD_UNKNOWN
|
||||
* */
|
||||
|
||||
/* If this is a server, reject the message */
|
||||
if (session->server) {
|
||||
rc = SSH_PACKET_DENIED;
|
||||
break;
|
||||
}
|
||||
|
||||
if (session->dh_handshake_state != DH_STATE_FINISHED) {
|
||||
rc = SSH_PACKET_DENIED;
|
||||
break;
|
||||
}
|
||||
|
||||
if (session->session_state != SSH_SESSION_STATE_AUTHENTICATING) {
|
||||
rc = SSH_PACKET_DENIED;
|
||||
break;
|
||||
}
|
||||
|
||||
if ((session->auth.state != SSH_AUTH_STATE_KBDINT_SENT) &&
|
||||
(session->auth.state != SSH_AUTH_STATE_PUBKEY_AUTH_SENT) &&
|
||||
(session->auth.state != SSH_AUTH_STATE_PASSWORD_AUTH_SENT) &&
|
||||
(session->auth.state != SSH_AUTH_STATE_GSSAPI_MIC_SENT) &&
|
||||
(session->auth.state != SSH_AUTH_STATE_AUTH_NONE_SENT))
|
||||
{
|
||||
rc = SSH_PACKET_DENIED;
|
||||
break;
|
||||
}
|
||||
|
||||
rc = SSH_PACKET_ALLOWED;
|
||||
break;
|
||||
case SSH2_MSG_USERAUTH_BANNER: // 53
|
||||
/*
|
||||
* States required:
|
||||
* - session_state == SSH_SESSION_STATE_AUTHENTICATING
|
||||
*
|
||||
* Transitions:
|
||||
* - None
|
||||
* */
|
||||
|
||||
if (session->session_state != SSH_SESSION_STATE_AUTHENTICATING) {
|
||||
rc = SSH_PACKET_DENIED;
|
||||
break;
|
||||
}
|
||||
|
||||
rc = SSH_PACKET_ALLOWED;
|
||||
break;
|
||||
case SSH2_MSG_USERAUTH_PK_OK: // 60
|
||||
// SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ: // 60
|
||||
// SSH2_MSG_USERAUTH_INFO_REQUEST: // 60
|
||||
// SSH2_MSG_USERAUTH_GSSAPI_RESPONSE: // 60
|
||||
|
||||
/*
|
||||
* States required:
|
||||
* - session_state == SSH_SESSION_STATE_AUTHENTICATING
|
||||
* - session->auth.state == SSH_AUTH_STATE_KBDINT_SENT
|
||||
* or
|
||||
* session->auth.state == SSH_AUTH_STATE_GSSAPI_REQUEST_SENT
|
||||
* or
|
||||
* session->auth.state == SSH_AUTH_STATE_PUBKEY_OFFER_SENT
|
||||
*
|
||||
* Transitions:
|
||||
* Depending on the current state, the message is treated
|
||||
* differently:
|
||||
* - session->auth.state == SSH_AUTH_STATE_KBDINT_SENT
|
||||
* - session->auth.state = SSH_AUTH_STATE_INFO
|
||||
* - session->auth.state == SSH_AUTH_STATE_GSSAPI_REQUEST_SENT
|
||||
* - session->auth.state = SSH_AUTH_STATE_GSSAPI_TOKEN
|
||||
* - session->auth.state == SSH_AUTH_STATE_PUBKEY_OFFER_SENT
|
||||
* - session->auth.state = SSH_AUTH_STATE_PK_OK
|
||||
* */
|
||||
|
||||
if (session->session_state != SSH_SESSION_STATE_AUTHENTICATING) {
|
||||
rc = SSH_PACKET_DENIED;
|
||||
break;
|
||||
}
|
||||
|
||||
if ((session->auth.state != SSH_AUTH_STATE_KBDINT_SENT) &&
|
||||
(session->auth.state != SSH_AUTH_STATE_PUBKEY_OFFER_SENT) &&
|
||||
(session->auth.state != SSH_AUTH_STATE_GSSAPI_REQUEST_SENT))
|
||||
{
|
||||
rc = SSH_PACKET_DENIED;
|
||||
break;
|
||||
}
|
||||
|
||||
rc = SSH_PACKET_ALLOWED;
|
||||
break;
|
||||
case SSH2_MSG_USERAUTH_INFO_RESPONSE: // 61
|
||||
// SSH2_MSG_USERAUTH_GSSAPI_TOKEN: // 61
|
||||
|
||||
/*
|
||||
* States required:
|
||||
* - session_state == SSH_SESSION_STATE_AUTHENTICATING
|
||||
* - session_state->auth.state == SSH_SESSION_STATE_GSSAPI_TOKEN
|
||||
* or
|
||||
* session_state->auth.state == SSH_SESSION_STATE_INFO
|
||||
*
|
||||
* Transitions:
|
||||
* - None
|
||||
* */
|
||||
|
||||
if (session->session_state != SSH_SESSION_STATE_AUTHENTICATING) {
|
||||
rc = SSH_PACKET_DENIED;
|
||||
break;
|
||||
}
|
||||
|
||||
if ((session->auth.state != SSH_AUTH_STATE_INFO) &&
|
||||
(session->auth.state != SSH_AUTH_STATE_GSSAPI_TOKEN))
|
||||
{
|
||||
rc = SSH_PACKET_DENIED;
|
||||
break;
|
||||
}
|
||||
|
||||
rc = SSH_PACKET_ALLOWED;
|
||||
break;
|
||||
case SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE: // 63
|
||||
/* TODO Not filtered */
|
||||
rc = SSH_PACKET_ALLOWED;
|
||||
break;
|
||||
case SSH2_MSG_USERAUTH_GSSAPI_ERROR: // 64
|
||||
/* TODO Not filtered */
|
||||
rc = SSH_PACKET_ALLOWED;
|
||||
break;
|
||||
case SSH2_MSG_USERAUTH_GSSAPI_ERRTOK: // 65
|
||||
/* TODO Not filtered */
|
||||
rc = SSH_PACKET_ALLOWED;
|
||||
break;
|
||||
case SSH2_MSG_USERAUTH_GSSAPI_MIC: // 66
|
||||
/* Server only */
|
||||
|
||||
/*
|
||||
* States required:
|
||||
* - session_state == SSH_SESSION_STATE_AUTHENTICATING
|
||||
* - session->gssapi->state == SSH_GSSAPI_STATE_RCV_MIC
|
||||
*
|
||||
* Transitions:
|
||||
* Depending on the result of the verification, the states are
|
||||
* changed:
|
||||
* - SSH_AUTH_SUCCESS:
|
||||
* - session->session_state = SSH_SESSION_STATE_AUTHENTICATED
|
||||
* - session->flags != SSH_SESSION_FLAG_AUTHENTICATED
|
||||
* - SSH_AUTH_PARTIAL:
|
||||
* - None
|
||||
* - any other case:
|
||||
* - None
|
||||
* */
|
||||
|
||||
/* If this is a client, reject the message */
|
||||
if (session->client) {
|
||||
rc = SSH_PACKET_DENIED;
|
||||
break;
|
||||
}
|
||||
|
||||
if (session->dh_handshake_state != DH_STATE_FINISHED) {
|
||||
rc = SSH_PACKET_DENIED;
|
||||
break;
|
||||
}
|
||||
|
||||
if (session->session_state != SSH_SESSION_STATE_AUTHENTICATING) {
|
||||
rc = SSH_PACKET_DENIED;
|
||||
break;
|
||||
}
|
||||
|
||||
rc = SSH_PACKET_ALLOWED;
|
||||
break;
|
||||
case SSH2_MSG_GLOBAL_REQUEST: // 80
|
||||
/*
|
||||
* States required:
|
||||
* - session_state == SSH_SESSION_STATE_AUTHENTICATED
|
||||
*
|
||||
* Transitions:
|
||||
* - None
|
||||
* */
|
||||
|
||||
if (session->session_state != SSH_SESSION_STATE_AUTHENTICATED) {
|
||||
rc = SSH_PACKET_DENIED;
|
||||
break;
|
||||
}
|
||||
|
||||
rc = SSH_PACKET_ALLOWED;
|
||||
break;
|
||||
case SSH2_MSG_REQUEST_SUCCESS: // 81
|
||||
/*
|
||||
* States required:
|
||||
* - session_state == SSH_SESSION_STATE_AUTHENTICATED
|
||||
* - session->global_req_state == SSH_CHANNEL_REQ_STATE_PENDING
|
||||
*
|
||||
* Transitions:
|
||||
* - session->global_req_state == SSH_CHANNEL_REQ_STATE_ACCEPTED
|
||||
* */
|
||||
|
||||
if (session->session_state != SSH_SESSION_STATE_AUTHENTICATED) {
|
||||
rc = SSH_PACKET_DENIED;
|
||||
break;
|
||||
}
|
||||
|
||||
if (session->global_req_state != SSH_CHANNEL_REQ_STATE_PENDING) {
|
||||
rc = SSH_PACKET_DENIED;
|
||||
break;
|
||||
}
|
||||
|
||||
rc = SSH_PACKET_ALLOWED;
|
||||
break;
|
||||
case SSH2_MSG_REQUEST_FAILURE: // 82
|
||||
/*
|
||||
* States required:
|
||||
* - session_state == SSH_SESSION_STATE_AUTHENTICATED
|
||||
* - session->global_req_state == SSH_CHANNEL_REQ_STATE_PENDING
|
||||
*
|
||||
* Transitions:
|
||||
* - session->global_req_state == SSH_CHANNEL_REQ_STATE_DENIED
|
||||
* */
|
||||
|
||||
if (session->session_state != SSH_SESSION_STATE_AUTHENTICATED) {
|
||||
rc = SSH_PACKET_DENIED;
|
||||
break;
|
||||
}
|
||||
|
||||
if (session->global_req_state != SSH_CHANNEL_REQ_STATE_PENDING) {
|
||||
rc = SSH_PACKET_DENIED;
|
||||
break;
|
||||
}
|
||||
|
||||
rc = SSH_PACKET_ALLOWED;
|
||||
break;
|
||||
case SSH2_MSG_CHANNEL_OPEN: // 90
|
||||
/*
|
||||
* States required:
|
||||
* - session_state == SSH_SESSION_STATE_AUTHENTICATED
|
||||
*
|
||||
* Transitions:
|
||||
* - None
|
||||
* */
|
||||
|
||||
if (session->session_state != SSH_SESSION_STATE_AUTHENTICATED) {
|
||||
rc = SSH_PACKET_DENIED;
|
||||
break;
|
||||
}
|
||||
|
||||
rc = SSH_PACKET_ALLOWED;
|
||||
break;
|
||||
case SSH2_MSG_CHANNEL_OPEN_CONFIRMATION: // 91
|
||||
/*
|
||||
* States required:
|
||||
* - session_state == SSH_SESSION_STATE_AUTHENTICATED
|
||||
*
|
||||
* Transitions:
|
||||
* - channel->state = SSH_CHANNEL_STATE_OPEN
|
||||
* - channel->flags &= ~SSH_CHANNEL_FLAG_NOT_BOUND
|
||||
* */
|
||||
|
||||
if (session->session_state != SSH_SESSION_STATE_AUTHENTICATED) {
|
||||
rc = SSH_PACKET_DENIED;
|
||||
break;
|
||||
}
|
||||
|
||||
rc = SSH_PACKET_ALLOWED;
|
||||
break;
|
||||
case SSH2_MSG_CHANNEL_OPEN_FAILURE: // 92
|
||||
/*
|
||||
* States required:
|
||||
* - session_state == SSH_SESSION_STATE_AUTHENTICATED
|
||||
*
|
||||
* Transitions:
|
||||
* - channel->state = SSH_CHANNEL_STATE_OPEN_DENIED
|
||||
* */
|
||||
|
||||
if (session->session_state != SSH_SESSION_STATE_AUTHENTICATED) {
|
||||
rc = SSH_PACKET_DENIED;
|
||||
break;
|
||||
}
|
||||
|
||||
rc = SSH_PACKET_ALLOWED;
|
||||
break;
|
||||
case SSH2_MSG_CHANNEL_WINDOW_ADJUST: // 93
|
||||
/*
|
||||
* States required:
|
||||
* - session_state == SSH_SESSION_STATE_AUTHENTICATED
|
||||
*
|
||||
* Transitions:
|
||||
* - None
|
||||
* */
|
||||
|
||||
if (session->session_state != SSH_SESSION_STATE_AUTHENTICATED) {
|
||||
rc = SSH_PACKET_DENIED;
|
||||
break;
|
||||
}
|
||||
|
||||
rc = SSH_PACKET_ALLOWED;
|
||||
break;
|
||||
case SSH2_MSG_CHANNEL_DATA: // 94
|
||||
/*
|
||||
* States required:
|
||||
* - session_state == SSH_SESSION_STATE_AUTHENTICATED
|
||||
*
|
||||
* Transitions:
|
||||
* - None
|
||||
* */
|
||||
|
||||
if (session->session_state != SSH_SESSION_STATE_AUTHENTICATED) {
|
||||
rc = SSH_PACKET_DENIED;
|
||||
break;
|
||||
}
|
||||
|
||||
rc = SSH_PACKET_ALLOWED;
|
||||
break;
|
||||
case SSH2_MSG_CHANNEL_EXTENDED_DATA: // 95
|
||||
/*
|
||||
* States required:
|
||||
* - session_state == SSH_SESSION_STATE_AUTHENTICATED
|
||||
*
|
||||
* Transitions:
|
||||
* - None
|
||||
* */
|
||||
|
||||
if (session->session_state != SSH_SESSION_STATE_AUTHENTICATED) {
|
||||
rc = SSH_PACKET_DENIED;
|
||||
break;
|
||||
}
|
||||
|
||||
rc = SSH_PACKET_ALLOWED;
|
||||
break;
|
||||
case SSH2_MSG_CHANNEL_EOF: // 96
|
||||
/*
|
||||
* States required:
|
||||
* - session_state == SSH_SESSION_STATE_AUTHENTICATED
|
||||
*
|
||||
* Transitions:
|
||||
* - None
|
||||
* */
|
||||
|
||||
if (session->session_state != SSH_SESSION_STATE_AUTHENTICATED) {
|
||||
rc = SSH_PACKET_DENIED;
|
||||
break;
|
||||
}
|
||||
|
||||
rc = SSH_PACKET_ALLOWED;
|
||||
break;
|
||||
case SSH2_MSG_CHANNEL_CLOSE: // 97
|
||||
/*
|
||||
* States required:
|
||||
* - session_state == SSH_SESSION_STATE_AUTHENTICATED
|
||||
*
|
||||
* Transitions:
|
||||
* - channel->state = SSH_CHANNEL_STATE_CLOSED
|
||||
* - channel->flags |= SSH_CHANNEL_FLAG_CLOSED_REMOTE
|
||||
* */
|
||||
|
||||
if (session->session_state != SSH_SESSION_STATE_AUTHENTICATED) {
|
||||
rc = SSH_PACKET_DENIED;
|
||||
break;
|
||||
}
|
||||
|
||||
rc = SSH_PACKET_ALLOWED;
|
||||
break;
|
||||
case SSH2_MSG_CHANNEL_REQUEST: // 98
|
||||
/*
|
||||
* States required:
|
||||
* - session_state == SSH_SESSION_STATE_AUTHENTICATED
|
||||
*
|
||||
* Transitions:
|
||||
* - Depends on the request
|
||||
* */
|
||||
|
||||
if (session->session_state != SSH_SESSION_STATE_AUTHENTICATED) {
|
||||
rc = SSH_PACKET_DENIED;
|
||||
break;
|
||||
}
|
||||
|
||||
rc = SSH_PACKET_ALLOWED;
|
||||
break;
|
||||
case SSH2_MSG_CHANNEL_SUCCESS: // 99
|
||||
/*
|
||||
* States required:
|
||||
* - session_state == SSH_SESSION_STATE_AUTHENTICATED
|
||||
* - channel->request_state == SSH_CHANNEL_REQ_STATE_PENDING
|
||||
*
|
||||
* Transitions:
|
||||
* - channel->request_state = SSH_CHANNEL_REQ_STATE_ACCEPTED
|
||||
* */
|
||||
|
||||
if (session->session_state != SSH_SESSION_STATE_AUTHENTICATED) {
|
||||
rc = SSH_PACKET_DENIED;
|
||||
break;
|
||||
}
|
||||
|
||||
rc = SSH_PACKET_ALLOWED;
|
||||
break;
|
||||
case SSH2_MSG_CHANNEL_FAILURE: // 100
|
||||
/*
|
||||
* States required:
|
||||
* - session_state == SSH_SESSION_STATE_AUTHENTICATED
|
||||
* - channel->request_state == SSH_CHANNEL_REQ_STATE_PENDING
|
||||
*
|
||||
* Transitions:
|
||||
* - channel->request_state = SSH_CHANNEL_REQ_STATE_DENIED
|
||||
* */
|
||||
|
||||
if (session->session_state != SSH_SESSION_STATE_AUTHENTICATED) {
|
||||
rc = SSH_PACKET_DENIED;
|
||||
break;
|
||||
}
|
||||
|
||||
rc = SSH_PACKET_ALLOWED;
|
||||
break;
|
||||
default:
|
||||
/* Unknown message, do not filter */
|
||||
rc = SSH_PACKET_UNKNOWN;
|
||||
goto end;
|
||||
}
|
||||
|
||||
end:
|
||||
#ifdef DEBUG_PACKET
|
||||
if (rc == SSH_PACKET_DENIED) {
|
||||
SSH_LOG(SSH_LOG_PACKET, "REJECTED packet type %d: ",
|
||||
session->in_packet.type);
|
||||
}
|
||||
|
||||
if (rc == SSH_PACKET_UNKNOWN) {
|
||||
SSH_LOG(SSH_LOG_PACKET, "UNKNOWN packet type %d",
|
||||
session->in_packet.type);
|
||||
}
|
||||
#endif
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* in nonblocking mode, socket_read will read as much as it can, and return */
|
||||
/* SSH_OK if it has read at least len bytes, otherwise, SSH_AGAIN. */
|
||||
/* in blocking mode, it will read at least len bytes and will block until it's ok. */
|
||||
@@ -157,6 +949,7 @@ int ssh_packet_socket_callback(const void *data, size_t receivedlen, void *user)
|
||||
uint32_t packet_len, compsize, payloadsize;
|
||||
uint8_t padding;
|
||||
size_t processed = 0; /* number of byte processed from the callback */
|
||||
enum ssh_packet_filter_result_e filter_result;
|
||||
|
||||
if(session->current_crypto != NULL) {
|
||||
current_macsize = hmac_digest_len(session->current_crypto->in_hmac);
|
||||
@@ -198,7 +991,9 @@ int ssh_packet_socket_callback(const void *data, size_t receivedlen, void *user)
|
||||
return 0;
|
||||
}
|
||||
|
||||
memset(&session->in_packet, 0, sizeof(PACKET));
|
||||
session->in_packet = (struct packet_struct) {
|
||||
.type = 0,
|
||||
};
|
||||
|
||||
if (session->in_buffer) {
|
||||
rc = ssh_buffer_reinit(session->in_buffer);
|
||||
@@ -342,8 +1137,21 @@ int ssh_packet_socket_callback(const void *data, size_t receivedlen, void *user)
|
||||
"packet: read type %hhd [len=%d,padding=%hhd,comp=%d,payload=%d]",
|
||||
session->in_packet.type, packet_len, padding, compsize, payloadsize);
|
||||
|
||||
/* Execute callbacks */
|
||||
ssh_packet_process(session, session->in_packet.type);
|
||||
/* Check if the packet is expected */
|
||||
filter_result = ssh_packet_incoming_filter(session);
|
||||
|
||||
switch(filter_result) {
|
||||
case SSH_PACKET_ALLOWED:
|
||||
/* Execute callbacks */
|
||||
ssh_packet_process(session, session->in_packet.type);
|
||||
break;
|
||||
case SSH_PACKET_DENIED:
|
||||
goto error;
|
||||
case SSH_PACKET_UNKNOWN:
|
||||
ssh_packet_send_unimplemented(session, session->recv_seq - 1);
|
||||
break;
|
||||
}
|
||||
|
||||
session->packet_state = PACKET_STATE_INIT;
|
||||
if (processed < receivedlen) {
|
||||
/* Handle a potential packet left in socket buffer */
|
||||
@@ -514,20 +1322,24 @@ SSH_PACKET_CALLBACK(ssh_packet_unimplemented){
|
||||
/** @internal
|
||||
* @parse the "Type" header field of a packet and updates the session
|
||||
*/
|
||||
int ssh_packet_parse_type(ssh_session session) {
|
||||
memset(&session->in_packet, 0, sizeof(PACKET));
|
||||
if(session->in_buffer == NULL) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
int ssh_packet_parse_type(struct ssh_session_struct *session)
|
||||
{
|
||||
session->in_packet = (struct packet_struct) {
|
||||
.type = 0,
|
||||
};
|
||||
|
||||
if(ssh_buffer_get_u8(session->in_buffer, &session->in_packet.type) == 0) {
|
||||
ssh_set_error(session, SSH_FATAL, "Packet too short to read type");
|
||||
return SSH_ERROR;
|
||||
}
|
||||
if (session->in_buffer == NULL) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
session->in_packet.valid = 1;
|
||||
if (ssh_buffer_get_u8(session->in_buffer, &session->in_packet.type) == 0) {
|
||||
ssh_set_error(session, SSH_FATAL, "Packet too short to read type");
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
return SSH_OK;
|
||||
session->in_packet.valid = 1;
|
||||
|
||||
return SSH_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -106,6 +106,8 @@ SSH_PACKET_CALLBACK(ssh_packet_dh_reply){
|
||||
switch(session->next_crypto->kex_type){
|
||||
case SSH_KEX_DH_GROUP1_SHA1:
|
||||
case SSH_KEX_DH_GROUP14_SHA1:
|
||||
case SSH_KEX_DH_GROUP16_SHA512:
|
||||
case SSH_KEX_DH_GROUP18_SHA512:
|
||||
rc=ssh_client_dh_reply(session, packet);
|
||||
break;
|
||||
#ifdef HAVE_ECDH
|
||||
@@ -264,9 +266,67 @@ SSH_PACKET_CALLBACK(ssh_packet_service_accept){
|
||||
(void)type;
|
||||
(void)user;
|
||||
|
||||
session->auth_service_state=SSH_AUTH_SERVICE_ACCEPTED;
|
||||
session->auth.service_state = SSH_AUTH_SERVICE_ACCEPTED;
|
||||
SSH_LOG(SSH_LOG_PACKET,
|
||||
"Received SSH_MSG_SERVICE_ACCEPT");
|
||||
|
||||
return SSH_PACKET_USED;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* @brief handles a SSH2_MSG_EXT_INFO packet defined in RFC 8308
|
||||
*
|
||||
*/
|
||||
SSH_PACKET_CALLBACK(ssh_packet_ext_info)
|
||||
{
|
||||
int rc;
|
||||
uint32_t nr_extensions = 0;
|
||||
uint32_t i;
|
||||
(void)type;
|
||||
(void)user;
|
||||
|
||||
SSH_LOG(SSH_LOG_PACKET, "Received SSH_MSG_EXT_INFO");
|
||||
|
||||
rc = ssh_buffer_get_u32(packet, &nr_extensions);
|
||||
if (rc == 0) {
|
||||
SSH_LOG(SSH_LOG_PACKET, "Failed to read number of extensions");
|
||||
return SSH_PACKET_USED;
|
||||
}
|
||||
|
||||
nr_extensions = ntohl(nr_extensions);
|
||||
if (nr_extensions > 128) {
|
||||
SSH_LOG(SSH_LOG_PACKET, "Invalid number of extensions");
|
||||
return SSH_PACKET_USED;
|
||||
}
|
||||
|
||||
SSH_LOG(SSH_LOG_PACKET, "Follows %u extensions", nr_extensions);
|
||||
|
||||
for (i = 0; i < nr_extensions; i++) {
|
||||
char *name = NULL;
|
||||
char *value = NULL;
|
||||
int cmp;
|
||||
|
||||
rc = ssh_buffer_unpack(packet, "ss", &name, &value);
|
||||
if (rc != SSH_OK) {
|
||||
SSH_LOG(SSH_LOG_PACKET, "Error reading extension name-value pair");
|
||||
return SSH_PACKET_USED;
|
||||
}
|
||||
|
||||
cmp = strcmp(name, "server-sig-algs");
|
||||
if (cmp == 0) {
|
||||
/* TODO check for NULL bytes */
|
||||
SSH_LOG(SSH_LOG_PACKET, "Extension: %s=<%s>", name, value);
|
||||
if (ssh_match_group(value, "rsa-sha2-512")) {
|
||||
session->extensions |= SSH_EXT_SIG_RSA_SHA512;
|
||||
}
|
||||
if (ssh_match_group(value, "rsa-sha2-256")) {
|
||||
session->extensions |= SSH_EXT_SIG_RSA_SHA256;
|
||||
}
|
||||
}
|
||||
free(name);
|
||||
free(value);
|
||||
}
|
||||
|
||||
return SSH_PACKET_USED;
|
||||
}
|
||||
|
||||
597
src/pki.c
@@ -193,6 +193,36 @@ enum ssh_keytypes_e ssh_key_type(const ssh_key key){
|
||||
return key->type;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Convert a signature type to a string.
|
||||
*
|
||||
* @param[in] type The algorithm type to convert.
|
||||
*
|
||||
* @return A string for the keytype or NULL if unknown.
|
||||
*/
|
||||
const char *
|
||||
ssh_key_signature_to_char(enum ssh_keytypes_e type,
|
||||
enum ssh_digest_e hash_type)
|
||||
{
|
||||
if (type != SSH_KEYTYPE_RSA) {
|
||||
return ssh_key_type_to_char(type);
|
||||
}
|
||||
|
||||
switch (hash_type) {
|
||||
case SSH_DIGEST_SHA256:
|
||||
return "rsa-sha2-256";
|
||||
case SSH_DIGEST_SHA512:
|
||||
return "rsa-sha2-512";
|
||||
case SSH_DIGEST_SHA1:
|
||||
return "ssh-rsa";
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* We should never reach this */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Convert a key type to a string.
|
||||
*
|
||||
@@ -223,6 +253,124 @@ const char *ssh_key_type_to_char(enum ssh_keytypes_e type) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static enum ssh_digest_e ssh_key_hash_from_name(const char *name)
|
||||
{
|
||||
if (name == NULL) {
|
||||
/* TODO we should rather fail */
|
||||
return SSH_DIGEST_AUTO;
|
||||
}
|
||||
|
||||
if (strcmp(name, "ssh-rsa") == 0) {
|
||||
return SSH_DIGEST_SHA1;
|
||||
} else if (strcmp(name, "rsa-sha2-256") == 0) {
|
||||
return SSH_DIGEST_SHA256;
|
||||
} else if (strcmp(name, "rsa-sha2-512") == 0) {
|
||||
return SSH_DIGEST_SHA512;
|
||||
}
|
||||
|
||||
/* we do not care for others now */
|
||||
return SSH_DIGEST_AUTO;
|
||||
}
|
||||
/**
|
||||
* @brief Checks the given key against the configured allowed
|
||||
* public key algorithm types
|
||||
*
|
||||
* @param[in] session The SSH session
|
||||
* @parma[in] type The key algorithm to check
|
||||
* @returns 1 if the key algorithm is allowed 0 otherwise
|
||||
*/
|
||||
int ssh_key_algorithm_allowed(ssh_session session, const char *type)
|
||||
{
|
||||
const char *allowed_list;
|
||||
|
||||
allowed_list = session->opts.pubkey_accepted_types;
|
||||
if (allowed_list == NULL) {
|
||||
allowed_list = ssh_kex_get_default_methods(SSH_HOSTKEYS);
|
||||
}
|
||||
|
||||
SSH_LOG(SSH_LOG_DEBUG, "Checking %s with list <%s>", type, allowed_list);
|
||||
return ssh_match_group(allowed_list, type);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Convert a key type to a hash type. This is usually unambiguous
|
||||
* for all the key types, unless the SHA2 extension (RFC 8332) is
|
||||
* negotiated during key exchange.
|
||||
*
|
||||
* @param[in] session SSH Session.
|
||||
*
|
||||
* @param[in] type The type to convert.
|
||||
*
|
||||
* @return A hash type to be used.
|
||||
*/
|
||||
enum ssh_digest_e ssh_key_type_to_hash(ssh_session session,
|
||||
enum ssh_keytypes_e type)
|
||||
{
|
||||
switch (type) {
|
||||
case SSH_KEYTYPE_RSA:
|
||||
if (ssh_key_algorithm_allowed(session, "rsa-sha2-512") &&
|
||||
(session->extensions & SSH_EXT_SIG_RSA_SHA512)) {
|
||||
return SSH_DIGEST_SHA512;
|
||||
}
|
||||
|
||||
if (ssh_key_algorithm_allowed(session, "rsa-sha2-256") &&
|
||||
(session->extensions & SSH_EXT_SIG_RSA_SHA256)) {
|
||||
return SSH_DIGEST_SHA256;
|
||||
}
|
||||
|
||||
/* Default algorithm for RSA is SHA1 */
|
||||
return SSH_DIGEST_SHA1;
|
||||
|
||||
default:
|
||||
/* Other key types use the default value (not used) */
|
||||
return SSH_DIGEST_AUTO;
|
||||
}
|
||||
|
||||
/* We should never reach this */
|
||||
return SSH_DIGEST_AUTO;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets signature algorithm name to be used with the given
|
||||
* key type.
|
||||
*
|
||||
* @param[in] session SSH session.
|
||||
* @param[in] type The algorithm type to convert.
|
||||
*
|
||||
* @return A string for the keytype or NULL if unknown.
|
||||
*/
|
||||
const char *
|
||||
ssh_key_get_signature_algorithm(ssh_session session,
|
||||
enum ssh_keytypes_e type)
|
||||
{
|
||||
enum ssh_digest_e hash_type;
|
||||
|
||||
hash_type = ssh_key_type_to_hash(session, type);
|
||||
|
||||
return ssh_key_signature_to_char(type, hash_type);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Convert a ssh key algorithm name to a ssh key algorithm type.
|
||||
*
|
||||
* @param[in] name The name to convert.
|
||||
*
|
||||
* @return The enum ssh key algorithm type.
|
||||
*/
|
||||
enum ssh_keytypes_e ssh_key_type_from_signature_name(const char *name) {
|
||||
if (name == NULL) {
|
||||
return SSH_KEYTYPE_UNKNOWN;
|
||||
}
|
||||
|
||||
if ((strcmp(name, "rsa-sha2-256") == 0) ||
|
||||
(strcmp(name, "rsa-sha2-512") == 0)) {
|
||||
return SSH_KEYTYPE_RSA;
|
||||
}
|
||||
|
||||
/* Otherwise the key type matches the signature type */
|
||||
return ssh_key_type_from_name(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Convert a ssh key name to a ssh key type.
|
||||
*
|
||||
@@ -448,6 +596,62 @@ int ssh_pki_import_privkey_base64(const char *b64_key,
|
||||
|
||||
return SSH_OK;
|
||||
}
|
||||
/**
|
||||
* @brief Convert a private key to a pem base64 encoded key, or OpenSSH format for
|
||||
* keytype ssh-ed25519
|
||||
*
|
||||
* @param[in] privkey The private key to export.
|
||||
*
|
||||
* @param[in] passphrase The passphrase to use to encrypt the key with or
|
||||
* NULL. An empty string means no passphrase.
|
||||
*
|
||||
* @param[in] auth_fn An auth function you may want to use or NULL.
|
||||
*
|
||||
* @param[in] auth_data Private data passed to the auth function.
|
||||
*
|
||||
* @param[out] b64_key A pointer to store the allocated base64 encoded key. You
|
||||
* need to free the buffer.
|
||||
*
|
||||
* @return SSH_OK on success, SSH_ERROR on error.
|
||||
*/
|
||||
int ssh_pki_export_privkey_base64(const ssh_key privkey,
|
||||
const char *passphrase,
|
||||
ssh_auth_callback auth_fn,
|
||||
void *auth_data,
|
||||
char **b64_key)
|
||||
{
|
||||
ssh_string blob = NULL;
|
||||
char *b64 = NULL;
|
||||
|
||||
if (privkey == NULL || !ssh_key_is_private(privkey)) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
if (privkey->type == SSH_KEYTYPE_ED25519){
|
||||
blob = ssh_pki_openssh_privkey_export(privkey,
|
||||
passphrase,
|
||||
auth_fn,
|
||||
auth_data);
|
||||
} else {
|
||||
blob = pki_private_key_to_pem(privkey,
|
||||
passphrase,
|
||||
auth_fn,
|
||||
auth_data);
|
||||
}
|
||||
if (blob == NULL) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
b64 = strndup(ssh_string_data(blob), ssh_string_len(blob));
|
||||
ssh_string_free(blob);
|
||||
if (b64 == NULL) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
*b64_key = b64;
|
||||
|
||||
return SSH_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Import a key from a file.
|
||||
@@ -662,10 +866,183 @@ ssh_private_key ssh_pki_convert_key_to_privatekey(const ssh_key key) {
|
||||
return privkey;
|
||||
}
|
||||
|
||||
int pki_import_privkey_buffer(enum ssh_keytypes_e type,
|
||||
ssh_buffer buffer,
|
||||
ssh_key *pkey)
|
||||
{
|
||||
ssh_key key = NULL;
|
||||
int rc;
|
||||
|
||||
key = ssh_key_new();
|
||||
if (key == NULL) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
key->type = type;
|
||||
key->type_c = ssh_key_type_to_char(type);
|
||||
key->flags = SSH_KEY_FLAG_PRIVATE | SSH_KEY_FLAG_PUBLIC;
|
||||
|
||||
switch (type) {
|
||||
case SSH_KEYTYPE_DSS:
|
||||
{
|
||||
ssh_string p = NULL;
|
||||
ssh_string q = NULL;
|
||||
ssh_string g = NULL;
|
||||
ssh_string pubkey = NULL;
|
||||
ssh_string privkey = NULL;
|
||||
|
||||
rc = ssh_buffer_unpack(buffer, "SSSSS", &p, &q, &g,
|
||||
&pubkey, &privkey);
|
||||
if (rc != SSH_OK) {
|
||||
SSH_LOG(SSH_LOG_WARN, "Unpack error");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
rc = pki_privkey_build_dss(key, p, q, g, pubkey, privkey);
|
||||
#ifdef DEBUG_CRYPTO
|
||||
ssh_print_hexa("p", ssh_string_data(p), ssh_string_len(p));
|
||||
ssh_print_hexa("q", ssh_string_data(q), ssh_string_len(q));
|
||||
ssh_print_hexa("g", ssh_string_data(g), ssh_string_len(g));
|
||||
ssh_print_hexa("pubkey", ssh_string_data(pubkey),
|
||||
ssh_string_len(pubkey));
|
||||
ssh_print_hexa("privkey", ssh_string_data(privkey),
|
||||
ssh_string_len(privkey));
|
||||
#endif
|
||||
ssh_string_burn(p);
|
||||
ssh_string_free(p);
|
||||
ssh_string_burn(q);
|
||||
ssh_string_free(q);
|
||||
ssh_string_burn(g);
|
||||
ssh_string_free(g);
|
||||
ssh_string_burn(pubkey);
|
||||
ssh_string_free(pubkey);
|
||||
ssh_string_burn(privkey);
|
||||
ssh_string_free(privkey);
|
||||
if (rc == SSH_ERROR) {
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SSH_KEYTYPE_RSA:
|
||||
{
|
||||
ssh_string n = NULL;
|
||||
ssh_string e = NULL;
|
||||
ssh_string d = NULL;
|
||||
ssh_string iqmp = NULL;
|
||||
ssh_string p = NULL;
|
||||
ssh_string q = NULL;
|
||||
|
||||
rc = ssh_buffer_unpack(buffer, "SSSSSS", &n, &e, &d,
|
||||
&iqmp, &p, &q);
|
||||
if (rc != SSH_OK) {
|
||||
SSH_LOG(SSH_LOG_WARN, "Unpack error");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
rc = pki_privkey_build_rsa(key, n, e, d, iqmp, p, q);
|
||||
#ifdef DEBUG_CRYPTO
|
||||
ssh_print_hexa("n", ssh_string_data(n), ssh_string_len(n));
|
||||
ssh_print_hexa("e", ssh_string_data(e), ssh_string_len(e));
|
||||
ssh_print_hexa("d", ssh_string_data(d), ssh_string_len(d));
|
||||
ssh_print_hexa("iqmp", ssh_string_data(iqmp),
|
||||
ssh_string_len(iqmp));
|
||||
ssh_print_hexa("p", ssh_string_data(p), ssh_string_len(p));
|
||||
ssh_print_hexa("q", ssh_string_data(q), ssh_string_len(q));
|
||||
#endif
|
||||
ssh_string_burn(n);
|
||||
ssh_string_free(n);
|
||||
ssh_string_burn(e);
|
||||
ssh_string_free(e);
|
||||
ssh_string_burn(d);
|
||||
ssh_string_free(d);
|
||||
ssh_string_burn(iqmp);
|
||||
ssh_string_free(iqmp);
|
||||
ssh_string_burn(p);
|
||||
ssh_string_free(p);
|
||||
ssh_string_burn(q);
|
||||
ssh_string_free(q);
|
||||
if (rc == SSH_ERROR) {
|
||||
SSH_LOG(SSH_LOG_WARN, "Failed to build RSA private key");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
break;
|
||||
#ifdef HAVE_ECC
|
||||
case SSH_KEYTYPE_ECDSA:
|
||||
{
|
||||
ssh_string e = NULL;
|
||||
ssh_string exp = NULL;
|
||||
ssh_string i = NULL;
|
||||
int nid;
|
||||
|
||||
rc = ssh_buffer_unpack(buffer, "SSS", &i, &e, &exp);
|
||||
if (rc != SSH_OK) {
|
||||
SSH_LOG(SSH_LOG_WARN, "Unpack error");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
nid = pki_key_ecdsa_nid_from_name(ssh_string_get_char(i));
|
||||
ssh_string_free(i);
|
||||
if (nid == -1) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
rc = pki_privkey_build_ecdsa(key, nid, e, exp);
|
||||
ssh_string_burn(e);
|
||||
ssh_string_free(e);
|
||||
ssh_string_burn(exp);
|
||||
ssh_string_free(exp);
|
||||
if (rc < 0) {
|
||||
SSH_LOG(SSH_LOG_WARN, "Failed to build ECDSA private key");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Update key type */
|
||||
key->type_c = ssh_pki_key_ecdsa_name(key);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
case SSH_KEYTYPE_ED25519:
|
||||
{
|
||||
ssh_string pubkey = NULL, privkey = NULL;
|
||||
|
||||
rc = ssh_buffer_unpack(buffer, "SS", &pubkey, &privkey);
|
||||
if (rc != SSH_OK){
|
||||
SSH_LOG(SSH_LOG_WARN, "Unpack error");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
rc = pki_privkey_build_ed25519(key, pubkey, privkey);
|
||||
ssh_string_burn(privkey);
|
||||
ssh_string_free(privkey);
|
||||
ssh_string_free(pubkey);
|
||||
if (rc != SSH_OK) {
|
||||
SSH_LOG(SSH_LOG_WARN, "Failed to build ed25519 key");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SSH_KEYTYPE_DSS_CERT01:
|
||||
case SSH_KEYTYPE_RSA_CERT01:
|
||||
case SSH_KEYTYPE_RSA1:
|
||||
case SSH_KEYTYPE_UNKNOWN:
|
||||
default:
|
||||
SSH_LOG(SSH_LOG_WARN, "Unknown private key type (%d)", type);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
*pkey = key;
|
||||
return SSH_OK;
|
||||
fail:
|
||||
ssh_key_free(key);
|
||||
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
static int pki_import_pubkey_buffer(ssh_buffer buffer,
|
||||
enum ssh_keytypes_e type,
|
||||
ssh_key *pkey) {
|
||||
ssh_key key;
|
||||
ssh_key key = NULL;
|
||||
int rc;
|
||||
|
||||
key = ssh_key_new();
|
||||
@@ -680,40 +1057,14 @@ static int pki_import_pubkey_buffer(ssh_buffer buffer,
|
||||
switch (type) {
|
||||
case SSH_KEYTYPE_DSS:
|
||||
{
|
||||
ssh_string p;
|
||||
ssh_string q;
|
||||
ssh_string g;
|
||||
ssh_string pubkey;
|
||||
|
||||
p = ssh_buffer_get_ssh_string(buffer);
|
||||
if (p == NULL) {
|
||||
goto fail;
|
||||
}
|
||||
q = ssh_buffer_get_ssh_string(buffer);
|
||||
if (q == NULL) {
|
||||
ssh_string_burn(p);
|
||||
ssh_string_free(p);
|
||||
|
||||
goto fail;
|
||||
}
|
||||
g = ssh_buffer_get_ssh_string(buffer);
|
||||
if (g == NULL) {
|
||||
ssh_string_burn(p);
|
||||
ssh_string_free(p);
|
||||
ssh_string_burn(q);
|
||||
ssh_string_free(q);
|
||||
|
||||
goto fail;
|
||||
}
|
||||
pubkey = ssh_buffer_get_ssh_string(buffer);
|
||||
if (pubkey == NULL) {
|
||||
ssh_string_burn(p);
|
||||
ssh_string_free(p);
|
||||
ssh_string_burn(q);
|
||||
ssh_string_free(q);
|
||||
ssh_string_burn(g);
|
||||
ssh_string_free(g);
|
||||
ssh_string p = NULL;
|
||||
ssh_string q = NULL;
|
||||
ssh_string g = NULL;
|
||||
ssh_string pubkey = NULL;
|
||||
|
||||
rc = ssh_buffer_unpack(buffer, "SSSS", &p, &q, &g, &pubkey);
|
||||
if (rc != SSH_OK) {
|
||||
SSH_LOG(SSH_LOG_WARN, "Unpack error");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@@ -732,24 +1083,19 @@ static int pki_import_pubkey_buffer(ssh_buffer buffer,
|
||||
ssh_string_burn(pubkey);
|
||||
ssh_string_free(pubkey);
|
||||
if (rc == SSH_ERROR) {
|
||||
SSH_LOG(SSH_LOG_WARN, "Failed to build DSA public key");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SSH_KEYTYPE_RSA:
|
||||
{
|
||||
ssh_string e;
|
||||
ssh_string n;
|
||||
|
||||
e = ssh_buffer_get_ssh_string(buffer);
|
||||
if (e == NULL) {
|
||||
goto fail;
|
||||
}
|
||||
n = ssh_buffer_get_ssh_string(buffer);
|
||||
if (n == NULL) {
|
||||
ssh_string_burn(e);
|
||||
ssh_string_free(e);
|
||||
ssh_string e = NULL;
|
||||
ssh_string n = NULL;
|
||||
|
||||
rc = ssh_buffer_unpack(buffer, "SS", &e, &n);
|
||||
if (rc != SSH_OK) {
|
||||
SSH_LOG(SSH_LOG_WARN, "Unpack error");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@@ -763,6 +1109,7 @@ static int pki_import_pubkey_buffer(ssh_buffer buffer,
|
||||
ssh_string_burn(n);
|
||||
ssh_string_free(n);
|
||||
if (rc == SSH_ERROR) {
|
||||
SSH_LOG(SSH_LOG_WARN, "Failed to build RSA public key");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
@@ -770,30 +1117,27 @@ static int pki_import_pubkey_buffer(ssh_buffer buffer,
|
||||
#ifdef HAVE_ECC
|
||||
case SSH_KEYTYPE_ECDSA:
|
||||
{
|
||||
ssh_string e;
|
||||
ssh_string i;
|
||||
ssh_string e = NULL;
|
||||
ssh_string i = NULL;
|
||||
int nid;
|
||||
|
||||
i = ssh_buffer_get_ssh_string(buffer);
|
||||
if (i == NULL) {
|
||||
rc = ssh_buffer_unpack(buffer, "SS", &i, &e);
|
||||
if (rc != SSH_OK) {
|
||||
SSH_LOG(SSH_LOG_WARN, "Unpack error");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
nid = pki_key_ecdsa_nid_from_name(ssh_string_get_char(i));
|
||||
ssh_string_free(i);
|
||||
if (nid == -1) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
||||
e = ssh_buffer_get_ssh_string(buffer);
|
||||
if (e == NULL) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
rc = pki_pubkey_build_ecdsa(key, nid, e);
|
||||
ssh_string_burn(e);
|
||||
ssh_string_free(e);
|
||||
if (rc < 0) {
|
||||
SSH_LOG(SSH_LOG_WARN, "Failed to build ECDSA public key");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@@ -910,8 +1254,8 @@ fail:
|
||||
int ssh_pki_import_pubkey_base64(const char *b64_key,
|
||||
enum ssh_keytypes_e type,
|
||||
ssh_key *pkey) {
|
||||
ssh_buffer buffer;
|
||||
ssh_string type_s;
|
||||
ssh_buffer buffer = NULL;
|
||||
ssh_string type_s = NULL;
|
||||
int rc;
|
||||
|
||||
if (b64_key == NULL || pkey == NULL) {
|
||||
@@ -958,7 +1302,7 @@ int ssh_pki_import_pubkey_base64(const char *b64_key,
|
||||
*/
|
||||
int ssh_pki_import_pubkey_blob(const ssh_string key_blob,
|
||||
ssh_key *pkey) {
|
||||
ssh_buffer buffer;
|
||||
ssh_buffer buffer = NULL;
|
||||
ssh_string type_s = NULL;
|
||||
enum ssh_keytypes_e type;
|
||||
int rc;
|
||||
@@ -1032,7 +1376,7 @@ int ssh_pki_import_pubkey_file(const char *filename, ssh_key *pkey)
|
||||
const char *q;
|
||||
FILE *file;
|
||||
off_t size;
|
||||
int rc;
|
||||
int rc, cmp;
|
||||
|
||||
if (pkey == NULL || filename == NULL || *filename == '\0') {
|
||||
return SSH_ERROR;
|
||||
@@ -1082,6 +1426,20 @@ int ssh_pki_import_pubkey_file(const char *filename, ssh_key *pkey)
|
||||
key_buf[size] = '\0';
|
||||
buflen = strlen(key_buf);
|
||||
|
||||
/* Test for new OpenSSH key format first */
|
||||
cmp = strncmp(key_buf, OPENSSH_HEADER_BEGIN, strlen(OPENSSH_HEADER_BEGIN));
|
||||
if (cmp == 0) {
|
||||
*pkey = ssh_pki_openssh_pubkey_import(key_buf);
|
||||
SAFE_FREE(key_buf);
|
||||
if (*pkey == NULL) {
|
||||
SSH_LOG(SSH_LOG_WARN, "Failed to import public key from OpenSSH"
|
||||
" private key file");
|
||||
return SSH_ERROR;
|
||||
}
|
||||
return SSH_OK;
|
||||
}
|
||||
|
||||
/* This the old one-line public key format */
|
||||
q = p = key_buf;
|
||||
for (i = 0; i < buflen; i++) {
|
||||
if (isspace((int)p[i])) {
|
||||
@@ -1507,8 +1865,10 @@ int ssh_pki_import_signature_blob(const ssh_string sig_blob,
|
||||
{
|
||||
ssh_signature sig;
|
||||
enum ssh_keytypes_e type;
|
||||
enum ssh_digest_e hash_type;
|
||||
ssh_string str;
|
||||
ssh_buffer buf;
|
||||
const char *alg = NULL;
|
||||
int rc;
|
||||
|
||||
if (sig_blob == NULL || psig == NULL) {
|
||||
@@ -1534,7 +1894,9 @@ int ssh_pki_import_signature_blob(const ssh_string sig_blob,
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
type = ssh_key_type_from_name(ssh_string_get_char(str));
|
||||
alg = ssh_string_get_char(str);
|
||||
type = ssh_key_type_from_signature_name(alg);
|
||||
hash_type = ssh_key_hash_from_name(alg);
|
||||
ssh_string_free(str);
|
||||
|
||||
str = ssh_buffer_get_ssh_string(buf);
|
||||
@@ -1543,7 +1905,7 @@ int ssh_pki_import_signature_blob(const ssh_string sig_blob,
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
sig = pki_signature_from_blob(pubkey, str, type);
|
||||
sig = pki_signature_from_blob(pubkey, str, type, hash_type);
|
||||
ssh_string_free(str);
|
||||
if (sig == NULL) {
|
||||
return SSH_ERROR;
|
||||
@@ -1593,22 +1955,45 @@ int ssh_pki_signature_verify_blob(ssh_session session,
|
||||
} else if (key->type == SSH_KEYTYPE_ED25519) {
|
||||
rc = pki_signature_verify(session, sig, key, digest, dlen);
|
||||
} else {
|
||||
unsigned char hash[SHA_DIGEST_LEN] = {0};
|
||||
unsigned char hash[SHA512_DIGEST_LEN] = {0};
|
||||
uint32_t hlen = 0;
|
||||
|
||||
sha1(digest, dlen, hash);
|
||||
if (sig->type != SSH_KEYTYPE_RSA && sig->hash_type != SSH_DIGEST_AUTO) {
|
||||
SSH_LOG(SSH_LOG_TRACE, "Only RSA keys support non-SHA1 hashes.");
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
switch (sig->hash_type) {
|
||||
case SSH_DIGEST_SHA256:
|
||||
sha256(digest, dlen, hash);
|
||||
hlen = SHA256_DIGEST_LEN;
|
||||
break;
|
||||
case SSH_DIGEST_SHA512:
|
||||
sha512(digest, dlen, hash);
|
||||
hlen = SHA512_DIGEST_LEN;
|
||||
break;
|
||||
case SSH_DIGEST_SHA1:
|
||||
case SSH_DIGEST_AUTO:
|
||||
sha1(digest, dlen, hash);
|
||||
hlen = SHA_DIGEST_LEN;
|
||||
break;
|
||||
default:
|
||||
SSH_LOG(SSH_LOG_TRACE, "Unknown sig->hash_type: %d", sig->hash_type);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
#ifdef DEBUG_CRYPTO
|
||||
ssh_print_hexa(key->type == SSH_KEYTYPE_DSS
|
||||
? "Hash to be verified with DSA"
|
||||
: "Hash to be verified with RSA",
|
||||
hash,
|
||||
SHA_DIGEST_LEN);
|
||||
hlen);
|
||||
#endif
|
||||
|
||||
rc = pki_signature_verify(session,
|
||||
sig,
|
||||
key,
|
||||
hash,
|
||||
SHA_DIGEST_LEN);
|
||||
hlen);
|
||||
}
|
||||
|
||||
ssh_signature_free(sig);
|
||||
@@ -1687,24 +2072,57 @@ ssh_string ssh_pki_do_sign(ssh_session session,
|
||||
ssh_buffer_get_len(buf));
|
||||
ssh_buffer_free(buf);
|
||||
} else {
|
||||
unsigned char hash[SHA_DIGEST_LEN] = {0};
|
||||
SHACTX ctx;
|
||||
unsigned char hash[SHA512_DIGEST_LEN] = {0};
|
||||
uint32_t hlen = 0;
|
||||
enum ssh_digest_e hash_type;
|
||||
ssh_buffer buf;
|
||||
|
||||
ctx = sha1_init();
|
||||
if (ctx == NULL) {
|
||||
buf = ssh_buffer_new();
|
||||
if (buf == NULL) {
|
||||
ssh_string_free(session_id);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sha1_update(ctx, session_id, ssh_string_len(session_id) + 4);
|
||||
sha1_update(ctx, ssh_buffer_get(sigbuf), ssh_buffer_get_len(sigbuf));
|
||||
sha1_final(hash, ctx);
|
||||
ssh_buffer_set_secure(buf);
|
||||
rc = ssh_buffer_pack(buf,
|
||||
"SP",
|
||||
session_id,
|
||||
ssh_buffer_get_len(sigbuf), ssh_buffer_get(sigbuf));
|
||||
if (rc != SSH_OK) {
|
||||
ssh_string_free(session_id);
|
||||
ssh_buffer_free(buf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
hash_type = ssh_key_type_to_hash(session, privkey->type);
|
||||
switch (hash_type) {
|
||||
case SSH_DIGEST_SHA256:
|
||||
sha256(ssh_buffer_get(buf), ssh_buffer_get_len(buf), hash);
|
||||
hlen = SHA256_DIGEST_LEN;
|
||||
break;
|
||||
case SSH_DIGEST_SHA512:
|
||||
sha512(ssh_buffer_get(buf), ssh_buffer_get_len(buf), hash);
|
||||
hlen = SHA512_DIGEST_LEN;
|
||||
break;
|
||||
case SSH_DIGEST_SHA1:
|
||||
case SSH_DIGEST_AUTO:
|
||||
sha1(ssh_buffer_get(buf), ssh_buffer_get_len(buf), hash);
|
||||
hlen = SHA_DIGEST_LEN;
|
||||
break;
|
||||
default:
|
||||
SSH_LOG(SSH_LOG_TRACE, "Unknown hash algorithm for type: %d",
|
||||
sig->type);
|
||||
ssh_string_free(session_id);
|
||||
ssh_buffer_free(buf);
|
||||
return NULL;
|
||||
}
|
||||
ssh_buffer_free(buf);
|
||||
|
||||
#ifdef DEBUG_CRYPTO
|
||||
ssh_print_hexa("Hash being signed", hash, SHA_DIGEST_LEN);
|
||||
ssh_print_hexa("Hash being signed", hash, hlen);
|
||||
#endif
|
||||
|
||||
sig = pki_do_sign(privkey, hash, SHA_DIGEST_LEN);
|
||||
sig = pki_do_sign_hash(privkey, hash, hlen, hash_type);
|
||||
}
|
||||
ssh_string_free(session_id);
|
||||
if (sig == NULL) {
|
||||
@@ -1827,21 +2245,36 @@ ssh_string ssh_srv_pki_do_sign_sessionid(ssh_session session,
|
||||
sig = NULL;
|
||||
}
|
||||
} else {
|
||||
unsigned char hash[SHA_DIGEST_LEN] = {0};
|
||||
SHACTX ctx;
|
||||
unsigned char hash[SHA512_DIGEST_LEN] = {0};
|
||||
uint32_t hlen = 0;
|
||||
enum ssh_digest_e hash_type;
|
||||
|
||||
ctx = sha1_init();
|
||||
if (ctx == NULL) {
|
||||
hash_type = ssh_key_type_to_hash(session, privkey->type);
|
||||
switch (hash_type) {
|
||||
case SSH_DIGEST_SHA256:
|
||||
sha256(crypto->secret_hash, crypto->digest_len, hash);
|
||||
hlen = SHA256_DIGEST_LEN;
|
||||
break;
|
||||
case SSH_DIGEST_SHA512:
|
||||
sha512(crypto->secret_hash, crypto->digest_len, hash);
|
||||
hlen = SHA512_DIGEST_LEN;
|
||||
break;
|
||||
case SSH_DIGEST_SHA1:
|
||||
case SSH_DIGEST_AUTO:
|
||||
sha1(crypto->secret_hash, crypto->digest_len, hash);
|
||||
hlen = SHA_DIGEST_LEN;
|
||||
break;
|
||||
default:
|
||||
SSH_LOG(SSH_LOG_TRACE, "Unknown sig->type: %d", sig->type);
|
||||
return NULL;
|
||||
}
|
||||
sha1_update(ctx, crypto->secret_hash, crypto->digest_len);
|
||||
sha1_final(hash, ctx);
|
||||
|
||||
|
||||
#ifdef DEBUG_CRYPTO
|
||||
ssh_print_hexa("Hash being signed", hash, SHA_DIGEST_LEN);
|
||||
ssh_print_hexa("Hash being signed", hash, hlen);
|
||||
#endif
|
||||
|
||||
sig = pki_do_sign_sessionid(privkey, hash, SHA_DIGEST_LEN);
|
||||
sig = pki_do_sign_sessionid_hash(privkey, hash, hlen, hash_type);
|
||||
if (sig == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||