mirror of
https://git.libssh.org/projects/libssh.git
synced 2026-02-05 04:40:31 +09:00
Compare commits
116 Commits
libssh-0.7
...
release-0-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a6a7922dbd | ||
|
|
608e81bc00 | ||
|
|
7e17838c0b | ||
|
|
84f6945a9c | ||
|
|
3ae187dbe7 | ||
|
|
26989ab001 | ||
|
|
5b2e39cd79 | ||
|
|
13af149ef9 | ||
|
|
3453cafd95 | ||
|
|
fa65fd3dd1 | ||
|
|
ec5fa5cc06 | ||
|
|
8577688174 | ||
|
|
31462a4d72 | ||
|
|
fd2ff2d29c | ||
|
|
0b09bd900f | ||
|
|
abc61fa1cc | ||
|
|
e94bff02ba | ||
|
|
3671c61023 | ||
|
|
2702f3ea3f | ||
|
|
4abd0522b4 | ||
|
|
62b6eb4436 | ||
|
|
4b7eba1eda | ||
|
|
9970b1fd7d | ||
|
|
d703f51861 | ||
|
|
a009702cd6 | ||
|
|
ed268e5948 | ||
|
|
10b4654ad5 | ||
|
|
9d7fc9d50b | ||
|
|
b8bc3a6582 | ||
|
|
07e8d8f1f2 | ||
|
|
34a927716a | ||
|
|
bae4090715 | ||
|
|
403ded1e97 | ||
|
|
6fd8de3376 | ||
|
|
5fe99f8b09 | ||
|
|
af155db080 | ||
|
|
df5a94d445 | ||
|
|
4bfe7f024c | ||
|
|
99ea177eea | ||
|
|
476630841f | ||
|
|
7f59662cad | ||
|
|
e9d6b15926 | ||
|
|
6885d32c05 | ||
|
|
e5c2af6316 | ||
|
|
08a1bebb58 | ||
|
|
6195b133bf | ||
|
|
6e65abbe63 | ||
|
|
bda836d744 | ||
|
|
c8c2647555 | ||
|
|
4ad74765f6 | ||
|
|
b1f93f600e | ||
|
|
28edbe1ef5 | ||
|
|
75cf66a3ee | ||
|
|
5021ed3074 | ||
|
|
3773366a25 | ||
|
|
c6fab4bf84 | ||
|
|
7d1dcb0dff | ||
|
|
d7c1384df0 | ||
|
|
d2bb97c1c6 | ||
|
|
3b6098597d | ||
|
|
964d8fdc11 | ||
|
|
5d339aa9e2 | ||
|
|
af7f69c515 | ||
|
|
ea92d5b230 | ||
|
|
f096e031ed | ||
|
|
a8be476ea9 | ||
|
|
b9f65b5740 | ||
|
|
99a58eb325 | ||
|
|
ed1cba705c | ||
|
|
0b13a6d265 | ||
|
|
74c0201219 | ||
|
|
83c51d1c13 | ||
|
|
c712d30311 | ||
|
|
2144049c7d | ||
|
|
9dd86859e8 | ||
|
|
810fbfb620 | ||
|
|
370d072eba | ||
|
|
56dfa69fc9 | ||
|
|
672f8412f0 | ||
|
|
83ff1ffcc3 | ||
|
|
fb35153b49 | ||
|
|
7539200773 | ||
|
|
254a166c02 | ||
|
|
3e938cb901 | ||
|
|
452b16ede2 | ||
|
|
bd47ff75ba | ||
|
|
0016ded7f9 | ||
|
|
d725b31752 | ||
|
|
c2e86c876c | ||
|
|
028516ba6a | ||
|
|
344b27ac6c | ||
|
|
a700259b01 | ||
|
|
14da14db05 | ||
|
|
474d63f24e | ||
|
|
b3589fbf6c | ||
|
|
dd68bae776 | ||
|
|
4768cf3e85 | ||
|
|
5a95681f01 | ||
|
|
13a3619102 | ||
|
|
c7636edf84 | ||
|
|
27e332b623 | ||
|
|
ebc8544c56 | ||
|
|
0f8e9b839c | ||
|
|
0c02d6effe | ||
|
|
7199b196b0 | ||
|
|
ca83b66066 | ||
|
|
d978f9b58a | ||
|
|
e539eaf9e0 | ||
|
|
b728f44ce9 | ||
|
|
2f0b671a61 | ||
|
|
1fadec37d6 | ||
|
|
2aabbd6245 | ||
|
|
fd6823691b | ||
|
|
b174ad8ae4 | ||
|
|
176778bb1c | ||
|
|
e5bf645010 |
@@ -1,13 +0,0 @@
|
||||
-DWITH_SERVER=1
|
||||
-DWITH_GSSAPI=1
|
||||
-DWITH_ZLIB=1
|
||||
-DWITH_SFTP=1
|
||||
-DWITH_SSH1=1
|
||||
-DWITH_PCAP=1
|
||||
-DHAVE_ECDH=1
|
||||
-DHAVE_ECC=1
|
||||
-Iinclude/libssh
|
||||
-Iinclude
|
||||
-Ibuild
|
||||
-Itests
|
||||
-Isrc
|
||||
5
.gitignore
vendored
5
.gitignore
vendored
@@ -1,9 +1,6 @@
|
||||
*.a
|
||||
*.o
|
||||
.*
|
||||
*.swp
|
||||
*~$
|
||||
obj
|
||||
build
|
||||
cscope.*
|
||||
tags
|
||||
build
|
||||
|
||||
2
AUTHORS
2
AUTHORS
@@ -1,7 +1,7 @@
|
||||
Author(s):
|
||||
Aris Adamantiadis <aris@0xbadc0de.be> (project initiator)
|
||||
|
||||
Andreas Schneider <asn@cryptomilk.org> (developer)
|
||||
Andreas Schneider <mail@cynapses.org> (developer)
|
||||
|
||||
Nick Zitzmann <seiryu (at) comcast (dot) net> (mostly client SFTP stuff)
|
||||
|
||||
|
||||
107
CMakeLists.txt
107
CMakeLists.txt
@@ -1,14 +1,14 @@
|
||||
project(libssh C)
|
||||
|
||||
# Required cmake version
|
||||
cmake_minimum_required(VERSION 2.8.5)
|
||||
cmake_minimum_required(VERSION 2.6.0)
|
||||
|
||||
# global needed variables
|
||||
set(APPLICATION_NAME ${PROJECT_NAME})
|
||||
|
||||
set(APPLICATION_VERSION_MAJOR "0")
|
||||
set(APPLICATION_VERSION_MINOR "7")
|
||||
set(APPLICATION_VERSION_PATCH "1")
|
||||
set(APPLICATION_VERSION_MINOR "4")
|
||||
set(APPLICATION_VERSION_PATCH "4")
|
||||
|
||||
set(APPLICATION_VERSION "${APPLICATION_VERSION_MAJOR}.${APPLICATION_VERSION_MINOR}.${APPLICATION_VERSION_PATCH}")
|
||||
|
||||
@@ -19,17 +19,16 @@ set(APPLICATION_VERSION "${APPLICATION_VERSION_MAJOR}.${APPLICATION_VERSION_MINO
|
||||
# Increment AGE. Set REVISION to 0
|
||||
# If the source code was changed, but there were no interface changes:
|
||||
# Increment REVISION.
|
||||
set(LIBRARY_VERSION "4.4.0")
|
||||
set(LIBRARY_VERSION "4.1.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
|
||||
${CMAKE_SOURCE_DIR}/cmake/Modules
|
||||
)
|
||||
|
||||
# add definitions
|
||||
include(DefineCMakeDefaults)
|
||||
include(DefinePlatformDefaults)
|
||||
include(DefineCompilerFlags)
|
||||
include(DefineInstallationPaths)
|
||||
include(DefineOptions.cmake)
|
||||
@@ -39,13 +38,15 @@ include(CPackConfig.cmake)
|
||||
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.")
|
||||
|
||||
# add macros
|
||||
include(MacroAddPlugin)
|
||||
include(MacroCopyFile)
|
||||
|
||||
# search for libraries
|
||||
if (WITH_ZLIB)
|
||||
find_package(ZLIB REQUIRED)
|
||||
endif (WITH_ZLIB)
|
||||
find_package(ZLIB REQUIRED)
|
||||
|
||||
if (WITH_GCRYPT)
|
||||
find_package(GCrypt 1.5.0 REQUIRED)
|
||||
find_package(GCrypt REQUIRED)
|
||||
if (NOT GCRYPT_FOUND)
|
||||
message(FATAL_ERROR "Could not find GCrypt")
|
||||
endif (NOT GCRYPT_FOUND)
|
||||
@@ -59,21 +60,6 @@ else (WITH_GCRYPT)
|
||||
endif (NOT OPENSSL_FOUND)
|
||||
endif(WITH_GCRYPT)
|
||||
|
||||
# Find out if we have threading available
|
||||
set(CMAKE_THREAD_PREFER_PTHREADS ON)
|
||||
find_package(Threads)
|
||||
|
||||
if (WITH_GSSAPI)
|
||||
find_package(GSSAPI)
|
||||
endif (WITH_GSSAPI)
|
||||
|
||||
if (WITH_NACL)
|
||||
find_package(NaCl)
|
||||
if (NOT NACL_FOUND)
|
||||
set(WITH_NACL OFF)
|
||||
endif (NOT NACL_FOUND)
|
||||
endif (WITH_NACL)
|
||||
|
||||
# config.h checks
|
||||
include(ConfigureChecks.cmake)
|
||||
configure_file(config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config.h)
|
||||
@@ -81,71 +67,12 @@ configure_file(config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config.h)
|
||||
# check subdirectories
|
||||
add_subdirectory(doc)
|
||||
add_subdirectory(include)
|
||||
add_subdirectory(src)
|
||||
add_subdirectory(libssh)
|
||||
|
||||
# pkg-config file
|
||||
configure_file(libssh.pc.cmake ${CMAKE_CURRENT_BINARY_DIR}/libssh.pc)
|
||||
configure_file(libssh_threads.pc.cmake ${CMAKE_CURRENT_BINARY_DIR}/libssh_threads.pc)
|
||||
install(
|
||||
FILES
|
||||
${CMAKE_CURRENT_BINARY_DIR}/libssh.pc
|
||||
${CMAKE_CURRENT_BINARY_DIR}/libssh_threads.pc
|
||||
DESTINATION
|
||||
${LIB_INSTALL_DIR}/pkgconfig
|
||||
COMPONENT
|
||||
pkgconfig
|
||||
)
|
||||
# build samples
|
||||
include_directories(${CMAKE_SOURCE_DIR}/include)
|
||||
|
||||
# cmake config files
|
||||
set(LIBSSH_LIBRARY_NAME ${CMAKE_SHARED_LIBRARY_PREFIX}ssh${CMAKE_SHARED_LIBRARY_SUFFIX})
|
||||
set(LIBSSH_THREADS_LIBRARY_NAME ${CMAKE_SHARED_LIBRARY_PREFIX}ssh${CMAKE_SHARED_LIBRARY_SUFFIX})
|
||||
|
||||
configure_file(${PROJECT_NAME}-config.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config.cmake @ONLY)
|
||||
configure_file(${PROJECT_NAME}-config-version.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config-version.cmake @ONLY)
|
||||
install(
|
||||
FILES
|
||||
${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config.cmake
|
||||
${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config-version.cmake
|
||||
DESTINATION
|
||||
${CMAKE_INSTALL_DIR}/${PROJECT_NAME}
|
||||
COMPONENT
|
||||
devel
|
||||
)
|
||||
|
||||
|
||||
# in tree build settings
|
||||
configure_file(libssh-build-tree-settings.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/libssh-build-tree-settings.cmake @ONLY)
|
||||
|
||||
if (WITH_EXAMPLES)
|
||||
add_subdirectory(examples)
|
||||
endif (WITH_EXAMPLES)
|
||||
|
||||
if (WITH_TESTING)
|
||||
find_package(CMocka REQUIRED)
|
||||
include(AddCMockaTest)
|
||||
add_subdirectory(tests)
|
||||
endif (WITH_TESTING)
|
||||
|
||||
|
||||
message(STATUS "********************************************")
|
||||
message(STATUS "********** ${PROJECT_NAME} build options : **********")
|
||||
|
||||
message(STATUS "zlib support: ${WITH_ZLIB}")
|
||||
message(STATUS "libgcrypt support: ${WITH_GCRYPT}")
|
||||
message(STATUS "libnacl support: ${WITH_NACL}")
|
||||
message(STATUS "SSH-1 support: ${WITH_SSH1}")
|
||||
message(STATUS "SFTP support: ${WITH_SFTP}")
|
||||
message(STATUS "Server support : ${WITH_SERVER}")
|
||||
message(STATUS "GSSAPI support : ${WITH_GSSAPI}")
|
||||
message(STATUS "Pcap debugging support : ${WITH_PCAP}")
|
||||
message(STATUS "With static library: ${WITH_STATIC_LIB}")
|
||||
message(STATUS "Unit testing: ${WITH_TESTING}")
|
||||
message(STATUS "Client code Unit testing: ${WITH_CLIENT_TESTING}")
|
||||
if (WITH_INTERNAL_DOC)
|
||||
message(STATUS "Internal documentation generation")
|
||||
else (WITH_INTERNAL_DOC)
|
||||
message(STATUS "Public API documentation generation")
|
||||
endif (WITH_INTERNAL_DOC)
|
||||
message(STATUS "Benchmarks: ${WITH_BENCHMARKS}")
|
||||
message(STATUS "********************************************")
|
||||
if (CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
||||
add_subdirectory(examples)
|
||||
endif (CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
||||
|
||||
|
||||
@@ -4,39 +4,34 @@
|
||||
### general settings
|
||||
set(CPACK_PACKAGE_NAME ${APPLICATION_NAME})
|
||||
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "The SSH library")
|
||||
set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/README")
|
||||
set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_SOURCE_DIR}/README")
|
||||
set(CPACK_PACKAGE_VENDOR "The SSH Library Development Team")
|
||||
set(CPACK_PACKAGE_INSTALL_DIRECTORY ${CPACK_PACKAGE_NAME})
|
||||
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/COPYING")
|
||||
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/COPYING")
|
||||
|
||||
|
||||
### versions
|
||||
set(CPACK_PACKAGE_VERSION_MAJOR ${APPLICATION_VERSION_MAJOR})
|
||||
set(CPACK_PACKAGE_VERSION_MINOR ${APPLICATION_VERSION_MINOR})
|
||||
set(CPACK_PACKAGE_VERSION_PATCH ${APPLICATION_VERSION_PATCH})
|
||||
set(CPACK_PACKAGE_VERSION_MAJOR "0")
|
||||
set(CPACK_PACKAGE_VERSION_MINOR "4")
|
||||
set(CPACK_PACKAGE_VERSION_PATCH "4")
|
||||
set(CPACK_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}")
|
||||
|
||||
|
||||
### source generator
|
||||
set(CPACK_SOURCE_GENERATOR "TGZ")
|
||||
set(CPACK_SOURCE_IGNORE_FILES "~$;[.]swp$;/[.]svn/;/[.]git/;.gitignore;/build/;/obj/;tags;cscope.*")
|
||||
set(CPACK_SOURCE_IGNORE_FILES "~$;[.]swp$;/[.]svn/;/[.]git/;.gitignore;/build/;tags;cscope.*")
|
||||
set(CPACK_SOURCE_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}")
|
||||
|
||||
if (WIN32)
|
||||
set(CPACK_GENERATOR "ZIP")
|
||||
|
||||
### nsis generator
|
||||
find_package(NSIS)
|
||||
if (NSIS_MAKE)
|
||||
set(CPACK_GENERATOR "${CPACK_GENERATOR};NSIS")
|
||||
set(CPACK_NSIS_DISPLAY_NAME "The SSH Library")
|
||||
set(CPACK_NSIS_COMPRESSOR "/SOLID zlib")
|
||||
set(CPACK_NSIS_MENU_LINKS "http://www.libssh.org/" "libssh homepage")
|
||||
endif (NSIS_MAKE)
|
||||
endif (WIN32)
|
||||
### nsis generator
|
||||
set(CPACK_GENERATOR "NSIS")
|
||||
|
||||
set(CPACK_PACKAGE_INSTALL_DIRECTORY "libssh")
|
||||
|
||||
set(CPACK_NSIS_DISPLAY_NAME "The SSH Library")
|
||||
set(CPACK_NSIS_COMPRESSOR "/SOLID zlib")
|
||||
set(CPACK_NSIS_MENU_LINKS "http://www.libssh.org/" "libssh homepage")
|
||||
|
||||
set(CPACK_PACKAGE_FILE_NAME ${APPLICATION_NAME}-${CPACK_PACKAGE_VERSION})
|
||||
|
||||
set(CPACK_COMPONENT_LIBRARIES_DISPLAY_NAME "Libraries")
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
set(UPDATE_TYPE "true")
|
||||
|
||||
set(CTEST_PROJECT_NAME "libssh")
|
||||
set(CTEST_NIGHTLY_START_TIME "01:00:00 UTC")
|
||||
|
||||
set(CTEST_DROP_METHOD "https")
|
||||
set(CTEST_DROP_SITE "test.libssh.org")
|
||||
set(CTEST_DROP_LOCATION "/submit.php?project=libssh")
|
||||
set(CTEST_DROP_SITE_CDASH TRUE)
|
||||
187
ChangeLog
187
ChangeLog
@@ -1,193 +1,6 @@
|
||||
ChangeLog
|
||||
==========
|
||||
|
||||
version 0.7.1 (released 2015-06-30)
|
||||
* Fixed SSH_AUTH_PARTIAL auth with auto public key
|
||||
* Fixed memory leak in session options
|
||||
* Fixed allocation of ed25519 public keys
|
||||
* Fixed channel exit-status and exit-signal
|
||||
* Reintroduce ssh_forward_listen()
|
||||
|
||||
version 0.7.0 (released 2015-05-11)
|
||||
* Added support for ed25519 keys
|
||||
* Added SHA2 algorithms for HMAC
|
||||
* Added improved and more secure buffer handling code
|
||||
* Added callback for auth_none_function
|
||||
* Added support for ECDSA private key signing
|
||||
* Added more tests
|
||||
* Fixed a lot of bugs
|
||||
* Improved API documentation
|
||||
|
||||
version 0.6.5 (released 2015-04-29)
|
||||
* Fixed CVE-2015-3146
|
||||
* Fixed port handling in config file
|
||||
* Fixed the build with libgcrypt
|
||||
* Fixed SFTP endian issues (rlo #179)
|
||||
* Fixed uninitilized sig variable (rlo #167)
|
||||
* Fixed polling issues which could result in a hang
|
||||
* Fixed handling of EINTR in ssh_poll() (rlo #186)
|
||||
* Fixed C99 issues with __func__
|
||||
* Fixed some memory leaks
|
||||
* Improved macro detection on Windows
|
||||
|
||||
version 0.6.4 (released 2014-12-19)
|
||||
* Fixed CVE-2014-8132.
|
||||
* Added SHA-2 for session ID signing with ECDSA keys.
|
||||
* Added support for ECDSA host keys.
|
||||
* Added support for more ECDSA hostkey algorithms.
|
||||
* Added ssh_pki_key_ecdsa_name() API.
|
||||
* Fixed setting the bindfd only after successful listen.
|
||||
* Fixed issues with user created sockets.
|
||||
* Fixed several issues in libssh C++ wrapper.
|
||||
* Fixed several documentation issues.
|
||||
* Fixed channel exit-signal request.
|
||||
* Fixed X11 request screen number in messages.
|
||||
* Fixed several memory leaks.
|
||||
|
||||
version 0.6.3 (released 2014-03-04)
|
||||
* Fixed CVE-2014-0017.
|
||||
* Fixed memory leak with ecdsa signatures.
|
||||
|
||||
version 0.6.2 (released 2014-03-04)
|
||||
* security: fix for vulnerability CVE-2014-0017
|
||||
|
||||
version 0.6.1 (released 2014-02-08)
|
||||
* Added support for libgcrypt 1.6.
|
||||
* Added ssh_channel_accept_forward().
|
||||
* Added known_hosts heuristic during connection (#138).
|
||||
* Added getters for session cipher names.
|
||||
* Fixed decrypt of zero length buffer.
|
||||
* Fixed padding in RSA signature blobs.
|
||||
* Fixed DSA signature extraction.
|
||||
* Fixed some memory leaks.
|
||||
* Fixed read of non-connected socket.
|
||||
* Fixed thread dectection.
|
||||
|
||||
version 0.6.0 (released 2014-01-08)
|
||||
* Added new publicy key API.
|
||||
* Added new userauth API.
|
||||
* Added ssh_get_publickey_hash() function.
|
||||
* Added ssh_get_poll_flags() function.
|
||||
* Added gssapi-mic userauth.
|
||||
* Added GSSAPIServerIdentity option.
|
||||
* Added GSSAPIClientIdentity option.
|
||||
* Added GSSAPIDelegateCredentials option.
|
||||
* Added new callback based server API.
|
||||
* Added Elliptic Curve DSA (ECDSA) support (with OpenSSL).
|
||||
* Added Elliptic Curve Diffie Hellman (ECDH) support.
|
||||
* Added Curve25519 for ECDH key exchange.
|
||||
* Added improved logging system.
|
||||
* Added SSH-agent forwarding.
|
||||
* Added key-reexchange.
|
||||
* Added more unit tests.
|
||||
* Improved documentation.
|
||||
* Fixed timeout handling.
|
||||
|
||||
version 0.5.5 (released 2013-07-26)
|
||||
* BUG 103: Fix ProxyCommand parsing.
|
||||
* Fix setting -D_FORTIFY_SOURCE=2.
|
||||
* Fix pollset error return if emtpy.
|
||||
* Fix NULL pointer checks in channel functions.
|
||||
* Several bugfixes.
|
||||
|
||||
version 0.5.4 (released 2013-01-22)
|
||||
* CVE-2013-0176 - NULL dereference leads to denial of service
|
||||
* Fixed several NULL pointer dereferences in SSHv1.
|
||||
* Fixed a free crash bug in options parsing.
|
||||
|
||||
version 0.5.3 (released 2012-11-20)
|
||||
* CVE-2012-4559 Fixed multiple double free() flaws.
|
||||
* CVE-2012-4560 Fixed multiple buffer overflow flaws.
|
||||
* CVE-2012-4561 Fixed multiple invalid free() flaws.
|
||||
* BUG #84 - Fix bug in sftp_mkdir not returning on error.
|
||||
* BUG #85 - Fixed a possible channel infinite loop if the connection dropped.
|
||||
* BUG #88 - Added missing channel request_state and set it to accepted.
|
||||
* BUG #89 - Reset error state to no error on successful SSHv1 authentiction.
|
||||
* Fixed a possible use after free in ssh_free().
|
||||
* Fixed multiple possible NULL pointer dereferences.
|
||||
* Fixed multiple memory leaks in error paths.
|
||||
* Fixed timeout handling.
|
||||
* Fixed regression in pre-connected socket setting.
|
||||
* Handle all unknown global messages.
|
||||
|
||||
version 0.5.2 (released 2011-09-17)
|
||||
* Increased window size x10.
|
||||
* Fixed SSHv1.
|
||||
* Fixed bugged lists.
|
||||
* Fixed use-after-free + inconsistent callbacks call in poll.
|
||||
* Fixed scp documentation.
|
||||
* Fixed possible infinite loop in channel_read().
|
||||
* Fixed handling of short reads of sftp_async_read().
|
||||
* Fixed handling request service timeout in blocking mode.
|
||||
* Fixed ssh_auth_list() documentation.
|
||||
* Fixed incorrect return values in ssh_channel_write().
|
||||
* Fixed an infinite loop in the termination callback.
|
||||
* Fixed handling of SSH_AGAIN in channel_open().
|
||||
* Fixed "status -5 inflating zlib packet"
|
||||
|
||||
version 0.5.1 (released 2011-08-09)
|
||||
* Added checks for NULL pointers in string.c.
|
||||
* Set the channel max packet size to 32768.
|
||||
* Don't (de)compress empty buffers.
|
||||
* Fixed ssh_scp_write so it works when doing recursive copy.
|
||||
* Fixed another source of endless wait.
|
||||
* Fixed an endless loop in case of a channel_open error.
|
||||
* Fixed session timeout handling.
|
||||
* Fixed ssh_channel_from_local() loop.
|
||||
* Fixed permissions of scp example when we copy a file.
|
||||
* Workaround ssh_get_user_home_dir on LDAP users.
|
||||
* Added pkg-config support for libssh_threads.
|
||||
* Fixed compilation without server and sftp modes.
|
||||
* Fix static .lib overwriting on Windows.
|
||||
|
||||
version 0.5.0 (released 2011-06-01)
|
||||
* Added ssh_ prefix to all functions.
|
||||
* Added complete Windows support.
|
||||
* Added improved server support.
|
||||
* Added unit tests for a lot of functions.
|
||||
* Added asynchronous service request.
|
||||
* Added a multiplatform ssh_getpass() function.
|
||||
* Added a tutorial.
|
||||
* Added a lot of documentation.
|
||||
* Fixed a lot of bugs.
|
||||
* Fixed several memory leaks.
|
||||
|
||||
version 0.4.8 (released 2011-01-15)
|
||||
* Fixed memory leaks in session signing.
|
||||
* Fixed memory leak in ssh_print_hexa.
|
||||
* Fixed problem with ssh_connect w/ timeout and fd > 1024.
|
||||
* Fixed some warnings on OS/2.
|
||||
* Fixed installation path for OS/2.
|
||||
|
||||
version 0.4.7 (released 2010-12-28)
|
||||
* Fixed a possible memory leak in ssh_get_user_home().
|
||||
* Fixed a memory leak in sftp_xstat.
|
||||
* Fixed uninitialized fd->revents member.
|
||||
* Fixed timout value in ssh_channel_accept().
|
||||
* Fixed length checks in ssh_analyze_banner().
|
||||
* Fixed a possible data overread and crash bug.
|
||||
* Fixed setting max_fd which breaks ssh_select().
|
||||
* Fixed some pedantic build warnings.
|
||||
* Fixed a memory leak with session->bindaddr.
|
||||
|
||||
version 0.4.6 (released 2010-09-03)
|
||||
* Added a cleanup function to free the ws2_32 library.
|
||||
* Fixed build with gcc 3.4.
|
||||
* Fixed the Windows build on Vista and newer.
|
||||
* Fixed the usage of WSAPoll() on Windows.
|
||||
* Fixed "@deprecated" in doxygen
|
||||
* Fixed some mingw warnings.
|
||||
* Fixed handling of opened channels.
|
||||
* Fixed keepalive problem on older openssh servers.
|
||||
* Fixed testing for big endian on Windows.
|
||||
* Fixed the Windows preprocessor macros and defines.
|
||||
|
||||
version 0.4.5 (released 2010-07-13)
|
||||
* Added option to bind a client to an ip address.
|
||||
* Fixed the ssh socket polling function.
|
||||
* Fixed Windows related bugs in bsd_poll().
|
||||
* Fixed serveral build warnings.
|
||||
|
||||
version 0.4.4 (released 2010-06-01)
|
||||
* Fixed a bug in the expand function for escape sequences.
|
||||
* Fixed a bug in the tilde expand function.
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
include(CheckIncludeFile)
|
||||
include(CheckIncludeFiles)
|
||||
include(CheckSymbolExists)
|
||||
include(CheckFunctionExists)
|
||||
include(CheckLibraryExists)
|
||||
@@ -16,53 +17,41 @@ set(SYSCONFDIR ${SYSCONF_INSTALL_DIR})
|
||||
set(BINARYDIR ${CMAKE_BINARY_DIR})
|
||||
set(SOURCEDIR ${CMAKE_SOURCE_DIR})
|
||||
|
||||
function(COMPILER_DUMPVERSION _OUTPUT_VERSION)
|
||||
# Remove whitespaces from the argument.
|
||||
# This is needed for CC="ccache gcc" cmake ..
|
||||
string(REPLACE " " "" _C_COMPILER_ARG "${CMAKE_C_COMPILER_ARG1}")
|
||||
|
||||
execute_process(
|
||||
COMMAND
|
||||
${CMAKE_C_COMPILER} ${_C_COMPILER_ARG} -dumpversion
|
||||
OUTPUT_VARIABLE _COMPILER_VERSION
|
||||
)
|
||||
|
||||
string(REGEX REPLACE "([0-9])\\.([0-9])(\\.[0-9])?" "\\1\\2"
|
||||
_COMPILER_VERSION "${_COMPILER_VERSION}")
|
||||
|
||||
set(${_OUTPUT_VERSION} ${_COMPILER_VERSION} PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
if(CMAKE_COMPILER_IS_GNUCC AND NOT MINGW AND NOT OS2)
|
||||
compiler_dumpversion(GNUCC_VERSION)
|
||||
if (NOT GNUCC_VERSION EQUAL 34)
|
||||
set(CMAKE_REQUIRED_FLAGS "-fvisibility=hidden")
|
||||
check_c_source_compiles(
|
||||
"void __attribute__((visibility(\"default\"))) test() {}
|
||||
int main(void){ return 0; }
|
||||
" WITH_VISIBILITY_HIDDEN)
|
||||
set(CMAKE_REQUIRED_FLAGS "")
|
||||
endif (NOT GNUCC_VERSION EQUAL 34)
|
||||
endif(CMAKE_COMPILER_IS_GNUCC AND NOT MINGW AND NOT OS2)
|
||||
if(CMAKE_COMPILER_IS_GNUCC)
|
||||
check_c_compiler_flag("-fvisibility=hidden" WITH_VISIBILITY_HIDDEN)
|
||||
endif(CMAKE_COMPILER_IS_GNUCC)
|
||||
|
||||
# HEADER FILES
|
||||
check_include_file(argp.h HAVE_ARGP_H)
|
||||
check_include_file(pty.h HAVE_PTY_H)
|
||||
check_include_file(utmp.h HAVE_UTMP_H)
|
||||
check_include_file(termios.h HAVE_TERMIOS_H)
|
||||
check_include_file(unistd.h HAVE_UNISTD_H)
|
||||
check_include_file(util.h HAVE_UTIL_H)
|
||||
check_include_file(libutil.h HAVE_LIBUTIL_H)
|
||||
check_include_file(sys/time.h HAVE_SYS_TIME_H)
|
||||
check_include_file(sys/param.h HAVE_SYS_PARAM_H)
|
||||
check_include_file(arpa/inet.h HAVE_ARPA_INET_H)
|
||||
|
||||
check_include_file(terminos.h HAVE_TERMIOS_H)
|
||||
if (WIN32)
|
||||
check_include_files("winsock2.h;ws2tcpip.h;wspiapi.h" HAVE_WSPIAPI_H)
|
||||
if (NOT HAVE_WSPIAPI_H)
|
||||
message(STATUS "WARNING: Without wspiapi.h, this build will only work on Windows XP and newer versions")
|
||||
message(STATUS "WARNING: Without wspiapi.h (or dependencies), this build will only work on Windows XP and newer versions")
|
||||
endif (NOT HAVE_WSPIAPI_H)
|
||||
check_include_files("winsock2.h;ws2tcpip.h" HAVE_WS2TCPIP_H)
|
||||
if (NOT HAVE_WS2TCPIP_H)
|
||||
message(ERROR "WARNING: Does not have ws2tcpip.h or winsock2.h")
|
||||
endif (NOT HAVE_WS2TCPIP_H)
|
||||
if (HAVE_WSPIAPI_H OR HAVE_WS2TCPIP_H)
|
||||
set(HAVE_GETADDRINFO TRUE)
|
||||
set(HAVE_GETHOSTBYNAME TRUE)
|
||||
endif (HAVE_WSPIAPI_H OR HAVE_WS2TCPIP_H)
|
||||
|
||||
check_function_exists(vsnprintf HAVE_VSNPRINTF)
|
||||
if(NOT HAVE_VSNPRINTF)
|
||||
check_function_exists(_vsnprintf_s HAVE__VSNPRINTF_S)
|
||||
check_function_exists(_vsnprintf HAVE__VSNPRINTF)
|
||||
endif(NOT HAVE_VSNPRINTF)
|
||||
check_function_exists(snprintf HAVE_SNPRINTF)
|
||||
if(NOT HAVE_SNPRINTF)
|
||||
check_function_exists(_snprintf HAVE__SNPRINTF)
|
||||
check_function_exists(_snprintf_s HAVE__SNPRINTF_S)
|
||||
endif(NOT HAVE_SNPRINTF)
|
||||
check_function_exists(strncpy HAVE_STRNCPY)
|
||||
|
||||
set(HAVE_SELECT TRUE)
|
||||
endif (WIN32)
|
||||
|
||||
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIRS})
|
||||
@@ -74,95 +63,36 @@ check_include_file(openssl/blowfish.h HAVE_OPENSSL_BLOWFISH_H)
|
||||
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIRS})
|
||||
check_include_file(openssl/des.h HAVE_OPENSSL_DES_H)
|
||||
|
||||
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIRS})
|
||||
check_include_file(openssl/ecdh.h HAVE_OPENSSL_ECDH_H)
|
||||
|
||||
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIRS})
|
||||
check_include_file(openssl/ec.h HAVE_OPENSSL_EC_H)
|
||||
|
||||
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIRS})
|
||||
check_include_file(openssl/ecdsa.h HAVE_OPENSSL_ECDSA_H)
|
||||
|
||||
if (CMAKE_HAVE_PTHREAD_H)
|
||||
set(HAVE_PTHREAD_H 1)
|
||||
endif (CMAKE_HAVE_PTHREAD_H)
|
||||
|
||||
if (NOT WITH_GCRYPT)
|
||||
if (HAVE_OPENSSL_EC_H AND HAVE_OPENSSL_ECDSA_H)
|
||||
set(HAVE_OPENSSL_ECC 1)
|
||||
endif (HAVE_OPENSSL_EC_H AND HAVE_OPENSSL_ECDSA_H)
|
||||
|
||||
if (HAVE_OPENSSL_ECC)
|
||||
set(HAVE_ECC 1)
|
||||
endif (HAVE_OPENSSL_ECC)
|
||||
endif (NOT WITH_GCRYPT)
|
||||
|
||||
# FUNCTIONS
|
||||
|
||||
check_function_exists(isblank HAVE_ISBLANK)
|
||||
check_function_exists(strncpy HAVE_STRNCPY)
|
||||
check_function_exists(vsnprintf HAVE_VSNPRINTF)
|
||||
check_function_exists(snprintf HAVE_SNPRINTF)
|
||||
|
||||
if (WIN32)
|
||||
check_function_exists(_strtoui64 HAVE__STRTOUI64)
|
||||
|
||||
check_function_exists(_vsnprintf_s HAVE__VSNPRINTF_S)
|
||||
check_function_exists(_vsnprintf HAVE__VSNPRINTF)
|
||||
check_function_exists(_snprintf HAVE__SNPRINTF)
|
||||
check_function_exists(_snprintf_s HAVE__SNPRINTF_S)
|
||||
|
||||
if (HAVE_WSPIAPI_H OR HAVE_WS2TCPIP_H)
|
||||
check_symbol_exists(ntohll winsock2.h HAVE_NTOHLL)
|
||||
check_symbol_exists(htonll winsock2.h HAVE_HTONLL)
|
||||
|
||||
set(CMAKE_REQUIRED_LIBRARIES ws2_32)
|
||||
check_symbol_exists(select "winsock2.h;ws2tcpip.h" HAVE_SELECT)
|
||||
check_symbol_exists(poll "winsock2.h;ws2tcpip.h" HAVE_SELECT)
|
||||
# The getaddrinfo function is defined to the WspiapiGetAddrInfo inline function
|
||||
check_symbol_exists(getaddrinfo "winsock2.h;ws2tcpip.h" HAVE_GETADDRINFO)
|
||||
set(CMAKE_REQUIRED_LIBRARIES)
|
||||
endif (HAVE_WSPIAPI_H OR HAVE_WS2TCPIP_H)
|
||||
|
||||
set(HAVE_SELECT TRUE)
|
||||
else (WIN32)
|
||||
check_function_exists(poll HAVE_POLL)
|
||||
check_function_exists(select HAVE_SELECT)
|
||||
check_function_exists(getaddrinfo HAVE_GETADDRINFO)
|
||||
|
||||
check_symbol_exists(ntohll arpa/inet.h HAVE_NTOHLL)
|
||||
check_symbol_exists(htonll arpa/inet.h HAVE_HTONLL)
|
||||
endif (WIN32)
|
||||
|
||||
|
||||
if (UNIX)
|
||||
if (NOT LINUX)
|
||||
# libsocket (Solaris)
|
||||
check_library_exists(socket getaddrinfo "" HAVE_LIBSOCKET)
|
||||
if (HAVE_LIBSOCKET)
|
||||
set(HAVE_GETADDRINFO TRUE)
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} socket)
|
||||
endif (HAVE_LIBSOCKET)
|
||||
# libsocket (Solaris)
|
||||
check_library_exists(socket getaddrinfo "" HAVE_LIBSOCKET)
|
||||
if (HAVE_LIBSOCKET)
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} socket)
|
||||
endif (HAVE_LIBSOCKET)
|
||||
# libnsl (Solaris)
|
||||
check_library_exists(nsl gethostbyname "" HAVE_LIBNSL)
|
||||
if (HAVE_LIBNSL)
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} nsl)
|
||||
endif (HAVE_LIBNSL)
|
||||
# libresolv
|
||||
check_library_exists(resolv hstrerror "" HAVE_LIBRESOLV)
|
||||
if (HAVE_LIBRESOLV)
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} resolv)
|
||||
endif (HAVE_LIBRESOLV)
|
||||
check_library_exists(rt nanosleep "" HAVE_LIBRT)
|
||||
# librt
|
||||
if (HAVE_LIBRT)
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} rt)
|
||||
endif (HAVE_LIBRT)
|
||||
|
||||
# libnsl/inet_pton (Solaris)
|
||||
check_library_exists(nsl inet_pton "" HAVE_LIBNSL)
|
||||
if (HAVE_LIBNSL)
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} nsl)
|
||||
endif (HAVE_LIBNSL)
|
||||
|
||||
# librt
|
||||
check_library_exists(rt nanosleep "" HAVE_LIBRT)
|
||||
endif (NOT LINUX)
|
||||
|
||||
check_library_exists(rt clock_gettime "" HAVE_CLOCK_GETTIME)
|
||||
if (HAVE_LIBRT OR HAVE_CLOCK_GETTIME)
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} rt)
|
||||
endif (HAVE_LIBRT OR HAVE_CLOCK_GETTIME)
|
||||
|
||||
check_library_exists(util forkpty "" HAVE_LIBUTIL)
|
||||
check_function_exists(cfmakeraw HAVE_CFMAKERAW)
|
||||
check_function_exists(strtoull HAVE_STRTOULL)
|
||||
check_function_exists(__strtoull HAVE___STRTOULL)
|
||||
check_function_exists(getaddrinfo HAVE_GETADDRINFO)
|
||||
check_function_exists(gethostbyname HAVE_GETHOSTBYNAME)
|
||||
check_function_exists(poll HAVE_POLL)
|
||||
check_function_exists(select HAVE_SELECT)
|
||||
check_function_exists(cfmakeraw HAVE_CFMAKERAW)
|
||||
check_function_exists(regcomp HAVE_REGCOMP)
|
||||
endif (UNIX)
|
||||
|
||||
set(LIBSSH_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} CACHE INTERNAL "libssh required system libraries")
|
||||
@@ -173,71 +103,14 @@ if (OPENSSL_FOUND)
|
||||
endif (OPENSSL_FOUND)
|
||||
|
||||
if (GCRYPT_FOUND)
|
||||
set(HAVE_LIBGCRYPT 1)
|
||||
if (GCRYPT_VERSION VERSION_GREATER "1.4.6")
|
||||
#set(HAVE_GCRYPT_ECC 1)
|
||||
#set(HAVE_ECC 1)
|
||||
endif (GCRYPT_VERSION VERSION_GREATER "1.4.6")
|
||||
set(HAVE_LIBGCRYPT 1)
|
||||
endif (GCRYPT_FOUND)
|
||||
|
||||
if (CMAKE_USE_PTHREADS_INIT)
|
||||
set(HAVE_PTHREAD 1)
|
||||
endif (CMAKE_USE_PTHREADS_INIT)
|
||||
if (Z_LIBRARY)
|
||||
set(HAVE_LIBZ 1)
|
||||
endif (Z_LIBRARY)
|
||||
|
||||
# OPTIONS
|
||||
check_c_source_compiles("
|
||||
__thread int tls;
|
||||
|
||||
int main(void) {
|
||||
return 0;
|
||||
}" HAVE_GCC_THREAD_LOCAL_STORAGE)
|
||||
|
||||
check_c_source_compiles("
|
||||
__declspec(thread) int tls;
|
||||
|
||||
int main(void) {
|
||||
return 0;
|
||||
}" HAVE_MSC_THREAD_LOCAL_STORAGE)
|
||||
|
||||
check_c_source_compiles("
|
||||
#include <string.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
char buf[] = \"This is some content\";
|
||||
|
||||
memset(buf, '\\\\0', sizeof(buf)); __asm__ volatile(\"\" : : \"r\"(&buf) : \"memory\");
|
||||
|
||||
return 0;
|
||||
}" HAVE_GCC_VOLATILE_MEMORY_PROTECTION)
|
||||
|
||||
check_c_source_compiles("
|
||||
#include <stdio.h>
|
||||
#define __VA_NARG__(...) (__VA_NARG_(_0, ## __VA_ARGS__, __RSEQ_N()) - 1)
|
||||
#define __VA_NARG_(...) __VA_ARG_N(__VA_ARGS__)
|
||||
#define __VA_ARG_N( _1, _2, _3, _4, _5, _6, _7, _8, _9,_10,N,...) N
|
||||
#define __RSEQ_N() 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
|
||||
#define myprintf(format, ...) printf((format), __VA_NARG__(__VA_ARGS__), __VA_ARGS__)
|
||||
int main(void) {
|
||||
myprintf(\"%d %d %d %d\",1,2,3);
|
||||
return 0;
|
||||
}" HAVE_GCC_NARG_MACRO)
|
||||
|
||||
check_c_source_compiles("
|
||||
#include <stdio.h>
|
||||
int main(void) {
|
||||
printf(\"%s\", __func__);
|
||||
return 0;
|
||||
}" HAVE_COMPILER__FUNC__)
|
||||
|
||||
check_c_source_compiles("
|
||||
#include <stdio.h>
|
||||
int main(void) {
|
||||
printf(\"%s\", __FUNCTION__);
|
||||
return 0;
|
||||
}" HAVE_COMPILER__FUNCTION__)
|
||||
|
||||
|
||||
if (WITH_DEBUG_CRYPTO)
|
||||
set(DEBUG_CRYPTO 1)
|
||||
endif (WITH_DEBUG_CRYPTO)
|
||||
@@ -246,11 +119,5 @@ if (WITH_DEBUG_CALLTRACE)
|
||||
set(DEBUG_CALLTRACE 1)
|
||||
endif (WITH_DEBUG_CALLTRACE)
|
||||
|
||||
if (WITH_GSSAPI AND NOT GSSAPI_FOUND)
|
||||
set(WITH_GSSAPI 0)
|
||||
endif (WITH_GSSAPI AND NOT GSSAPI_FOUND)
|
||||
|
||||
# ENDIAN
|
||||
if (NOT WIN32)
|
||||
test_big_endian(WORDS_BIGENDIAN)
|
||||
endif (NOT WIN32)
|
||||
test_big_endian(WORDS_BIGENDIAN)
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
option(WITH_GSSAPI "Build with GSSAPI support" ON)
|
||||
option(WITH_ZLIB "Build with ZLIB support" ON)
|
||||
option(WITH_LIBZ "Build with ZLIB support" ON)
|
||||
option(WITH_SSH1 "Build with SSH1 support" OFF)
|
||||
option(WITH_SFTP "Build with SFTP support" ON)
|
||||
option(WITH_SERVER "Build with SSH server support" ON)
|
||||
@@ -7,27 +6,4 @@ option(WITH_STATIC_LIB "Build with a static library" OFF)
|
||||
option(WITH_DEBUG_CRYPTO "Build with cryto debug output" OFF)
|
||||
option(WITH_DEBUG_CALLTRACE "Build with calltrace debug output" ON)
|
||||
option(WITH_GCRYPT "Compile against libgcrypt" OFF)
|
||||
option(WITH_PCAP "Compile with Pcap generation support" ON)
|
||||
option(WITH_INTERNAL_DOC "Compile doxygen internal documentation" OFF)
|
||||
option(WITH_TESTING "Build with unit tests" OFF)
|
||||
option(WITH_CLIENT_TESTING "Build with client tests; requires a running sshd" OFF)
|
||||
option(WITH_BENCHMARKS "Build benchmarks tools" OFF)
|
||||
option(WITH_EXAMPLES "Build examples" ON)
|
||||
option(WITH_NACL "Build with libnacl (curve25519" ON)
|
||||
if (WITH_ZLIB)
|
||||
set(WITH_LIBZ ON)
|
||||
else (WITH_ZLIB)
|
||||
set(WITH_LIBZ OFF)
|
||||
endif (WITH_ZLIB)
|
||||
|
||||
if(WITH_BENCHMARKS)
|
||||
set(WITH_TESTING ON)
|
||||
endif(WITH_BENCHMARKS)
|
||||
|
||||
if (WITH_TESTING)
|
||||
set(WITH_STATIC_LIB ON)
|
||||
endif (WITH_TESTING)
|
||||
|
||||
if (WITH_NACL)
|
||||
set(WITH_NACL ON)
|
||||
endif (WITH_NACL)
|
||||
option(WITH_PCAP "Compile with Pcap generation support" OFF)
|
||||
|
||||
1272
Doxyfile.internal
Normal file
1272
Doxyfile.internal
Normal file
File diff suppressed because it is too large
Load Diff
29
INSTALL
29
INSTALL
@@ -18,26 +18,16 @@ optional:
|
||||
Note that these version numbers are version we know works correctly. If you
|
||||
build and run libssh successfully with an older version, please let us know.
|
||||
|
||||
Windows binaries known to be working:
|
||||
|
||||
- http://www.slproweb.com/products/Win32OpenSSL.html
|
||||
- http://zlib.net/ -> zlib compiled DLL
|
||||
|
||||
We installed them in C:\Program Files
|
||||
|
||||
## Building
|
||||
First, you need to configure the compilation, using CMake. Go inside the
|
||||
`build` dir. Create it if it doesn't exist.
|
||||
|
||||
GNU/Linux, MacOS X, MSYS/MinGW:
|
||||
GNU/Linux and MacOS X:
|
||||
|
||||
cmake -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Debug ..
|
||||
make
|
||||
|
||||
On Windows you should choose a makefile gernerator with -G or use
|
||||
|
||||
cmake-gui.exe ..
|
||||
|
||||
### CMake standard options
|
||||
Here is a list of the most interesting options provided out of the box by
|
||||
CMake.
|
||||
@@ -57,7 +47,7 @@ Options are defined in the following files:
|
||||
|
||||
They can be changed with the -D option:
|
||||
|
||||
`cmake -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Debug -DWITH_ZLIB=OFF ..`
|
||||
`cmake -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Debug -DWITH_LIBZ=OFF ..`
|
||||
|
||||
### Browsing/editing CMake options
|
||||
|
||||
@@ -69,17 +59,6 @@ and MacOS X).
|
||||
- On Windows: run `cmakesetup`
|
||||
- On GNU/Linux and MacOS X: run `ccmake ..`
|
||||
|
||||
### Useful Windows options:
|
||||
|
||||
If you have installed OpenSSL or ZLIB in non standard directories, maybe you
|
||||
want to set:
|
||||
|
||||
OPENSSL_ROOT_DIR
|
||||
|
||||
and
|
||||
|
||||
ZLIB_ROOT_DIR
|
||||
|
||||
## Installing
|
||||
|
||||
If you want to install libssh after compilation run:
|
||||
@@ -88,9 +67,7 @@ If you want to install libssh after compilation run:
|
||||
|
||||
## Running
|
||||
|
||||
The libssh binary can be found in the `build/src` directory.
|
||||
You can use `build/examples/samplessh` which is a sample client to
|
||||
test libssh on UNIX.
|
||||
The libssh binary can be found in the `build/libssh` directory.
|
||||
|
||||
## About this document
|
||||
|
||||
|
||||
119
README
119
README
@@ -1,12 +1,5 @@
|
||||
_ _ _ _
|
||||
(_) (_) (_) (_)
|
||||
(_) _ (_) _ _ _ _ _ (_) _
|
||||
(_) (_) (_)(_) _ (_)(_) (_)(_) (_)(_) _
|
||||
(_) (_) (_) (_) _ (_) _ (_) (_) (_)
|
||||
(_) (_) (_)(_)(_) (_)(_) (_)(_) (_) (_).org
|
||||
|
||||
The SSH library
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
libssh: the SSH library
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
1* Why ?
|
||||
-_-_-_-_-_
|
||||
@@ -36,12 +29,6 @@ http://www.libssh.org
|
||||
4* API Changes !
|
||||
-_-_-_-_-_-_-_-_-_
|
||||
|
||||
Changes between 0.4 and 0.5
|
||||
---------------------------
|
||||
|
||||
We use the ssh_ prefix as namespace for every function now. There is a legacy.h
|
||||
which could be used to get the old function names.
|
||||
|
||||
Changes between 0.3 and 0.4
|
||||
---------------------------
|
||||
|
||||
@@ -59,105 +46,3 @@ header file and it is documented. Example:
|
||||
|
||||
ssh_options_set(session, SSH_OPTIONS_HOST, "localhost");
|
||||
|
||||
5* Copyright policy
|
||||
-_-_-_-_-_-_-_-_-_-_
|
||||
|
||||
libssh is a project with distributed copyright ownership, which means we prefer
|
||||
the copyright on parts of libssh to be held by individuals rather than
|
||||
corporations if possible. There are historical legal reasons for this, but one
|
||||
of the best ways to explain it is that it’s much easier to work with
|
||||
individuals who have ownership than corporate legal departments if we ever need
|
||||
to make reasonable compromises with people using and working with libssh.
|
||||
|
||||
We track the ownership of every part of libssh via git, our source code control
|
||||
system, so we know the provenance of every piece of code that is committed to
|
||||
libssh.
|
||||
|
||||
So if possible, if you’re doing libssh changes on behalf of a company who
|
||||
normally owns all the work you do please get them to assign personal copyright
|
||||
ownership of your changes to you as an individual, that makes things very easy
|
||||
for us to work with and avoids bringing corporate legal departments into the
|
||||
picture.
|
||||
|
||||
If you can’t do this we can still accept patches from you owned by your
|
||||
employer under a standard employment contract with corporate copyright
|
||||
ownership. It just requires a simple set-up process first.
|
||||
|
||||
We use a process very similar to the way things are done in the Linux Kernel
|
||||
community, so it should be very easy to get a sign off from your corporate
|
||||
legal department. The only changes we’ve made are to accommodate the license we
|
||||
use, which is LGPLv2 (or later) whereas the Linux kernel uses GPLv2.
|
||||
|
||||
The process is called signing.
|
||||
|
||||
How to sign your work
|
||||
----------------------
|
||||
|
||||
Once you have permission to contribute to libssh from your employer, simply
|
||||
email a copy of the following text from your corporate email address to:
|
||||
|
||||
contributing@libssh.org
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
libssh Developer's Certificate of Origin. Version 1.0
|
||||
|
||||
By making a contribution to this project, I certify that:
|
||||
|
||||
(a) The contribution was created in whole or in part by me and I
|
||||
have the right to submit it under the appropriate
|
||||
version of the GNU General Public License; or
|
||||
|
||||
(b) The contribution is based upon previous work that, to the best of
|
||||
my knowledge, is covered under an appropriate open source license
|
||||
and I have the right under that license to submit that work with
|
||||
modifications, whether created in whole or in part by me, under
|
||||
the GNU General Public License, in the appropriate version; or
|
||||
|
||||
(c) The contribution was provided directly to me by some other
|
||||
person who certified (a) or (b) and I have not modified it.
|
||||
|
||||
(d) I understand and agree that this project and the contribution are
|
||||
public and that a record of the contribution (including all
|
||||
metadata and personal information I submit with it, including my
|
||||
sign-off) is maintained indefinitely and may be redistributed
|
||||
consistent with the libssh Team's policies and the requirements of
|
||||
the GNU GPL where they are relevant.
|
||||
|
||||
(e) I am granting this work to this project under the terms of the
|
||||
GNU Lesser General Public License as published by the
|
||||
Free Software Foundation; either version 2.1 of
|
||||
the License, or (at the option of the project) any later version.
|
||||
|
||||
http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
We will maintain a copy of that email as a record that you have the rights to
|
||||
contribute code to libssh under the required licenses whilst working for the
|
||||
company where the email came from.
|
||||
|
||||
Then when sending in a patch via the normal mechanisms described above, add a
|
||||
line that states:
|
||||
|
||||
|
||||
Signed-off-by: Random J Developer <random@developer.example.org>
|
||||
|
||||
|
||||
using your real name and the email address you sent the original email you used
|
||||
to send the libssh Developer’s Certificate of Origin to us (sorry, no
|
||||
pseudonyms or anonymous contributions.)
|
||||
|
||||
That’s it! Such code can then quite happily contain changes that have copyright
|
||||
messages such as:
|
||||
|
||||
|
||||
(c) Example Corporation.
|
||||
|
||||
|
||||
and can be merged into the libssh codebase in the same way as patches from any
|
||||
other individual. You don’t need to send in a copy of the libssh Developer’s
|
||||
Certificate of Origin for each patch, or inside each patch. Just the sign-off
|
||||
message is all that is required once we’ve received the initial email.
|
||||
|
||||
Have fun and happy libssh hacking!
|
||||
|
||||
The libssh Team
|
||||
|
||||
@@ -1,354 +0,0 @@
|
||||
Coding conventions in the libssh tree
|
||||
======================================
|
||||
|
||||
===========
|
||||
Quick Start
|
||||
===========
|
||||
|
||||
Coding style guidelines are about reducing the number of unnecessary
|
||||
reformatting patches and making things easier for developers to work together.
|
||||
|
||||
You don't have to like them or even agree with them, but once put in place we
|
||||
all have to abide by them (or vote to change them). However, coding style
|
||||
should never outweigh coding itself and so the guidelines described here are
|
||||
hopefully easy enough to follow as they are very common and supported by tools
|
||||
and editors.
|
||||
|
||||
The basic style for C code, is the Linux kernel coding style (See
|
||||
Documentation/CodingStyle in the kernel source tree). This closely matches what
|
||||
libssh developers use already anyways, with a few exceptions as mentioned
|
||||
below.
|
||||
|
||||
But to save you the trouble of reading the Linux kernel style guide, here
|
||||
are the highlights.
|
||||
|
||||
* Maximum Line Width is 80 Characters
|
||||
The reason is not about people with low-res screens but rather sticking
|
||||
to 80 columns prevents you from easily nesting more than one level of
|
||||
if statements or other code blocks.
|
||||
|
||||
* Use 4 Spaces to Indent
|
||||
|
||||
* No Trailing Whitespace
|
||||
Clean up your files before committing.
|
||||
|
||||
* Follow the K&R guidelines. We won't go through all of them here. Do you
|
||||
have a copy of "The C Programming Language" anyways right?
|
||||
|
||||
|
||||
=============
|
||||
Editor Hints
|
||||
=============
|
||||
|
||||
Emacs
|
||||
------
|
||||
Add the follow to your $HOME/.emacs file:
|
||||
|
||||
(add-hook 'c-mode-hook
|
||||
(lambda ()
|
||||
(c-set-style "linux")
|
||||
(c-toggle-auto-state)))
|
||||
|
||||
|
||||
Vim
|
||||
----
|
||||
|
||||
For the basic vi editor included with all variants of \*nix, add the
|
||||
following to $HOME/.vimrc:
|
||||
|
||||
set ts=4 sw=4 et cindent
|
||||
|
||||
You can use the Vim gitmodline plugin to store this in the git config:
|
||||
|
||||
http://git.cryptomilk.org/projects/vim-gitmodeline.git/
|
||||
|
||||
For Vim, the following settings in $HOME/.vimrc will also deal with
|
||||
displaying trailing whitespace:
|
||||
|
||||
if has("syntax") && (&t_Co > 2 || has("gui_running"))
|
||||
syntax on
|
||||
function! ActivateInvisibleCharIndicator()
|
||||
syntax match TrailingSpace "[ \t]\+$" display containedin=ALL
|
||||
highlight TrailingSpace ctermbg=Red
|
||||
endf
|
||||
autocmd BufNewFile,BufRead * call ActivateInvisibleCharIndicator()
|
||||
endif
|
||||
" Show tabs, trailing whitespace, and continued lines visually
|
||||
set list listchars=tab:»·,trail:·,extends:…
|
||||
|
||||
" highlight overly long lines same as TODOs.
|
||||
set textwidth=80
|
||||
autocmd BufNewFile,BufRead *.c,*.h exec 'match Todo /\%>' . &textwidth . 'v.\+/'
|
||||
|
||||
|
||||
==========================
|
||||
FAQ & Statement Reference
|
||||
==========================
|
||||
|
||||
Comments
|
||||
---------
|
||||
|
||||
Comments should always use the standard C syntax. C++ style comments are not
|
||||
currently allowed.
|
||||
|
||||
The lines before a comment should be empty. If the comment directly belongs to
|
||||
the following code, there should be no empty line after the comment, except if
|
||||
the comment contains a summary of multiple following code blocks.
|
||||
|
||||
This is good:
|
||||
|
||||
...
|
||||
int i;
|
||||
|
||||
/*
|
||||
* This is a multi line comment,
|
||||
* which explains the logical steps we have to do:
|
||||
*
|
||||
* 1. We need to set i=5, because...
|
||||
* 2. We need to call complex_fn1
|
||||
*/
|
||||
|
||||
/* This is a one line comment about i = 5. */
|
||||
i = 5;
|
||||
|
||||
/*
|
||||
* This is a multi line comment,
|
||||
* explaining the call to complex_fn1()
|
||||
*/
|
||||
ret = complex_fn1();
|
||||
if (ret != 0) {
|
||||
...
|
||||
|
||||
/**
|
||||
* @brief This is a doxygen comment.
|
||||
*
|
||||
* This is a more detailed explanation of
|
||||
* this simple function.
|
||||
*
|
||||
* @param[in] param1 The parameter value of the function.
|
||||
*
|
||||
* @param[out] result1 The result value of the function.
|
||||
*
|
||||
* @return 0 on success and -1 on error.
|
||||
*/
|
||||
int example(int param1, int *result1);
|
||||
|
||||
This is bad:
|
||||
|
||||
...
|
||||
int i;
|
||||
/*
|
||||
* This is a multi line comment,
|
||||
* which explains the logical steps we have to do:
|
||||
*
|
||||
* 1. We need to set i=5, because...
|
||||
* 2. We need to call complex_fn1
|
||||
*/
|
||||
/* This is a one line comment about i = 5. */
|
||||
i = 5;
|
||||
/*
|
||||
* This is a multi line comment,
|
||||
* explaining the call to complex_fn1()
|
||||
*/
|
||||
ret = complex_fn1();
|
||||
if (ret != 0) {
|
||||
...
|
||||
|
||||
/*This is a one line comment.*/
|
||||
|
||||
/* This is a multi line comment,
|
||||
with some more words...*/
|
||||
|
||||
/*
|
||||
* This is a multi line comment,
|
||||
* with some more words...*/
|
||||
|
||||
Indention & Whitespace & 80 columns
|
||||
------------------------------------
|
||||
|
||||
To avoid confusion, indentations have to be 4 spaces. Do not use tabs!. When
|
||||
wrapping parameters for function calls, align the parameter list with the first
|
||||
parameter on the previous line. For example,
|
||||
|
||||
var1 = foo(arg1,
|
||||
arg2,
|
||||
arg3);
|
||||
|
||||
The previous example is intended to illustrate alignment of function
|
||||
parameters across lines and not as encourage for gratuitous line
|
||||
splitting. Never split a line before columns 70 - 79 unless you
|
||||
have a really good reason. Be smart about formatting.
|
||||
|
||||
|
||||
If, switch, & Code blocks
|
||||
--------------------------
|
||||
|
||||
Always follow an 'if' keyword with a space but don't include additional
|
||||
spaces following or preceding the parentheses in the conditional.
|
||||
This is good:
|
||||
|
||||
if (x == 1)
|
||||
|
||||
This is bad:
|
||||
|
||||
if ( x == 1 )
|
||||
|
||||
or
|
||||
|
||||
if (x==1)
|
||||
|
||||
Yes we have a lot of code that uses the second and third form and we are trying
|
||||
to clean it up without being overly intrusive.
|
||||
|
||||
Note that this is a rule about parentheses following keywords and not
|
||||
functions. Don't insert a space between the name and left parentheses when
|
||||
invoking functions.
|
||||
|
||||
Braces for code blocks used by for, if, switch, while, do..while, etc. should
|
||||
begin on the same line as the statement keyword and end on a line of their own.
|
||||
You should always include braces, even if the block only contains one
|
||||
statement. NOTE: Functions are different and the beginning left brace should
|
||||
be located in the first column on the next line.
|
||||
|
||||
If the beginning statement has to be broken across lines due to length, the
|
||||
beginning brace should be on a line of its own.
|
||||
|
||||
The exception to the ending rule is when the closing brace is followed by
|
||||
another language keyword such as else or the closing while in a do..while loop.
|
||||
|
||||
Good examples:
|
||||
|
||||
if (x == 1) {
|
||||
printf("good\n");
|
||||
}
|
||||
|
||||
for (x = 1; x < 10; x++) {
|
||||
print("%d\n", x);
|
||||
}
|
||||
|
||||
for (really_really_really_really_long_var_name = 0;
|
||||
really_really_really_really_long_var_name < 10;
|
||||
really_really_really_really_long_var_name++)
|
||||
{
|
||||
print("%d\n", really_really_really_really_long_var_name);
|
||||
}
|
||||
|
||||
do {
|
||||
printf("also good\n");
|
||||
} while (1);
|
||||
|
||||
Bad examples:
|
||||
|
||||
while (1)
|
||||
{
|
||||
print("I'm in a loop!\n"); }
|
||||
|
||||
for (x=1;
|
||||
x<10;
|
||||
x++)
|
||||
{
|
||||
print("no good\n");
|
||||
}
|
||||
|
||||
if (i < 10)
|
||||
print("I should be in braces.\n");
|
||||
|
||||
|
||||
Goto
|
||||
-----
|
||||
|
||||
While many people have been academically taught that "goto"s are fundamentally
|
||||
evil, they can greatly enhance readability and reduce memory leaks when used as
|
||||
the single exit point from a function. But in no libssh world what so ever is a
|
||||
goto outside of a function or block of code a good idea.
|
||||
|
||||
Good Examples:
|
||||
|
||||
int function foo(int y)
|
||||
{
|
||||
int *z = NULL;
|
||||
int rc = 0;
|
||||
|
||||
if (y < 10) {
|
||||
z = malloc(sizeof(int)*y);
|
||||
if (z == NULL) {
|
||||
rc = 1;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
print("Allocated %d elements.\n", y);
|
||||
|
||||
done:
|
||||
if (z != NULL) {
|
||||
free(z);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
Typedefs
|
||||
---------
|
||||
|
||||
libssh tries to avoid "typedef struct { .. } x_t;" so we do always try to use
|
||||
"struct x { .. };". We know there are still such typedefs in the code, but for
|
||||
new code, please don't do that anymore.
|
||||
|
||||
Make use of helper variables
|
||||
-----------------------------
|
||||
|
||||
Please try to avoid passing function calls as function parameters in new code.
|
||||
This makes the code much easier to read and it's also easier to use the "step"
|
||||
command within gdb.
|
||||
|
||||
Good Example:
|
||||
|
||||
char *name;
|
||||
|
||||
name = get_some_name();
|
||||
if (name == NULL) {
|
||||
...
|
||||
}
|
||||
|
||||
rc = some_function_my_name(name);
|
||||
...
|
||||
|
||||
|
||||
Bad Example:
|
||||
|
||||
rc = some_function_my_name(get_some_name());
|
||||
...
|
||||
|
||||
Please try to avoid passing function return values to if- or while-conditions.
|
||||
The reason for this is better handling of code under a debugger.
|
||||
|
||||
Good example:
|
||||
|
||||
x = malloc(sizeof(short) * 10);
|
||||
if (x == NULL) {
|
||||
fprintf(stderr, "Unable to alloc memory!\n");
|
||||
}
|
||||
|
||||
Bad example:
|
||||
|
||||
if ((x = malloc(sizeof(short)*10)) == NULL ) {
|
||||
fprintf(stderr, "Unable to alloc memory!\n");
|
||||
}
|
||||
|
||||
There are exceptions to this rule. One example is walking a data structure in
|
||||
an iterator style:
|
||||
|
||||
while ((opt = poptGetNextOpt(pc)) != -1) {
|
||||
... do something with opt ...
|
||||
}
|
||||
|
||||
But in general, please try to avoid this pattern.
|
||||
|
||||
|
||||
Control-Flow changing macros
|
||||
-----------------------------
|
||||
|
||||
Macros like STATUS_NOT_OK_RETURN that change control flow (return/goto/etc)
|
||||
from within the macro are considered bad, because they look like function calls
|
||||
that never change control flow. Please do not introduce them.
|
||||
@@ -1,118 +0,0 @@
|
||||
How to contribute a patch to libssh
|
||||
====================================
|
||||
|
||||
Simple, just make the code change, and email it as either a "diff -u"
|
||||
change, or as a "git format-patch" change against the original source
|
||||
code to libssh@libssh.org, or attach it to a bug report at
|
||||
https://red.libssh.org/
|
||||
|
||||
For larger code changes, breaking the changes up into a set of simple
|
||||
patches, each of which does a single thing, are much easier to review.
|
||||
Patch sets like that will most likely have an easier time being merged
|
||||
into the libssh code than large single patches that make lots of
|
||||
changes in one large diff.
|
||||
|
||||
Ownership of the contributed code
|
||||
==================================
|
||||
|
||||
libssh is a project with distributed copyright ownership, which means
|
||||
we prefer the copyright on parts of libssh to be held by individuals
|
||||
rather than corporations if possible. There are historical legal
|
||||
reasons for this, but one of the best ways to explain it is that it's
|
||||
much easier to work with individuals who have ownership than corporate
|
||||
legal departments if we ever need to make reasonable compromises with
|
||||
people using and working with libssh.
|
||||
|
||||
We track the ownership of every part of libssh via http://git.libssh.org,
|
||||
our source code control system, so we know the provenance of every piece
|
||||
of code that is committed to libssh.
|
||||
|
||||
So if possible, if you're doing libssh changes on behalf of a company
|
||||
who normally owns all the work you do please get them to assign
|
||||
personal copyright ownership of your changes to you as an individual,
|
||||
that makes things very easy for us to work with and avoids bringing
|
||||
corporate legal departments into the picture.
|
||||
|
||||
If you can't do this we can still accept patches from you owned by
|
||||
your employer under a standard employment contract with corporate
|
||||
copyright ownership. It just requires a simple set-up process first.
|
||||
|
||||
We use a process very similar to the way things are done in the Linux
|
||||
Kernel community, so it should be very easy to get a sign off from
|
||||
your corporate legal department. The only changes we've made are to
|
||||
accommodate the license we use, which is LGPLv2 (or later) whereas the
|
||||
Linux kernel uses GPLv2.
|
||||
|
||||
The process is called signing.
|
||||
|
||||
How to sign your work
|
||||
----------------------
|
||||
|
||||
Once you have permission to contribute to libssh from your employer, simply
|
||||
email a copy of the following text from your corporate email address to:
|
||||
|
||||
contributing@libssh.org
|
||||
|
||||
|
||||
|
||||
libssh Developer's Certificate of Origin. Version 1.0
|
||||
|
||||
|
||||
By making a contribution to this project, I certify that:
|
||||
|
||||
(a) The contribution was created in whole or in part by me and I
|
||||
have the right to submit it under the appropriate
|
||||
version of the GNU General Public License; or
|
||||
|
||||
(b) The contribution is based upon previous work that, to the best of
|
||||
my knowledge, is covered under an appropriate open source license
|
||||
and I have the right under that license to submit that work with
|
||||
modifications, whether created in whole or in part by me, under
|
||||
the GNU General Public License, in the appropriate version; or
|
||||
|
||||
(c) The contribution was provided directly to me by some other
|
||||
person who certified (a) or (b) and I have not modified it.
|
||||
|
||||
(d) I understand and agree that this project and the contribution are
|
||||
public and that a record of the contribution (including all
|
||||
metadata and personal information I submit with it, including my
|
||||
sign-off) is maintained indefinitely and may be redistributed
|
||||
consistent with the libssh Team's policies and the requirements of
|
||||
the GNU GPL where they are relevant.
|
||||
|
||||
(e) I am granting this work to this project under the terms of the
|
||||
GNU Lesser General Public License as published by the
|
||||
Free Software Foundation; either version 2.1 of
|
||||
the License, or (at the option of the project) any later version.
|
||||
|
||||
http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
|
||||
|
||||
We will maintain a copy of that email as a record that you have the
|
||||
rights to contribute code to libssh under the required licenses whilst
|
||||
working for the company where the email came from.
|
||||
|
||||
Then when sending in a patch via the normal mechanisms described
|
||||
above, add a line that states:
|
||||
|
||||
Signed-off-by: Random J Developer <random@developer.example.org>
|
||||
|
||||
using your real name and the email address you sent the original email
|
||||
you used to send the libssh Developer's Certificate of Origin to us
|
||||
(sorry, no pseudonyms or anonymous contributions.)
|
||||
|
||||
That's it! Such code can then quite happily contain changes that have
|
||||
copyright messages such as:
|
||||
|
||||
(c) Example Corporation.
|
||||
|
||||
and can be merged into the libssh codebase in the same way as patches
|
||||
from any other individual. You don't need to send in a copy of the
|
||||
libssh Developer's Certificate of Origin for each patch, or inside each
|
||||
patch. Just the sign-off message is all that is required once we've
|
||||
received the initial email.
|
||||
|
||||
Have fun and happy libssh hacking !
|
||||
|
||||
The libssh Team
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#
|
||||
# Script to build libssh on UNIX.
|
||||
#
|
||||
# Copyright (c) 2006-2007 Andreas Schneider <asn@cryptomilk.org>
|
||||
# Copyright (c) 2006-2007 Andreas Schneider <mail@cynapses.org>
|
||||
#
|
||||
|
||||
SOURCE_DIR=".."
|
||||
@@ -62,8 +62,8 @@ function clean_build_dir() {
|
||||
}
|
||||
|
||||
function usage () {
|
||||
echo "Usage: `basename $0` [--prefix /install_prefix|--build [debug|final]|--clean|--verbose|--libsuffix (32|64)|--help|--clang|--cmakedir /directory|--make
|
||||
(gmake|make)|--ccompiler (gcc|cc)|--withstaticlib|--unittesting|--clientunittesting|--withssh1|--withserver]"
|
||||
echo "Usage: `basename $0` [--prefix /install_prefix|--build [debug|final]|--clean|--verbose|--libsuffix (32|64)|--help|--cmakedir /directory|--make
|
||||
(gmake|make)|--ccompiler (gcc|cc)|--withstaticlib|--unittesting|--withss1|--withserver]"
|
||||
cleanup_and_exit
|
||||
}
|
||||
|
||||
@@ -100,9 +100,6 @@ while test -n "$1"; do
|
||||
clean_build_dir
|
||||
cleanup_and_exit
|
||||
;;
|
||||
*-clang)
|
||||
OPTIONS="${OPTIONS} -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++"
|
||||
;;
|
||||
*-verbose)
|
||||
DOVERBOSE="1"
|
||||
;;
|
||||
@@ -135,18 +132,19 @@ while test -n "$1"; do
|
||||
;;
|
||||
*-withstaticlib)
|
||||
OPTIONS="${OPTIONS} -DWITH_STATIC_LIB=ON"
|
||||
shift
|
||||
;;
|
||||
*-unittesting)
|
||||
OPTIONS="${OPTIONS} -DWITH_TESTING=ON"
|
||||
;;
|
||||
*-clientunittesting)
|
||||
OPTIONS="${OPTIONS} -DWITH_CLIENT_TESTING=ON"
|
||||
OPTIONS="${OPTIONS} -DUNIT_TESTING=ON"
|
||||
shift
|
||||
;;
|
||||
*-withssh1)
|
||||
OPTIONS="${OPTIONS} -DWITH_SSH1=ON"
|
||||
shift
|
||||
;;
|
||||
*-withserver)
|
||||
OPTIONS="${OPTIONS} -DWITH_SERVER=ON"
|
||||
shift
|
||||
;;
|
||||
----noarg)
|
||||
echo "$ARG does not take an argument"
|
||||
@@ -1,30 +0,0 @@
|
||||
# - ADD_CHECK_TEST(test_name test_source linklib1 ... linklibN)
|
||||
|
||||
# Copyright (c) 2007 Daniel Gollub <dgollub@suse.de>
|
||||
# Copyright (c) 2007-2010 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.
|
||||
|
||||
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)
|
||||
|
||||
function (ADD_CMOCKA_TEST _testName _testSource)
|
||||
add_executable(${_testName} ${_testSource})
|
||||
target_link_libraries(${_testName} ${ARGN})
|
||||
add_test(${_testName} ${CMAKE_CURRENT_BINARY_DIR}/${_testName})
|
||||
endfunction (ADD_CMOCKA_TEST)
|
||||
@@ -1,26 +0,0 @@
|
||||
# - Check whether the C compiler supports a given flag in the
|
||||
# context of a stack checking compiler option.
|
||||
|
||||
# CHECK_C_COMPILER_FLAG_SSP(FLAG VARIABLE)
|
||||
#
|
||||
# FLAG - the compiler flag
|
||||
# VARIABLE - variable to store the result
|
||||
#
|
||||
# This actually calls check_c_source_compiles.
|
||||
# See help for CheckCSourceCompiles for a listing of variables
|
||||
# that can modify the build.
|
||||
|
||||
# Copyright (c) 2006, Alexander Neundorf, <neundorf@kde.org>
|
||||
#
|
||||
# Redistribution and use is allowed according to the terms of the BSD license.
|
||||
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
|
||||
|
||||
|
||||
include(CheckCSourceCompiles)
|
||||
|
||||
function(CHECK_C_COMPILER_FLAG_SSP _FLAG _RESULT)
|
||||
set(SAFE_CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS}")
|
||||
set(CMAKE_REQUIRED_DEFINITIONS "${_FLAG}")
|
||||
check_c_source_compiles("int main(int argc, char **argv) { char buffer[256]; return buffer[argc]=0;}" ${_RESULT})
|
||||
set(CMAKE_REQUIRED_DEFINITIONS "${SAFE_CMAKE_REQUIRED_DEFINITIONS}")
|
||||
endfunction(CHECK_C_COMPILER_FLAG_SSP)
|
||||
@@ -25,6 +25,3 @@ if (NOT CMAKE_BUILD_TYPE)
|
||||
"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)
|
||||
|
||||
@@ -1,84 +1,59 @@
|
||||
# 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)")
|
||||
if (${CMAKE_C_COMPILER_ID} MATCHES GNU)
|
||||
# add -Wconversion ?
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99 -pedantic -Wall -Wextra -Wshadow -Wmissing-prototypes -Wdeclaration-after-statement -Wunused -Wfloat-equal -Wpointer-arith -Wwrite-strings -Wformat-security -Wmissing-format-attribute")
|
||||
|
||||
# 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)
|
||||
|
||||
# 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("-fstack-protector" WITH_STACK_PROTECTOR)
|
||||
if (WITH_STACK_PROTECTOR)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fstack-protector")
|
||||
endif (WITH_STACK_PROTECTOR)
|
||||
|
||||
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)
|
||||
check_c_compiler_flag("-D_FORTIFY_SOURCE=2" WITH_FORTIFY_SOURCE)
|
||||
if (WITH_FORTIFY_SOURCE)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_FORTIFY_SOURCE=2")
|
||||
endif (WITH_FORTIFY_SOURCE)
|
||||
|
||||
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)")
|
||||
endif (${CMAKE_C_COMPILER_ID} MATCHES GNU)
|
||||
|
||||
#
|
||||
# Check for large filesystem support
|
||||
#
|
||||
if (CMAKE_SIZEOF_VOID_P MATCHES "8")
|
||||
# with large file support
|
||||
execute_process(
|
||||
COMMAND
|
||||
getconf LFS64_CFLAGS
|
||||
OUTPUT_VARIABLE
|
||||
_lfs_CFLAGS
|
||||
ERROR_QUIET
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
else (CMAKE_SIZEOF_VOID_P MATCHES "8")
|
||||
# with large file support
|
||||
execute_process(
|
||||
COMMAND
|
||||
getconf LFS_CFLAGS
|
||||
OUTPUT_VARIABLE
|
||||
_lfs_CFLAGS
|
||||
ERROR_QUIET
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
endif (CMAKE_SIZEOF_VOID_P MATCHES "8")
|
||||
if (_lfs_CFLAGS)
|
||||
string(REGEX REPLACE "[\r\n]" " " "${_lfs_CFLAGS}" "${${_lfs_CFLAGS}}")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${_lfs_CFLAGS}")
|
||||
endif (_lfs_CFLAGS)
|
||||
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)
|
||||
|
||||
# suppress warning about "deprecated" functions
|
||||
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")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_CRT_SECURE_NO_WARNINGS")
|
||||
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)
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
if (UNIX OR OS2)
|
||||
if (UNIX)
|
||||
IF (NOT APPLICATION_NAME)
|
||||
MESSAGE(STATUS "${PROJECT_NAME} is used as APPLICATION_NAME")
|
||||
SET(APPLICATION_NAME ${PROJECT_NAME})
|
||||
@@ -47,10 +47,6 @@ if (UNIX OR OS2)
|
||||
CACHE PATH "The subdirectory to the header prefix (default prefix/include)"
|
||||
)
|
||||
|
||||
set(CMAKE_INSTALL_DIR
|
||||
"${LIB_INSTALL_DIR}/cmake"
|
||||
CACHE PATH "The subdirectory to install cmake config files")
|
||||
|
||||
SET(DATA_INSTALL_DIR
|
||||
"${DATA_INSTALL_PREFIX}"
|
||||
CACHE PATH "The parent directory where applications can install their data (default prefix/share/${APPLICATION_NAME})"
|
||||
@@ -94,16 +90,18 @@ if (UNIX OR OS2)
|
||||
"${SHARE_INSTALL_PREFIX}/info"
|
||||
CACHE PATH "The ${APPLICATION_NAME} info install dir (default prefix/info)"
|
||||
)
|
||||
else()
|
||||
endif (UNIX)
|
||||
|
||||
if (WIN32)
|
||||
# Same same
|
||||
set(BIN_INSTALL_DIR "bin" CACHE PATH "-")
|
||||
set(SBIN_INSTALL_DIR "sbin" CACHE PATH "-")
|
||||
set(LIB_INSTALL_DIR "lib${LIB_SUFFIX}" CACHE PATH "-")
|
||||
set(SBIN_INSTALL_DIR "." CACHE PATH "-")
|
||||
set(LIB_INSTALL_DIR "lib" CACHE PATH "-")
|
||||
set(INCLUDE_INSTALL_DIR "include" CACHE PATH "-")
|
||||
set(CMAKE_INSTALL_DIR "CMake" CACHE PATH "-")
|
||||
set(PLUGIN_INSTALL_DIR "plugins" CACHE PATH "-")
|
||||
set(HTML_INSTALL_DIR "doc/HTML" CACHE PATH "-")
|
||||
set(ICON_INSTALL_DIR "icons" CACHE PATH "-")
|
||||
set(SOUND_INSTALL_DIR "soudns" CACHE PATH "-")
|
||||
set(ICON_INSTALL_DIR "." CACHE PATH "-")
|
||||
set(SOUND_INSTALL_DIR "." CACHE PATH "-")
|
||||
set(LOCALE_INSTALL_DIR "lang" CACHE PATH "-")
|
||||
endif ()
|
||||
endif (WIN32)
|
||||
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
# Set system vars
|
||||
|
||||
if (CMAKE_SYSTEM_NAME MATCHES "Linux")
|
||||
set(LINUX TRUE)
|
||||
endif(CMAKE_SYSTEM_NAME MATCHES "Linux")
|
||||
|
||||
if (CMAKE_SYSTEM_NAME MATCHES "FreeBSD")
|
||||
set(FREEBSD TRUE)
|
||||
set(BSD TRUE)
|
||||
endif (CMAKE_SYSTEM_NAME MATCHES "FreeBSD")
|
||||
|
||||
if (CMAKE_SYSTEM_NAME MATCHES "OpenBSD")
|
||||
set(OPENBSD TRUE)
|
||||
set(BSD TRUE)
|
||||
endif (CMAKE_SYSTEM_NAME MATCHES "OpenBSD")
|
||||
|
||||
if (CMAKE_SYSTEM_NAME MATCHES "NetBSD")
|
||||
set(NETBSD TRUE)
|
||||
set(BSD TRUE)
|
||||
endif (CMAKE_SYSTEM_NAME MATCHES "NetBSD")
|
||||
|
||||
if (CMAKE_SYSTEM_NAME MATCHES "(Solaris|SunOS)")
|
||||
set(SOLARIS TRUE)
|
||||
endif (CMAKE_SYSTEM_NAME MATCHES "(Solaris|SunOS)")
|
||||
|
||||
if (CMAKE_SYSTEM_NAME MATCHES "OS2")
|
||||
set(OS2 TRUE)
|
||||
endif (CMAKE_SYSTEM_NAME MATCHES "OS2")
|
||||
|
||||
if (CMAKE_SYSTEM_NAME MATCHES "Darwin")
|
||||
set (OSX TRUE)
|
||||
endif (CMAKE_SYSTEM_NAME MATCHES "Darwin")
|
||||
@@ -1,60 +0,0 @@
|
||||
# - Try to find Argp
|
||||
# Once done this will define
|
||||
#
|
||||
# ARGP_FOUND - system has Argp
|
||||
# ARGP_INCLUDE_DIRS - the Argp include directory
|
||||
# ARGP_LIBRARIES - Link these to use Argp
|
||||
# ARGP_DEFINITIONS - Compiler switches required for using Argp
|
||||
#
|
||||
# Copyright (c) 2010 Andreas Schneider <asn@cryptomilk.org>
|
||||
#
|
||||
# Redistribution and use is allowed according to the terms of the New
|
||||
# BSD license.
|
||||
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
|
||||
#
|
||||
|
||||
|
||||
if (ARGP_LIBRARIES AND ARGP_INCLUDE_DIRS)
|
||||
# in cache already
|
||||
set(ARGP_FOUND TRUE)
|
||||
else (ARGP_LIBRARIES AND ARGP_INCLUDE_DIRS)
|
||||
|
||||
find_path(ARGP_INCLUDE_DIR
|
||||
NAMES
|
||||
argp.h
|
||||
PATHS
|
||||
/usr/include
|
||||
/usr/local/include
|
||||
/opt/local/include
|
||||
/sw/include
|
||||
)
|
||||
|
||||
find_library(ARGP_LIBRARY
|
||||
NAMES
|
||||
argp
|
||||
PATHS
|
||||
/usr/lib
|
||||
/usr/local/lib
|
||||
/opt/local/lib
|
||||
/sw/lib
|
||||
)
|
||||
|
||||
set(ARGP_INCLUDE_DIRS
|
||||
${ARGP_INCLUDE_DIR}
|
||||
)
|
||||
|
||||
if (ARGP_LIBRARY)
|
||||
set(ARGP_LIBRARIES
|
||||
${ARGP_LIBRARIES}
|
||||
${ARGP_LIBRARY}
|
||||
)
|
||||
endif (ARGP_LIBRARY)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(Argp DEFAULT_MSG ARGP_LIBRARIES ARGP_INCLUDE_DIRS)
|
||||
|
||||
# show the ARGP_INCLUDE_DIRS and ARGP_LIBRARIES variables only in the advanced view
|
||||
mark_as_advanced(ARGP_INCLUDE_DIRS ARGP_LIBRARIES)
|
||||
|
||||
endif (ARGP_LIBRARIES AND ARGP_INCLUDE_DIRS)
|
||||
|
||||
@@ -1,66 +0,0 @@
|
||||
# - Try to find CMocka
|
||||
# Once done this will define
|
||||
#
|
||||
# CMOCKA_ROOT_DIR - Set this variable to the root installation of CMocka
|
||||
#
|
||||
# Read-Only variables:
|
||||
# CMOCKA_FOUND - system has CMocka
|
||||
# CMOCKA_INCLUDE_DIR - the CMocka include directory
|
||||
# CMOCKA_LIBRARIES - Link these to use CMocka
|
||||
# CMOCKA_DEFINITIONS - Compiler switches required for using CMocka
|
||||
#
|
||||
#=============================================================================
|
||||
# Copyright (c) 2011-2012 Andreas Schneider <asn@cryptomilk.org>
|
||||
#
|
||||
# Distributed under the OSI-approved BSD License (the "License");
|
||||
# see accompanying file Copyright.txt for details.
|
||||
#
|
||||
# This software is distributed WITHOUT ANY WARRANTY; without even the
|
||||
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
# See the License for more information.
|
||||
#=============================================================================
|
||||
#
|
||||
|
||||
set(_CMOCKA_ROOT_HINTS
|
||||
)
|
||||
|
||||
set(_CMOCKA_ROOT_PATHS
|
||||
"$ENV{PROGRAMFILES}/cmocka"
|
||||
)
|
||||
|
||||
find_path(CMOCKA_ROOT_DIR
|
||||
NAMES
|
||||
include/cmocka.h
|
||||
HINTS
|
||||
${_CMOCKA_ROOT_HINTS}
|
||||
PATHS
|
||||
${_CMOCKA_ROOT_PATHS}
|
||||
)
|
||||
mark_as_advanced(CMOCKA_ROOT_DIR)
|
||||
|
||||
find_path(CMOCKA_INCLUDE_DIR
|
||||
NAMES
|
||||
cmocka.h
|
||||
PATHS
|
||||
${CMOCKA_ROOT_DIR}/include
|
||||
)
|
||||
|
||||
find_library(CMOCKA_LIBRARY
|
||||
NAMES
|
||||
cmocka
|
||||
PATHS
|
||||
${CMOCKA_ROOT_DIR}/lib
|
||||
)
|
||||
|
||||
if (CMOCKA_LIBRARY)
|
||||
set(CMOCKA_LIBRARIES
|
||||
${CMOCKA_LIBRARIES}
|
||||
${CMOCKA_LIBRARY}
|
||||
)
|
||||
endif (CMOCKA_LIBRARY)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(CMocka DEFAULT_MSG CMOCKA_LIBRARIES CMOCKA_INCLUDE_DIR)
|
||||
|
||||
# show the CMOCKA_INCLUDE_DIR and CMOCKA_LIBRARIES variables only in the advanced view
|
||||
mark_as_advanced(CMOCKA_INCLUDE_DIR CMOCKA_LIBRARIES)
|
||||
@@ -6,70 +6,72 @@
|
||||
# GCRYPT_LIBRARIES - Link these to use GCrypt
|
||||
# GCRYPT_DEFINITIONS - Compiler switches required for using GCrypt
|
||||
#
|
||||
#=============================================================================
|
||||
# Copyright (c) 2009-2012 Andreas Schneider <asn@cryptomilk.org>
|
||||
# Copyright (c) 2009 Andreas Schneider <mail@cynapses.org>
|
||||
#
|
||||
# Distributed under the OSI-approved BSD License (the "License");
|
||||
# see accompanying file Copyright.txt for details.
|
||||
#
|
||||
# This software is distributed WITHOUT ANY WARRANTY; without even the
|
||||
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
# See the License for more information.
|
||||
#=============================================================================
|
||||
# Redistribution and use is allowed according to the terms of the New
|
||||
# BSD license.
|
||||
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
|
||||
#
|
||||
|
||||
set(_GCRYPT_ROOT_HINTS
|
||||
$ENV{GCRYTPT_ROOT_DIR}
|
||||
${GCRYPT_ROOT_DIR})
|
||||
|
||||
set(_GCRYPT_ROOT_PATHS
|
||||
"$ENV{PROGRAMFILES}/libgcrypt")
|
||||
if (GCRYPT_LIBRARIES AND GCRYPT_INCLUDE_DIRS)
|
||||
# in cache already
|
||||
set(GCRYPT_FOUND TRUE)
|
||||
else (GCRYPT_LIBRARIES AND GCRYPT_INCLUDE_DIRS)
|
||||
|
||||
set(_GCRYPT_ROOT_HINTS_AND_PATHS
|
||||
HINTS ${_GCRYPT_ROOT_HINTS}
|
||||
PATHS ${_GCRYPT_ROOT_PATHS})
|
||||
|
||||
|
||||
find_path(GCRYPT_INCLUDE_DIR
|
||||
find_path(GCRYPT_INCLUDE_DIR
|
||||
NAMES
|
||||
gcrypt.h
|
||||
HINTS
|
||||
${_GCRYPT_ROOT_HINTS_AND_PATHS}
|
||||
)
|
||||
gcrypt.h
|
||||
PATHS
|
||||
/usr/include
|
||||
/usr/local/include
|
||||
/opt/local/include
|
||||
/sw/include
|
||||
)
|
||||
mark_as_advanced(GCRYPT_INCLUDE_DIR)
|
||||
|
||||
find_library(GCRYPT_LIBRARY
|
||||
find_library(GCRYPT_LIBRARY
|
||||
NAMES
|
||||
gcrypt
|
||||
gcrypt11
|
||||
libgcrypt-11
|
||||
HINTS
|
||||
${_GCRYPT_ROOT_HINTS_AND_PATHS}
|
||||
)
|
||||
set(GCRYPT_LIBRARIES ${GCRYPT_LIBRARY})
|
||||
gcrypt
|
||||
PATHS
|
||||
/usr/lib
|
||||
/usr/local/lib
|
||||
/opt/local/lib
|
||||
/sw/lib
|
||||
)
|
||||
mark_as_advanced(GCRYPT_LIBRARY)
|
||||
|
||||
if (GCRYPT_INCLUDE_DIR)
|
||||
file(STRINGS "${GCRYPT_INCLUDE_DIR}/gcrypt.h" _gcrypt_version_str REGEX "^#define GCRYPT_VERSION \"[0-9]+.[0-9]+.[0-9]+\"")
|
||||
if (GCRYPT_LIBRARY)
|
||||
set(GCRYPT_FOUND TRUE CACHE INTERNAL "Wether the gcrypt library has been found" FORCE)
|
||||
endif (GCRYPT_LIBRARY)
|
||||
|
||||
string(REGEX REPLACE "^.*GCRYPT_VERSION.*([0-9]+.[0-9]+.[0-9]+).*" "\\1" GCRYPT_VERSION "${_gcrypt_version_str}")
|
||||
endif (GCRYPT_INCLUDE_DIR)
|
||||
set(GCRYPT_INCLUDE_DIRS
|
||||
${GCRYPT_INCLUDE_DIR}
|
||||
)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
if (GCRYPT_VERSION)
|
||||
find_package_handle_standard_args(GCrypt
|
||||
REQUIRED_VARS
|
||||
GCRYPT_INCLUDE_DIR
|
||||
GCRYPT_LIBRARIES
|
||||
VERSION_VAR
|
||||
GCRYPT_VERSION
|
||||
FAIL_MESSAGE
|
||||
"Could NOT find GCrypt, try to set the path to GCrypt root folder in the system variable GCRYPT_ROOT_DIR"
|
||||
if (GCRYPT_FOUND)
|
||||
set(GCRYPT_LIBRARIES
|
||||
${GCRYPT_LIBRARIES}
|
||||
${GCRYPT_LIBRARY}
|
||||
)
|
||||
else (GCRYPT_VERSION)
|
||||
find_package_handle_standard_args(GCrypt
|
||||
"Could NOT find GCrypt, try to set the path to GCrypt root folder in the system variable GCRYPT_ROOT_DIR"
|
||||
GCRYPT_INCLUDE_DIR
|
||||
GCRYPT_LIBRARIES)
|
||||
endif (GCRYPT_VERSION)
|
||||
endif (GCRYPT_FOUND)
|
||||
|
||||
if (GCRYPT_INCLUDE_DIRS AND GCRYPT_LIBRARIES)
|
||||
set(GCRYPT_FOUND TRUE)
|
||||
endif (GCRYPT_INCLUDE_DIRS AND GCRYPT_LIBRARIES)
|
||||
|
||||
if (GCRYPT_FOUND)
|
||||
if (NOT GCrypt_FIND_QUIETLY)
|
||||
message(STATUS "Found GCrypt: ${GCRYPT_LIBRARIES}")
|
||||
endif (NOT GCrypt_FIND_QUIETLY)
|
||||
else (GCRYPT_FOUND)
|
||||
if (GCrypt_FIND_REQUIRED)
|
||||
message(FATAL_ERROR "Could not find GCrypt")
|
||||
endif (GCrypt_FIND_REQUIRED)
|
||||
endif (GCRYPT_FOUND)
|
||||
|
||||
# show the GCRYPT_INCLUDE_DIRS and GCRYPT_LIBRARIES variables only in the advanced view
|
||||
mark_as_advanced(GCRYPT_INCLUDE_DIRS GCRYPT_LIBRARIES)
|
||||
|
||||
endif (GCRYPT_LIBRARIES AND GCRYPT_INCLUDE_DIRS)
|
||||
|
||||
# show the GCRYPT_INCLUDE_DIRS and GCRYPT_LIBRARIES variables only in the advanced view
|
||||
mark_as_advanced(GCRYPT_INCLUDE_DIR GCRYPT_LIBRARIES)
|
||||
|
||||
@@ -1,324 +0,0 @@
|
||||
# - Try to find GSSAPI
|
||||
# Once done this will define
|
||||
#
|
||||
# KRB5_CONFIG - Path to krb5-config
|
||||
# GSSAPI_ROOT_DIR - Set this variable to the root installation of GSSAPI
|
||||
#
|
||||
# Read-Only variables:
|
||||
# GSSAPI_FLAVOR_MIT - set to TURE if MIT Kerberos has been found
|
||||
# GSSAPI_FLAVOR_HEIMDAL - set to TRUE if Heimdal Keberos has been found
|
||||
# GSSAPI_FOUND - system has GSSAPI
|
||||
# GSSAPI_INCLUDE_DIR - the GSSAPI include directory
|
||||
# GSSAPI_LIBRARIES - Link these to use GSSAPI
|
||||
# GSSAPI_DEFINITIONS - Compiler switches required for using GSSAPI
|
||||
#
|
||||
#=============================================================================
|
||||
# Copyright (c) 2013 Andreas Schneider <asn@cryptomilk.org>
|
||||
#
|
||||
# Distributed under the OSI-approved BSD License (the "License");
|
||||
# see accompanying file Copyright.txt for details.
|
||||
#
|
||||
# This software is distributed WITHOUT ANY WARRANTY; without even the
|
||||
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
# See the License for more information.
|
||||
#=============================================================================
|
||||
#
|
||||
|
||||
find_path(GSSAPI_ROOT_DIR
|
||||
NAMES
|
||||
include/gssapi.h
|
||||
include/gssapi/gssapi.h
|
||||
HINTS
|
||||
${_GSSAPI_ROOT_HINTS}
|
||||
PATHS
|
||||
${_GSSAPI_ROOT_PATHS}
|
||||
)
|
||||
mark_as_advanced(GSSAPI_ROOT_DIR)
|
||||
|
||||
if (UNIX)
|
||||
find_program(KRB5_CONFIG
|
||||
NAMES
|
||||
krb5-config
|
||||
PATHS
|
||||
${GSSAPI_ROOT_DIR}/bin
|
||||
/opt/local/bin)
|
||||
mark_as_advanced(KRB5_CONFIG)
|
||||
|
||||
if (KRB5_CONFIG)
|
||||
# Check if we have MIT KRB5
|
||||
execute_process(
|
||||
COMMAND
|
||||
${KRB5_CONFIG} --vendor
|
||||
RESULT_VARIABLE
|
||||
_GSSAPI_VENDOR_RESULT
|
||||
OUTPUT_VARIABLE
|
||||
_GSSAPI_VENDOR_STRING)
|
||||
|
||||
if (_GSSAPI_VENDOR_STRING MATCHES ".*Massachusetts.*")
|
||||
set(GSSAPI_FLAVOR_MIT TRUE)
|
||||
else()
|
||||
execute_process(
|
||||
COMMAND
|
||||
${KRB5_CONFIG} --libs gssapi
|
||||
RESULT_VARIABLE
|
||||
_GSSAPI_LIBS_RESULT
|
||||
OUTPUT_VARIABLE
|
||||
_GSSAPI_LIBS_STRING)
|
||||
|
||||
if (_GSSAPI_LIBS_STRING MATCHES ".*roken.*")
|
||||
set(GSSAPI_FLAVOR_HEIMDAL TRUE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Get the include dir
|
||||
execute_process(
|
||||
COMMAND
|
||||
${KRB5_CONFIG} --cflags gssapi
|
||||
RESULT_VARIABLE
|
||||
_GSSAPI_INCLUDE_RESULT
|
||||
OUTPUT_VARIABLE
|
||||
_GSSAPI_INCLUDE_STRING)
|
||||
string(REGEX REPLACE "(\r?\n)+$" "" _GSSAPI_INCLUDE_STRING "${_GSSAPI_INCLUDE_STRING}")
|
||||
string(REGEX REPLACE " *-I" "" _GSSAPI_INCLUDEDIR "${_GSSAPI_INCLUDE_STRING}")
|
||||
endif()
|
||||
|
||||
if (NOT GSSAPI_FLAVOR_MIT AND NOT GSSAPI_FLAVOR_HEIMDAL)
|
||||
# Check for HEIMDAL
|
||||
find_package(PkgConfig)
|
||||
if (PKG_CONFIG_FOUND)
|
||||
pkg_check_modules(_GSSAPI heimdal-gssapi)
|
||||
endif (PKG_CONFIG_FOUND)
|
||||
|
||||
if (_GSSAPI_FOUND)
|
||||
set(GSSAPI_FLAVOR_HEIMDAL TRUE)
|
||||
else()
|
||||
find_path(_GSSAPI_ROKEN
|
||||
NAMES
|
||||
roken.h
|
||||
PATHS
|
||||
${GSSAPI_ROOT_DIR}/include
|
||||
${_GSSAPI_INCLUDEDIR})
|
||||
if (_GSSAPI_ROKEN)
|
||||
set(GSSAPI_FLAVOR_HEIMDAL TRUE)
|
||||
endif()
|
||||
endif ()
|
||||
endif()
|
||||
endif (UNIX)
|
||||
|
||||
find_path(GSSAPI_INCLUDE_DIR
|
||||
NAMES
|
||||
gssapi.h
|
||||
gssapi/gssapi.h
|
||||
PATHS
|
||||
${GSSAPI_ROOT_DIR}/include
|
||||
${_GSSAPI_INCLUDEDIR}
|
||||
)
|
||||
|
||||
if (GSSAPI_FLAVOR_MIT)
|
||||
find_library(GSSAPI_LIBRARY
|
||||
NAMES
|
||||
gssapi_krb5
|
||||
PATHS
|
||||
${GSSAPI_ROOT_DIR}/lib
|
||||
${_GSSAPI_LIBDIR}
|
||||
)
|
||||
|
||||
find_library(KRB5_LIBRARY
|
||||
NAMES
|
||||
krb5
|
||||
PATHS
|
||||
${GSSAPI_ROOT_DIR}/lib
|
||||
${_GSSAPI_LIBDIR}
|
||||
)
|
||||
|
||||
find_library(K5CRYPTO_LIBRARY
|
||||
NAMES
|
||||
k5crypto
|
||||
PATHS
|
||||
${GSSAPI_ROOT_DIR}/lib
|
||||
${_GSSAPI_LIBDIR}
|
||||
)
|
||||
|
||||
find_library(COM_ERR_LIBRARY
|
||||
NAMES
|
||||
com_err
|
||||
PATHS
|
||||
${GSSAPI_ROOT_DIR}/lib
|
||||
${_GSSAPI_LIBDIR}
|
||||
)
|
||||
|
||||
if (GSSAPI_LIBRARY)
|
||||
set(GSSAPI_LIBRARIES
|
||||
${GSSAPI_LIBRARIES}
|
||||
${GSSAPI_LIBRARY}
|
||||
)
|
||||
endif (GSSAPI_LIBRARY)
|
||||
|
||||
if (KRB5_LIBRARY)
|
||||
set(GSSAPI_LIBRARIES
|
||||
${GSSAPI_LIBRARIES}
|
||||
${KRB5_LIBRARY}
|
||||
)
|
||||
endif (KRB5_LIBRARY)
|
||||
|
||||
if (K5CRYPTO_LIBRARY)
|
||||
set(GSSAPI_LIBRARIES
|
||||
${GSSAPI_LIBRARIES}
|
||||
${K5CRYPTO_LIBRARY}
|
||||
)
|
||||
endif (K5CRYPTO_LIBRARY)
|
||||
|
||||
if (COM_ERR_LIBRARY)
|
||||
set(GSSAPI_LIBRARIES
|
||||
${GSSAPI_LIBRARIES}
|
||||
${COM_ERR_LIBRARY}
|
||||
)
|
||||
endif (COM_ERR_LIBRARY)
|
||||
endif (GSSAPI_FLAVOR_MIT)
|
||||
|
||||
if (GSSAPI_FLAVOR_HEIMDAL)
|
||||
find_library(GSSAPI_LIBRARY
|
||||
NAMES
|
||||
gssapi
|
||||
PATHS
|
||||
${GSSAPI_ROOT_DIR}/lib
|
||||
${_GSSAPI_LIBDIR}
|
||||
)
|
||||
|
||||
find_library(KRB5_LIBRARY
|
||||
NAMES
|
||||
krb5
|
||||
PATHS
|
||||
${GSSAPI_ROOT_DIR}/lib
|
||||
${_GSSAPI_LIBDIR}
|
||||
)
|
||||
|
||||
find_library(HCRYPTO_LIBRARY
|
||||
NAMES
|
||||
hcrypto
|
||||
PATHS
|
||||
${GSSAPI_ROOT_DIR}/lib
|
||||
${_GSSAPI_LIBDIR}
|
||||
)
|
||||
|
||||
find_library(COM_ERR_LIBRARY
|
||||
NAMES
|
||||
com_err
|
||||
PATHS
|
||||
${GSSAPI_ROOT_DIR}/lib
|
||||
${_GSSAPI_LIBDIR}
|
||||
)
|
||||
|
||||
find_library(HEIMNTLM_LIBRARY
|
||||
NAMES
|
||||
heimntlm
|
||||
PATHS
|
||||
${GSSAPI_ROOT_DIR}/lib
|
||||
${_GSSAPI_LIBDIR}
|
||||
)
|
||||
|
||||
find_library(HX509_LIBRARY
|
||||
NAMES
|
||||
hx509
|
||||
PATHS
|
||||
${GSSAPI_ROOT_DIR}/lib
|
||||
${_GSSAPI_LIBDIR}
|
||||
)
|
||||
|
||||
find_library(ASN1_LIBRARY
|
||||
NAMES
|
||||
asn1
|
||||
PATHS
|
||||
${GSSAPI_ROOT_DIR}/lib
|
||||
${_GSSAPI_LIBDIR}
|
||||
)
|
||||
|
||||
find_library(WIND_LIBRARY
|
||||
NAMES
|
||||
wind
|
||||
PATHS
|
||||
${GSSAPI_ROOT_DIR}/lib
|
||||
${_GSSAPI_LIBDIR}
|
||||
)
|
||||
|
||||
find_library(ROKEN_LIBRARY
|
||||
NAMES
|
||||
roken
|
||||
PATHS
|
||||
${GSSAPI_ROOT_DIR}/lib
|
||||
${_GSSAPI_LIBDIR}
|
||||
)
|
||||
|
||||
if (GSSAPI_LIBRARY)
|
||||
set(GSSAPI_LIBRARIES
|
||||
${GSSAPI_LIBRARIES}
|
||||
${GSSAPI_LIBRARY}
|
||||
)
|
||||
endif (GSSAPI_LIBRARY)
|
||||
|
||||
if (KRB5_LIBRARY)
|
||||
set(GSSAPI_LIBRARIES
|
||||
${GSSAPI_LIBRARIES}
|
||||
${KRB5_LIBRARY}
|
||||
)
|
||||
endif (KRB5_LIBRARY)
|
||||
|
||||
if (HCRYPTO_LIBRARY)
|
||||
set(GSSAPI_LIBRARIES
|
||||
${GSSAPI_LIBRARIES}
|
||||
${HCRYPTO_LIBRARY}
|
||||
)
|
||||
endif (HCRYPTO_LIBRARY)
|
||||
|
||||
if (COM_ERR_LIBRARY)
|
||||
set(GSSAPI_LIBRARIES
|
||||
${GSSAPI_LIBRARIES}
|
||||
${COM_ERR_LIBRARY}
|
||||
)
|
||||
endif (COM_ERR_LIBRARY)
|
||||
|
||||
if (HEIMNTLM_LIBRARY)
|
||||
set(GSSAPI_LIBRARIES
|
||||
${GSSAPI_LIBRARIES}
|
||||
${HEIMNTLM_LIBRARY}
|
||||
)
|
||||
endif (HEIMNTLM_LIBRARY)
|
||||
|
||||
if (HX509_LIBRARY)
|
||||
set(GSSAPI_LIBRARIES
|
||||
${GSSAPI_LIBRARIES}
|
||||
${HX509_LIBRARY}
|
||||
)
|
||||
endif (HX509_LIBRARY)
|
||||
|
||||
if (ASN1_LIBRARY)
|
||||
set(GSSAPI_LIBRARIES
|
||||
${GSSAPI_LIBRARIES}
|
||||
${ASN1_LIBRARY}
|
||||
)
|
||||
endif (ASN1_LIBRARY)
|
||||
|
||||
if (WIND_LIBRARY)
|
||||
set(GSSAPI_LIBRARIES
|
||||
${GSSAPI_LIBRARIES}
|
||||
${WIND_LIBRARY}
|
||||
)
|
||||
endif (WIND_LIBRARY)
|
||||
|
||||
if (ROKEN_LIBRARY)
|
||||
set(GSSAPI_LIBRARIES
|
||||
${GSSAPI_LIBRARIES}
|
||||
${WIND_LIBRARY}
|
||||
)
|
||||
endif (ROKEN_LIBRARY)
|
||||
endif (GSSAPI_FLAVOR_HEIMDAL)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(GSSAPI DEFAULT_MSG GSSAPI_LIBRARIES GSSAPI_INCLUDE_DIR)
|
||||
|
||||
if (GSSAPI_INCLUDE_DIRS AND GSSAPI_LIBRARIES)
|
||||
set(GSSAPI_FOUND TRUE)
|
||||
endif (GSSAPI_INCLUDE_DIRS AND GSSAPI_LIBRARIES)
|
||||
|
||||
# show the GSSAPI_INCLUDE_DIRS and GSSAPI_LIBRARIES variables only in the advanced view
|
||||
mark_as_advanced(GSSAPI_INCLUDE_DIRS GSSAPI_LIBRARIES)
|
||||
@@ -1,55 +0,0 @@
|
||||
# - Try to find NSIS
|
||||
# Once done this will define
|
||||
#
|
||||
# NSIS_ROOT_PATH - Set this variable to the root installation of NSIS
|
||||
#
|
||||
# Read-Only variables:
|
||||
#
|
||||
# NSIS_FOUND - system has NSIS
|
||||
# NSIS_MAKE - NSIS creator executable
|
||||
#
|
||||
#=============================================================================
|
||||
# Copyright (c) 2010-2013 Andreas Schneider <asn@cryptomilk.org>
|
||||
#
|
||||
# Distributed under the OSI-approved BSD License (the "License");
|
||||
# see accompanying file Copyright.txt for details.
|
||||
#
|
||||
# This software is distributed WITHOUT ANY WARRANTY; without even the
|
||||
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
# See the License for more information.
|
||||
#=============================================================================
|
||||
#
|
||||
|
||||
if (WIN32)
|
||||
set(_NSIS_ROOT_HINTS
|
||||
"[HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\NSIS;Default]")
|
||||
|
||||
set(_NSIS_ROOT_PATHS
|
||||
$ENV{PROGRAMFILES}/NSIS)
|
||||
|
||||
find_path(NSIS_ROOT_PATH
|
||||
NAMES
|
||||
Include/Library.nsh
|
||||
HINTS
|
||||
${_NSIS_ROOT_HINTS}
|
||||
PATHS
|
||||
${_NSIS_ROOT_PATHS}
|
||||
)
|
||||
mark_as_advanced(NSIS_ROOT_PATH)
|
||||
endif (WIN32)
|
||||
|
||||
find_program(NSIS_MAKE
|
||||
NAMES
|
||||
makensis
|
||||
PATHS
|
||||
${NSIS_ROOT_PATH}
|
||||
)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(NSIS DEFAULT_MSG NSIS_MAKE)
|
||||
|
||||
if (NSIS_MAKE)
|
||||
set(NSIS_FOUND TRUE)
|
||||
endif (NSIS_MAKE)
|
||||
|
||||
mark_as_advanced(NSIS_MAKE)
|
||||
@@ -1,61 +0,0 @@
|
||||
# - Try to find NaCl
|
||||
# Once done this will define
|
||||
#
|
||||
# NACL_FOUND - system has NaCl
|
||||
# NACL_INCLUDE_DIRS - the NaCl include directory
|
||||
# NACL_LIBRARIES - Link these to use NaCl
|
||||
# NACL_DEFINITIONS - Compiler switches required for using NaCl
|
||||
#
|
||||
# Copyright (c) 2010 Andreas Schneider <asn@cryptomilk.org>
|
||||
# Copyright (c) 2013 Aris Adamantiadis <aris@badcode.be>
|
||||
#
|
||||
# Redistribution and use is allowed according to the terms of the New
|
||||
# BSD license.
|
||||
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
|
||||
#
|
||||
|
||||
|
||||
if (NACL_LIBRARIES AND NACL_INCLUDE_DIRS)
|
||||
# in cache already
|
||||
set(NACL_FOUND TRUE)
|
||||
else (NACL_LIBRARIES AND NACL_INCLUDE_DIRS)
|
||||
|
||||
find_path(NACL_INCLUDE_DIR
|
||||
NAMES
|
||||
nacl/crypto_box_curve25519xsalsa20poly1305.h
|
||||
PATHS
|
||||
/usr/include
|
||||
/usr/local/include
|
||||
/opt/local/include
|
||||
/sw/include
|
||||
)
|
||||
|
||||
find_library(NACL_LIBRARY
|
||||
NAMES
|
||||
nacl
|
||||
PATHS
|
||||
/usr/lib
|
||||
/usr/local/lib
|
||||
/opt/local/lib
|
||||
/sw/lib
|
||||
)
|
||||
|
||||
set(NACL_INCLUDE_DIRS
|
||||
${NACL_INCLUDE_DIR}
|
||||
)
|
||||
|
||||
if (NACL_LIBRARY)
|
||||
set(NACL_LIBRARIES
|
||||
${NACL_LIBRARIES}
|
||||
${NACL_LIBRARY}
|
||||
)
|
||||
endif (NACL_LIBRARY)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(NaCl DEFAULT_MSG NACL_LIBRARIES NACL_INCLUDE_DIRS)
|
||||
|
||||
# show the NACL_INCLUDE_DIRS and NACL_LIBRARIES variables only in the advanced view
|
||||
mark_as_advanced(NACL_INCLUDE_DIRS NACL_LIBRARIES)
|
||||
|
||||
endif (NACL_LIBRARIES AND NACL_INCLUDE_DIRS)
|
||||
|
||||
185
cmake/Modules/FindOpenSSL.cmake
Normal file
185
cmake/Modules/FindOpenSSL.cmake
Normal file
@@ -0,0 +1,185 @@
|
||||
# - Try to find OpenSSL
|
||||
# Once done this will define
|
||||
#
|
||||
# OPENSSL_FOUND - system has OpenSSL
|
||||
# OPENSSL_INCLUDE_DIRS - the OpenSSL include directory
|
||||
# OPENSSL_LIBRARIES - Link these to use OpenSSL
|
||||
# OPENSSL_DEFINITIONS - Compiler switches required for using OpenSSL
|
||||
#
|
||||
# Copyright (c) 2009 Andreas Schneider <mail@cynapses.org>
|
||||
#
|
||||
# Redistribution and use is allowed according to the terms of the New
|
||||
# BSD license.
|
||||
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
|
||||
#
|
||||
|
||||
|
||||
if (OPENSSL_LIBRARIES AND OPENSSL_INCLUDE_DIRS)
|
||||
# in cache already
|
||||
set(OPENSSL_FOUND TRUE)
|
||||
else (OPENSSL_LIBRARIES AND OPENSSL_INCLUDE_DIRS)
|
||||
# use pkg-config to get the directories and then use these values
|
||||
# in the FIND_PATH() and FIND_LIBRARY() calls
|
||||
if (${CMAKE_MAJOR_VERSION} EQUAL 2 AND ${CMAKE_MINOR_VERSION} EQUAL 4)
|
||||
include(UsePkgConfig)
|
||||
pkgconfig(openssl _OPENSSL_INCLUDEDIR _OPENSSL_LIBDIR _OPENSSL_LDFLAGS _OPENSSL_CFLAGS)
|
||||
else (${CMAKE_MAJOR_VERSION} EQUAL 2 AND ${CMAKE_MINOR_VERSION} EQUAL 4)
|
||||
find_package(PkgConfig)
|
||||
if (PKG_CONFIG_FOUND)
|
||||
pkg_check_modules(_OPENSSL openssl)
|
||||
endif (PKG_CONFIG_FOUND)
|
||||
endif (${CMAKE_MAJOR_VERSION} EQUAL 2 AND ${CMAKE_MINOR_VERSION} EQUAL 4)
|
||||
|
||||
find_path(OPENSSL_INCLUDE_DIR
|
||||
NAMES
|
||||
openssl/ssl.h
|
||||
PATHS
|
||||
${_OPENSSL_DIR}/include
|
||||
${_OPENSSL_INCLUDEDIR}
|
||||
/usr/include
|
||||
/usr/local/include
|
||||
/usr/local/ssl/include
|
||||
/opt/local/include
|
||||
/sw/include
|
||||
/usr/lib/sfw/include
|
||||
)
|
||||
mark_as_advanced(OPENSSL_INCLUDE_DIR)
|
||||
|
||||
find_library(SSL_LIBRARY
|
||||
NAMES
|
||||
ssl
|
||||
libssl
|
||||
PATHS
|
||||
${_OPENSSL_DIR}/lib
|
||||
${_OPENSSL_LIBDIR}
|
||||
/usr/lib
|
||||
/usr/local/lib
|
||||
/usr/local/ssl/lib
|
||||
/opt/local/lib
|
||||
/sw/lib
|
||||
/usr/sfw/lib/64
|
||||
/usr/sfw/lib
|
||||
)
|
||||
mark_as_advanced(SSL_LIBRARY)
|
||||
|
||||
find_library(SSLEAY32_LIBRARY
|
||||
NAMES
|
||||
ssleay32
|
||||
PATHS
|
||||
${_OPENSSL_DIR}/lib
|
||||
${_OPENSSL_LIBDIR}
|
||||
/usr/lib
|
||||
/usr/local/lib
|
||||
/usr/local/ssl/lib
|
||||
/opt/local/lib
|
||||
/sw/lib
|
||||
/usr/sfw/lib/64
|
||||
/usr/sfw/lib
|
||||
)
|
||||
mark_as_advanced(SSLEAY32_LIBRARY)
|
||||
|
||||
find_library(SSLEAY32MD_LIBRARY
|
||||
NAMES
|
||||
ssleay32MD
|
||||
PATHS
|
||||
${_OPENSSL_DIR}/lib
|
||||
${_OPENSSL_LIBDIR}
|
||||
/usr/lib
|
||||
/usr/local/lib
|
||||
/usr/local/ssl/lib
|
||||
/opt/local/lib
|
||||
/sw/lib
|
||||
/usr/sfw/lib/64
|
||||
/usr/sfw/lib
|
||||
)
|
||||
mark_as_advanced(SSLEAY32MD_LIBRARY)
|
||||
|
||||
find_library(CRYPTO_LIBRARY
|
||||
NAMES
|
||||
crypto
|
||||
libcrypto
|
||||
eay
|
||||
eay32
|
||||
libeay
|
||||
libeay32
|
||||
PATHS
|
||||
${_OPENSSL_DIR}/lib
|
||||
${_OPENSSL_LIBDIR}
|
||||
/lib
|
||||
/usr/lib
|
||||
/usr/local/lib
|
||||
/usr/local/ssl/lib
|
||||
/opt/local/lib
|
||||
/sw/lib
|
||||
/usr/sfw/lib/64
|
||||
/usr/sfw/lib
|
||||
)
|
||||
mark_as_advanced(CRYPTO_LIBRARY)
|
||||
|
||||
if (SSL_LIBRARY)
|
||||
set(SSL_FOUND TRUE CACHE INTERNAL "Wether the ssl library has been found" FORCE)
|
||||
endif (SSL_LIBRARY)
|
||||
|
||||
if (SSLEAY32_LIBRARY)
|
||||
set(SSLEAY32_FOUND TRUE CACHE INTERNAL "Wether the ssleay32 library has been found" FORCE)
|
||||
endif (SSLEAY32_LIBRARY)
|
||||
|
||||
if (SSLEAY32MD_LIBRARY)
|
||||
set(SSLEAY32MD_FOUND TRUE CACHE INTERNAL "Wether the ssleay32MD library has been found" FORCE)
|
||||
endif (SSLEAY32MD_LIBRARY)
|
||||
|
||||
if (CRYPTO_LIBRARY)
|
||||
set(CRYPTO_FOUND TRUE CACHE INTERNAL "Wether the crypto library has been found" FORCE)
|
||||
endif (CRYPTO_LIBRARY)
|
||||
|
||||
set(OPENSSL_INCLUDE_DIRS
|
||||
${OPENSSL_INCLUDE_DIR}
|
||||
)
|
||||
|
||||
if (SSL_FOUND)
|
||||
set(OPENSSL_LIBRARIES
|
||||
${OPENSSL_LIBRARIES}
|
||||
${SSL_LIBRARY}
|
||||
)
|
||||
endif (SSL_FOUND)
|
||||
|
||||
if (SSLEAY32_FOUND)
|
||||
set(OPENSSL_LIBRARIES
|
||||
${OPENSSL_LIBRARIES}
|
||||
${SSLEAY32_LIBRARY}
|
||||
)
|
||||
endif (SSLEAY32_FOUND)
|
||||
|
||||
if (SSLEAY32MD_FOUND)
|
||||
set(OPENSSL_LIBRARIES
|
||||
${OPENSSL_LIBRARIES}
|
||||
${SSLEAY32MD_LIBRARY}
|
||||
)
|
||||
endif (SSLEAY32MD_FOUND)
|
||||
|
||||
if (CRYPTO_FOUND)
|
||||
set(OPENSSL_LIBRARIES
|
||||
${OPENSSL_LIBRARIES}
|
||||
${CRYPTO_LIBRARY}
|
||||
)
|
||||
endif (CRYPTO_FOUND)
|
||||
|
||||
if (OPENSSL_INCLUDE_DIRS AND OPENSSL_LIBRARIES)
|
||||
set(OPENSSL_FOUND TRUE)
|
||||
endif (OPENSSL_INCLUDE_DIRS AND OPENSSL_LIBRARIES)
|
||||
|
||||
if (OPENSSL_FOUND)
|
||||
if (NOT OpenSSL_FIND_QUIETLY)
|
||||
message(STATUS "Found OpenSSL: ${OPENSSL_LIBRARIES}")
|
||||
endif (NOT OpenSSL_FIND_QUIETLY)
|
||||
else (OPENSSL_FOUND)
|
||||
if (OpenSSL_FIND_REQUIRED)
|
||||
message(FATAL_ERROR "Could not find OpenSSL")
|
||||
endif (OpenSSL_FIND_REQUIRED)
|
||||
endif (OPENSSL_FOUND)
|
||||
|
||||
# show the OPENSSL_INCLUDE_DIRS and OPENSSL_LIBRARIES variables only in the advanced view
|
||||
mark_as_advanced(OPENSSL_INCLUDE_DIRS OPENSSL_LIBRARIES)
|
||||
|
||||
endif (OPENSSL_LIBRARIES AND OPENSSL_INCLUDE_DIRS)
|
||||
|
||||
81
cmake/Modules/FindZLIB.cmake
Normal file
81
cmake/Modules/FindZLIB.cmake
Normal file
@@ -0,0 +1,81 @@
|
||||
# - Try to find ZLIB
|
||||
# Once done this will define
|
||||
#
|
||||
# ZLIB_FOUND - system has ZLIB
|
||||
# ZLIB_INCLUDE_DIRS - the ZLIB include directory
|
||||
# ZLIB_LIBRARIES - Link these to use ZLIB
|
||||
# ZLIB_DEFINITIONS - Compiler switches required for using ZLIB
|
||||
#
|
||||
# Copyright (c) 2009 Andreas Schneider <mail@cynapses.org>
|
||||
#
|
||||
# Redistribution and use is allowed according to the terms of the New
|
||||
# BSD license.
|
||||
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
|
||||
#
|
||||
|
||||
|
||||
if (ZLIB_LIBRARIES AND ZLIB_INCLUDE_DIRS)
|
||||
# in cache already
|
||||
set(ZLIB_FOUND TRUE)
|
||||
else (ZLIB_LIBRARIES AND ZLIB_INCLUDE_DIRS)
|
||||
|
||||
find_path(ZLIB_INCLUDE_DIR
|
||||
NAMES
|
||||
zlib.h
|
||||
PATHS
|
||||
${_ZLIB_DIR}/include
|
||||
/usr/include
|
||||
/usr/local/include
|
||||
/opt/local/include
|
||||
/sw/include
|
||||
)
|
||||
mark_as_advanced(ZLIB_INCLUDE_DIR)
|
||||
|
||||
find_library(Z_LIBRARY
|
||||
NAMES
|
||||
z
|
||||
zlib
|
||||
zlib1
|
||||
PATHS
|
||||
${_ZLIB_DIR}/lib
|
||||
/usr/lib
|
||||
/usr/local/lib
|
||||
/opt/local/lib
|
||||
/sw/lib
|
||||
)
|
||||
mark_as_advanced(Z_LIBRARY)
|
||||
|
||||
if (Z_LIBRARY)
|
||||
set(Z_FOUND TRUE)
|
||||
endif (Z_LIBRARY)
|
||||
|
||||
set(ZLIB_INCLUDE_DIRS
|
||||
${ZLIB_INCLUDE_DIR}
|
||||
)
|
||||
|
||||
if (Z_FOUND)
|
||||
set(ZLIB_LIBRARIES
|
||||
${ZLIB_LIBRARIES}
|
||||
${Z_LIBRARY}
|
||||
)
|
||||
endif (Z_FOUND)
|
||||
|
||||
if (ZLIB_INCLUDE_DIRS AND ZLIB_LIBRARIES)
|
||||
set(ZLIB_FOUND TRUE)
|
||||
endif (ZLIB_INCLUDE_DIRS AND ZLIB_LIBRARIES)
|
||||
|
||||
if (ZLIB_FOUND)
|
||||
if (NOT ZLIB_FIND_QUIETLY)
|
||||
message(STATUS "Found ZLIB: ${ZLIB_LIBRARIES}")
|
||||
endif (NOT ZLIB_FIND_QUIETLY)
|
||||
else (ZLIB_FOUND)
|
||||
if (ZLIB_FIND_REQUIRED)
|
||||
message(FATAL_ERROR "Could not find ZLIB")
|
||||
endif (ZLIB_FIND_REQUIRED)
|
||||
endif (ZLIB_FOUND)
|
||||
|
||||
# show the ZLIB_INCLUDE_DIRS and ZLIB_LIBRARIES variables only in the advanced view
|
||||
mark_as_advanced(ZLIB_INCLUDE_DIRS ZLIB_LIBRARIES)
|
||||
|
||||
endif (ZLIB_LIBRARIES AND ZLIB_INCLUDE_DIRS)
|
||||
|
||||
21
cmake/Modules/MacroAddCompileFlags.cmake
Normal file
21
cmake/Modules/MacroAddCompileFlags.cmake
Normal file
@@ -0,0 +1,21 @@
|
||||
# - MACRO_ADD_COMPILE_FLAGS(target_name flag1 ... flagN)
|
||||
|
||||
# Copyright (c) 2006, Oswald Buddenhagen, <ossi@kde.org>
|
||||
# Copyright (c) 2006, Andreas Schneider, <mail@cynapses.org>
|
||||
#
|
||||
# Redistribution and use is allowed according to the terms of the BSD license.
|
||||
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
|
||||
|
||||
|
||||
macro (MACRO_ADD_COMPILE_FLAGS _target)
|
||||
|
||||
get_target_property(_flags ${_target} COMPILE_FLAGS)
|
||||
if (_flags)
|
||||
set(_flags ${_flags} ${ARGN})
|
||||
else (_flags)
|
||||
set(_flags ${ARGN})
|
||||
endif (_flags)
|
||||
|
||||
set_target_properties(${_target} PROPERTIES COMPILE_FLAGS ${_flags})
|
||||
|
||||
endmacro (MACRO_ADD_COMPILE_FLAGS)
|
||||
20
cmake/Modules/MacroAddLinkFlags.cmake
Normal file
20
cmake/Modules/MacroAddLinkFlags.cmake
Normal file
@@ -0,0 +1,20 @@
|
||||
# - MACRO_ADD_LINK_FLAGS(target_name flag1 ... flagN)
|
||||
|
||||
# Copyright (c) 2006, Oswald Buddenhagen, <ossi@kde.org>
|
||||
# Copyright (c) 2006, Andreas Schneider, <mail@cynapses.org>
|
||||
#
|
||||
# Redistribution and use is allowed according to the terms of the BSD license.
|
||||
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
|
||||
|
||||
macro (MACRO_ADD_LINK_FLAGS _target)
|
||||
|
||||
get_target_property(_flags ${_target} LINK_FLAGS)
|
||||
if (_flags)
|
||||
set(_flags "${_flags} ${ARGN}")
|
||||
else (_flags)
|
||||
set(_flags "${ARGN}")
|
||||
endif (_flags)
|
||||
|
||||
set_target_properties(${_target} PROPERTIES LINK_FLAGS "${_flags}")
|
||||
|
||||
endmacro (MACRO_ADD_LINK_FLAGS)
|
||||
30
cmake/Modules/MacroAddPlugin.cmake
Normal file
30
cmake/Modules/MacroAddPlugin.cmake
Normal file
@@ -0,0 +1,30 @@
|
||||
# - MACRO_ADD_PLUGIN(name [WITH_PREFIX] file1 .. fileN)
|
||||
#
|
||||
# Create a plugin from the given source files.
|
||||
# If WITH_PREFIX is given, the resulting plugin will have the
|
||||
# prefix "lib", otherwise it won't.
|
||||
#
|
||||
# Copyright (c) 2006, Alexander Neundorf, <neundorf@kde.org>
|
||||
# Copyright (c) 2006, Laurent Montel, <montel@kde.org>
|
||||
# Copyright (c) 2006, Andreas Schneider, <mail@cynapses.org>
|
||||
#
|
||||
# Redistribution and use is allowed according to the terms of the BSD license.
|
||||
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
|
||||
|
||||
|
||||
macro (MACRO_ADD_PLUGIN _target_NAME _with_PREFIX)
|
||||
|
||||
if (${_with_PREFIX} STREQUAL "WITH_PREFIX")
|
||||
set(_first_SRC)
|
||||
else (${_with_PREFIX} STREQUAL "WITH_PREFIX")
|
||||
set(_first_SRC ${_with_PREFIX})
|
||||
endif (${_with_PREFIX} STREQUAL "WITH_PREFIX")
|
||||
|
||||
add_library(${_target_NAME} MODULE ${_first_SRC} ${ARGN})
|
||||
|
||||
if (_first_SRC)
|
||||
set_target_properties(${_target_NAME} PROPERTIES PREFIX "")
|
||||
endif (_first_SRC)
|
||||
|
||||
endmacro (MACRO_ADD_PLUGIN _name _sources)
|
||||
|
||||
33
cmake/Modules/MacroCopyFile.cmake
Normal file
33
cmake/Modules/MacroCopyFile.cmake
Normal file
@@ -0,0 +1,33 @@
|
||||
# - macro_copy_file(_src _dst)
|
||||
# Copies a file to ${_dst} only if ${_src} is different (newer) than ${_dst}
|
||||
#
|
||||
# Example:
|
||||
# macro_copy_file(${CMAKE_CURRENT_SOURCE_DIR}/icon.png ${CMAKE_CURRENT_BINARY_DIR}/.)
|
||||
# Copies file icon.png to ${CMAKE_CURRENT_BINARY_DIR} directory
|
||||
#
|
||||
# Copyright (c) 2006-2007 Wengo
|
||||
# Copyright (c) 2006-2008 Andreas Schneider <mail@cynapses.org>
|
||||
#
|
||||
# Redistribution and use is allowed according to the terms of the BSD license.
|
||||
# For details see the accompanying COPYING file.
|
||||
|
||||
|
||||
macro (macro_copy_file _src _dst)
|
||||
# Removes all path containing .svn or CVS or CMakeLists.txt during the copy
|
||||
if (NOT ${_src} MATCHES ".*\\.svn|CVS|CMakeLists\\.txt.*")
|
||||
|
||||
if (CMAKE_VERBOSE_MAKEFILE)
|
||||
message(STATUS "Copy file from ${_src} to ${_dst}")
|
||||
endif (CMAKE_VERBOSE_MAKEFILE)
|
||||
|
||||
# Creates directory if necessary
|
||||
get_filename_component(_path ${_dst} PATH)
|
||||
file(MAKE_DIRECTORY ${_path})
|
||||
|
||||
execute_process(
|
||||
COMMAND
|
||||
${CMAKE_COMMAND} -E copy_if_different ${_src} ${_dst}
|
||||
OUTPUT_QUIET
|
||||
)
|
||||
endif (NOT ${_src} MATCHES ".*\\.svn|CVS|CMakeLists\\.txt.*")
|
||||
endmacro (macro_copy_file)
|
||||
@@ -2,18 +2,10 @@
|
||||
#
|
||||
# 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.
|
||||
# The doxygen target is added to the doc target as 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})
|
||||
@@ -21,120 +13,88 @@
|
||||
# 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".
|
||||
# DOXYFILE_OUTPUT_DIR - Path where the Doxygen output is stored. Defaults to "doc".
|
||||
#
|
||||
# DOXYFILE_LATEX_DIR - Directory where the Doxygen LaTeX output is stored. Defaults to "latex".
|
||||
#
|
||||
# DOXYFILE_HTML_DIR - Directory where the Doxygen html output is stored. Defaults to "html".
|
||||
#
|
||||
|
||||
#
|
||||
# Copyright (c) 2009, 2010, 2011 Tobias Rautenkranz <tobias@rautenkranz.ch>
|
||||
# Copyright (c) 2009-2010 Tobias Rautenkranz <tobias@rautenkranz.ch>
|
||||
# Copyright (c) 2010 Andreas Schneider <mail@cynapses.org>
|
||||
#
|
||||
# Redistribution and use is allowed according to the terms of the New
|
||||
# BSD license.
|
||||
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
|
||||
#
|
||||
|
||||
macro(usedoxygen_set_default name value type docstring)
|
||||
if(NOT DEFINED "${name}")
|
||||
set("${name}" "${value}" CACHE "${type}" "${docstring}")
|
||||
endif()
|
||||
macro(usedoxygen_set_default name value)
|
||||
if(NOT DEFINED "${name}")
|
||||
set("${name}" "${value}")
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
find_package(Doxygen)
|
||||
|
||||
if(DOXYGEN_FOUND)
|
||||
find_file(DOXYFILE_IN "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")
|
||||
find_file(DOXYFILE_IN
|
||||
NAMES
|
||||
doxy.config.in
|
||||
PATHS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${CMAKE_ROOT}/Modules/
|
||||
NO_DEFAULT_PATH)
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(DOXYFILE_IN DEFAULT_MSG "DOXYFILE_IN")
|
||||
endif()
|
||||
|
||||
if(DOXYGEN_FOUND AND DOXYFILE_IN_FOUND)
|
||||
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}")
|
||||
add_custom_target(doxygen ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/doxy.config)
|
||||
|
||||
usedoxygen_set_default(DOXYFILE_LATEX YES BOOL "Generate LaTeX API documentation" OFF)
|
||||
usedoxygen_set_default(DOXYFILE_LATEX_DIR "latex" STRING "LaTex output directory")
|
||||
usedoxygen_set_default(DOXYFILE_OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}")
|
||||
usedoxygen_set_default(DOXYFILE_HTML_DIR "html")
|
||||
|
||||
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}")
|
||||
|
||||
set(DOXYFILE_LATEX FALSE)
|
||||
set(DOXYFILE_PDFLATEX FALSE)
|
||||
set(DOXYFILE_DOT FALSE)
|
||||
|
||||
set_property(DIRECTORY
|
||||
APPEND PROPERTY
|
||||
ADDITIONAL_MAKE_CLEAN_FILES
|
||||
"${DOXYFILE_OUTPUT_DIR}/${DOXYFILE_HTML_DIR}")
|
||||
find_package(LATEX)
|
||||
if(LATEX_COMPILER AND MAKEINDEX_COMPILER)
|
||||
set(DOXYFILE_LATEX TRUE)
|
||||
usedoxygen_set_default(DOXYFILE_LATEX_DIR "latex")
|
||||
|
||||
add_custom_target(doxygen
|
||||
COMMAND "${DOXYGEN_EXECUTABLE}"
|
||||
"${DOXYFILE}"
|
||||
COMMENT "Writing documentation to ${DOXYFILE_OUTPUT_DIR}..."
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
set_property(DIRECTORY APPEND PROPERTY
|
||||
ADDITIONAL_MAKE_CLEAN_FILES
|
||||
"${DOXYFILE_OUTPUT_DIR}/${DOXYFILE_LATEX_DIR}")
|
||||
|
||||
set(DOXYFILE_DOT "NO")
|
||||
if(DOXYGEN_DOT_EXECUTABLE)
|
||||
set(DOXYFILE_DOT "YES")
|
||||
endif()
|
||||
if(PDFLATEX_COMPILER)
|
||||
set(DOXYFILE_PDFLATEX TRUE)
|
||||
endif()
|
||||
if(DOXYGEN_DOT_EXECUTABLE)
|
||||
set(DOXYFILE_DOT TRUE)
|
||||
endif()
|
||||
|
||||
## LaTeX
|
||||
set(DOXYFILE_PDFLATEX "NO")
|
||||
add_custom_command(TARGET doxygen
|
||||
POST_BUILD
|
||||
COMMAND ${CMAKE_MAKE_PROGRAM}
|
||||
WORKING_DIRECTORY "${DOXYFILE_OUTPUT_DIR}/${DOXYFILE_LATEX_DIR}")
|
||||
endif()
|
||||
|
||||
set_property(DIRECTORY APPEND PROPERTY
|
||||
ADDITIONAL_MAKE_CLEAN_FILES
|
||||
"${DOXYFILE_OUTPUT_DIR}/${DOXYFILE_LATEX_DIR}")
|
||||
configure_file(${DOXYFILE_IN} ${CMAKE_CURRENT_BINARY_DIR}/doxy.config ESCAPE_QUOTES IMMEDIATE @ONLY)
|
||||
if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/doxy.trac.in)
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/doxy.trac.in ${CMAKE_CURRENT_BINARY_DIR}/doxy.trac ESCAPE_QUOTES IMMEDIATE @ONLY)
|
||||
add_custom_target(doxygen-trac ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/doxy.trac)
|
||||
endif()
|
||||
|
||||
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()
|
||||
get_target_property(DOC_TARGET doc TYPE)
|
||||
if(NOT DOC_TARGET)
|
||||
add_custom_target(doc)
|
||||
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)
|
||||
add_dependencies(doc doxygen)
|
||||
endif()
|
||||
|
||||
124
config.h.cmake
124
config.h.cmake
@@ -17,30 +17,12 @@
|
||||
/* Define to 1 if you have the <argp.h> header file. */
|
||||
#cmakedefine HAVE_ARGP_H 1
|
||||
|
||||
/* Define to 1 if you have the <aprpa/inet.h> header file. */
|
||||
#cmakedefine HAVE_ARPA_INET_H 1
|
||||
|
||||
/* Define to 1 if you have the <pty.h> header file. */
|
||||
#cmakedefine HAVE_PTY_H 1
|
||||
|
||||
/* Define to 1 if you have the <utmp.h> header file. */
|
||||
#cmakedefine HAVE_UTMP_H 1
|
||||
|
||||
/* Define to 1 if you have the <util.h> header file. */
|
||||
#cmakedefine HAVE_UTIL_H 1
|
||||
|
||||
/* Define to 1 if you have the <libutil.h> header file. */
|
||||
#cmakedefine HAVE_LIBUTIL_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/time.h> header file. */
|
||||
#cmakedefine HAVE_SYS_TIME_H 1
|
||||
|
||||
/* Define to 1 if you have the <termios.h> header file. */
|
||||
#cmakedefine HAVE_TERMIOS_H 1
|
||||
|
||||
/* Define to 1 if you have the <unistd.h> header file. */
|
||||
#cmakedefine HAVE_UNISTD_H 1
|
||||
|
||||
/* Define to 1 if you have the <openssl/aes.h> header file. */
|
||||
#cmakedefine HAVE_OPENSSL_AES_H 1
|
||||
|
||||
@@ -53,52 +35,29 @@
|
||||
/* Define to 1 if you have the <openssl/des.h> header file. */
|
||||
#cmakedefine HAVE_OPENSSL_DES_H 1
|
||||
|
||||
/* Define to 1 if you have the <openssl/ecdh.h> header file. */
|
||||
#cmakedefine HAVE_OPENSSL_ECDH_H 1
|
||||
|
||||
/* Define to 1 if you have the <openssl/ec.h> header file. */
|
||||
#cmakedefine HAVE_OPENSSL_EC_H 1
|
||||
|
||||
/* Define to 1 if you have the <openssl/ecdsa.h> header file. */
|
||||
#cmakedefine HAVE_OPENSSL_ECDSA_H 1
|
||||
|
||||
/* Define to 1 if you have the <pthread.h> header file. */
|
||||
#cmakedefine HAVE_PTHREAD_H 1
|
||||
|
||||
/* Define to 1 if you have eliptic curve cryptography in openssl */
|
||||
#cmakedefine HAVE_OPENSSL_ECC 1
|
||||
|
||||
/* Define to 1 if you have eliptic curve cryptography in gcrypt */
|
||||
#cmakedefine HAVE_GCRYPT_ECC 1
|
||||
|
||||
/* Define to 1 if you have eliptic curve cryptography */
|
||||
#cmakedefine HAVE_ECC 1
|
||||
|
||||
/*************************** FUNCTIONS ***************************/
|
||||
|
||||
/* Define to 1 if you have the `snprintf' function. */
|
||||
#cmakedefine HAVE_SNPRINTF 1
|
||||
|
||||
/* Define to 1 if you have the `_snprintf' function. */
|
||||
#cmakedefine HAVE__SNPRINTF 1
|
||||
|
||||
/* Define to 1 if you have the `_snprintf_s' function. */
|
||||
#cmakedefine HAVE__SNPRINTF_S 1
|
||||
|
||||
/* Define to 1 if you have the `vsnprintf' function. */
|
||||
#cmakedefine HAVE_VSNPRINTF 1
|
||||
#cmakedefine HAVE_VSNPRINTF
|
||||
|
||||
/* Define to 1 if you have the `_vsnprintf' function. */
|
||||
#cmakedefine HAVE__VSNPRINTF 1
|
||||
#cmakedefine HAVE__VSNPRINTF
|
||||
|
||||
/* Define to 1 if you have the `_vsnprintf_s' function. */
|
||||
#cmakedefine HAVE__VSNPRINTF_S 1
|
||||
#cmakedefine HAVE__VSNPRINTF_S
|
||||
|
||||
/* Define to 1 if you have the `snprintf' function. */
|
||||
#cmakedefine HAVE_SNPRINTF
|
||||
|
||||
/* Define to 1 if you have the `_snprintf' function. */
|
||||
#cmakedefine HAVE__SNPRINTF
|
||||
|
||||
/* Define to 1 if you have the `_snprintf_s' function. */
|
||||
#cmakedefine HAVE__SNPRINTF_S
|
||||
|
||||
/* Define to 1 if you have the `isblank' function. */
|
||||
#cmakedefine HAVE_ISBLANK 1
|
||||
|
||||
/* Define to 1 if you have the `strncpy' function. */
|
||||
#cmakedefine HAVE_STRNCPY 1
|
||||
#cmakedefine HAVE_STRNCPY
|
||||
|
||||
/* Define to 1 if you have the `cfmakeraw' function. */
|
||||
#cmakedefine HAVE_CFMAKERAW 1
|
||||
@@ -106,29 +65,17 @@
|
||||
/* Define to 1 if you have the `getaddrinfo' function. */
|
||||
#cmakedefine HAVE_GETADDRINFO 1
|
||||
|
||||
/* Define to 1 if you have the `gethostbyname' function. */
|
||||
#cmakedefine HAVE_GETHOSTBYNAME 1
|
||||
|
||||
/* Define to 1 if you have the `poll' function. */
|
||||
#cmakedefine HAVE_POLL 1
|
||||
|
||||
/* Define to 1 if you have the `select' function. */
|
||||
#cmakedefine HAVE_SELECT 1
|
||||
|
||||
/* Define to 1 if you have the `clock_gettime' function. */
|
||||
#cmakedefine HAVE_CLOCK_GETTIME 1
|
||||
|
||||
/* Define to 1 if you have the `ntohll' function. */
|
||||
#cmakedefine HAVE_NTOHLL 1
|
||||
|
||||
/* Define to 1 if you have the `htonll' function. */
|
||||
#cmakedefine HAVE_HTONLL 1
|
||||
|
||||
/* Define to 1 if you have the `strtoull' function. */
|
||||
#cmakedefine HAVE_STRTOULL 1
|
||||
|
||||
/* Define to 1 if you have the `__strtoull' function. */
|
||||
#cmakedefine HAVE___STRTOULL 1
|
||||
|
||||
/* Define to 1 if you have the `_strtoui64' function. */
|
||||
#cmakedefine HAVE__STRTOUI64 1
|
||||
/* Define to 1 if you have the `regcomp' function. */
|
||||
#cmakedefine HAVE_REGCOMP 1
|
||||
|
||||
/*************************** LIBRARIES ***************************/
|
||||
|
||||
@@ -138,25 +85,13 @@
|
||||
/* Define to 1 if you have the `gcrypt' library (-lgcrypt). */
|
||||
#cmakedefine HAVE_LIBGCRYPT 1
|
||||
|
||||
/* Define to 1 if you have the `pthread' library (-lpthread). */
|
||||
#cmakedefine HAVE_PTHREAD 1
|
||||
/* Define to 1 if you have the `z' library (-lz). */
|
||||
#cmakedefine HAVE_LIBZ 1
|
||||
|
||||
/**************************** OPTIONS ****************************/
|
||||
|
||||
#cmakedefine HAVE_GCC_THREAD_LOCAL_STORAGE 1
|
||||
#cmakedefine HAVE_MSC_THREAD_LOCAL_STORAGE 1
|
||||
|
||||
#cmakedefine HAVE_GCC_VOLATILE_MEMORY_PROTECTION 1
|
||||
#cmakedefine HAVE_GCC_NARG_MACRO 1
|
||||
|
||||
#cmakedefine HAVE_COMPILER__FUNC__ 1
|
||||
#cmakedefine HAVE_COMPILER__FUNCTION__ 1
|
||||
|
||||
/* Define to 1 if you want to enable GSSAPI */
|
||||
#cmakedefine WITH_GSSAPI 1
|
||||
|
||||
/* Define to 1 if you want to enable ZLIB */
|
||||
#cmakedefine WITH_ZLIB 1
|
||||
#cmakedefine WITH_LIBZ 1
|
||||
|
||||
/* Define to 1 if you want to enable SFTP */
|
||||
#cmakedefine WITH_SFTP 1
|
||||
@@ -176,11 +111,22 @@
|
||||
/* Define to 1 if you want to enable calltrace debug output */
|
||||
#cmakedefine DEBUG_CALLTRACE 1
|
||||
|
||||
/* Define to 1 if you want to enable NaCl support */
|
||||
#cmakedefine WITH_NACL 1
|
||||
|
||||
/*************************** ENDIAN *****************************/
|
||||
|
||||
/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
|
||||
significant byte first (like Motorola and SPARC, unlike Intel). */
|
||||
#cmakedefine WORDS_BIGENDIAN 1
|
||||
|
||||
/************************* MS Windows ***************************/
|
||||
|
||||
#ifdef _WIN32
|
||||
# ifdef _MSC_VER
|
||||
/* On Microsoft compilers define inline to __inline on all others use inline */
|
||||
# undef inline
|
||||
# define inline __inline
|
||||
|
||||
# undef strdup
|
||||
# define strdup _strdup
|
||||
# endif // _MSC_VER
|
||||
#endif /* _WIN32 */
|
||||
|
||||
|
||||
886
doc/API.html
Normal file
886
doc/API.html
Normal file
@@ -0,0 +1,886 @@
|
||||
<!DOCTYPE HTML SYSTEM>
|
||||
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=ISO-8859-1">
|
||||
<head>
|
||||
<title>
|
||||
Libssh's Documentation
|
||||
</title>
|
||||
<link href="style.css" rel="stylesheet" type="text/css">
|
||||
</head>
|
||||
|
||||
<div id="titre">
|
||||
<div align="center">
|
||||
LIBSSH API GUIDE <br>
|
||||
Or everything you ever wanted to know about a simple and fast ssh library.
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h2> 0 Introduction</h2>
|
||||
|
||||
<div class="tout">
|
||||
Before inserting ssh hooks into your programs, you must know some basics about
|
||||
the ssh protocol, and understand why the ssh library must implement them. <br>
|
||||
Lot of the protocols specifications are hidden by the ssh library API (of
|
||||
course !) but some still needs an attention from the end-user programmer.<br>
|
||||
Note that libssh is still an alpha product, and the API may vary from one
|
||||
version to another. The only guess I can make is that the API won't radically
|
||||
change. <br>
|
||||
The SSH protocol was designed for some goals which I resume here : <br>
|
||||
-Privacy of data<br>
|
||||
-Security<br>
|
||||
-Authentication of the server<br>
|
||||
-Authentication of the client.<br>
|
||||
The client MUST be sure who's speaking to before entering into any
|
||||
authentication way. That's where the end programmer must ensure the given
|
||||
fingerprints *are* from the legitimate server. A ssh connection must follow
|
||||
the following steps:<br>
|
||||
<br>
|
||||
1- Before connecting the socket, you can set up if you wish one or other
|
||||
server public key authentication ie. DSA or RSA.
|
||||
You can choose cryptographic algorithms you trust and compression algorithms
|
||||
if any.<br>
|
||||
2- The connection is made. A secure handshake is made, and resulting from it,
|
||||
a public key from the server is gained.
|
||||
You MUST verify that the public key is legitimate.<br>
|
||||
3- The client must authenticate : the two implemented ways are password, and
|
||||
public keys (from dsa and rsa key-pairs generated by openssh). It is
|
||||
harmless to authenticate to a fake server with these keys because the
|
||||
protocol ensures the data you sign can't be used twice. It just avoids
|
||||
man-in-the-middle attacks.<br>
|
||||
4- Now that the user has been authenticated, you must open one or several
|
||||
channels. channels are different subways for information into a single ssh
|
||||
connection. Each channel has a standard stream (stdout) and an error
|
||||
stream (stderr). You can theoretically open an infinity of channel.<br>
|
||||
5- With the channel you opened, you can do several things :<br>
|
||||
-Open a shell. You may want to request a pseudo virtual terminal before <br>
|
||||
-Execute a command. The virtual terminal is usable, too<br>
|
||||
-Invoke the sftp subsystem. (look at chapter 6)<br>
|
||||
-invoke your own subsystem. This is out the scope of this
|
||||
document but it is easy to do.<br>
|
||||
6- When everything is finished, just close the channels, and then the
|
||||
connection.<br>
|
||||
<br>
|
||||
At every place, a function which returns an error code (typically -1 for int
|
||||
values, NULL for pointers) also sets an error message and an error code.
|
||||
I high-lined the main steps, now that's you to follow them :)
|
||||
<br>
|
||||
</div>
|
||||
<h2> 1- Setting the options </h2>
|
||||
<div class="tout">
|
||||
The options mechanism will change during updates of the library, but the
|
||||
functions which exists now will certainly be kept.
|
||||
<br><br>
|
||||
The ssh system needs to know the preferences of the user, the trust into one
|
||||
or another algorithm and such. More important informations have to be given
|
||||
before connecting : the host name of the server, the port (if non default),
|
||||
the binding address, the default username, ... <br>
|
||||
The options structure is given to a ssh_connect function, then this option
|
||||
structure is used again and again by the ssh implementation. you shall not
|
||||
free it manually, and you shall not share it with multiple sessions.<br>
|
||||
Two ways are given for setting the options : the easy one (of course !) and
|
||||
the long-but-accurate one.<br><br>
|
||||
</div>
|
||||
<h3>a) the easy way</h3><br>
|
||||
<div class="tout">
|
||||
Lot of ssh options in fact come from the command line of the program... <br>
|
||||
you could parse them and then use the long way for every argument, but libssh
|
||||
has a mechanism to do that for you, automatically.<br>
|
||||
<br>
|
||||
<div class="prot">
|
||||
SSH_OPTIONS *ssh_getopt(int *argcptr, char **argv);
|
||||
</div>
|
||||
this function will return you a new options pointer based on the arguments
|
||||
you give in parameters. <br> better, they clean the argv array from used parameters
|
||||
so you can use them after in your own program<br>
|
||||
<div class="ex">
|
||||
int main(int argc, char **argv){<br>
|
||||
SSH_OPTIONS *opt;<br>
|
||||
opt=ssh_getopt(&argc, argv);<br>
|
||||
if(!opt){<br>
|
||||
...<br>
|
||||
}<br>
|
||||
</div>
|
||||
the function will return NULL if some problem is appearing.<br>
|
||||
As a matter of portability for you own programs, the hostname isn't always<br>
|
||||
the first argument from the command line, so the single arguments (not
|
||||
preceded by a -something) won't be parsed.<br>
|
||||
<div class="ex">
|
||||
example: <br>
|
||||
user@host:~$ myssh -u aris localhost <br>
|
||||
-u aris will be caught, localhost will not.<br>
|
||||
</div>
|
||||
|
||||
cfr the options_set_user() function in the next part for more informations
|
||||
about it.<br>
|
||||
</div>
|
||||
<h3>b) the long way</h3>
|
||||
<div class="tout">
|
||||
<div class="prot">
|
||||
SSH_OPTIONS *options_new();
|
||||
</div>
|
||||
This function returns an empty but initialized option structure pointer.<br>
|
||||
The structure is freed by ssh_disconnect described later, so don't use the
|
||||
existing function options_free() (it's an internal function).<br>
|
||||
So : use it only for <b>one</b> ssh_connect(), <b>never</b> free it.<br>
|
||||
<br>
|
||||
<div class="prot">
|
||||
SSH_OPTIONS *options_copy(SSH_OPTIONS *opt);
|
||||
</div>
|
||||
If you need to replicate an option object before using it, use this function.
|
||||
<br><br>
|
||||
|
||||
The following functions are all of the following form : <br>
|
||||
<div class="prot">
|
||||
int options_set_something(SSH_OPTIONS *opt, something);
|
||||
</div>
|
||||
the something parameters are always internaly copied, so you don't have to
|
||||
strdup them.<br>
|
||||
some return eather 0 or -1, in which case an error message appears in the
|
||||
error functions, others never fail (return void)<br>
|
||||
the error codes and descriptions for these functions are recoverable throught <i>ssh_get_error(NULL);</i>
|
||||
<br>
|
||||
<div class="prot">
|
||||
int options_set_wanted_method(SSH_OPTIONS *opt,int method, char *list);
|
||||
</div>
|
||||
Passing an option structure, a ssh macro for the method, and a list of allowed
|
||||
parameters indicates libssh you want to use these.<br>
|
||||
The macros are :<br>
|
||||
KEX_ALGO<br>
|
||||
KEX_HOSTKEY Server public key type expected<br>
|
||||
KEX_CRYPT_C_S 2 Cryptographic algorithm client->server<br>
|
||||
KEX_CRYPT_S_C 3 Cryptographic algorithm server->client<br>
|
||||
KEX_MAC_C_S 4<br>
|
||||
KEX_MAC_S_C 5<br>
|
||||
KEX_COMP_C_S 6 Compression method for the stream ("zlib" or "none"), client to server<br>
|
||||
KEX_COMP_S_C 7 Compression method for the stream ("zlib" or "none"), server to client<br>
|
||||
KEX_LANG_C_S 8<br>
|
||||
KEX_LANG_S_C 9<br>
|
||||
<br>
|
||||
Currently, only KEX_HOSTKEY and ,KEX_CRYPT_C_S,S_C, KEX_COMP_C_S and S_C work
|
||||
as expected. the list is a comma separated string of prefered
|
||||
algorithms/methods, in order of preference.<br>
|
||||
<br>
|
||||
<div class="ex">
|
||||
example : this sets the ssh stream to be compressed in client->server mode only
|
||||
<br>
|
||||
|
||||
ret = option_set_wanted_method(options,KEX_COMP_C_S,"zlib");
|
||||
</div>
|
||||
<div class="ex">
|
||||
example: this will set the cryptographic algorithms wanted from server to
|
||||
client to aes128-cbc and then aes192-cbc if the first one isn't supported by
|
||||
server:<br>
|
||||
ret = option_set_wanted_method(options,KEX_CRYPT_S_C,"aes128-cbc,aes192-cbc");
|
||||
</div>
|
||||
<div class="ex">
|
||||
if you prefer getting the Dss key from a server instead of rsa, but you still
|
||||
accept rsa if dss isn't available :<br>
|
||||
options_set_wanted_method(options,KEX_HOSTKEY,"ssh-dss,ssh-rsa");
|
||||
</div>
|
||||
return value: <br>0 if the option is valid, -1 else.<br> An error is set in that case.
|
||||
<br><br>
|
||||
<div class="prot">
|
||||
void options_set_port(SSH_OPTIONS *opt, unsigned int port);
|
||||
</div>
|
||||
this function sets the server port.
|
||||
<div class="prot">
|
||||
void options_set_host(SSH_OPTIONS *opt, const char *hostname);
|
||||
</div>
|
||||
this function sets the hostname of the server. It also supports
|
||||
"user@hostname" syntax in which case the user options is set too.
|
||||
<div class="prot">
|
||||
void options_set_fd(SSH_OPTIONS *opt, int fd);
|
||||
</div>
|
||||
permits you to specify an opened file descriptor you've opened yourself.
|
||||
<br>
|
||||
It's a good way of bypassing the internal FD opening in libssh, but there are things you should take care of : <br>
|
||||
-The file descriptor should be returned to libssh without nonblocking settings<br>
|
||||
-If you wish to use <i>is_server_known()</i> You should also set <i>options_set_host</i>... Otherwise libssh won't have any mean of certifying the server is known or not.<br><br>
|
||||
<div class="prot">
|
||||
void options_set_bindaddr(SSH_OPTIONS *opt, char *bindaddr);
|
||||
</div>
|
||||
this function allows you to set the binding address, in case your computer has
|
||||
multiple IP or interfaces. it supports both hostnames and IP's
|
||||
<br><br>
|
||||
<div class="prot">
|
||||
void options_set_username(SSH_OPTIONS *opt,char *username);
|
||||
</div>
|
||||
sets username for authenticating in this session.
|
||||
<br><br>
|
||||
|
||||
<div class="prot">
|
||||
void option_set_timeout(SSH_OPTIONS *opt,long seconds, long usec);
|
||||
</div>
|
||||
sets the timeout for connecting to the socket. It does not include a timeout for the name resolving or handshake.
|
||||
<br>
|
||||
<br>
|
||||
<div class="prot">
|
||||
void options_set_ssh_dir(SSH_OPTIONS *opt, char *dir);
|
||||
</div>
|
||||
this function sets the .ssh/ directory used by libssh. You may use a %s
|
||||
which will be replaced by the home directory of the user.
|
||||
NEVER accept parameters others than the user's one, they may contain
|
||||
format strings which are a security hole if a malicious agent gives it.
|
||||
<br><br>
|
||||
<div class="prot">
|
||||
void options_set_known_hosts_file(SSH_OPTIONS *opt, char *dir);
|
||||
</div>
|
||||
same than <i>options_set_ssh_dir()</i> for known_hosts file.
|
||||
<br><br>
|
||||
<div class="prot">
|
||||
void options_set_identity(SSH_OPTIONS *opt, char *identity);
|
||||
</div>
|
||||
same than upper for the identity file (they come by pair, the one asked is the file without the .pub suffix)
|
||||
<br><br>
|
||||
<div class="prot">
|
||||
void options_set_status_callback(SSH_OPTIONS *opt, void (*callback)(void *arg, float status), void *arg);
|
||||
</div>
|
||||
Because more and more developpers use libssh with GUI, I've added this function to make the ssh_connect function more
|
||||
interactive. This permits to set a callback of the form
|
||||
<div class="prot">void function(void *userarg, float status);</div> with status going from 0 to 1 during ssh_connect. The callback won't ever be called after the connection is made.
|
||||
<br><br>
|
||||
</div>
|
||||
<h2>
|
||||
2- Connecting the ssh server
|
||||
</H2>
|
||||
<div class="tout">
|
||||
The API provides an abstract data type, SSH_SESSION, which describes the
|
||||
connection to one particular server. You can make several connections to
|
||||
different servers under the same process because of this structure.
|
||||
<br>
|
||||
<br>
|
||||
<div class="prot">
|
||||
SSH_SESSION *ssh_connect(SSH_OPTIONS *options);
|
||||
</div>
|
||||
This function returns a handle on the newly connection. This function expects
|
||||
to have a pre-set options structure.
|
||||
<br>
|
||||
It returns NULL in case of error, in which case you can look at error messages
|
||||
for more informations.
|
||||
<br><br>
|
||||
<div class="prot">
|
||||
void ssh_disconnect(SSH_SESSION *session);
|
||||
</div>
|
||||
This function sends a polite disconnect message, and does clean the session.<br>
|
||||
This is the proper way of finishing a ssh connection.<br>
|
||||
<br>
|
||||
<div class="prot">
|
||||
int ssh_get_pubkey_hash(SSH_SESSION *session, char hash[MD5_DIGEST_LEN]);
|
||||
</div>
|
||||
This function places the MD5 hash of the server public key into the hash array.<br>
|
||||
It's IMPORTANT to verify it matches the previous known value. One server always
|
||||
have the same hash. No other server/attacker can emulate it (or it'd be caught
|
||||
by the public key verification procedure automatically made by libssh).
|
||||
<br>
|
||||
You can skip this step if you correctly handle <i>is_server_known()</i>
|
||||
<br><br>
|
||||
<div class="prot">
|
||||
int ssh_is_server_known(SSH_SESSION *session);
|
||||
</div>
|
||||
|
||||
Checks the user's known host file to look for a previous connection to the specified server. Return values:<br>
|
||||
SSH_SERVER_KNOWN_OK : the host is known and the key has not changed<br>
|
||||
SSH_SERVER_KNOWN_CHANGED : The host's key has changed. Either you are under
|
||||
an active attack or the key changed. The API doesn't give any way to modify the key in known hosts yet. I Urge end developers to WARN the user about the possibility of an attack.<br>
|
||||
SSH_SERVER_FOUND_OTHER: The host gave us a public key of one type, which does
|
||||
not exist yet in our known host file, but there is an other type of key which is know.<br>
|
||||
IE server sent a DSA key and we had a RSA key.<br>
|
||||
Be carreful it's a possible attack (coder should use option_set_wanted_method() to specify
|
||||
which key to use).<br>
|
||||
SSH_SERVER_NOT_KNOWN: the server is unknown in known hosts. Possible reasons :
|
||||
case not matching, alias, ... In any case the user MUST confirm the Md5 hash is correct.<br>
|
||||
SSH_SERVER_ERROR : Some error happened while opening known host file.<br>
|
||||
<br>
|
||||
<div class="prot">
|
||||
int ssh_write_knownhost(SSH_SESSION *session);
|
||||
</div>
|
||||
write the current connected host as known in the known host file. returns a negative value if something went wrong. You generaly use it when ssh_is_server_known returned SSH_SERVER_NOT_KNOWN.
|
||||
<br><br>
|
||||
<div class="prot">
|
||||
int pubkey_get_hash(SSH_SESSION *session,char hash[MD5_DIGEST_LEN]);
|
||||
</div>
|
||||
deprecated but left for binary compatibility (will be removed in newer versions).
|
||||
</div>
|
||||
|
||||
<h2>3- Authenticating to server</h2>
|
||||
<div class="tout">
|
||||
The ssh library supports the two most used authentication methods from SSH.
|
||||
In every function, there is a "username" argument. If null is given instead,
|
||||
the server will use the default username (which is guessed from what you gave
|
||||
to options_set_user or options_set_hostname or even the local user running the code).
|
||||
<br>
|
||||
|
||||
Authentication methods :<br>
|
||||
<h3>A) Public keys</h3><br>
|
||||
The public key is the only method which does not compromise your key if the
|
||||
remote host has been compromised (the server can't do anything more than
|
||||
getting your public key). This is not the case of a password authentication
|
||||
(the server can get your plaintext password).<br>
|
||||
Libssh is obviously fully compatible with the openssh public and private keys.<br>
|
||||
The things go this way : you scan a list of files which contain public keys.<br>
|
||||
For each key, you send it to ssh server until the server acknowledges a key
|
||||
(a key it knows). Then, you get the private key for this key and send a
|
||||
message proving you own that private key.<br>
|
||||
Here again, two ways for the public key authentication... the easy and the
|
||||
complicated one.<br>
|
||||
<br>
|
||||
<h4> easy way:</h4>
|
||||
<div class="prot">
|
||||
int ssh_userauth_autopubkey(SSH_SESSION *session);
|
||||
</div>
|
||||
This function will try the most common places for finding the public and
|
||||
private keys (your home directory) or eventualy the identity files asked by
|
||||
the <i>options_set_identity()</i> function.<br>
|
||||
The return values are :<br>
|
||||
SSH_AUTH_ERROR : some serious error happened during authentication<br>
|
||||
SSH_AUTH_DENIED : no key matched<br>
|
||||
SSH_AUTH_SUCCESS : you are now authenticated<br>
|
||||
SSH_AUTH_PARTIAL : some key matched but you still have to give an other mean
|
||||
of authentication (like password).<br>
|
||||
<br>
|
||||
<h4> peanful way:</h4>
|
||||
there are three steps : you get a public key, you ask the server if the key
|
||||
matches a known one, if true, you get the private key and authenticate with
|
||||
it.<br>
|
||||
<div class="prot">
|
||||
STRING *publickey_from_file(char *filename,int *_type);
|
||||
</div>
|
||||
will return an handle on a public key. if you give a pointer to an int,
|
||||
a symbolic value will be placed there. Do it because you need it in next
|
||||
step.<br><br>
|
||||
<div class="prot">
|
||||
int ssh_userauth_offer_pubkey(SSH_SESSION *session, char *username,
|
||||
int type, STRING *publickey);
|
||||
</div>
|
||||
this function will offer a public key to the server. SSH_AUTH_SUCCESS is
|
||||
returned if the key is accepted (in which case you'll want to get the
|
||||
private key), SSH_AUTH_DENIED otherwise.<br>
|
||||
Still watch for SSH_AUTH_ERROR as connection problems might happen.
|
||||
<br>
|
||||
in case of SSH_AUTH_SUCCESS,
|
||||
<br>
|
||||
<div class="prot">
|
||||
PRIVATE_KEY *privatekey_from_file(SSH_SESSION *session,char *filename,
|
||||
int type,char *passphrase);
|
||||
</div>
|
||||
will get the privatekey from the filename previously set by
|
||||
publickey_from_next_file(). You can call it with a passphrase for
|
||||
unlocking the key. If passphrase==NULL, the default prompt will be used.<br>
|
||||
The function returns NULL if the private key wasn't opened
|
||||
(ie bad passphrase or missing file).<br>
|
||||
<br>
|
||||
<div class="prot">
|
||||
int ssh_userauth_pubkey(SSH_SESSION *session, char *username,
|
||||
STRING *publickey, PRIVATE_KEY *privatekey);
|
||||
</div>
|
||||
Will try to authenticate using the public and private key. It shall return
|
||||
SSH_AUTH_SUCCESS if you are authenticated, SSH_AUTH_ERROR, SSH_AUTH_DENIED or
|
||||
SSH_AUTH_PARTIAL depending of return condition.<br>
|
||||
|
||||
each public key (of type STRING) must be freed with the libc "free" function.<br>
|
||||
The private key must be freed with private_key_free(PRIVATE_KEY *) which
|
||||
will clean the memory before (don't worry about passphrase leaking).<br>
|
||||
<br>
|
||||
|
||||
<h3> B) Password</h3><br>
|
||||
<div class="prot">
|
||||
int ssh_userauth_password(SSH_SESSION *session,char *username,char *password);
|
||||
</div>
|
||||
Will return SSH_AUTH_SUCCESS if the password matched, one of other constants
|
||||
otherwise. It's your work to ask the password and to free it in a secure
|
||||
manner.<br><br>
|
||||
|
||||
<h3> C) Keyboard-interactive</h3><br>
|
||||
<div class="prot">
|
||||
int ssh_userauth_kbdint(SSH_SESSION *session, char *user, char *submethods);
|
||||
</div>
|
||||
This is the main keyboard-interactive function. It will return SSH_AUTH_SUCCESS,SSH_AUTH_DENIED, SSH_AUTH_PARTIAL, SSH_AUTH_ERROR depending on the result of the request.<br>
|
||||
The keyboard-interactive authentication method of SSH2 is a feature which permits the server to ask a certain number of questions in an interactive manner to the client, until it decides to accept or deny the login.<br>
|
||||
To begin, you call this function (you can omit user if it was set previously and omit submethods - instead you know what you do - just put them to NULL) and store the answer.
|
||||
If the answer is SSH_AUTH_INFO, it means the server has sent a few questions to ask your user, which you can retrieve with the following functions. Then, set the answers and call back ssh_userauth_kbdint with same arguments. It may again ask a few other questions etc. until you get an other SSH_AUTH code than SSH_AUTH_INFO.<br>
|
||||
Few remarks :<br>
|
||||
-Even the first call can return SSH_AUTH_DENIED or SSH_AUTH_SUCCESS.<br>
|
||||
-The server can send an empty question set (this is the default behavior on my system) after you have sent the answers to the first questions.
|
||||
you must still parse the answer, it might contain some message from the server saying hello or such things. Just call ssh_userauth_kbdint() once more<br>
|
||||
<br>
|
||||
<div class="prot">
|
||||
int ssh_userauth_kbdint_getnprompts(SSH_SESSION *session);
|
||||
</div>
|
||||
After you called ssh_userauth_kbdint and got SSH_AUTH_INFO, the session contains a few questions (or prompts) from the server. This function returns the number of prompts and answers.<br>
|
||||
It could be zero, in which case you must act as said previously.<br>
|
||||
|
||||
<div class="prot">
|
||||
char *ssh_userauth_kbdint_getname(SSH_SESSION *session);
|
||||
</div>
|
||||
this functions returns the "name" of the message block. The meaning is explained later.<br>
|
||||
This function returns a pointer that stays valid until the next ssh_userauth_kbdint() call and must not be freed.<br>
|
||||
|
||||
<div class="prot">
|
||||
char *ssh_userauth_kbdint_getinstruction(SSH_SESSION *session);
|
||||
</div>
|
||||
this functions returns the "instruction" of the message block. The meaning is explained later.<br>
|
||||
This function returns a pointer that stays valid until the next ssh_userauth_kbdint() call and must not be freed.<br>
|
||||
|
||||
<div class="prot">
|
||||
char *ssh_userauth_kbdint_getprompt(SSH_SESSION *session,int i, char *echo);
|
||||
</div>
|
||||
This functions returns a pointer to the nth prompt. The character pointed by echo, if different from null, will contain a boolean value after the call, which means that the user prompt must be echoed or not.<br>
|
||||
zero means that the echo is Off (like for a password prompt).<br>
|
||||
any other value means the echo is on.<br>
|
||||
This function returns a pointer that stays valid until the next ssh_userauth_kbdint() call and must not be freed.<br>
|
||||
|
||||
<div class="prot">
|
||||
void ssh_userauth_kbdint_setanswer(SSH_SESSION *session, unsigned int i, char *a
|
||||
nswer);
|
||||
</div>
|
||||
This function sets the ith answer. The string you give will be duplicated, and this copy will be discarded once it is no longer necessary.<br>
|
||||
care must be taken so you discard the content of the original string after this function call.<br>
|
||||
|
||||
<h3> A little note about how to use the informations from keyboard-interactive authentication</h3>
|
||||
<br>
|
||||
The words from the original drafts explain everything
|
||||
<div class="prot">
|
||||
3.3 User Interface
|
||||
|
||||
Upon receiving a request message, the client SHOULD prompt the user
|
||||
as follows:<br>
|
||||
A command line interface (CLI) client SHOULD print the name and
|
||||
instruction (if non-empty), adding newlines. Then for each prompt in
|
||||
turn, the client SHOULD display the prompt and read the user input.<br>
|
||||
<br>
|
||||
A graphical user interface (GUI) client has many choices on how to
|
||||
prompt the user. One possibility is to use the name field (possibly
|
||||
prefixed with the application's name) as the title of a dialog window
|
||||
in which the prompt(s) are presented. In that dialog window, the
|
||||
instruction field would be a text message, and the prompts would be
|
||||
labels for text entry fields. All fields SHOULD be presented to the
|
||||
user, for example an implementation SHOULD NOT discard the name field
|
||||
because its windows lack titles; it SHOULD instead find another way
|
||||
to display this information. If prompts are presented in a dialog
|
||||
window, then the client SHOULD NOT present each prompt in a separate
|
||||
window.<br>
|
||||
<br>
|
||||
All clients MUST properly handle an instruction field with embedded
|
||||
newlines. They SHOULD also be able to display at least 30 characters
|
||||
for the name and prompts. If the server presents names or prompts
|
||||
longer than 30 characters, the client MAY truncate these fields to
|
||||
the length it can display. If the client does truncate any fields,
|
||||
there MUST be an obvious indication that such truncation has occured.<br>
|
||||
The instruction field SHOULD NOT be truncated.<br>
|
||||
Clients SHOULD use control character filtering as discussed in
|
||||
[SSH-ARCH] to avoid attacks by including terminal control characters
|
||||
in the fields to be displayed.<br>
|
||||
<br>
|
||||
For each prompt, the corresponding echo field indicates whether or
|
||||
not the user input should be echoed as characters are typed. Clients
|
||||
SHOULD correctly echo/mask user input for each prompt independently
|
||||
of other prompts in the request message. If a client does not honor
|
||||
the echo field for whatever reason, then the client MUST err on the
|
||||
side of masking input. A GUI client might like to have a checkbox
|
||||
toggling echo/mask. Clients SHOULD NOT add any additional characters
|
||||
to the prompt such as ": " (colon-space); the server is responsible
|
||||
for supplying all text to be displayed to the user. Clients MUST
|
||||
also accept empty responses from the user and pass them on as empty
|
||||
strings.<br>
|
||||
|
||||
</div>
|
||||
<br>
|
||||
<h3> D) "none"</h3><br>
|
||||
In fact this mode only serve to get the list of supported authentications.<br>
|
||||
however, it also serves to get the banner message from the server, if any.<br>
|
||||
You should firstly try this method, at least for getting the banner, then to enter if there is no password at all.<br>
|
||||
<div class="prot">
|
||||
int ssh_userauth_none(SSH_SESSION *session, char *username);
|
||||
</div>
|
||||
if the account has no password (and the server is configured to let you
|
||||
pass), the function might answer SSH_AUTH_SUCCESS. That's why
|
||||
ssh_auth_autopubkey already calls it for you.
|
||||
<br><br>
|
||||
<div class="prot">
|
||||
char *ssh_get_issue_banner(SSH_SESSION *session);
|
||||
</div>
|
||||
if during authentication, the server has given a banner, you can get it
|
||||
this way. the function returns NULL if no banner exists, and you have to
|
||||
free the returned pointer.<br><br>
|
||||
</div>
|
||||
|
||||
<h2>4- Opening a channel</h2>
|
||||
<div class="tout">
|
||||
Maybe you want to use the sftp subsystem : all this is done for you, you
|
||||
better read at the end of the paper how to use the sftp functions.<br>
|
||||
You probably want to open one or more shells, or call one or more programs.<br>
|
||||
|
||||
So you need a channel.<br>
|
||||
<div class="prot">
|
||||
CHANNEL *channel;
|
||||
</div>
|
||||
This is an handler to a channel object. it describes your channel.
|
||||
<br>
|
||||
<div class="prot">
|
||||
CHANNEL *channel_open_session(SSH_SESSION *session);
|
||||
</div>
|
||||
This will open a channel for use into a session (which can be used for executing
|
||||
a command or a shell. Not for tcp forwarding).<br>
|
||||
The function returns NULL if for a reason or another the channel can't be
|
||||
opened.<br>
|
||||
<i>
|
||||
CHANNEL *open_session_channel(...)</i> is deprecated and should not be used in future
|
||||
applications.<br><br>
|
||||
<div class="prot">
|
||||
CHANNEL *channel_open_forward(SSH_SESSION *session, char *remotehost,
|
||||
int remoteport, char *sourcehost, int localport);
|
||||
</div>
|
||||
Ask the server to tunnel a TCP connection. The server will connect to
|
||||
remotehost:remoteport and libssh will return an handle to the channel if it is allowed.<br>
|
||||
Otherwise, NULL will be returned. sourcehost and localport are generaly
|
||||
used in message debugging purpose and have no effect on the result.<br>
|
||||
<br>
|
||||
When you've finished with your channel, you may send an EOF message and
|
||||
then close it :<br>
|
||||
<div class="prot">
|
||||
void channel_send_eof(CHANNEL *channel);
|
||||
</div>
|
||||
sends an end of file into channel. It doesn't close the channel and you can still read it.<br><br>
|
||||
|
||||
<div class="prot">
|
||||
void channel_free(CHANNEL *channel);
|
||||
</div>
|
||||
closes and destroy the channel.
|
||||
<br>
|
||||
<div class="prot">
|
||||
void channel_close(CHANNEL *channel);
|
||||
</div>
|
||||
sends an EOF and close the channel. (if you don't know what to do, use channel_free). It doesn't free the channel.
|
||||
|
||||
</div>
|
||||
<h2>5- The shell</h2>
|
||||
<div class="tout">
|
||||
<div class="prot">
|
||||
int channel_request_env(CHANNEL *channel, char *name, char *value);
|
||||
</div>
|
||||
Ask the server to set the "name" environment variable to "value". For security
|
||||
reasons, some variables won't be accepted by the server. It returns 0 otherwise.<br><br>
|
||||
<div class="prot">
|
||||
int channel_request_pty(CHANNEL *channel);
|
||||
</div>
|
||||
ask the server to allocate a pseudo terminal for the current channel.<br>
|
||||
the function returns 0 on success.<br><br>
|
||||
|
||||
<div class="prot">
|
||||
int channel_request_pty_size(CHANNEL *channel, char *terminal, int cols, int rows);
|
||||
</div>
|
||||
ask the server to allocate a pty. The terminal parameter is the type of pty
|
||||
(vt100,xterm,...), cols and rows are the size of the new terminal (80x24 by example).<br><br>
|
||||
<div class="prot">
|
||||
int channel_change_pty_size(CHANNEL *channel, int cols,int rows);
|
||||
</div>
|
||||
changes the window size (terminal) of the current session;<br><br>
|
||||
<div class="prot">
|
||||
int channel_request_shell(CHANNEL *channel);
|
||||
</div>
|
||||
This function requests a shell. After its success, a shell is running at the other side of the channel.<br><br>
|
||||
<div class="prot">
|
||||
int channel_request_exec(CHANNEL *channel, char *cmd);
|
||||
</div>
|
||||
run a shell command without an interactive shell, ie $SHELL -c "command".<br>
|
||||
returns 0 on success.<br><br>
|
||||
|
||||
You might ask the server to open a subsystem for you. this is done this way :
|
||||
<div class="prot">
|
||||
int channel_request_subsystem(CHANNEL *channel, char *subsystem);
|
||||
</div>
|
||||
There are some functions used to manipulate the channels :
|
||||
<br><br>
|
||||
<div class="prot">
|
||||
int channel_write(CHANNEL *channel,void *data,int len);
|
||||
</div>
|
||||
writes len bytes of data into the channel. It returns the number of bytes written. The current implementation is a blocking write
|
||||
of the complete data buffer, but it may vary.<br><br>
|
||||
<div class="prot">
|
||||
int channel_read(CHANNEL *channel, BUFFER *buffer,int bytes,int is_stderr);
|
||||
</div>
|
||||
It makes a blocking read on the channel, of "bytes" bytes and returns the
|
||||
result into an allocated buffer you passed in. (with <i>buffer_new()</i>).<br>
|
||||
it will read on stderr, if is_stderr is set.<br>
|
||||
The function might read less bytes than "bytes" variable if an End of File
|
||||
happened. Otherwise, the function will always block reading until "bytes"
|
||||
bytes are read.<br>
|
||||
with "bytes"=0, <i>channel_read()</i> will read the current state of the read buffer, but will read at least one byte (and block if nothing is available, except EOF case).<br>
|
||||
|
||||
You don't need to free and allocate a new buffer each time you call this function, just pass the same object each time.<br>
|
||||
look at the <i>buffer_</i> functions further for the correct way of retrieving the data.<br><br>
|
||||
|
||||
<div class="prot">
|
||||
int channel_read_nonblocking (CHANNEL *channel, char *dest, int len, int is_stderr);
|
||||
</div>
|
||||
Non-blocking read on channel, at most len bytes of data are read. Returns 0 if EOF or if no data available.
|
||||
<br><br>
|
||||
<div class="prot">
|
||||
int channel_is_open(CHANNEL *channel);
|
||||
</div>
|
||||
returns 0 if the channel has been closed by remote host, something else otherwise.<br><br>
|
||||
<div class="prot">
|
||||
int channel_poll(CHANNEL *channel, int is_stderr);
|
||||
</div>
|
||||
This nonblocking function returns the number of bytes immediatly available for
|
||||
reading on the channel and stdin/stderr.<br><br>
|
||||
|
||||
More interesting, if you are going to do channel multiplexing, this function
|
||||
is for you :<br><br>
|
||||
<div class="prot">
|
||||
int ssh_select(CHANNEL **channels,CHANNEL **outchannels, int maxfd,
|
||||
fd_set *readfds, struct timeval *timeout);
|
||||
</div>
|
||||
channels is an array of channel pointers, finished by a NULL pointer.<br>
|
||||
It can be used ever and ever, as it is never written.<br>
|
||||
outchannels is an array of size at least greater or equal to "channels".<br>
|
||||
It hasn't to be initialized.<br>
|
||||
maxfd is the maximum file descriptor from your own filedescriptors.<br>
|
||||
readfds is a pointer to a fd_set structure, like in the original
|
||||
select implementation (man select).<br>
|
||||
the struct timeval *timeout has the same meaning than in
|
||||
select(2) (man select).<br>
|
||||
|
||||
There is no support for writing or special events as in <i>select(2)</i> yet.<br>
|
||||
The function returns -1 if an error occured, or SSH_EINTR if select was interrupted by a syscall. This is not an error, you may restart the function.<br>
|
||||
<b>note about signals:</b> libssh is not threadsafe, and most functions are not
|
||||
reetrant when using the same data structures : it means you *cannot* do anything
|
||||
with a channel from a ssh session passed to <i>ssh_select</i> during a signal.
|
||||
<br>take a look at sample.c on how to bypass that limitation.<br>
|
||||
the function works this way : it returns in the readfds the filedescriptors which have data ready for reading (the given filedescriptors have a greatest priority).<br>
|
||||
Then, if no file descriptor can be read, the function looks for every
|
||||
channel from the array to get a channel with data bufferized. If nothing is
|
||||
available, it waits for activity on any channel/file descriptor and returns
|
||||
immediatly, or waits until timeout.<br>
|
||||
You will find the channels that can be read in the outchannels array (finished by NULL) and the filedescriptors in your fd_set (man FD_ISSET).<br>
|
||||
this is the "heart" of your main loop.<br>
|
||||
<br>
|
||||
<h3>The BUFFER object.</h3>
|
||||
Reading is done through the BUFFER object. here is the public interface :
|
||||
<br>
|
||||
<div class="prot">
|
||||
BUFFER *buffer_new();
|
||||
</div>
|
||||
creates a buffer object.
|
||||
<br><br>
|
||||
<div class="prot">
|
||||
void *buffer_get(BUFFER *buffer);
|
||||
</div>
|
||||
returns a pointer to the begining of buffer.
|
||||
<br><br>
|
||||
<div class="prot">
|
||||
int buffer_get_len(BUFFER *buffer);
|
||||
</div>
|
||||
returns buffer's data size.
|
||||
<br><br>
|
||||
<div class="prot">
|
||||
void buffer_free(BUFFER *buffer);
|
||||
</div>
|
||||
destoys the buffer.
|
||||
<br>
|
||||
<br>
|
||||
How to use the buffer system when you've read something:<br>
|
||||
I've seen people doing such code:<br>
|
||||
<div class="prot">
|
||||
char buffer[256];<br>
|
||||
channel_read(channel,buf,1234,0);<br>
|
||||
strcpy(buffer,buf.data);<br>
|
||||
</div>
|
||||
The correct way of doing this:
|
||||
<div class="prot">
|
||||
char buffer[256];<br>
|
||||
int i;<br>
|
||||
i=channel_read(channel,buf,1234,0);<br>
|
||||
if(i<=0)<br>
|
||||
go_out()...<br>
|
||||
if(i>=256)<br>
|
||||
i=255;<br>
|
||||
memcpy(buffer,buffer_get(buf),i);<br>
|
||||
buffer[i]=0;
|
||||
</div>
|
||||
Do not expect the buffer to be null-terminated. Don't access the internal structure of buffer. Check the sizes before copying.<br>
|
||||
</div>
|
||||
<h2>6- The SFTP subsystem</h2>
|
||||
<div class="tout">
|
||||
SFTP is a secure implementation of a file transfer protocol. The current
|
||||
implemented version is 3. All functions aren't implemented yet but the most
|
||||
important are.<br>
|
||||
<br>
|
||||
<h3>A) Opening the session</h3>
|
||||
<div class="prot">
|
||||
SFTP_SESSION *sftp_new(SSH_SESSION *session);
|
||||
int sftp_init(SFTP_SESSION *sftp);
|
||||
</div>
|
||||
The former returns a SFTP_SESSION handle. It returns NULL if things didn't
|
||||
work as expected.<br>
|
||||
sftp_init makes some initialisation work. It returns 0 if things went right.
|
||||
Both of them must be called.<br>
|
||||
<h3>B) Opening and reading a directory</h3>
|
||||
<div class="prot">
|
||||
SFTP_DIR *sftp_opendir(SFTP_SESSION *session, char *path);
|
||||
</div>
|
||||
opens a directory for file listing. Returns NULL in error case.
|
||||
<br><br>
|
||||
<div class="prot">
|
||||
SFTP_ATTRIBUTES *sftp_readdir(SFTP_SESSION *session, SFTP_DIR *dir);
|
||||
</div>
|
||||
This function reads one file attribute from an opened directory. It
|
||||
returns NULL if the directory is EOF, or if something wrong happened.
|
||||
<br><br>
|
||||
<div class="prot">
|
||||
int sftp_dir_eof(SFTP_DIR *dir);
|
||||
</div>
|
||||
When a <i>sftp_readdir()</i> returned NULL, you can use this function to
|
||||
tell if an EOF occured. the function returns 0 if no EOF occured.
|
||||
<br><br>
|
||||
<div class="prot">
|
||||
void sftp_attributes_free(SFTP_ATTRIBUTES *file);
|
||||
</div>
|
||||
You have to free any SFTP_ATTRIBUTE structure given by an other function
|
||||
with it.<br><br>
|
||||
<div class="prot">
|
||||
int sftp_dir_close(SFTP_DIR *dir);
|
||||
</div>
|
||||
closes an opened directory. returns 0 when no error occured.
|
||||
<br><br>
|
||||
<h3>C) Opening, reading, writing files</h3>
|
||||
<div class="prot">
|
||||
SFTP_FILE *sftp_open(SFTP_SESSION *session, char *file, int access,
|
||||
SFTP_ATTRIBUTES *attr);
|
||||
</div>
|
||||
Opens a file. The access flags are the same than the stdio flags.<br>
|
||||
see open(2) for more details.<br>
|
||||
attr are the wanted attributes for the new file. If you supply NULL,
|
||||
default values will be used.<br>
|
||||
rem: more work is going on parsing/making the attributes structure
|
||||
<br><br>
|
||||
<div class="prot">
|
||||
int sftp_read(SFTP_FILE *file, void *dest, int len);
|
||||
</div>
|
||||
read on a file. Works as the fread() function. It is blocking by default but you can change the default behaviour with <i>sftp_file_set_nonblocking()</i>.
|
||||
<br><br>
|
||||
<div class="prot">
|
||||
void sftp_file_set_nonblocking(SFTP_FILE *file);
|
||||
</div>
|
||||
sets the file non blocking. reads on this file won't ever block. You can't detect end of files this way.<br>
|
||||
*** TODO more work going there for EOF ****
|
||||
<br><br>
|
||||
<div class="prot">
|
||||
void sftp_file_set_blocking(SFTP_FILE *file);
|
||||
</div>
|
||||
restore the default setting of sftp_read.
|
||||
<br><br>
|
||||
<div class="prot">
|
||||
int sftp_write(SFTP_FILE *file, void *source, int len);
|
||||
</div>
|
||||
works as fwrite() function. It is a blocking write.<br>
|
||||
<br>
|
||||
<div class="prot">
|
||||
void sftp_seek(SFTP_FILE *file, int new_offset);
|
||||
</div>
|
||||
seek into the file for reading/writing at an other place.
|
||||
<br><br>
|
||||
<div class="prot">
|
||||
unsigned long sftp_tell(SFTP_FILE *file);
|
||||
</div>
|
||||
returns the current offset (both writing and reading) into the opened file.
|
||||
<br><br>
|
||||
<div class="prot">
|
||||
void sftp_rewind(SFTP_FILE *file);
|
||||
</div>
|
||||
same as sftp_seek(file,0);
|
||||
<br><br>
|
||||
<div class="prot">
|
||||
int sftp_file_close(SFTP_FILE *file);
|
||||
</div>
|
||||
closes a file handle. returns 0 in no error case.
|
||||
<br><br>
|
||||
<div class="prot">
|
||||
int sftp_rm(SFTP_SESSION *sftp, char *file);
|
||||
</div>
|
||||
deletes a file.
|
||||
<br><br>
|
||||
<div class="prot">
|
||||
int sftp_rmdir(SFTP_SESSION *sftp, char *directory);
|
||||
</div>
|
||||
<br>
|
||||
deletes a directory.
|
||||
<br><br>
|
||||
<div class="prot">
|
||||
int sftp_mkdir(SFTP_SESSION *sftp, char *directory, SFTP_ATTRIBUTES *attr);
|
||||
</div>
|
||||
makes a directory, with the given attributes. You can't pass NULL for attr and hope it works.
|
||||
<br><br>
|
||||
<div class="prot">
|
||||
int sftp_rename(SFTP_SESSION *sftp, char *original, char *newname);
|
||||
</div>
|
||||
changes the name of a file or directory.
|
||||
<br><br>
|
||||
<div class="prot">
|
||||
int sftp_setstat(SFTP_SESSION *sftp, char *file, SFTP_ATTRIBUTES *attr);
|
||||
</div>
|
||||
changes the attributes of a file or directory.
|
||||
<br><br>
|
||||
<div class="prot">
|
||||
char *sftp_canonicalize_path(SFTP_SESSION *sftp, char *path);
|
||||
</div>
|
||||
gives the canonicalized form of some path. You have to
|
||||
free the pointer given in return.<br>
|
||||
(returns NULL if error).
|
||||
<br><br>
|
||||
|
||||
(a function to make proper SFTP_ATTRIBUTES structures is on the way )
|
||||
|
||||
<h3>D) Closing the session</h3>
|
||||
<div class="prot">
|
||||
void sftp_free(SFTP_SESSION *sftp);
|
||||
</div>
|
||||
it closes the sftp channel and subsystem.
|
||||
</div>
|
||||
|
||||
<h2>7- Handling the errors</h2>
|
||||
<div class="tout">
|
||||
When some function returns an error code, it's allways possible to get an
|
||||
english message describing the problem. the function ssh_get_error()
|
||||
returns a pointer to the static error buffer.<br>
|
||||
ssh_error_code() returns the error code number. it's declared as an enum:<br>
|
||||
SSH_NO_ERROR, SSH_REQUEST_DENIED, SSH_INVALID_REQUEST, SSH_CONNECTION_LOST,
|
||||
SSH_FATAL, SSH_INVALID_DATA.<br><br>
|
||||
SSH_REQUEST_DENIED means the ssh server refused your request but the situation is
|
||||
recoverable. the others mean something happened to the connection (some
|
||||
encryption problems, server problems, library bug, ...).<br>
|
||||
SSH_INVALID_REQUEST means the library got some garbage from server. (But might be
|
||||
recoverable).<br>
|
||||
SSH_FATAL means the connection has an important problem and isn't probably
|
||||
recoverable.<br>
|
||||
<br>
|
||||
Most of time, the error returned are SSH_FATAL, but some functions (generaly the
|
||||
<i>ssh_request_*</i> ones) may fail because of server denying request. In these cases, SSH_REQUEST_DENIED is returned.<br><br>
|
||||
|
||||
You'll see in the prototype SSH_SESSION *session. That's because for thread
|
||||
safety, error messages that can be attached to a session aren't static
|
||||
anymore. So, any error that could happen during ssh_getopt(), options_* or
|
||||
ssh_connect() will be retreavable giving NULL as argument.<br>
|
||||
<br>
|
||||
<div class="prot">
|
||||
char *ssh_get_error(SSH_SESSION *session);
|
||||
</div>
|
||||
returns a pointer to a static message error from the given session. No
|
||||
message freeing is needed.<br><br>
|
||||
<div class="prot">
|
||||
enum ssh_error ssh_get_error_code(SSH_SESSION *session);
|
||||
</div>
|
||||
returns the error code that last happened along with the message.
|
||||
<br><br>
|
||||
</div>
|
||||
|
||||
<h2>8- Final word</h2>
|
||||
<div class="tout">
|
||||
I made this library because nothing in the Open source or free software community was existing yet. This project is a very personnal one as it's the first "useful" thing I ever wrote.
|
||||
I hope it fits your needs, but remember the experimental state of libssh : if
|
||||
something doesn't work, please mail me. If something lacks, please ask for it.
|
||||
If something stinks, please write a patch and send it !
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
1
doc/TracFooter.html
Normal file
1
doc/TracFooter.html
Normal file
@@ -0,0 +1 @@
|
||||
<!-- Doxygen TracFooter -->
|
||||
4
doc/TracHeader.html
Normal file
4
doc/TracHeader.html
Normal file
@@ -0,0 +1,4 @@
|
||||
<!-- Doxygen TracHeader -->
|
||||
<style>@import url(/chrome/site/doxygen.css);</style>
|
||||
<style>@import url(/chrome/site/tabs.css);</style>
|
||||
<!-- /Doxygen TracHeader -->
|
||||
@@ -1,375 +0,0 @@
|
||||
/**
|
||||
@page libssh_tutor_authentication Chapter 2: A deeper insight on authentication
|
||||
@section authentication_details A deeper insight on authentication
|
||||
|
||||
In our guided tour, we merely mentioned that the user needed to authenticate.
|
||||
We didn't explain much in detail how that was supposed to happen.
|
||||
This chapter explains better the four authentication methods: with public keys,
|
||||
with a password, with challenges and responses (keyboard-interactive), and with
|
||||
no authentication at all.
|
||||
|
||||
If your software is supposed to connect to an arbitrary server, then you
|
||||
might need to support all authentication methods. If your software will
|
||||
connect only to a given server, then it might be enough for your software
|
||||
to support only the authentication methods used by that server. If you are
|
||||
the administrator of the server, it might be your call to choose those
|
||||
authentication methods.
|
||||
|
||||
It is not the purpose of this document to review in detail the advantages
|
||||
and drawbacks of each authentication method. You are therefore invited
|
||||
to read the abundant documentation on this topic to fully understand the
|
||||
advantages and security risks linked to each method.
|
||||
|
||||
|
||||
@subsection pubkeys Authenticating with public keys
|
||||
|
||||
libssh is fully compatible with the openssh public and private keys. You
|
||||
can either use the automatic public key authentication method provided by
|
||||
libssh, or roll your own using the public key functions.
|
||||
|
||||
The process of authenticating by public key to a server is the following:
|
||||
- you scan a list of files that contain public keys. each key is sent to
|
||||
the SSH server, until the server acknowledges a key (a key it knows can be
|
||||
used to authenticate the user).
|
||||
- then, you retrieve the private key for this key and send a message
|
||||
proving that you know that private key.
|
||||
|
||||
The function ssh_userauth_autopubkey() does this using the available keys in
|
||||
"~/.ssh/". The return values are the following:
|
||||
- SSH_AUTH_ERROR: some serious error happened during authentication
|
||||
- SSH_AUTH_DENIED: no key matched
|
||||
- SSH_AUTH_SUCCESS: you are now authenticated
|
||||
- SSH_AUTH_PARTIAL: some key matched but you still have to provide an other
|
||||
mean of authentication (like a password).
|
||||
|
||||
The ssh_userauth_publickey_auto() function also tries to authenticate using the
|
||||
SSH agent, if you have one running, or the "none" method otherwise.
|
||||
|
||||
If you wish to authenticate with public key by your own, follow these steps:
|
||||
- Retrieve the public key with ssh_import_pubkey_file().
|
||||
- Offer the public key to the SSH server using ssh_userauth_try_publickey().
|
||||
If the return value is SSH_AUTH_SUCCESS, the SSH server accepts to
|
||||
authenticate using the public key and you can go to the next step.
|
||||
- Retrieve the private key, using the ssh_pki_import_privkey_file() function.
|
||||
If a passphrase is needed, either the passphrase specified as argument or
|
||||
a callback will be used.
|
||||
- Authenticate using ssh_userauth_publickey() with your private key.
|
||||
- Do not forget cleaning up memory using ssh_key_free().
|
||||
|
||||
Here is a minimalistic example of public key authentication:
|
||||
|
||||
@code
|
||||
int authenticate_pubkey(ssh_session session)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = ssh_userauth_publickey_auto(session, NULL);
|
||||
|
||||
if (rc == SSH_AUTH_ERROR)
|
||||
{
|
||||
fprintf(stderr, "Authentication failed: %s\n",
|
||||
ssh_get_error(session));
|
||||
return SSH_AUTH_ERROR;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
@endcode
|
||||
|
||||
@see ssh_userauth_publickey_auto()
|
||||
@see ssh_userauth_try_publickey()
|
||||
@see ssh_userauth_publickey()
|
||||
@see ssh_pki_import_pubkey_file()
|
||||
@see ssh_pki_import_privkey_file()
|
||||
@see ssh_key_free()
|
||||
|
||||
|
||||
@subsection password Authenticating with a password
|
||||
|
||||
The function ssh_userauth_password() serves the purpose of authenticating
|
||||
using a password. It will return SSH_AUTH_SUCCESS if the password worked,
|
||||
or one of other constants otherwise. It's your work to ask the password
|
||||
and to deallocate it in a secure manner.
|
||||
|
||||
If your server complains that the password is wrong, but you can still
|
||||
authenticate using openssh's client (issuing password), it's probably
|
||||
because openssh only accept keyboard-interactive. Switch to
|
||||
keyboard-interactive authentication, or try to configure plain text passwords
|
||||
on the SSH server.
|
||||
|
||||
Here is a small example of password authentication:
|
||||
|
||||
@code
|
||||
int authenticate_password(ssh_session session)
|
||||
{
|
||||
char *password;
|
||||
int rc;
|
||||
|
||||
password = getpass("Enter your password: ");
|
||||
rc = ssh_userauth_password(session, NULL, password);
|
||||
if (rc == SSH_AUTH_ERROR)
|
||||
{
|
||||
fprintf(stderr, "Authentication failed: %s\n",
|
||||
ssh_get_error(session));
|
||||
return SSH_AUTH_ERROR;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
@endcode
|
||||
|
||||
@see ssh_userauth_password
|
||||
|
||||
|
||||
@subsection keyb_int The keyboard-interactive authentication method
|
||||
|
||||
The keyboard-interactive method is, as its name tells, interactive. The
|
||||
server will issue one or more challenges that the user has to answer,
|
||||
until the server takes an authentication decision.
|
||||
|
||||
ssh_userauth_kbdint() is the the main keyboard-interactive function.
|
||||
It will return SSH_AUTH_SUCCESS,SSH_AUTH_DENIED, SSH_AUTH_PARTIAL,
|
||||
SSH_AUTH_ERROR, or SSH_AUTH_INFO, depending on the result of the request.
|
||||
|
||||
The keyboard-interactive authentication method of SSH2 is a feature that
|
||||
permits the server to ask a certain number of questions in an interactive
|
||||
manner to the client, until it decides to accept or deny the login.
|
||||
|
||||
To begin, you call ssh_userauth_kbdint() (just set user and submethods to
|
||||
NULL) and store the answer.
|
||||
|
||||
If the answer is SSH_AUTH_INFO, it means that the server has sent a few
|
||||
questions that you should ask the user. You can retrieve these questions
|
||||
with the following functions: ssh_userauth_kbdint_getnprompts(),
|
||||
ssh_userauth_kbdint_getname(), ssh_userauth_kbdint_getinstruction(), and
|
||||
ssh_userauth_kbdint_getprompt().
|
||||
|
||||
Set the answer for each question in the challenge using
|
||||
ssh_userauth_kbdint_setanswer().
|
||||
|
||||
Then, call again ssh_userauth_kbdint() and start the process again until
|
||||
these functions returns something else than SSH_AUTH_INFO.
|
||||
|
||||
Here are a few remarks:
|
||||
- Even the first call can return SSH_AUTH_DENIED or SSH_AUTH_SUCCESS.
|
||||
- The server can send an empty question set (this is the default behavior
|
||||
on my system) after you have sent the answers to the first questions.
|
||||
You must still parse the answer, it might contain some
|
||||
message from the server saying hello or such things. Just call
|
||||
ssh_userauth_kbdint() until needed.
|
||||
- The meaning of "name", "prompt", "instruction" may be a little
|
||||
confusing. An explanation is given in the RFC section that follows.
|
||||
|
||||
Here is a little note about how to use the information from
|
||||
keyboard-interactive authentication, coming from the RFC itself (rfc4256):
|
||||
|
||||
@verbatim
|
||||
|
||||
3.3 User Interface Upon receiving a request message, the client SHOULD
|
||||
prompt the user as follows: A command line interface (CLI) client SHOULD
|
||||
print the name and instruction (if non-empty), adding newlines. Then for
|
||||
each prompt in turn, the client SHOULD display the prompt and read the
|
||||
user input.
|
||||
|
||||
A graphical user interface (GUI) client has many choices on how to prompt
|
||||
the user. One possibility is to use the name field (possibly prefixed
|
||||
with the application's name) as the title of a dialog window in which
|
||||
the prompt(s) are presented. In that dialog window, the instruction field
|
||||
would be a text message, and the prompts would be labels for text entry
|
||||
fields. All fields SHOULD be presented to the user, for example an
|
||||
implementation SHOULD NOT discard the name field because its windows lack
|
||||
titles; it SHOULD instead find another way to display this information. If
|
||||
prompts are presented in a dialog window, then the client SHOULD NOT
|
||||
present each prompt in a separate window.
|
||||
|
||||
All clients MUST properly handle an instruction field with embedded
|
||||
newlines. They SHOULD also be able to display at least 30 characters for
|
||||
the name and prompts. If the server presents names or prompts longer than 30
|
||||
characters, the client MAY truncate these fields to the length it can
|
||||
display. If the client does truncate any fields, there MUST be an obvious
|
||||
indication that such truncation has occured.
|
||||
|
||||
The instruction field SHOULD NOT be truncated. Clients SHOULD use control
|
||||
character filtering as discussed in [SSH-ARCH] to avoid attacks by
|
||||
including terminal control characters in the fields to be displayed.
|
||||
|
||||
For each prompt, the corresponding echo field indicates whether or not
|
||||
the user input should be echoed as characters are typed. Clients SHOULD
|
||||
correctly echo/mask user input for each prompt independently of other
|
||||
prompts in the request message. If a client does not honor the echo field
|
||||
for whatever reason, then the client MUST err on the side of
|
||||
masking input. A GUI client might like to have a checkbox toggling
|
||||
echo/mask. Clients SHOULD NOT add any additional characters to the prompt
|
||||
such as ": " (colon-space); the server is responsible for supplying all
|
||||
text to be displayed to the user. Clients MUST also accept empty responses
|
||||
from the user and pass them on as empty strings.
|
||||
@endverbatim
|
||||
|
||||
The following example shows how to perform keyboard-interactive authentication:
|
||||
|
||||
@code
|
||||
int authenticate_kbdint(ssh_session session)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = ssh_userauth_kbdint(session, NULL, NULL);
|
||||
while (rc == SSH_AUTH_INFO)
|
||||
{
|
||||
const char *name, *instruction;
|
||||
int nprompts, iprompt;
|
||||
|
||||
name = ssh_userauth_kbdint_getname(session);
|
||||
instruction = ssh_userauth_kbdint_getinstruction(session);
|
||||
nprompts = ssh_userauth_kbdint_getnprompts(session);
|
||||
|
||||
if (strlen(name) > 0)
|
||||
printf("%s\n", name);
|
||||
if (strlen(instruction) > 0)
|
||||
printf("%s\n", instruction);
|
||||
for (iprompt = 0; iprompt < nprompts; iprompt++)
|
||||
{
|
||||
const char *prompt;
|
||||
char echo;
|
||||
|
||||
prompt = ssh_userauth_kbdint_getprompt(session, iprompt, &echo);
|
||||
if (echo)
|
||||
{
|
||||
char buffer[128], *ptr;
|
||||
|
||||
printf("%s", prompt);
|
||||
if (fgets(buffer, sizeof(buffer), stdin) == NULL)
|
||||
return SSH_AUTH_ERROR;
|
||||
buffer[sizeof(buffer) - 1] = '\0';
|
||||
if ((ptr = strchr(buffer, '\n')) != NULL)
|
||||
*ptr = '\0';
|
||||
if (ssh_userauth_kbdint_setanswer(session, iprompt, buffer) < 0)
|
||||
return SSH_AUTH_ERROR;
|
||||
memset(buffer, 0, strlen(buffer));
|
||||
}
|
||||
else
|
||||
{
|
||||
char *ptr;
|
||||
|
||||
ptr = getpass(prompt);
|
||||
if (ssh_userauth_kbdint_setanswer(session, iprompt, ptr) < 0)
|
||||
return SSH_AUTH_ERROR;
|
||||
}
|
||||
}
|
||||
rc = ssh_userauth_kbdint(session, NULL, NULL);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
@endcode
|
||||
|
||||
@see ssh_userauth_kbdint()
|
||||
@see ssh_userauth_kbdint_getnprompts()
|
||||
@see ssh_userauth_kbdint_getname()
|
||||
@see ssh_userauth_kbdint_getinstruction()
|
||||
@see ssh_userauth_kbdint_getprompt()
|
||||
@see ssh_userauth_kbdint_setanswer()
|
||||
|
||||
|
||||
@subsection none Authenticating with "none" method
|
||||
|
||||
The primary purpose of the "none" method is to get authenticated **without**
|
||||
any credential. Don't do that, use one of the other authentication methods,
|
||||
unless you really want to grant anonymous access.
|
||||
|
||||
If the account has no password, and if the server is configured to let you
|
||||
pass, ssh_userauth_none() might answer SSH_AUTH_SUCCESS.
|
||||
|
||||
The following example shows how to perform "none" authentication:
|
||||
|
||||
@code
|
||||
int authenticate_kbdint(ssh_session session)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = ssh_userauth_none(session, NULL);
|
||||
return rc;
|
||||
}
|
||||
@endcode
|
||||
|
||||
@subsection auth_list Getting the list of supported authentications
|
||||
|
||||
You are not meant to choose a given authentication method, you can
|
||||
let the server tell you which methods are available. Once you know them,
|
||||
you try them one after the other.
|
||||
|
||||
The following example shows how to get the list of available authentication
|
||||
methods with ssh_userauth_list() and how to use the result:
|
||||
|
||||
@code
|
||||
int test_several_auth_methods(ssh_session session)
|
||||
{
|
||||
int method, rc;
|
||||
|
||||
rc = ssh_userauth_none(session, NULL);
|
||||
if (rc != SSH_AUTH_SUCCESS) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
method = ssh_userauth_list(session, NULL);
|
||||
|
||||
if (method & SSH_AUTH_METHOD_NONE)
|
||||
{ // For the source code of function authenticate_none(),
|
||||
// refer to the corresponding example
|
||||
rc = authenticate_none(session);
|
||||
if (rc == SSH_AUTH_SUCCESS) return rc;
|
||||
}
|
||||
if (method & SSH_AUTH_METHOD_PUBLICKEY)
|
||||
{ // For the source code of function authenticate_pubkey(),
|
||||
// refer to the corresponding example
|
||||
rc = authenticate_pubkey(session);
|
||||
if (rc == SSH_AUTH_SUCCESS) return rc;
|
||||
}
|
||||
if (method & SSH_AUTH_METHOD_INTERACTIVE)
|
||||
{ // For the source code of function authenticate_kbdint(),
|
||||
// refer to the corresponding example
|
||||
rc = authenticate_kbdint(session);
|
||||
if (rc == SSH_AUTH_SUCCESS) return rc;
|
||||
}
|
||||
if (method & SSH_AUTH_METHOD_PASSWORD)
|
||||
{ // For the source code of function authenticate_password(),
|
||||
// refer to the corresponding example
|
||||
rc = authenticate_password(session);
|
||||
if (rc == SSH_AUTH_SUCCESS) return rc;
|
||||
}
|
||||
return SSH_AUTH_ERROR;
|
||||
}
|
||||
@endcode
|
||||
|
||||
|
||||
@subsection banner Getting the banner
|
||||
|
||||
The SSH server might send a banner, which you can retrieve with
|
||||
ssh_get_issue_banner(), then display to the user.
|
||||
|
||||
The following example shows how to retrieve and dispose the issue banner:
|
||||
|
||||
@code
|
||||
int display_banner(ssh_session session)
|
||||
{
|
||||
int rc;
|
||||
char *banner;
|
||||
|
||||
/*
|
||||
*** Does not work without calling ssh_userauth_none() first ***
|
||||
*** That will be fixed ***
|
||||
*/
|
||||
rc = ssh_userauth_none(session, NULL);
|
||||
if (rc == SSH_AUTH_ERROR)
|
||||
return rc;
|
||||
|
||||
banner = ssh_get_issue_banner(session);
|
||||
if (banner)
|
||||
{
|
||||
printf("%s\n", banner);
|
||||
free(banner);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
@endcode
|
||||
|
||||
*/
|
||||
@@ -1,94 +0,0 @@
|
||||
/**
|
||||
@page libssh_tutor_command Chapter 4: Passing a remote command
|
||||
@section remote_command Passing a remote command
|
||||
|
||||
Previous chapter has shown how to open a full shell session, with an attached
|
||||
terminal or not. If you only need to execute a command on the remote end,
|
||||
you don't need all that complexity.
|
||||
|
||||
The method described here is suited for executing only one remote command.
|
||||
If you need to issue several commands in a row, you should consider using
|
||||
a non-interactive remote shell, as explained in previous chapter.
|
||||
|
||||
@see shell
|
||||
|
||||
|
||||
@subsection exec_remote Executing a remote command
|
||||
|
||||
The first steps for executing a remote command are identical to those
|
||||
for opening remote shells. You first need a SSH channel, and then
|
||||
a SSH session that uses this channel:
|
||||
|
||||
@code
|
||||
int show_remote_files(ssh_session session)
|
||||
{
|
||||
ssh_channel channel;
|
||||
int rc;
|
||||
|
||||
channel = ssh_channel_new(session);
|
||||
if (channel == NULL) return SSH_ERROR;
|
||||
|
||||
rc = ssh_channel_open_session(channel);
|
||||
if (rc != SSH_OK)
|
||||
{
|
||||
ssh_channel_free(channel);
|
||||
return rc;
|
||||
}
|
||||
@endcode
|
||||
|
||||
Once a session is open, you can start the remote command with
|
||||
ssh_channel_request_exec():
|
||||
|
||||
@code
|
||||
rc = ssh_channel_request_exec(channel, "ls -l");
|
||||
if (rc != SSH_OK)
|
||||
{
|
||||
ssh_channel_close(channel);
|
||||
ssh_channel_free(channel);
|
||||
return rc;
|
||||
}
|
||||
@endcode
|
||||
|
||||
If the remote command displays data, you get them with ssh_channel_read().
|
||||
This function returns the number of bytes read. If there is no more
|
||||
data to read on the channel, this function returns 0, and you can go to next step.
|
||||
If an error has been encountered, it returns a negative value:
|
||||
|
||||
@code
|
||||
char buffer[256];
|
||||
int nbytes;
|
||||
|
||||
nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
|
||||
while (nbytes > 0)
|
||||
{
|
||||
if (fwrite(buffer, 1, nbytes, stdout) != nbytes)
|
||||
{
|
||||
ssh_channel_close(channel);
|
||||
ssh_channel_free(channel);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
|
||||
}
|
||||
|
||||
if (nbytes < 0)
|
||||
{
|
||||
ssh_channel_close(channel);
|
||||
ssh_channel_free(channel);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
@endcode
|
||||
|
||||
Once you read the result of the remote command, you send an
|
||||
end-of-file to the channel, close it, and free the memory
|
||||
that it used:
|
||||
|
||||
@code
|
||||
ssh_channel_send_eof(channel);
|
||||
ssh_channel_close(channel);
|
||||
ssh_channel_free(channel);
|
||||
|
||||
return SSH_OK;
|
||||
}
|
||||
@endcode
|
||||
|
||||
*/
|
||||
@@ -1,119 +0,0 @@
|
||||
curve25519-sha256@libssh.org.txt Aris Adamantiadis <aris@badcode.be>
|
||||
21/9/2013
|
||||
|
||||
1. Introduction
|
||||
|
||||
This document describes the key exchange methode curve25519-sha256@libssh.org
|
||||
for SSH version 2 protocol. It is provided as an alternative to the existing
|
||||
key exchange mechanisms based on either Diffie-Hellman or Elliptic Curve Diffie-
|
||||
Hellman [RFC5656].
|
||||
The reason is the following : During summer of 2013, revelations from ex-
|
||||
consultant at NSA Edward Snowden gave proof that NSA willingly inserts backdoors
|
||||
into softwares, hardware components and published standards. While it is still
|
||||
believed that the mathematics behind ECC cryptography are still sound and solid,
|
||||
some people (including Bruce Schneier [SCHNEIER]), showed their lack of confidence
|
||||
in NIST-published curves such as nistp256, nistp384, nistp521, for which constant
|
||||
parameters (including the generator point) are defined without explanation. It
|
||||
is also believed that NSA had a word to say in their definition. These curves
|
||||
are not the most secure or fastest possible for their key sizes [DJB], and
|
||||
researchers think it is possible that NSA have ways of cracking NIST curves.
|
||||
It is also interesting to note that SSH belongs to the list of protocols the NSA
|
||||
claims to be able to eavesdrop. Having a secure replacement would make passive
|
||||
attacks much harder if such a backdoor exists.
|
||||
|
||||
However an alternative exists in the form of Curve25519. This algorithm has been
|
||||
proposed in 2006 by DJB [Curve25519]. Its main strengths are its speed, its
|
||||
constant-time run time (and resistance against side-channel attacks), and its
|
||||
lack of nebulous hard-coded constants.
|
||||
|
||||
The reference version being used in this document is the one described in
|
||||
[Curve25519] as implemented in the library NaCl [NaCl].
|
||||
This document does not attempt to provide alternatives to the ecdsa-sha1-*
|
||||
authentication keys.
|
||||
|
||||
2. Key exchange
|
||||
|
||||
The key exchange procedure is very similar to the one described chapter 4 of
|
||||
[RFC5656]. Public ephemeral keys are transmitted over SSH encapsulated into
|
||||
standard SSH strings.
|
||||
|
||||
The following is an overview of the key exchange process:
|
||||
|
||||
Client Server
|
||||
------ ------
|
||||
Generate ephemeral key pair.
|
||||
SSH_MSG_KEX_ECDH_INIT -------->
|
||||
Verify that client public key
|
||||
length is 32 bytes.
|
||||
Generate ephemeral key pair.
|
||||
Compute shared secret.
|
||||
Generate and sign exchange hash.
|
||||
<-------- SSH_MSG_KEX_ECDH_REPLY
|
||||
Verify that server public key length is 32 bytes.
|
||||
* Verify host keys belong to server.
|
||||
Compute shared secret.
|
||||
Generate exchange hash.
|
||||
Verify server's signature.
|
||||
|
||||
* Optional but strongly recommanded as this protects against MITM attacks.
|
||||
|
||||
This is implemented using the same messages as described in RFC5656 chapter 4
|
||||
|
||||
3. Method Name
|
||||
|
||||
The name of this key exchange method is "curve25519-sha256@libssh.org".
|
||||
|
||||
4. Implementation considerations
|
||||
|
||||
The whole method is based on the curve25519 scalar multiplication. In this
|
||||
method, a private key is a scalar of 256 bits, and a public key is a point
|
||||
of 256 bits.
|
||||
|
||||
4.1. Private key generation
|
||||
|
||||
A 32 bytes private key should be generated for each new connection,
|
||||
using a secure PRNG. The following actions must be done on the private key:
|
||||
mysecret[0] &= 248;
|
||||
mysecret[31] &= 127;
|
||||
mysecret[31] |= 64;
|
||||
In order to keep the key valid. However, many cryptographic libraries will do
|
||||
this automatically.
|
||||
It should be noted that, in opposition to NIST curves, no special validation
|
||||
should be done to ensure the result is a valid and secure private key.
|
||||
|
||||
4.2 Public key generation
|
||||
|
||||
The 32 bytes public key of either a client or a server must be generated using
|
||||
the 32 bytes private key and a common generator base. This base is defined as 9
|
||||
followed by all zeroes:
|
||||
const unsigned char basepoint[32] = {9};
|
||||
|
||||
The public key is calculated using the cryptographic scalar multiplication:
|
||||
const unsigned char privkey[32];
|
||||
unsigned char pubkey[32];
|
||||
crypto_scalarmult (pubkey, privkey, basepoint);
|
||||
However some cryptographic libraries may provide a combined function:
|
||||
crypto_scalarmult_base (pubkey, privkey);
|
||||
|
||||
It should be noted that, in opposition to NIST curves, no special validation
|
||||
should be done to ensure the received public keys are valid curves point. The
|
||||
Curve25519 algorithm ensure that every possible public key maps to a valid
|
||||
ECC Point.
|
||||
|
||||
4.3 Shared secret generation
|
||||
|
||||
The shared secret, k, is defined in SSH specifications to be a big integer.
|
||||
This number is calculated using the following procedure:
|
||||
|
||||
X is the 32 bytes point obtained by the scalar multiplication of the other
|
||||
side's public key and the local private key scalar.
|
||||
|
||||
The whole 32 bytes of the number X are then converted into a big integer k.
|
||||
This conversion follows the network byte order. This step differs from
|
||||
RFC5656.
|
||||
|
||||
[RFC5656] http://tools.ietf.org/html/rfc5656
|
||||
[SCHNEIER] https://www.schneier.com/blog/archives/2013/09/the_nsa_is_brea.html#c1675929
|
||||
[DJB] http://cr.yp.to/talks/2013.05.31/slides-dan+tanja-20130531-4x3.pdf
|
||||
[Curve25519] "Curve25519: new Diffie-Hellman speed records."
|
||||
http://cr.yp.to/ecdh/curve25519-20060209.pdf
|
||||
1445
doc/doxy.config.in
Normal file
1445
doc/doxy.config.in
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,230 +0,0 @@
|
||||
/**
|
||||
@page libssh_tutor_forwarding Chapter 7: Forwarding connections (tunnel)
|
||||
@section forwarding_connections Forwarding connections
|
||||
|
||||
Port forwarding comes in SSH protocol in two different flavours:
|
||||
direct or reverse port forwarding. Direct port forwarding is also
|
||||
named local port forwardind, and reverse port forwarding is also called
|
||||
remote port forwarding. SSH also allows X11 tunnels.
|
||||
|
||||
|
||||
|
||||
@subsection forwarding_direct Direct port forwarding
|
||||
|
||||
Direct port forwarding is from client to server. The client opens a tunnel,
|
||||
and forwards whatever data to the server. Then, the server connects to an
|
||||
end point. The end point can reside on another machine or on the SSH
|
||||
server itself.
|
||||
|
||||
Example of use of direct port forwarding:
|
||||
@verbatim
|
||||
Mail client application Google Mail
|
||||
| ^
|
||||
5555 (arbitrary) |
|
||||
| 143 (IMAP2)
|
||||
V |
|
||||
SSH client =====> SSH server
|
||||
|
||||
Legend:
|
||||
--P-->: port connexion through port P
|
||||
=====>: SSH tunnel
|
||||
@endverbatim
|
||||
A mail client connects to port 5555 of a client. An encrypted tunnel is
|
||||
established to the server. The server connects to port 143 of Google Mail (the
|
||||
end point). Now the local mail client can retreive mail.
|
||||
|
||||
|
||||
@subsection forwarding_reverse Reverse port forwarding
|
||||
|
||||
The reverse forwarding is slightly different. It goes from server to client,
|
||||
even though the client has the initiative of establishing the tunnel.
|
||||
Once the tunnel is established, the server will listen on a port. Whenever
|
||||
a connection to this port is made, the server forwards the data to the client.
|
||||
|
||||
Example of use of reverse port forwarding:
|
||||
@verbatim
|
||||
Local mail server Mail client application
|
||||
^ |
|
||||
| 5555 (arbitrary)
|
||||
143 (IMAP2) |
|
||||
| V
|
||||
SSH client <===== SSH server
|
||||
|
||||
Legend:
|
||||
--P-->: port connexion through port P
|
||||
=====>: SSH tunnel
|
||||
@endverbatim
|
||||
In this example, the SSH client establishes the tunnel,
|
||||
but it is used to forward the connections established at
|
||||
the server to the client.
|
||||
|
||||
|
||||
@subsection forwarding_x11 X11 tunnels
|
||||
|
||||
X11 tunnels allow a remote application to display locally.
|
||||
|
||||
Example of use of X11 tunnels:
|
||||
@verbatim
|
||||
Local display Graphical application
|
||||
(X11 server) (X11 client)
|
||||
^ |
|
||||
| V
|
||||
SSH client <===== SSH server
|
||||
|
||||
Legend:
|
||||
----->: X11 connection through X11 display number
|
||||
=====>: SSH tunnel
|
||||
@endverbatim
|
||||
The SSH tunnel is established by the client.
|
||||
|
||||
How to establish X11 tunnels with libssh has already been described in
|
||||
this tutorial.
|
||||
|
||||
@see x11
|
||||
|
||||
|
||||
@subsection libssh_direct Doing direct port forwarding with libssh
|
||||
|
||||
To do direct port forwarding, call function ssh_channel_open_forward():
|
||||
- you need a separate channel for the tunnel as first parameter;
|
||||
- second and third parameters are the remote endpoint;
|
||||
- fourth and fifth parameters are sent to the remote server
|
||||
so that they can be logged on that server.
|
||||
|
||||
If you don't plan to forward the data you will receive to any local port,
|
||||
just put fake values like "localhost" and 5555 as your local host and port.
|
||||
|
||||
The example below shows how to open a direct channel that would be
|
||||
used to retrieve google's home page from the remote SSH server.
|
||||
|
||||
@code
|
||||
int direct_forwarding(ssh_session session)
|
||||
{
|
||||
ssh_channel forwarding_channel;
|
||||
int rc;
|
||||
char *http_get = "GET / HTTP/1.1\nHost: www.google.com\n\n";
|
||||
int nbytes, nwritten;
|
||||
|
||||
forwarding_channel = ssh_channel_new(session);
|
||||
if (forwarding_channel == NULL) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = ssh_channel_open_forward(forwarding_channel,
|
||||
"www.google.com", 80,
|
||||
"localhost", 5555);
|
||||
if (rc != SSH_OK)
|
||||
{
|
||||
ssh_channel_free(forwarding_channel);
|
||||
return rc;
|
||||
}
|
||||
|
||||
nbytes = strlen(http_get);
|
||||
nwritten = ssh_channel_write(forwarding_channel,
|
||||
http_get,
|
||||
nbytes);
|
||||
if (nbytes != nwritten)
|
||||
{
|
||||
ssh_channel_free(forwarding_channel);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
...
|
||||
|
||||
ssh_channel_free(forwarding_channel);
|
||||
return SSH_OK;
|
||||
}
|
||||
@endcode
|
||||
|
||||
The data sent by Google can be retrieved for example with ssh_select()
|
||||
and ssh_channel_read(). Goggle's home page can then be displayed on the
|
||||
local SSH client, saved into a local file, made available on a local port,
|
||||
or whatever use you have for it.
|
||||
|
||||
|
||||
@subsection libssh_reverse Doing reverse port forwarding with libssh
|
||||
|
||||
To do reverse port forwarding, call ssh_channel_listen_forward(),
|
||||
then ssh_channel_accept_forward().
|
||||
|
||||
When you call ssh_channel_listen_forward(), you can let the remote server
|
||||
chose the non-priviledged port it should listen to. Otherwise, you can chose
|
||||
your own priviledged or non-priviledged port. Beware that you should have
|
||||
administrative priviledges on the remote server to open a priviledged port
|
||||
(port number < 1024).
|
||||
|
||||
Below is an example of a very rough web server waiting for connections on port
|
||||
8080 of remote SSH server. The incoming connections are passed to the
|
||||
local libssh application, which handles them:
|
||||
|
||||
@code
|
||||
int web_server(ssh_session session)
|
||||
{
|
||||
int rc;
|
||||
ssh_channel channel;
|
||||
char buffer[256];
|
||||
int nbytes, nwritten;
|
||||
int port = 0;
|
||||
char *helloworld = ""
|
||||
"HTTP/1.1 200 OK\n"
|
||||
"Content-Type: text/html\n"
|
||||
"Content-Length: 113\n"
|
||||
"\n"
|
||||
"<html>\n"
|
||||
" <head>\n"
|
||||
" <title>Hello, World!</title>\n"
|
||||
" </head>\n"
|
||||
" <body>\n"
|
||||
" <h1>Hello, World!</h1>\n"
|
||||
" </body>\n"
|
||||
"</html>\n";
|
||||
|
||||
rc = ssh_channel_listen_forward(session, NULL, 8080, NULL);
|
||||
if (rc != SSH_OK)
|
||||
{
|
||||
fprintf(stderr, "Error opening remote port: %s\n",
|
||||
ssh_get_error(session));
|
||||
return rc;
|
||||
}
|
||||
|
||||
channel = ssh_channel_accept_forward(session, 60000, &port);
|
||||
if (channel == NULL)
|
||||
{
|
||||
fprintf(stderr, "Error waiting for incoming connection: %s\n",
|
||||
ssh_get_error(session));
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
while (1)
|
||||
{
|
||||
nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
|
||||
if (nbytes < 0)
|
||||
{
|
||||
fprintf(stderr, "Error reading incoming data: %s\n",
|
||||
ssh_get_error(session));
|
||||
ssh_channel_send_eof(channel);
|
||||
ssh_channel_free(channel);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
if (strncmp(buffer, "GET /", 5)) continue;
|
||||
|
||||
nbytes = strlen(helloworld);
|
||||
nwritten = ssh_channel_write(channel, helloworld, nbytes);
|
||||
if (nwritten != nbytes)
|
||||
{
|
||||
fprintf(stderr, "Error sending answer: %s\n",
|
||||
ssh_get_error(session));
|
||||
ssh_channel_send_eof(channel);
|
||||
ssh_channel_free(channel);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
printf("Sent answer\n");
|
||||
}
|
||||
|
||||
ssh_channel_send_eof(channel);
|
||||
ssh_channel_free(channel);
|
||||
return SSH_OK;
|
||||
}
|
||||
@endcode
|
||||
|
||||
*/
|
||||
@@ -1,454 +0,0 @@
|
||||
/**
|
||||
@page libssh_tutor_guided_tour Chapter 1: A typical SSH session
|
||||
@section ssh_session A typical SSH session
|
||||
|
||||
A SSH session goes through the following steps:
|
||||
|
||||
- Before connecting to the server, you can set up if you wish one or other
|
||||
server public key authentication, i.e. DSA or RSA. You can choose
|
||||
cryptographic algorithms you trust and compression algorithms if any. You
|
||||
must of course set up the hostname.
|
||||
|
||||
- The connection is established. A secure handshake is made, and resulting from
|
||||
it, a public key from the server is gained. You MUST verify that the public
|
||||
key is legitimate, using for instance the MD5 fingerprint or the known hosts
|
||||
file.
|
||||
|
||||
- The client must authenticate: the classical ways are password, or
|
||||
public keys (from dsa and rsa key-pairs generated by openssh).
|
||||
If a SSH agent is running, it is possible to use it.
|
||||
|
||||
- Now that the user has been authenticated, you must open one or several
|
||||
channels. Channels are different subways for information into a single ssh
|
||||
connection. Each channel has a standard stream (stdout) and an error stream
|
||||
(stderr). You can theoretically open an infinity of channels.
|
||||
|
||||
- With the channel you opened, you can do several things:
|
||||
- Execute a single command.
|
||||
- Open a shell. You may want to request a pseudo-terminal before.
|
||||
- Invoke the sftp subsystem to transfer files.
|
||||
- Invoke the scp subsystem to transfer files.
|
||||
- Invoke your own subsystem. This is outside the scope of this document,
|
||||
but can be done.
|
||||
|
||||
- When everything is finished, just close the channels, and then the connection.
|
||||
|
||||
The sftp and scp subsystems use channels, but libssh hides them to
|
||||
the programmer. If you want to use those subsystems, instead of a channel,
|
||||
you'll usually open a "sftp session" or a "scp session".
|
||||
|
||||
|
||||
@subsection setup Creating the session and setting options
|
||||
|
||||
The most important object in a SSH connection is the SSH session. In order
|
||||
to allocate a new SSH session, you use ssh_new(). Don't forget to
|
||||
always verify that the allocation successed.
|
||||
@code
|
||||
#include <libssh/libssh.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
ssh_session my_ssh_session = ssh_new();
|
||||
if (my_ssh_session == NULL)
|
||||
exit(-1);
|
||||
...
|
||||
ssh_free(my_ssh_session);
|
||||
}
|
||||
@endcode
|
||||
|
||||
libssh follows the allocate-it-deallocate-it pattern. Each object that you allocate
|
||||
using xxxxx_new() must be deallocated using xxxxx_free(). In this case, ssh_new()
|
||||
does the allocation and ssh_free() does the contrary.
|
||||
|
||||
The ssh_options_set() function sets the options of the session. The most important options are:
|
||||
- SSH_OPTIONS_HOST: the name of the host you want to connect to
|
||||
- SSH_OPTIONS_PORT: the used port (default is port 22)
|
||||
- SSH_OPTIONS_USER: the system user under which you want to connect
|
||||
- SSH_OPTIONS_LOG_VERBOSITY: the quantity of messages that are printed
|
||||
|
||||
The complete list of options can be found in the documentation of ssh_options_set().
|
||||
The only mandatory option is SSH_OPTIONS_HOST. If you don't use SSH_OPTIONS_USER,
|
||||
the local username of your account will be used.
|
||||
|
||||
Here is a small example of how to use it:
|
||||
|
||||
@code
|
||||
#include <libssh/libssh.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
ssh_session my_ssh_session;
|
||||
int verbosity = SSH_LOG_PROTOCOL;
|
||||
int port = 22;
|
||||
|
||||
my_ssh_session = ssh_new();
|
||||
if (my_ssh_session == NULL)
|
||||
exit(-1);
|
||||
|
||||
ssh_options_set(my_ssh_session, SSH_OPTIONS_HOST, "localhost");
|
||||
ssh_options_set(my_ssh_session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity);
|
||||
ssh_options_set(my_ssh_session, SSH_OPTIONS_PORT, &port);
|
||||
|
||||
...
|
||||
|
||||
ssh_free(my_ssh_session);
|
||||
}
|
||||
@endcode
|
||||
|
||||
Please notice that all parameters are passed to ssh_options_set() as pointers,
|
||||
even if you need to set an integer value.
|
||||
|
||||
@see ssh_new
|
||||
@see ssh_free
|
||||
@see ssh_options_set
|
||||
@see ssh_options_parse_config
|
||||
@see ssh_options_copy
|
||||
@see ssh_options_getopt
|
||||
|
||||
|
||||
@subsection connect Connecting to the server
|
||||
|
||||
Once all settings have been made, you can connect using ssh_connect(). That
|
||||
function will return SSH_OK if the connection worked, SSH_ERROR otherwise.
|
||||
|
||||
You can get the English error string with ssh_get_error() in order to show the
|
||||
user what went wrong. Then, use ssh_disconnect() when you want to stop
|
||||
the session.
|
||||
|
||||
Here's an example:
|
||||
|
||||
@code
|
||||
#include <libssh/libssh.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
ssh_session my_ssh_session;
|
||||
int rc;
|
||||
|
||||
my_ssh_session = ssh_new();
|
||||
if (my_ssh_session == NULL)
|
||||
exit(-1);
|
||||
|
||||
ssh_options_set(my_ssh_session, SSH_OPTIONS_HOST, "localhost");
|
||||
|
||||
rc = ssh_connect(my_ssh_session);
|
||||
if (rc != SSH_OK)
|
||||
{
|
||||
fprintf(stderr, "Error connecting to localhost: %s\n",
|
||||
ssh_get_error(my_ssh_session));
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
...
|
||||
|
||||
ssh_disconnect(my_ssh_session);
|
||||
ssh_free(my_ssh_session);
|
||||
}
|
||||
@endcode
|
||||
|
||||
|
||||
@subsection serverauth Authenticating the server
|
||||
|
||||
Once you're connected, the following step is mandatory: you must check that the server
|
||||
you just connected to is known and safe to use (remember, SSH is about security and
|
||||
authentication).
|
||||
|
||||
There are two ways of doing this:
|
||||
- The first way (recommended) is to use the ssh_is_server_known()
|
||||
function. This function will look into the known host file
|
||||
(~/.ssh/known_hosts on UNIX), look for the server hostname's pattern,
|
||||
and determine whether this host is present or not in the list.
|
||||
- The second way is to use ssh_get_pubkey_hash() to get a binary version
|
||||
of the public key hash value. You can then use your own database to check
|
||||
if this public key is known and secure.
|
||||
|
||||
You can also use the ssh_get_pubkey_hash() to show the public key hash
|
||||
value to the user, in case he knows what the public key hash value is
|
||||
(some paranoid people write their public key hash values on paper before
|
||||
going abroad, just in case ...).
|
||||
|
||||
If the remote host is being used to for the first time, you can ask the user whether
|
||||
he/she trusts it. Once he/she concluded that the host is valid and worth being
|
||||
added in the known hosts file, you use ssh_write_knownhost() to register it in
|
||||
the known hosts file, or any other way if you use your own database.
|
||||
|
||||
The following example is part of the examples suite available in the
|
||||
examples/ directory:
|
||||
|
||||
@code
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
int verify_knownhost(ssh_session session)
|
||||
{
|
||||
int state, hlen;
|
||||
unsigned char *hash = NULL;
|
||||
char *hexa;
|
||||
char buf[10];
|
||||
|
||||
state = ssh_is_server_known(session);
|
||||
|
||||
hlen = ssh_get_pubkey_hash(session, &hash);
|
||||
if (hlen < 0)
|
||||
return -1;
|
||||
|
||||
switch (state)
|
||||
{
|
||||
case SSH_SERVER_KNOWN_OK:
|
||||
break; /* ok */
|
||||
|
||||
case SSH_SERVER_KNOWN_CHANGED:
|
||||
fprintf(stderr, "Host key for server changed: it is now:\n");
|
||||
ssh_print_hexa("Public key hash", hash, hlen);
|
||||
fprintf(stderr, "For security reasons, connection will be stopped\n");
|
||||
free(hash);
|
||||
return -1;
|
||||
|
||||
case SSH_SERVER_FOUND_OTHER:
|
||||
fprintf(stderr, "The host key for this server was not found but an other"
|
||||
"type of key exists.\n");
|
||||
fprintf(stderr, "An attacker might change the default server key to"
|
||||
"confuse your client into thinking the key does not exist\n");
|
||||
free(hash);
|
||||
return -1;
|
||||
|
||||
case SSH_SERVER_FILE_NOT_FOUND:
|
||||
fprintf(stderr, "Could not find known host file.\n");
|
||||
fprintf(stderr, "If you accept the host key here, the file will be"
|
||||
"automatically created.\n");
|
||||
/* fallback to SSH_SERVER_NOT_KNOWN behavior */
|
||||
|
||||
case SSH_SERVER_NOT_KNOWN:
|
||||
hexa = ssh_get_hexa(hash, hlen);
|
||||
fprintf(stderr,"The server is unknown. Do you trust the host key?\n");
|
||||
fprintf(stderr, "Public key hash: %s\n", hexa);
|
||||
free(hexa);
|
||||
if (fgets(buf, sizeof(buf), stdin) == NULL)
|
||||
{
|
||||
free(hash);
|
||||
return -1;
|
||||
}
|
||||
if (strncasecmp(buf, "yes", 3) != 0)
|
||||
{
|
||||
free(hash);
|
||||
return -1;
|
||||
}
|
||||
if (ssh_write_knownhost(session) < 0)
|
||||
{
|
||||
fprintf(stderr, "Error %s\n", strerror(errno));
|
||||
free(hash);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case SSH_SERVER_ERROR:
|
||||
fprintf(stderr, "Error %s", ssh_get_error(session));
|
||||
free(hash);
|
||||
return -1;
|
||||
}
|
||||
|
||||
free(hash);
|
||||
return 0;
|
||||
}
|
||||
@endcode
|
||||
|
||||
@see ssh_connect
|
||||
@see ssh_disconnect
|
||||
@see ssh_get_error
|
||||
@see ssh_get_error_code
|
||||
@see ssh_get_pubkey_hash
|
||||
@see ssh_is_server_known
|
||||
@see ssh_write_knownhost
|
||||
|
||||
|
||||
@subsection auth Authenticating the user
|
||||
|
||||
The authentication process is the way a service provider can identify a
|
||||
user and verify his/her identity. The authorization process is about enabling
|
||||
the authenticated user the access to ressources. In SSH, the two concepts
|
||||
are linked. After authentication, the server can grant the user access to
|
||||
several ressources such as port forwarding, shell, sftp subsystem, and so on.
|
||||
|
||||
libssh supports several methods of authentication:
|
||||
- "none" method. This method allows to get the available authentications
|
||||
methods. It also gives the server a chance to authenticate the user with
|
||||
just his/her login. Some very old hardware uses this feature to fallback
|
||||
the user on a "telnet over SSH" style of login.
|
||||
- password method. A password is sent to the server, which accepts it or not.
|
||||
- keyboard-interactive method. The server sends several challenges to the
|
||||
user, who must answer correctly. This makes possible the authentication
|
||||
via a codebook for instance ("give code at 23:R on page 3").
|
||||
- public key method. The host knows the public key of the user, and the
|
||||
user must prove he knows the associated private key. This can be done
|
||||
manually, or delegated to the SSH agent as we'll see later.
|
||||
|
||||
All these methods can be combined. You can for instance force the user to
|
||||
authenticate with at least two of the authentication methods. In that case,
|
||||
one speaks of "Partial authentication". A partial authentication is a
|
||||
response from authentication functions stating that your credential was
|
||||
accepted, but yet another one is required to get in.
|
||||
|
||||
The example below shows an authentication with password:
|
||||
|
||||
@code
|
||||
#include <libssh/libssh.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
ssh_session my_ssh_session;
|
||||
int rc;
|
||||
char *password;
|
||||
|
||||
// Open session and set options
|
||||
my_ssh_session = ssh_new();
|
||||
if (my_ssh_session == NULL)
|
||||
exit(-1);
|
||||
ssh_options_set(my_ssh_session, SSH_OPTIONS_HOST, "localhost");
|
||||
|
||||
// Connect to server
|
||||
rc = ssh_connect(my_ssh_session);
|
||||
if (rc != SSH_OK)
|
||||
{
|
||||
fprintf(stderr, "Error connecting to localhost: %s\n",
|
||||
ssh_get_error(my_ssh_session));
|
||||
ssh_free(my_ssh_session);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
// Verify the server's identity
|
||||
// For the source code of verify_knowhost(), check previous example
|
||||
if (verify_knownhost(my_ssh_session) < 0)
|
||||
{
|
||||
ssh_disconnect(my_ssh_session);
|
||||
ssh_free(my_ssh_session);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
// Authenticate ourselves
|
||||
password = getpass("Password: ");
|
||||
rc = ssh_userauth_password(my_ssh_session, NULL, password);
|
||||
if (rc != SSH_AUTH_SUCCESS)
|
||||
{
|
||||
fprintf(stderr, "Error authenticating with password: %s\n",
|
||||
ssh_get_error(my_ssh_session));
|
||||
ssh_disconnect(my_ssh_session);
|
||||
ssh_free(my_ssh_session);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
...
|
||||
|
||||
ssh_disconnect(my_ssh_session);
|
||||
ssh_free(my_ssh_session);
|
||||
}
|
||||
@endcode
|
||||
|
||||
@see @ref authentication_details
|
||||
|
||||
|
||||
@subsection using_ssh Doing something
|
||||
|
||||
At this point, the authenticity of both server and client is established.
|
||||
Time has come to take advantage of the many possibilities offered by the SSH
|
||||
protocol: execute a remote command, open remote shells, transfer files,
|
||||
forward ports, etc.
|
||||
|
||||
The example below shows how to execute a remote command:
|
||||
|
||||
@code
|
||||
int show_remote_processes(ssh_session session)
|
||||
{
|
||||
ssh_channel channel;
|
||||
int rc;
|
||||
char buffer[256];
|
||||
int nbytes;
|
||||
|
||||
channel = ssh_channel_new(session);
|
||||
if (channel == NULL)
|
||||
return SSH_ERROR;
|
||||
|
||||
rc = ssh_channel_open_session(channel);
|
||||
if (rc != SSH_OK)
|
||||
{
|
||||
ssh_channel_free(channel);
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = ssh_channel_request_exec(channel, "ps aux");
|
||||
if (rc != SSH_OK)
|
||||
{
|
||||
ssh_channel_close(channel);
|
||||
ssh_channel_free(channel);
|
||||
return rc;
|
||||
}
|
||||
|
||||
nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
|
||||
while (nbytes > 0)
|
||||
{
|
||||
if (write(1, buffer, nbytes) != (unsigned int) nbytes)
|
||||
{
|
||||
ssh_channel_close(channel);
|
||||
ssh_channel_free(channel);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
|
||||
}
|
||||
|
||||
if (nbytes < 0)
|
||||
{
|
||||
ssh_channel_close(channel);
|
||||
ssh_channel_free(channel);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
ssh_channel_send_eof(channel);
|
||||
ssh_channel_close(channel);
|
||||
ssh_channel_free(channel);
|
||||
|
||||
return SSH_OK;
|
||||
}
|
||||
@endcode
|
||||
|
||||
@see @ref opening_shell
|
||||
@see @ref remote_command
|
||||
@see @ref sftp_subsystem
|
||||
@see @ref scp_subsystem
|
||||
|
||||
|
||||
@subsection errors Handling the errors
|
||||
|
||||
All the libssh functions which return an error value also set an English error message
|
||||
describing the problem.
|
||||
|
||||
Error values are typically SSH_ERROR for integer values, or NULL for pointers.
|
||||
|
||||
The function ssh_get_error() returns a pointer to the static error message.
|
||||
|
||||
ssh_error_code() returns the error code number : SSH_NO_ERROR,
|
||||
SSH_REQUEST_DENIED, SSH_INVALID_REQUEST, SSH_CONNECTION_LOST, SSH_FATAL,
|
||||
or SSH_INVALID_DATA. SSH_REQUEST_DENIED means the ssh server refused your
|
||||
request, but the situation is recoverable. The others mean something happened
|
||||
to the connection (some encryption problems, server problems, ...).
|
||||
SSH_INVALID_REQUEST means the library got some garbage from server, but
|
||||
might be recoverable. SSH_FATAL means the connection has an important
|
||||
problem and isn't probably recoverable.
|
||||
|
||||
Most of time, the error returned are SSH_FATAL, but some functions
|
||||
(generaly the ssh_request_xxx ones) may fail because of server denying request.
|
||||
In these cases, SSH_REQUEST_DENIED is returned.
|
||||
|
||||
For thread safety, errors are bound to ssh_session objects.
|
||||
As long as your ssh_session object is not NULL, you can retrieve the last error
|
||||
message and error code from the ssh_session using ssh_get_error() and
|
||||
ssh_get_error_code() respectively.
|
||||
|
||||
The SFTP subsystem has its own error codes, in addition to libssh ones.
|
||||
|
||||
|
||||
*/
|
||||
@@ -1,49 +0,0 @@
|
||||
/**
|
||||
@page libssh_tutorial The Tutorial
|
||||
@section introduction Introduction
|
||||
|
||||
libssh is a C library that enables you to write a program that uses the
|
||||
SSH protocol. With it, you can remotely execute programs, transfer
|
||||
files, or use a secure and transparent tunnel for your remote programs.
|
||||
The SSH protocol is encrypted, ensures data integrity, and provides strong
|
||||
means of authenticating both the server of the client. The library hides
|
||||
a lot of technical details from the SSH protocol, but this does not
|
||||
mean that you should not try to know about and understand these details.
|
||||
|
||||
libssh is a Free Software / Open Source project. The libssh library
|
||||
is distributed under LGPL license. The libssh project has nothing to do with
|
||||
"libssh2", which is a completly different and independant project.
|
||||
|
||||
libssh can run on top of either libgcrypt or libcrypto,
|
||||
two general-purpose cryptographic libraries.
|
||||
|
||||
This tutorial concentrates for its main part on the "client" side of libssh.
|
||||
To learn how to accept incoming SSH connexions (how to write a SSH server),
|
||||
you'll have to jump to the end of this document.
|
||||
|
||||
This tutorial describes libssh version 0.5.0. This version is a little different
|
||||
from the 0.4.X series. However, the examples should work with
|
||||
little changes on versions like 0.4.2 and later.
|
||||
|
||||
|
||||
Table of contents:
|
||||
|
||||
@subpage libssh_tutor_guided_tour
|
||||
|
||||
@subpage libssh_tutor_authentication
|
||||
|
||||
@subpage libssh_tutor_shell
|
||||
|
||||
@subpage libssh_tutor_command
|
||||
|
||||
@subpage libssh_tutor_sftp
|
||||
|
||||
@subpage libssh_tutor_scp
|
||||
|
||||
@subpage libssh_tutor_forwarding
|
||||
|
||||
@subpage libssh_tutor_threads
|
||||
|
||||
@subpage libssh_tutor_todo
|
||||
|
||||
*/
|
||||
385
doc/libssh-0.2-api-1.txt
Normal file
385
doc/libssh-0.2-api-1.txt
Normal file
@@ -0,0 +1,385 @@
|
||||
The new libssh 0.2 API
|
||||
----------------------
|
||||
|
||||
Version 1
|
||||
|
||||
A. Introduction
|
||||
---------------
|
||||
|
||||
With the time from the first release of libssh, I have received lots of
|
||||
comments about the current API. Myself, I found it quite limiting when doing
|
||||
my first libssh-server drafts. Thus, I am moving to a stronger API.
|
||||
This API must still be simple. I am not introducing complex changes. An API
|
||||
well designed must hide the implementation details. Implementation can change
|
||||
easily within bugfixes - but API cannot change each release.
|
||||
|
||||
To the people already using libssh 0.11 : sorry. Once I have the complete API
|
||||
redesigned, I will write a migration paper. It won't be too hard normally.
|
||||
|
||||
Here are the things that were lacking in the previous API and *must* change:
|
||||
|
||||
* A non-blocking mode connection type
|
||||
* Functions to relegate File descriptor listening to Calling functions and to
|
||||
the programmer. (I'll explain later).
|
||||
* Along with that, good buffering system (well, it's not an API but).
|
||||
* Leave the "functions returns a pointer when it works and NULL when it does
|
||||
not work". It gives serious problems to implement bindings (A C++
|
||||
constructor should not fail and should not depend on a network thing
|
||||
* Make the Session structure an abstract structure that can work with both
|
||||
client and *servers*. That mean we should have a Server object which listen
|
||||
to clients on a bound port, does the different handshakes and return a
|
||||
session.
|
||||
Since C is not per se an Object language, I won't use inheritance between
|
||||
objects.
|
||||
* This same server thing must provide the reverse capabilities than the
|
||||
client. That is, accept the handshake, in a nonblocking way. Accept channel
|
||||
requests, or send them to the controller program.
|
||||
* Support for program forking : Imagine you have a Ssh server object. You
|
||||
accept a connection and receive a session, then you receive a channel. You
|
||||
may want to keep the good old days fork() tricks. Libssh will give a way to
|
||||
destroy handlers from sessions which belong to an other process without
|
||||
disturbing the session.
|
||||
* So often I received the comment back saying that it was not clear why a
|
||||
session or a channel was terminated. This is over.
|
||||
* And of course I received lot of mails about the fact I'm doing namespace
|
||||
polution. this will be resolved this time.
|
||||
So, please read this draft not as a formal documentation but like a roadmap of
|
||||
things that each kind of object must do.
|
||||
|
||||
B. Description of objects and functions
|
||||
|
||||
Initialization and finalization
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Initialization is for now called automatically, so you don't have to take care
|
||||
of that.
|
||||
As for finalization, we need to finalize the underlying cryptographic library
|
||||
(either OpenSSL or libgcrypt). Be sure that you call ssh_finalize when this
|
||||
library won't be used anymore, even by other libraries (i.e. if you use libssh
|
||||
and another library that uses OpenSSL, call ssh_finalize when any function of
|
||||
both these libraries won't be called).
|
||||
If you trust your operating system to clean up the mess after a process
|
||||
terminates, you can skip this call.
|
||||
|
||||
Options structure
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
struct ssh_options *ssh_options_new()
|
||||
|
||||
ssh_options_getopt(options, *argc, argv)
|
||||
|
||||
ssh_options_copy(options)
|
||||
|
||||
char ** ssh_options_get_supported_algos(options,type)
|
||||
returns a list of the algos supported by libssh, type being one of
|
||||
SSH_HOSTKEYS, SSH_KEX, SSH_CRYPT, SSH_MAC, SSH_COMP, SSH_LANG
|
||||
|
||||
ssh_options_set_wanted_algos(options,type, char *list)
|
||||
list being comma-separated list of algos, and type being the upper constants
|
||||
but with _C_S or _S_V added to them.
|
||||
|
||||
ssh_options_set_port(options, port)
|
||||
|
||||
ssh_options_set_host(options, host)
|
||||
|
||||
ssh_options_set_fd(options, fd)
|
||||
|
||||
ssh_options_set_bind(options, bindaddr, port)
|
||||
this options sets the address to bind for a client *or* a server. a port of
|
||||
zero means whatever port is free (what most clients want).
|
||||
|
||||
ssh_options_set_username(options, username)
|
||||
|
||||
ssh_options_set_connect_timeout(options, seconds, usec)
|
||||
|
||||
ssh_options_set_ssh_dir(options, dir)
|
||||
ssh_options_set_known_hosts_file(options, file)
|
||||
ssh_options_set_identity(options, file)
|
||||
|
||||
ssh_options_set_banner(options, banner)
|
||||
ssh_options_allow_ssh1(options, bool allow)
|
||||
ssh_options_allow_ssh2(options, bool allow)
|
||||
|
||||
options_set_status_callback has moved into ssh_* functions.
|
||||
|
||||
ssh_session Structure
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
This session structure represents a ssh socket to a server *or* a client.
|
||||
|
||||
ssh_session *ssh_new()
|
||||
|
||||
ssh_set_options(ssh_session,ssh_options)
|
||||
|
||||
ssh_connect(session);
|
||||
it will return some status describing at which point of the connection it is,
|
||||
or an error code. If the connection method is non-blocking, the function
|
||||
will be called more than once, though the return value SSH_AGAIN.
|
||||
|
||||
ssh_set_blocking(session, bool blocking)
|
||||
set blocking mode or non blocking mode.
|
||||
|
||||
ssh_get_fd(session)
|
||||
get the currently used connection file descriptor or equivalent (windows)
|
||||
|
||||
ssh_set_fd_toread(session)
|
||||
ssh_set_fd_towrite(session)
|
||||
ssh_set_fd_except(session)
|
||||
Serve to notify the library that data is actualy available to be read on the
|
||||
file descriptor socket. why ? because on most platforms select can't be done
|
||||
twice on the same socket when the first reported data to read or to write
|
||||
|
||||
ssh_get_status(session)
|
||||
Returns the current status bitmask : connection Open or closed, data
|
||||
pending to read or not (even if connection closed), connection closed on
|
||||
error or on an exit message
|
||||
|
||||
ssh_get_disconnect_message(session)
|
||||
Returns the connection disconnect error/exit message
|
||||
|
||||
ssh_get_pubkey_hash(session, hash)
|
||||
get the public key hash from the server.
|
||||
|
||||
ssh_is_server_known(session)
|
||||
ssh_write_knownhost(session)
|
||||
these 2 functions will be kept
|
||||
|
||||
ssh_disconnect(session)
|
||||
standard disconnect
|
||||
|
||||
ssh_disconnect_error(session,error code, message)
|
||||
disconnect with a message
|
||||
|
||||
ssh_set_username(session)
|
||||
set the user name to log in
|
||||
|
||||
ssh_userauth_* functions will be kept as they are now, excepted the fact that
|
||||
the username field will disapear.
|
||||
the public key mechanism may get some more functions, like retrieving a public
|
||||
key from a private key and authenticating without a public key.
|
||||
|
||||
ssh_get_issue_banner(session)
|
||||
get the issue banner from the server, that is the welcome message.
|
||||
|
||||
ssh_silent_free(session)
|
||||
This function silently free all data structures used by the session and
|
||||
closes the socket. It may be used for instance when the process forked and
|
||||
doesn't want to keep track of this session. This is obviously not possible to
|
||||
do with separate channels.
|
||||
|
||||
The channel_struct structure
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The channels will change a bit. the constructor thing will change, and the way
|
||||
to multiplex different connections will change too. channel functions will be
|
||||
prefixed with "ssh_"
|
||||
|
||||
struct channel_struct *ssh_channel_new()
|
||||
|
||||
ssh_channel_open_session(channel)
|
||||
will return if the channel allocation failed or not.
|
||||
|
||||
ssh_channel_open_forward(channel, ...) won't change. it will report an error if
|
||||
the channel allocation failed.
|
||||
|
||||
ssh_channel_send_eof(channel)
|
||||
send EOF
|
||||
ssh_channel_close(channel)
|
||||
closes a channel but doesn't destroy it. you may read unread data still in
|
||||
the buffer. Once you closed the buffer, the other party can't send you data,
|
||||
while it could still do it if you only sent an EOF.
|
||||
ssh_channel_is_closed(channel)
|
||||
returns true if the channel was closed at one of both sides. a closed chan
|
||||
may still have data to read, if you closed yourself the connection. otherwise
|
||||
(you didn't close it) the closed notification only comes when you read the
|
||||
last buffer byte, or when trying to write into the channel (the SIGPIPE-like
|
||||
behaviour).
|
||||
|
||||
ssh_channel_is_eof(channel)
|
||||
reports if the other side has sent an EOF. This functions returns FALSE if
|
||||
there is still data to read. A closed channel is always EOF.
|
||||
ssh_channel_free(channel)
|
||||
completely free the channel. closes it before if it was not done.
|
||||
|
||||
ssh_channel_request_env(channel, name, value)
|
||||
set an environment variable.
|
||||
|
||||
ssh_channel_request_pty(channel)
|
||||
ssh_channel_request_pty_size()
|
||||
ssh_channel_change_pty_size()
|
||||
ssh_channel_request_shell()
|
||||
ssh_channel_request_exec()
|
||||
ssh_channel_request_subsystem()
|
||||
These functions won't change.
|
||||
|
||||
int ssh_channel_write(channel,data, len,stderr)
|
||||
Depending on the blocking/non blocking mode of the channel, the behaviour may
|
||||
change.
|
||||
stderr is the extended buffer. It's generaly only a server->client stream.
|
||||
|
||||
ssh_channel_set_blocking(bool blocking)
|
||||
|
||||
int ssh_channel_read(channel, buffer, maxlen, is_stderr)
|
||||
the behaviour will be this one:
|
||||
-if the chan is in non blocking mode, it will poll what's available to read
|
||||
and return this. otherwise (nothing to read) it will return 0.
|
||||
-if the chan is blocking, it will block until at least one byte is
|
||||
available.
|
||||
ssh_channel_nonblocking disapears for the later reason.
|
||||
|
||||
int channel_poll(channel, is_stderr)
|
||||
polls the network and reports the number of bytes ready to be read in the
|
||||
chan.
|
||||
|
||||
ssh_session ssh_channel_get_session(channel)
|
||||
returns the session pointer associated to the channel, for simplicity
|
||||
reasons.
|
||||
|
||||
int ssh_channel_select(CHANNELS *readchans, CHANNELS *writechans, CHANNELS
|
||||
*exceptchans, struct timeval *timeout)
|
||||
This function won't work the same way ssh_select did.
|
||||
I removed the custom file descriptor thing for 2 reasons:
|
||||
1- it's not windows compliant. D'ouh !
|
||||
2- most programmers won't want to depend on libssh for socket multiplexing.
|
||||
that's why i let the programmer poll the fds himself and then use
|
||||
ssh_set_fd_toread, towrite or except. Then, he may use ssh_channel_select
|
||||
with a NULL timeout to poll which channels have something to read, write or
|
||||
error report.
|
||||
Here is how it's going to work. The coder sets 3 different arrays with the
|
||||
channels he wants to select(), the last entry being a NULL pointer. The
|
||||
function will first poll them and return the chans that must be
|
||||
read/write/excepted. If nothing has this state, the function will select()
|
||||
using the timeout.
|
||||
The function will return 0 if everything is ok, SSH_TIMEOUT or SSH_EINTR if
|
||||
the select was interrupted by a signal. It is dangerous to execute any
|
||||
channel-related functions into signal handlers. they should set a flag that
|
||||
you read into your loop. this "trap" (SSH_EINTR) will permit you to catch
|
||||
them faster and make your program responsive and look fast.
|
||||
the function will return -1 if a serious problem happens.
|
||||
|
||||
|
||||
Error handling
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
when an error happens, the programmer can get the error code and description
|
||||
with ssh_get_error(session). the creation of a failess constructor for
|
||||
ssh_session was needed for this reason.
|
||||
|
||||
ssh_get_error_code(session) will return an error code into this subset:
|
||||
SSH_NO_ERROR : no error :)
|
||||
SSH_REQUEST_DENIED : you request for a functionality or a service that is not
|
||||
allowed. The session can continue.
|
||||
SSH_FATAL : Unrecoverable error. The session can't continue and you should
|
||||
disconnect the session. It includes the connection being cut without a
|
||||
disconnect() message.
|
||||
If a disconnect() message or the channel was closed, a read on such a channel
|
||||
won't produce an error. otherwise it will return -1 with a SSH_FATAL error
|
||||
code.
|
||||
|
||||
Server socket binding
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
It is not possible to bind a socket for ssh with a SSH_SESSION type, because a
|
||||
single bound port may lead to multiple ssh connections. That's why the
|
||||
SSH_BIND structure must be created. It uses options from the SSH_OPTIONS
|
||||
structure.
|
||||
|
||||
SSH_BIND *ssh_bind_new()
|
||||
creates a structure
|
||||
ssh_bind_set_options(bind, options)
|
||||
set the option structure
|
||||
int ssh_bind_listen(bind)
|
||||
bind and listen to the port. This call is not blocking. if some error
|
||||
happens, it returns -1 and the error code can be found with perror().
|
||||
|
||||
ssh_bind_set_blocking(bind, bool blocking)
|
||||
should ssh_bind_accept() block or not.
|
||||
|
||||
int ssh_bind_get_fd(bind)
|
||||
return the bound file descriptor, that is the listener socket. you may put it
|
||||
into a select() in your code to detect a connection attempt.
|
||||
|
||||
ssh_bind_set_fd_toaccept(bind)
|
||||
say that the listener socket has a connection to accept (to avoid
|
||||
ssh_bind_accept() to do a select on it).
|
||||
|
||||
SSH_SESSION *ssh_bind_accept(bind)
|
||||
return a server handle to a ssh session. if the mode is blocking, the
|
||||
function will always return a pointer to a session. if the mode is not
|
||||
blocking, the function can return NULL if there is no connection to accept.
|
||||
|
||||
This SSH_SESSION handle must then pass through the functions explained above.
|
||||
|
||||
|
||||
*server functions *
|
||||
|
||||
int ssh_accept(session)
|
||||
when a new connection is accepted, the handshake must be done. this function
|
||||
will do the banner handshake and the key exchange.
|
||||
it will return SSH_AGAIN if the session mode is non blocking, and the
|
||||
function must be called again until an error occurs or the kex is done.
|
||||
|
||||
Here, I had a few choises about *how* to implement the message parsing as a
|
||||
server. There are multiple ways to do it, one being callbacks and one being
|
||||
"Message" reading, parsing and then choice going to the user to use it and
|
||||
answer. I've choosen the latter because i believe it's the stronger method.
|
||||
A ssh server can receive 30 different kind of messages having to be dealt by
|
||||
the high level routines, like channel request_shell or authentication. Having
|
||||
a callback for all of them would produce a huge kludge of callbacks, with
|
||||
no relations on when there were called etc.
|
||||
A message based parsing allows the user to filtrate the messages he's
|
||||
interested into and to use a default answer for the others. Then, the callback
|
||||
thing is still possible to handle through a simple message code/callback
|
||||
function array.
|
||||
|
||||
I did not define yet what it would look like, but i'm sure there will be a
|
||||
SSH_MESSAGE (they won't have a 1/1 correspondance with ssh packets) which will
|
||||
be read through
|
||||
SSH_MESSAGE *ssh_server_read_message(session).
|
||||
with all of the non-blocking stuff in head like returning NULL if the message
|
||||
is not full.
|
||||
Then, the message can be parsed, ie
|
||||
int ssh_message_get_code(message)
|
||||
which will return SSH_MESSAGE_AUTH
|
||||
then
|
||||
int ssh_message_get_subcode(message)
|
||||
which then will returh SSH_MESSAGE_AUTH_PASSWORD or _NONE or _PUBKEY etc.
|
||||
|
||||
Then, once the message was parsed, the message will have to be answered, ie
|
||||
with the generic functions like
|
||||
ssh_message_accept(message) which says 'Ok your request is accepted' or
|
||||
ssh_message_deny(message) which says 'Your request is refused'.
|
||||
|
||||
There would be specific message answer functions for some kind of messages
|
||||
like the authentication one. you may want to reply that the authentication is
|
||||
Partial rather than denied, and that you still accept some kind of auths, like
|
||||
ssh_message_auth_reply(message,SSH_AUTH_PARTIAL,SSH_AUTH_PASSWORD |
|
||||
SSH_AUTH_PUBKEY | SSH_AUTH_KEYBINT);
|
||||
|
||||
I won't let the user have to deal with the channels himself. When a channel is
|
||||
going to be created by the remote size, a message will come asking to open a
|
||||
channel. the programmer can either deny or accept, in which case a CHANNEL
|
||||
object will be created and returned to the programmer. then, all standard
|
||||
channel functions will run.
|
||||
|
||||
C. Change log of this document
|
||||
|
||||
3. Add paragraph about initalization and finalization.
|
||||
|
||||
2. ssh_options_set_username finaly is kept into the options, because it can be
|
||||
set by ssh_options_getopt()
|
||||
|
||||
1. first release
|
||||
|
||||
D. End notes
|
||||
|
||||
I think libssh must have a very simple to use, powerful and exhaustive API. It
|
||||
must have no design flaw either.
|
||||
While I got some good experience at the SSH protocol, I've never writen
|
||||
more-than-100 lines programs than use libssh and I don't really know the
|
||||
problems of the library. I'd like people who don't understand some detail into
|
||||
the API I describe here, who have comments or opinions about it to write me
|
||||
the soonest possible to limit the damages if I made something the completely
|
||||
wrong way.
|
||||
Thanks for your patience.
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
/**
|
||||
|
||||
@page libssh_linking The Linking HowTo
|
||||
|
||||
@section dynamic Dynamic Linking
|
||||
|
||||
On UNIX and Windows systems its the same, you need at least the libssh.h
|
||||
header file and the libssh shared library.
|
||||
|
||||
@section static Static Linking
|
||||
|
||||
@warning <b>The libssh library is licensed under the LGPL! Make sure you
|
||||
understand what this means to your codebase if you want to distribute
|
||||
binaries and link statically against LGPL code!</b>
|
||||
|
||||
On UNIX systems linking against the static version of the library is the
|
||||
same as linking against the shared library. Both have the same name. Some
|
||||
build system require to use the full path to the static library.
|
||||
|
||||
To be able to compile the application you're developing you need to either pass
|
||||
LIBSSH_STATIC as a define in the compiler command line or define it before you
|
||||
include libssh.h. This is required cause the dynamic library needs to specify
|
||||
the dllimport attribute.
|
||||
|
||||
@code
|
||||
#define LIBSSH_STATIC 1
|
||||
#include <libssh/libssh.h>
|
||||
@endcode
|
||||
|
||||
*/
|
||||
232
doc/mainpage.dox
232
doc/mainpage.dox
@@ -1,224 +1,12 @@
|
||||
/**
|
||||
* @mainpage
|
||||
* This manual documents the libssh C API.
|
||||
*
|
||||
* There are several other places to look for libssh information, such as the
|
||||
* <a href="http://dev.libssh.org/wiki/Tutorial" target="_blank">tutorial</a>
|
||||
* and the specification; those can be found at the <a
|
||||
* href="http://www.libssh.org/" target="_blank">libssh website</a>.
|
||||
*
|
||||
* To be continued...
|
||||
*/
|
||||
|
||||
@mainpage
|
||||
|
||||
This is the online reference for developing with the libssh library. It
|
||||
documents the libssh C API and the C++ wrapper.
|
||||
|
||||
@section main-linking Linking
|
||||
|
||||
We created a small howto how to link libssh against your application, read
|
||||
@subpage libssh_linking.
|
||||
|
||||
@section main-tutorial Tutorial
|
||||
|
||||
You should start by reading @subpage libssh_tutorial, then reading the documentation of
|
||||
the interesting functions as you go.
|
||||
|
||||
@section main-features Features
|
||||
|
||||
The libssh library provides:
|
||||
|
||||
- <strong>Key Exchange Methods</strong>: <i>curve25519-sha256@libssh.org, ecdh-sha2-nistp256</i>, diffie-hellman-group1-sha1, diffie-hellman-group14-sha1
|
||||
- <strong>Hostkey Types</strong>: <i>ecdsa-sha2-nistp256</i>, ssh-dss, ssh-rsa
|
||||
- <strong>Ciphers</strong>: <i>aes256-ctr, aes192-ctr, aes128-ctr</i>, aes256-cbc (rijndael-cbc@lysator.liu.se), aes192-cbc, aes128-cbc, 3des-cbc, des-cbc-ssh1, blowfish-cbc, none
|
||||
- <strong>Compression Schemes</strong>: zlib, <i>zlib@openssh.com</i>, none
|
||||
- <strong>MAC hashes</strong>: hmac-sha1, none
|
||||
- <strong>Authentication</strong>: none, password, public-key, hostbased, keyboard-interactive, <i>gssapi-with-mic</i>
|
||||
- <strong>Channels</strong>: shell, exec (incl. SCP wrapper), direct-tcpip, subsystem, <i>auth-agent-req@openssh.com</i>
|
||||
- <strong>Global Requests</strong>: tcpip-forward, forwarded-tcpip
|
||||
- <strong>Channel Requests</strong>: x11, pty, <i>exit-status, signal, exit-signal, keepalive@openssh.com, auth-agent-req@openssh.com</i>
|
||||
- <strong>Subsystems</strong>: sftp(version 3), publickey(version 2), <i>OpenSSH Extensions</i>
|
||||
- <strong>SFTP</strong>: <i>statvfs@openssh.com, fstatvfs@openssh.com</i>
|
||||
- <strong>Thread-safe</strong>: Just don't share sessions
|
||||
- <strong>Non-blocking</strong>: it can be used both blocking and non-blocking
|
||||
- <strong>Your sockets</strong>: the app hands over the socket, or uses libssh sockets
|
||||
- <b>OpenSSL</b> or <b>gcrypt</b>: builds with either
|
||||
|
||||
@section main-additional-features Additional Features
|
||||
|
||||
- Client <b>and</b> server support
|
||||
- SSHv2 and SSHv1 protocol support
|
||||
- Supports <a href="http://test.libssh.org/" target="_blank">Linux, UNIX, BSD, Solaris, OS/2 and Windows</a>
|
||||
- Automated test cases with nightly <a href="http://test.libssh.org/" target="_blank">tests</a>
|
||||
- Event model based on poll(2), or a poll(2)-emulation.
|
||||
|
||||
@section main-copyright Copyright Policy
|
||||
|
||||
libssh is a project with distributed copyright ownership, which means we prefer
|
||||
the copyright on parts of libssh to be held by individuals rather than
|
||||
corporations if possible. There are historical legal reasons for this, but one
|
||||
of the best ways to explain it is that it’s much easier to work with
|
||||
individuals who have ownership than corporate legal departments if we ever need
|
||||
to make reasonable compromises with people using and working with libssh.
|
||||
|
||||
We track the ownership of every part of libssh via git, our source code control
|
||||
system, so we know the provenance of every piece of code that is committed to
|
||||
libssh.
|
||||
|
||||
So if possible, if you’re doing libssh changes on behalf of a company who
|
||||
normally owns all the work you do please get them to assign personal copyright
|
||||
ownership of your changes to you as an individual, that makes things very easy
|
||||
for us to work with and avoids bringing corporate legal departments into the
|
||||
picture.
|
||||
|
||||
If you can’t do this we can still accept patches from you owned by your
|
||||
employer under a standard employment contract with corporate copyright
|
||||
ownership. It just requires a simple set-up process first.
|
||||
|
||||
We use a process very similar to the way things are done in the Linux Kernel
|
||||
community, so it should be very easy to get a sign off from your corporate
|
||||
legal department. The only changes we’ve made are to accommodate the license we
|
||||
use, which is LGPLv2 (or later) whereas the Linux kernel uses GPLv2.
|
||||
|
||||
The process is called signing.
|
||||
|
||||
How to sign your work
|
||||
----------------------
|
||||
|
||||
Once you have permission to contribute to libssh from your employer, simply
|
||||
email a copy of the following text from your corporate email address to:
|
||||
|
||||
contributing@libssh.org
|
||||
|
||||
@verbatim
|
||||
libssh Developer's Certificate of Origin. Version 1.0
|
||||
|
||||
By making a contribution to this project, I certify that:
|
||||
|
||||
(a) The contribution was created in whole or in part by me and I
|
||||
have the right to submit it under the appropriate
|
||||
version of the GNU General Public License; or
|
||||
|
||||
(b) The contribution is based upon previous work that, to the best of
|
||||
my knowledge, is covered under an appropriate open source license
|
||||
and I have the right under that license to submit that work with
|
||||
modifications, whether created in whole or in part by me, under
|
||||
the GNU General Public License, in the appropriate version; or
|
||||
|
||||
(c) The contribution was provided directly to me by some other
|
||||
person who certified (a) or (b) and I have not modified it.
|
||||
|
||||
(d) I understand and agree that this project and the contribution are
|
||||
public and that a record of the contribution (including all
|
||||
metadata and personal information I submit with it, including my
|
||||
sign-off) is maintained indefinitely and may be redistributed
|
||||
consistent with the libssh Team's policies and the requirements of
|
||||
the GNU GPL where they are relevant.
|
||||
|
||||
(e) I am granting this work to this project under the terms of the
|
||||
GNU Lesser General Public License as published by the
|
||||
Free Software Foundation; either version 2.1 of
|
||||
the License, or (at the option of the project) any later version.
|
||||
|
||||
http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
@endverbatim
|
||||
|
||||
We will maintain a copy of that email as a record that you have the rights to
|
||||
contribute code to libssh under the required licenses whilst working for the
|
||||
company where the email came from.
|
||||
|
||||
Then when sending in a patch via the normal mechanisms described above, add a
|
||||
line that states:
|
||||
|
||||
@verbatim
|
||||
Signed-off-by: Random J Developer <random@developer.example.org>
|
||||
@endverbatim
|
||||
|
||||
using your real name and the email address you sent the original email you used
|
||||
to send the libssh Developer’s Certificate of Origin to us (sorry, no
|
||||
pseudonyms or anonymous contributions.)
|
||||
|
||||
That’s it! Such code can then quite happily contain changes that have copyright
|
||||
messages such as:
|
||||
|
||||
@verbatim
|
||||
(c) Example Corporation.
|
||||
@endverbatim
|
||||
|
||||
and can be merged into the libssh codebase in the same way as patches from any
|
||||
other individual. You don’t need to send in a copy of the libssh Developer’s
|
||||
Certificate of Origin for each patch, or inside each patch. Just the sign-off
|
||||
message is all that is required once we’ve received the initial email.
|
||||
|
||||
Have fun and happy libssh hacking!
|
||||
|
||||
The libssh Team
|
||||
|
||||
@section main-rfc Internet standard
|
||||
|
||||
@subsection main-rfc-secsh Secure Shell (SSH)
|
||||
|
||||
The following RFC documents described SSH-2 protcol as an Internet standard.
|
||||
|
||||
- <a href="http://tools.ietf.org/html/rfc4250" target="_blank">RFC 4250</a>,
|
||||
The Secure Shell (SSH) Protocol Assigned Numbers
|
||||
- <a href="http://tools.ietf.org/html/rfc4251" target="_blank">RFC 4251</a>,
|
||||
The Secure Shell (SSH) Protocol Architecture
|
||||
- <a href="http://tools.ietf.org/html/rfc4252" target="_blank">RFC 4252</a>,
|
||||
The Secure Shell (SSH) Authentication Protocol
|
||||
- <a href="http://tools.ietf.org/html/rfc4253" target="_blank">RFC 4253</a>,
|
||||
The Secure Shell (SSH) Transport Layer Protocol
|
||||
- <a href="http://tools.ietf.org/html/rfc4254" target="_blank">RFC 4254</a>,
|
||||
The Secure Shell (SSH) Connection Protocol
|
||||
- <a href="http://tools.ietf.org/html/rfc4255" target="_blank">RFC 4255</a>,
|
||||
Using DNS to Securely Publish Secure Shell (SSH) Key Fingerprints
|
||||
- <a href="http://tools.ietf.org/html/rfc4256" target="_blank">RFC 4256</a>,
|
||||
Generic Message Exchange Authentication for the Secure Shell Protocol (SSH)
|
||||
- <a href="http://tools.ietf.org/html/rfc4335" target="_blank">RFC 4335</a>,
|
||||
The Secure Shell (SSH) Session Channel Break Extension
|
||||
- <a href="http://tools.ietf.org/html/rfc4344" target="_blank">RFC 4344</a>,
|
||||
The Secure Shell (SSH) Transport Layer Encryption Modes
|
||||
- <a href="http://tools.ietf.org/html/rfc4345" target="_blank">RFC 4345</a>,
|
||||
Improved Arcfour Modes for the Secure Shell (SSH) Transport Layer Protocol
|
||||
|
||||
It was later modified and expanded by the following RFCs.
|
||||
|
||||
- <a href="http://tools.ietf.org/html/rfc4419" target="_blank">RFC 4419</a>,
|
||||
Diffie-Hellman Group Exchange for the Secure Shell (SSH) Transport Layer
|
||||
Protocol
|
||||
- <a href="http://tools.ietf.org/html/rfc4432" target="_blank">RFC 4432</a>,
|
||||
RSA Key Exchange for the Secure Shell (SSH) Transport Layer Protocol
|
||||
- <a href="http://tools.ietf.org/html/rfc4462" target="_blank">RFC 4462</a>,
|
||||
Generic Security Service Application Program Interface (GSS-API)
|
||||
Authentication and Key Exchange for the Secure Shell (SSH) Protocol
|
||||
- <a href="http://tools.ietf.org/html/rfc4716" target="_blank">RFC 4716</a>,
|
||||
The Secure Shell (SSH) Public Key File Format
|
||||
- <a href="http://tools.ietf.org/html/rfc5647" target="_blank">RFC 5647</a>,
|
||||
AES Galois Counter Mode for the Secure Shell Transport Layer Protocol
|
||||
- <a href="http://tools.ietf.org/html/rfc5656" target="_blank">RFC 5656</a>,
|
||||
Elliptic Curve Algorithm Integration in the Secure Shell Transport Layer
|
||||
|
||||
Interesting cryptography documents:
|
||||
|
||||
- <a href="http://www.cryptsoft.com/pkcs11doc/" target="_blank">PKCS #11</a>, PKCS #11 reference documents, describing interface with smartcards.
|
||||
|
||||
@subsection main-rfc-sftp Secure Shell File Transfer Protocol (SFTP)
|
||||
|
||||
The protocol is not an Internet standard but it is still widely implemented.
|
||||
OpenSSH and most other implementation implement Version 3 of the protocol. We
|
||||
do the same in libssh.
|
||||
|
||||
- <a href="http://tools.ietf.org/html/draft-ietf-secsh-filexfer-02" target="_blank">
|
||||
draft-ietf-secsh-filexfer-02.txt</a>,
|
||||
SSH File Transfer Protocol
|
||||
|
||||
@subsection main-rfc-extensions Secure Shell Extensions
|
||||
|
||||
The libssh project has an extension to support Curve25519 which is also supported by
|
||||
the OpenSSH project.
|
||||
|
||||
- <a href="http://git.libssh.org/projects/libssh.git/tree/doc/curve25519-sha256@libssh.org.txt" target="_blank">curve25519-sha256@libssh.org</a>,
|
||||
Curve25519-SHA256 for ECDH KEX
|
||||
|
||||
The OpenSSH project has defined some extensions to the protocol. We support some of
|
||||
them like the statvfs calls in SFTP or the ssh-agent.
|
||||
|
||||
- <a href="http://api.libssh.org/rfc/PROTOCOL" target="_blank">
|
||||
OpenSSH's deviations and extensions</a>
|
||||
- <a href="http://api.libssh.org/rfc/PROTOCOL.agent" target="_blank">
|
||||
OpenSSH's ssh-agent</a>
|
||||
- <a href="http://api.libssh.org/rfc/PROTOCOL.certkeys" target="_blank">
|
||||
OpenSSH's pubkey certificate authentication</a>
|
||||
|
||||
*/
|
||||
|
||||
268
doc/scp.dox
268
doc/scp.dox
@@ -1,268 +0,0 @@
|
||||
/**
|
||||
@page libssh_tutor_scp Chapter 6: The SCP subsystem
|
||||
@section scp_subsystem The SCP subsystem
|
||||
|
||||
The SCP subsystem has far less functionnality than the SFTP subsystem.
|
||||
However, if you only need to copy files from and to the remote system,
|
||||
it does its job.
|
||||
|
||||
|
||||
@subsection scp_session Opening and closing a SCP session
|
||||
|
||||
Like in the SFTP subsystem, you don't handle the SSH channels directly.
|
||||
Instead, you open a "SCP session".
|
||||
|
||||
When you open your SCP session, you have to choose between read or write mode.
|
||||
You can't do both in the same session. So you specify either SSH_SCP_READ or
|
||||
SSH_SCP_WRITE as the second parameter of function ssh_scp_new().
|
||||
|
||||
Another important mode flag for opening your SCP session is SSH_SCP_RECURSIVE.
|
||||
When you use SSH_SCP_RECURSIVE, you declare that you are willing to emulate
|
||||
the behaviour of "scp -r" command in your program, no matter it is for
|
||||
reading or for writing.
|
||||
|
||||
Once your session is created, you initialize it with ssh_scp_init(). When
|
||||
you have finished transferring files, you terminate the SCP connection with
|
||||
ssh_scp_close(). Finally, you can dispose the SCP connection with
|
||||
ssh_scp_free().
|
||||
|
||||
The example below does the maintenance work to open a SCP connection for writing in
|
||||
recursive mode:
|
||||
|
||||
@code
|
||||
int scp_write(ssh_session session)
|
||||
{
|
||||
ssh_scp scp;
|
||||
int rc;
|
||||
|
||||
scp = ssh_scp_new
|
||||
(session, SSH_SCP_WRITE | SSH_SCP_RECURSIVE, ".");
|
||||
if (scp == NULL)
|
||||
{
|
||||
fprintf(stderr, "Error allocating scp session: %s\n",
|
||||
ssh_get_error(session));
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
rc = ssh_scp_init(scp);
|
||||
if (rc != SSH_OK)
|
||||
{
|
||||
fprintf(stderr, "Error initializing scp session: %s\n",
|
||||
ssh_get_error(session));
|
||||
ssh_scp_free(scp);
|
||||
return rc;
|
||||
}
|
||||
|
||||
...
|
||||
|
||||
ssh_scp_close(scp);
|
||||
ssh_scp_free(scp);
|
||||
return SSH_OK;
|
||||
}
|
||||
@endcode
|
||||
|
||||
The example below shows how to open a connection to read a single file:
|
||||
|
||||
@code
|
||||
int scp_read(ssh_session session)
|
||||
{
|
||||
ssh_scp scp;
|
||||
int rc;
|
||||
|
||||
scp = ssh_scp_new
|
||||
(session, SSH_SCP_READ, "helloworld/helloworld.txt");
|
||||
if (scp == NULL)
|
||||
{
|
||||
fprintf(stderr, "Error allocating scp session: %s\n",
|
||||
ssh_get_error(session));
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
rc = ssh_scp_init(scp);
|
||||
if (rc != SSH_OK)
|
||||
{
|
||||
fprintf(stderr, "Error initializing scp session: %s\n",
|
||||
ssh_get_error(session));
|
||||
ssh_scp_free(scp);
|
||||
return rc;
|
||||
}
|
||||
|
||||
...
|
||||
|
||||
ssh_scp_close(scp);
|
||||
ssh_scp_free(scp);
|
||||
return SSH_OK;
|
||||
}
|
||||
|
||||
@endcode
|
||||
|
||||
|
||||
@subsection scp_write Creating files and directories
|
||||
|
||||
You create directories with ssh_scp_push_directory(). In recursive mode,
|
||||
you are placed in this directory once it is created. If the directory
|
||||
already exists and if you are in recursive mode, you simply enter that
|
||||
directory.
|
||||
|
||||
Creating files is done in two steps. First, you prepare the writing with
|
||||
ssh_scp_push_file(). Then, you write the data with ssh_scp_write().
|
||||
The length of the data to write must be identical between both function calls.
|
||||
There's no need to "open" nor "close" the file, this is done automatically
|
||||
on the remote end. If the file already exists, it is overwritten and truncated.
|
||||
|
||||
The following example creates a new directory named "helloworld/", then creates
|
||||
a file named "helloworld.txt" in that directory:
|
||||
|
||||
@code
|
||||
int scp_helloworld(ssh_session session, ssh_scp scp)
|
||||
{
|
||||
int rc;
|
||||
const char *helloworld = "Hello, world!\n";
|
||||
int length = strlen(helloworld);
|
||||
|
||||
rc = ssh_scp_push_directory(scp, "helloworld", S_IRWXU);
|
||||
if (rc != SSH_OK)
|
||||
{
|
||||
fprintf(stderr, "Can't create remote directory: %s\n",
|
||||
ssh_get_error(session));
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = ssh_scp_push_file
|
||||
(scp, "helloworld.txt", length, S_IRUSR | S_IWUSR);
|
||||
if (rc != SSH_OK)
|
||||
{
|
||||
fprintf(stderr, "Can't open remote file: %s\n",
|
||||
ssh_get_error(session));
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = ssh_scp_write(scp, helloworld, length);
|
||||
if (rc != SSH_OK)
|
||||
{
|
||||
fprintf(stderr, "Can't write to remote file: %s\n",
|
||||
ssh_get_error(session));
|
||||
return rc;
|
||||
}
|
||||
|
||||
return SSH_OK;
|
||||
}
|
||||
@endcode
|
||||
|
||||
|
||||
@subsection scp_recursive_write Copying full directory trees to the remote server
|
||||
|
||||
Let's say you want to copy the following tree of files to the remote site:
|
||||
|
||||
@verbatim
|
||||
+-- file1
|
||||
+-- B --+
|
||||
| +-- file2
|
||||
-- A --+
|
||||
| +-- file3
|
||||
+-- C --+
|
||||
+-- file4
|
||||
@endverbatim
|
||||
|
||||
You would do it that way:
|
||||
- open the session in recursive mode
|
||||
- enter directory A
|
||||
- enter its subdirectory B
|
||||
- create file1 in B
|
||||
- create file2 in B
|
||||
- leave directory B
|
||||
- enter subdirectory C
|
||||
- create file3 in C
|
||||
- create file4 in C
|
||||
- leave directory C
|
||||
- leave directory A
|
||||
|
||||
To leave a directory, call ssh_scp_leave_directory().
|
||||
|
||||
|
||||
@subsection scp_read Reading files and directories
|
||||
|
||||
|
||||
To receive files, you pull requests from the other side with ssh_scp_pull_request().
|
||||
If this function returns SSH_SCP_REQUEST_NEWFILE, then you must get ready for
|
||||
the reception. You can get the size of the data to receive with ssh_scp_request_get_size()
|
||||
and allocate a buffer accordingly. When you are ready, you accept the request with
|
||||
ssh_scp_accept_request(), then read the data with ssh_scp_read().
|
||||
|
||||
The following example receives a single file. The name of the file to
|
||||
receive has been given earlier, when the scp session was opened:
|
||||
|
||||
@code
|
||||
int scp_receive(ssh_session session, ssh_scp scp)
|
||||
{
|
||||
int rc;
|
||||
int size, mode;
|
||||
char *filename, *buffer;
|
||||
|
||||
rc = ssh_scp_pull_request(scp);
|
||||
if (rc != SSH_SCP_REQUEST_NEWFILE)
|
||||
{
|
||||
fprintf(stderr, "Error receiving information about file: %s\n",
|
||||
ssh_get_error(session));
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
size = ssh_scp_request_get_size(scp);
|
||||
filename = strdup(ssh_scp_request_get_filename(scp));
|
||||
mode = ssh_scp_request_get_permissions(scp);
|
||||
printf("Receiving file %s, size %d, permisssions 0%o\n",
|
||||
filename, size, mode);
|
||||
free(filename);
|
||||
|
||||
buffer = malloc(size);
|
||||
if (buffer == NULL)
|
||||
{
|
||||
fprintf(stderr, "Memory allocation error\n");
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
ssh_scp_accept_request(scp);
|
||||
rc = ssh_scp_read(scp, buffer, size);
|
||||
if (rc == SSH_ERROR)
|
||||
{
|
||||
fprintf(stderr, "Error receiving file data: %s\n",
|
||||
ssh_get_error(session));
|
||||
free(buffer);
|
||||
return rc;
|
||||
}
|
||||
printf("Done\n");
|
||||
|
||||
write(1, buffer, size);
|
||||
free(buffer);
|
||||
|
||||
rc = ssh_scp_pull_request(scp);
|
||||
if (rc != SSH_SCP_REQUEST_EOF)
|
||||
{
|
||||
fprintf(stderr, "Unexpected request: %s\n",
|
||||
ssh_get_error(session));
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
return SSH_OK;
|
||||
}
|
||||
@endcode
|
||||
|
||||
In this example, since we just requested a single file, we expect ssh_scp_request()
|
||||
to return SSH_SCP_REQUEST_NEWFILE first, then SSH_SCP_REQUEST_EOF. That's quite a
|
||||
naive approach; for example, the remote server might send a warning as well
|
||||
(return code SSH_SCP_REQUEST_WARNING) and the example would fail. A more comprehensive
|
||||
reception program would receive the requests in a loop and analyze them carefully
|
||||
until SSH_SCP_REQUEST_EOF has been received.
|
||||
|
||||
|
||||
@subsection scp_recursive_read Receiving full directory trees from the remote server
|
||||
|
||||
If you opened the SCP session in recursive mode, the remote end will be
|
||||
telling you when to change directory.
|
||||
|
||||
In that case, when ssh_scp_pull_request() answers
|
||||
SSH_SCP_REQUEST_NEWDIRECTORY, you should make that local directory (if
|
||||
it does not exist yet) and enter it. When ssh_scp_pull_request() answers
|
||||
SSH_SCP_REQUEST_ENDDIRECTORY, you should leave the current directory.
|
||||
|
||||
*/
|
||||
431
doc/sftp.dox
431
doc/sftp.dox
@@ -1,431 +0,0 @@
|
||||
/**
|
||||
@page libssh_tutor_sftp Chapter 5: The SFTP subsystem
|
||||
@section sftp_subsystem The SFTP subsystem
|
||||
|
||||
SFTP stands for "Secure File Transfer Protocol". It enables you to safely
|
||||
transfer files between the local and the remote computer. It reminds a lot
|
||||
of the old FTP protocol.
|
||||
|
||||
SFTP is a rich protocol. It lets you do over the network almost everything
|
||||
that you can do with local files:
|
||||
- send files
|
||||
- modify only a portion of a file
|
||||
- receive files
|
||||
- receive only a portion of a file
|
||||
- get file owner and group
|
||||
- get file permissions
|
||||
- set file owner and group
|
||||
- set file permissions
|
||||
- remove files
|
||||
- rename files
|
||||
- create a directory
|
||||
- remove a directory
|
||||
- retrieve the list of files in a directory
|
||||
- get the target of a symbolic link
|
||||
- create symbolic links
|
||||
- get information about mounted filesystems.
|
||||
|
||||
The current implemented version of the SFTP protocol is version 3. All functions
|
||||
aren't implemented yet, but the most important are.
|
||||
|
||||
|
||||
@subsection sftp_session Opening and closing a SFTP session
|
||||
|
||||
Unlike with remote shells and remote commands, when you use the SFTP subsystem,
|
||||
you don't handle directly the SSH channels. Instead, you open a "SFTP session".
|
||||
|
||||
The function sftp_new() creates a new SFTP session. The function sftp_init()
|
||||
initializes it. The function sftp_free() deletes it.
|
||||
|
||||
As you see, all the SFTP-related functions start with the "sftp_" prefix
|
||||
instead of the usual "ssh_" prefix.
|
||||
|
||||
The example below shows how to use these functions:
|
||||
|
||||
@code
|
||||
#include <libssh/sftp.h>
|
||||
|
||||
int sftp_helloworld(ssh_session session)
|
||||
{
|
||||
sftp_session sftp;
|
||||
int rc;
|
||||
|
||||
sftp = sftp_new(session);
|
||||
if (sftp == NULL)
|
||||
{
|
||||
fprintf(stderr, "Error allocating SFTP session: %s\n",
|
||||
ssh_get_error(session));
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
rc = sftp_init(sftp);
|
||||
if (rc != SSH_OK)
|
||||
{
|
||||
fprintf(stderr, "Error initializing SFTP session: %s.\n",
|
||||
sftp_get_error(sftp));
|
||||
sftp_free(sftp);
|
||||
return rc;
|
||||
}
|
||||
|
||||
...
|
||||
|
||||
sftp_free(sftp);
|
||||
return SSH_OK;
|
||||
}
|
||||
@endcode
|
||||
|
||||
|
||||
@subsection sftp_errors Analyzing SFTP errors
|
||||
|
||||
In case of a problem, the function sftp_get_error() returns a SFTP-specific
|
||||
error number, in addition to the regular SSH error number returned by
|
||||
ssh_get_error_number().
|
||||
|
||||
Possible errors are:
|
||||
- SSH_FX_OK: no error
|
||||
- SSH_FX_EOF: end-of-file encountered
|
||||
- SSH_FX_NO_SUCH_FILE: file does not exist
|
||||
- SSH_FX_PERMISSION_DENIED: permission denied
|
||||
- SSH_FX_FAILURE: generic failure
|
||||
- SSH_FX_BAD_MESSAGE: garbage received from server
|
||||
- SSH_FX_NO_CONNECTION: no connection has been set up
|
||||
- SSH_FX_CONNECTION_LOST: there was a connection, but we lost it
|
||||
- SSH_FX_OP_UNSUPPORTED: operation not supported by libssh yet
|
||||
- SSH_FX_INVALID_HANDLE: invalid file handle
|
||||
- SSH_FX_NO_SUCH_PATH: no such file or directory path exists
|
||||
- SSH_FX_FILE_ALREADY_EXISTS: an attempt to create an already existing file or directory has been made
|
||||
- SSH_FX_WRITE_PROTECT: write-protected filesystem
|
||||
- SSH_FX_NO_MEDIA: no media was in remote drive
|
||||
|
||||
|
||||
@subsection sftp_mkdir Creating a directory
|
||||
|
||||
The function sftp_mkdir() tahes the "SFTP session" we juste created as
|
||||
its first argument. It also needs the name of the file to create, and the
|
||||
desired permissions. The permissions are the same as for the usual mkdir()
|
||||
function. To get a comprehensive list of the available permissions, use the
|
||||
"man 2 stat" command. The desired permissions are combined with the remote
|
||||
user's mask to determine the effective permissions.
|
||||
|
||||
The code below creates a directory named "helloworld" in the current directory that
|
||||
can be read and written only by its owner:
|
||||
|
||||
@code
|
||||
#include <libssh/sftp.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
int sftp_helloworld(ssh_session session, sftp_session sftp)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = sftp_mkdir(sftp, "helloworld", S_IRWXU);
|
||||
if (rc != SSH_OK)
|
||||
{
|
||||
if (sftp_get_error(sftp) != SSH_FX_FILE_ALREADY_EXISTS)
|
||||
{
|
||||
fprintf(stderr, "Can't create directory: %s\n",
|
||||
ssh_get_error(session));
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
...
|
||||
|
||||
return SSH_OK;
|
||||
}
|
||||
@endcode
|
||||
|
||||
Unlike its equivalent in the SCP subsystem, this function does NOT change the
|
||||
current directory to the newly created subdirectory.
|
||||
|
||||
|
||||
@subsection sftp_write Copying a file to the remote computer
|
||||
|
||||
You handle the contents of a remote file just like you would do with a
|
||||
local file: you open the file in a given mode, move the file pointer in it,
|
||||
read or write data, and close the file.
|
||||
|
||||
The sftp_open() function is very similar to the regular open() function,
|
||||
excepted that it returns a file handle of type sftp_file. This file handle
|
||||
is then used by the other file manipulation functions and remains valid
|
||||
until you close the remote file with sftp_close().
|
||||
|
||||
The example below creates a new file named "helloworld.txt" in the
|
||||
newly created "helloworld" directory. If the file already exists, it will
|
||||
be truncated. It then writes the famous "Hello, World!" sentence to the
|
||||
file, followed by a new line character. Finally, the file is closed:
|
||||
|
||||
@code
|
||||
#include <libssh/sftp.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
int sftp_helloworld(ssh_session session, sftp_session sftp)
|
||||
{
|
||||
int access_type = O_WRONLY | O_CREAT | O_TRUNC;
|
||||
sftp_file file;
|
||||
const char *helloworld = "Hello, World!\n";
|
||||
int length = strlen(helloworld);
|
||||
int rc, nwritten;
|
||||
|
||||
...
|
||||
|
||||
file = sftp_open(sftp, "helloworld/helloworld.txt",
|
||||
access_type, S_IRWXU);
|
||||
if (file == NULL)
|
||||
{
|
||||
fprintf(stderr, "Can't open file for writing: %s\n",
|
||||
ssh_get_error(session));
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
nwritten = sftp_write(file, helloworld, length);
|
||||
if (nwritten != length)
|
||||
{
|
||||
fprintf(stderr, "Can't write data to file: %s\n",
|
||||
ssh_get_error(session));
|
||||
sftp_close(file);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
rc = sftp_close(file);
|
||||
if (rc != SSH_OK)
|
||||
{
|
||||
fprintf(stderr, "Can't close the written file: %s\n",
|
||||
ssh_get_error(session));
|
||||
return rc;
|
||||
}
|
||||
|
||||
return SSH_OK;
|
||||
}
|
||||
@endcode
|
||||
|
||||
|
||||
@subsection sftp_read Reading a file from the remote computer
|
||||
|
||||
The nice thing with reading a file over the network through SFTP is that it
|
||||
can be done both in a synchronous way or an asynchronous way. If you read the file
|
||||
asynchronously, your program can do something else while it waits for the
|
||||
results to come.
|
||||
|
||||
Synchronous read is done with sftp_read().
|
||||
|
||||
Files are normally transferred in chunks. A good chunk size is 16 KB. The following
|
||||
example transfers the remote file "/etc/profile" in 16 KB chunks. For each chunk we
|
||||
request, sftp_read blocks till the data has been received:
|
||||
|
||||
@code
|
||||
// Good chunk size
|
||||
#define MAX_XFER_BUF_SIZE 16384
|
||||
|
||||
int sftp_read_sync(ssh_session session, sftp_session sftp)
|
||||
{
|
||||
int access_type;
|
||||
sftp_file file;
|
||||
char buffer[MAX_XFER_BUF_SIZE];
|
||||
int nbytes, nwritten, rc;
|
||||
int fd;
|
||||
|
||||
access_type = O_RDONLY;
|
||||
file = sftp_open(sftp, "/etc/profile",
|
||||
access_type, 0);
|
||||
if (file == NULL) {
|
||||
fprintf(stderr, "Can't open file for reading: %s\n",
|
||||
ssh_get_error(session));
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
fd = open("/path/to/profile", O_CREAT);
|
||||
if (fd < 0) {
|
||||
fprintf(stderr, "Can't open file for writing: %s\n",
|
||||
strerror(errno));
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
nbytes = sftp_read(file, buffer, sizeof(buffer));
|
||||
if (nbytes == 0) {
|
||||
break; // EOF
|
||||
} else if (nbytes < 0) {
|
||||
fprintf(stderr, "Error while reading file: %s\n",
|
||||
ssh_get_error(session));
|
||||
sftp_close(file);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
nwritten = write(fd, buf, nbytes);
|
||||
if (nwritten != nbytes) {
|
||||
fprintf(stderr, "Error writing: %s\n",
|
||||
strerror(errno));
|
||||
sftp_close(file);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
rc = sftp_close(file);
|
||||
if (rc != SSH_OK) {
|
||||
fprintf(stderr, "Can't close the read file: %s\n",
|
||||
ssh_get_error(session));
|
||||
return rc;
|
||||
}
|
||||
|
||||
return SSH_OK;
|
||||
}
|
||||
@endcode
|
||||
|
||||
Asynchronous read is done in two steps, first sftp_async_read_begin(), which
|
||||
returns a "request handle", and then sftp_async_read(), which uses that request handle.
|
||||
If the file has been opened in nonblocking mode, then sftp_async_read()
|
||||
might return SSH_AGAIN, which means that the request hasn't completed yet
|
||||
and that the function should be called again later on. Otherwise,
|
||||
sftp_async_read() waits for the data to come. To open a file in nonblocking mode,
|
||||
call sftp_file_set_nonblocking() right after you opened it. Default is blocking mode.
|
||||
|
||||
The example below reads a very big file in asynchronous, nonblocking, mode. Each
|
||||
time the data are not ready yet, a counter is incrementer.
|
||||
|
||||
@code
|
||||
// Good chunk size
|
||||
#define MAX_XFER_BUF_SIZE 16384
|
||||
|
||||
int sftp_read_async(ssh_session session, sftp_session sftp)
|
||||
{
|
||||
int access_type;
|
||||
sftp_file file;
|
||||
char buffer[MAX_XFER_BUF_SIZE];
|
||||
int async_request;
|
||||
int nbytes;
|
||||
long counter;
|
||||
int rc;
|
||||
|
||||
access_type = O_RDONLY;
|
||||
file = sftp_open(sftp, "some_very_big_file",
|
||||
access_type, 0);
|
||||
if (file == NULL) {
|
||||
fprintf(stderr, "Can't open file for reading: %s\n",
|
||||
ssh_get_error(session));
|
||||
return SSH_ERROR;
|
||||
}
|
||||
sftp_file_set_nonblocking(file);
|
||||
|
||||
async_request = sftp_async_read_begin(file, sizeof(buffer));
|
||||
counter = 0L;
|
||||
usleep(10000);
|
||||
if (async_request >= 0) {
|
||||
nbytes = sftp_async_read(file, buffer, sizeof(buffer),
|
||||
async_request);
|
||||
} else {
|
||||
nbytes = -1;
|
||||
}
|
||||
|
||||
while (nbytes > 0 || nbytes == SSH_AGAIN) {
|
||||
if (nbytes > 0) {
|
||||
write(1, buffer, nbytes);
|
||||
async_request = sftp_async_read_begin(file, sizeof(buffer));
|
||||
} else {
|
||||
counter++;
|
||||
}
|
||||
usleep(10000);
|
||||
|
||||
if (async_request >= 0) {
|
||||
nbytes = sftp_async_read(file, buffer, sizeof(buffer),
|
||||
async_request);
|
||||
} else {
|
||||
nbytes = -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (nbytes < 0) {
|
||||
fprintf(stderr, "Error while reading file: %s\n",
|
||||
ssh_get_error(session));
|
||||
sftp_close(file);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
printf("The counter has reached value: %ld\n", counter);
|
||||
|
||||
rc = sftp_close(file);
|
||||
if (rc != SSH_OK) {
|
||||
fprintf(stderr, "Can't close the read file: %s\n",
|
||||
ssh_get_error(session));
|
||||
return rc;
|
||||
}
|
||||
|
||||
return SSH_OK;
|
||||
}
|
||||
@endcode
|
||||
|
||||
@subsection sftp_ls Listing the contents of a directory
|
||||
|
||||
The functions sftp_opendir(), sftp_readdir(), sftp_dir_eof(),
|
||||
and sftp_closedir() enable to list the contents of a directory.
|
||||
They use a new handle_type, "sftp_dir", which gives access to the
|
||||
directory being read.
|
||||
|
||||
In addition, sftp_readdir() returns a "sftp_attributes" which is a pointer
|
||||
to a structure with informations about a directory entry:
|
||||
- name: the name of the file or directory
|
||||
- size: its size in bytes
|
||||
- etc.
|
||||
|
||||
sftp_readdir() might return NULL under two conditions:
|
||||
- when the end of the directory has been met
|
||||
- when an error occured
|
||||
|
||||
To tell the difference, call sftp_dir_eof().
|
||||
|
||||
The attributes must be freed with sftp_attributes_free() when no longer
|
||||
needed.
|
||||
|
||||
The following example reads the contents of some remote directory:
|
||||
|
||||
@code
|
||||
int sftp_list_dir(ssh_session session, sftp_session sftp)
|
||||
{
|
||||
sftp_dir dir;
|
||||
sftp_attributes attributes;
|
||||
int rc;
|
||||
|
||||
dir = sftp_opendir(sftp, "/var/log");
|
||||
if (!dir)
|
||||
{
|
||||
fprintf(stderr, "Directory not opened: %s\n",
|
||||
ssh_get_error(session));
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
printf("Name Size Perms Owner\tGroup\n");
|
||||
|
||||
while ((attributes = sftp_readdir(sftp, dir)) != NULL)
|
||||
{
|
||||
printf("%-20s %10llu %.8o %s(%d)\t%s(%d)\n",
|
||||
attributes->name,
|
||||
(long long unsigned int) attributes->size,
|
||||
attributes->permissions,
|
||||
attributes->owner,
|
||||
attributes->uid,
|
||||
attributes->group,
|
||||
attributes->gid);
|
||||
|
||||
sftp_attributes_free(attributes);
|
||||
}
|
||||
|
||||
if (!sftp_dir_eof(dir))
|
||||
{
|
||||
fprintf(stderr, "Can't list directory: %s\n",
|
||||
ssh_get_error(session));
|
||||
sftp_closedir(dir);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
rc = sftp_closedir(dir);
|
||||
if (rc != SSH_OK)
|
||||
{
|
||||
fprintf(stderr, "Can't close directory: %s\n",
|
||||
ssh_get_error(session));
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
@endcode
|
||||
|
||||
*/
|
||||
361
doc/shell.dox
361
doc/shell.dox
@@ -1,361 +0,0 @@
|
||||
/**
|
||||
@page libssh_tutor_shell Chapter 3: Opening a remote shell
|
||||
@section opening_shell Opening a remote shell
|
||||
|
||||
We already mentioned that a single SSH connection can be shared
|
||||
between several "channels". Channels can be used for different purposes.
|
||||
|
||||
This chapter shows how to open one of these channels, and how to use it to
|
||||
start a command interpreter on a remote computer.
|
||||
|
||||
|
||||
@subsection open_channel Opening and closing a channel
|
||||
|
||||
The ssh_channel_new() function creates a channel. It returns the channel as
|
||||
a variable of type ssh_channel.
|
||||
|
||||
Once you have this channel, you open a SSH session that uses it with
|
||||
ssh_channel_open_session().
|
||||
|
||||
Once you don't need the channel anymore, you can send an end-of-file
|
||||
to it with ssh_channel_close(). At this point, you can destroy the channel
|
||||
with ssh_channel_free().
|
||||
|
||||
The code sample below achieves these tasks:
|
||||
|
||||
@code
|
||||
int shell_session(ssh_session session)
|
||||
{
|
||||
ssh_channel channel;
|
||||
int rc;
|
||||
|
||||
channel = ssh_channel_new(session);
|
||||
if (channel == NULL)
|
||||
return SSH_ERROR;
|
||||
|
||||
rc = ssh_channel_open_session(channel);
|
||||
if (rc != SSH_OK)
|
||||
{
|
||||
ssh_channel_free(channel);
|
||||
return rc;
|
||||
}
|
||||
|
||||
...
|
||||
|
||||
ssh_channel_close(channel);
|
||||
ssh_channel_send_eof(channel);
|
||||
ssh_channel_free(channel);
|
||||
|
||||
return SSH_OK;
|
||||
}
|
||||
@endcode
|
||||
|
||||
|
||||
@subsection interactive Interactive and non-interactive sessions
|
||||
|
||||
A "shell" is a command interpreter. It is said to be "interactive"
|
||||
if there is a human user typing the commands, one after the
|
||||
other. The contrary, a non-interactive shell, is similar to
|
||||
the execution of commands in the background: there is no attached
|
||||
terminal.
|
||||
|
||||
If you plan using an interactive shell, you need to create a
|
||||
pseud-terminal on the remote side. A remote terminal is usually referred
|
||||
to as a "pty", for "pseudo-teletype". The remote processes won't see the
|
||||
difference with a real text-oriented terminal.
|
||||
|
||||
If needed, you request the pty with the function ssh_channel_request_pty().
|
||||
Then you define its dimensions (number of rows and columns)
|
||||
with ssh_channel_change_pty_size().
|
||||
|
||||
Be your session interactive or not, the next step is to request a
|
||||
shell with ssh_channel_request_shell().
|
||||
|
||||
@code
|
||||
int interactive_shell_session(ssh_channel channel)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = ssh_channel_request_pty(channel);
|
||||
if (rc != SSH_OK) return rc;
|
||||
|
||||
rc = ssh_channel_change_pty_size(channel, 80, 24);
|
||||
if (rc != SSH_OK) return rc;
|
||||
|
||||
rc = ssh_channel_request_shell(channel);
|
||||
if (rc != SSH_OK) return rc;
|
||||
|
||||
...
|
||||
|
||||
return rc;
|
||||
}
|
||||
@endcode
|
||||
|
||||
|
||||
@subsection read_data Displaying the data sent by the remote computer
|
||||
|
||||
In your program, you will usually need to receive all the data "displayed"
|
||||
into the remote pty. You will usually analyse, log, or display this data.
|
||||
|
||||
ssh_channel_read() and ssh_channel_read_nonblocking() are the simplest
|
||||
way to read data from a channel. If you only need to read from a single
|
||||
channel, they should be enough.
|
||||
|
||||
The example below shows how to wait for remote data using ssh_channel_read():
|
||||
|
||||
@code
|
||||
int interactive_shell_session(ssh_channel channel)
|
||||
{
|
||||
int rc;
|
||||
char buffer[256];
|
||||
int nbytes;
|
||||
|
||||
rc = ssh_channel_request_pty(channel);
|
||||
if (rc != SSH_OK) return rc;
|
||||
|
||||
rc = ssh_channel_change_pty_size(channel, 80, 24);
|
||||
if (rc != SSH_OK) return rc;
|
||||
|
||||
rc = ssh_channel_request_shell(channel);
|
||||
if (rc != SSH_OK) return rc;
|
||||
|
||||
while (ssh_channel_is_open(channel) &&
|
||||
!ssh_channel_is_eof(channel))
|
||||
{
|
||||
nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
|
||||
if (nbytes < 0)
|
||||
return SSH_ERROR;
|
||||
|
||||
if (nbytes > 0)
|
||||
write(1, buffer, nbytes);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
@endcode
|
||||
|
||||
Unlike ssh_channel_read(), ssh_channel_read_nonblocking() never waits for
|
||||
remote data to be ready. It returns immediately.
|
||||
|
||||
If you plan to use ssh_channel_read_nonblocking() repeatedly in a loop,
|
||||
you should use a "passive wait" function like usleep(3) in the same
|
||||
loop. Otherwise, your program will consume all the CPU time, and your
|
||||
computer might become unresponsive.
|
||||
|
||||
|
||||
@subsection write_data Sending user input to the remote computer
|
||||
|
||||
User's input is sent to the remote site with ssh_channel_write().
|
||||
|
||||
The following example shows how to combine a nonblocking read from a SSH
|
||||
channel with a nonblocking read from the keyboard. The local input is then
|
||||
sent to the remote computer:
|
||||
|
||||
@code
|
||||
/* Under Linux, this function determines whether a key has been pressed.
|
||||
Under Windows, it is a standard function, so you need not redefine it.
|
||||
*/
|
||||
int kbhit()
|
||||
{
|
||||
struct timeval tv = { 0L, 0L };
|
||||
fd_set fds;
|
||||
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(0, &fds);
|
||||
|
||||
return select(1, &fds, NULL, NULL, &tv);
|
||||
}
|
||||
|
||||
/* A very simple terminal emulator:
|
||||
- print data received from the remote computer
|
||||
- send keyboard input to the remote computer
|
||||
*/
|
||||
int interactive_shell_session(ssh_channel channel)
|
||||
{
|
||||
/* Session and terminal initialization skipped */
|
||||
...
|
||||
|
||||
char buffer[256];
|
||||
int nbytes, nwritten;
|
||||
|
||||
while (ssh_channel_is_open(channel) &&
|
||||
!ssh_channel_is_eof(channel))
|
||||
{
|
||||
nbytes = ssh_channel_read_nonblocking(channel, buffer, sizeof(buffer), 0);
|
||||
if (nbytes < 0) return SSH_ERROR;
|
||||
if (nbytes > 0)
|
||||
{
|
||||
nwritten = write(1, buffer, nbytes);
|
||||
if (nwritten != nbytes) return SSH_ERROR;
|
||||
|
||||
if (!kbhit())
|
||||
{
|
||||
usleep(50000L); // 0.05 second
|
||||
continue;
|
||||
}
|
||||
|
||||
nbytes = read(0, buffer, sizeof(buffer));
|
||||
if (nbytes < 0) return SSH_ERROR;
|
||||
if (nbytes > 0)
|
||||
{
|
||||
nwritten = ssh_channel_write(channel, buffer, nbytes);
|
||||
if (nwritten != nbytes) return SSH_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
@endcode
|
||||
|
||||
Of course, this is a poor terminal emulator, since the echo from the keys
|
||||
pressed should not be done locally, but should be done by the remote side.
|
||||
Also, user's input should not be sent once "Enter" key is pressed, but
|
||||
immediately after each key is pressed. This can be accomplished
|
||||
by setting the local terminal to "raw" mode with the cfmakeraw(3) function.
|
||||
cfmakeraw() is a standard function under Linux, on other systems you can
|
||||
recode it with:
|
||||
|
||||
@code
|
||||
static void cfmakeraw(struct termios *termios_p)
|
||||
{
|
||||
termios_p->c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
|
||||
termios_p->c_oflag &= ~OPOST;
|
||||
termios_p->c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
|
||||
termios_p->c_cflag &= ~(CSIZE|PARENB);
|
||||
termios_p->c_cflag |= CS8;
|
||||
}
|
||||
@endcode
|
||||
|
||||
If you are not using a local terminal, but some kind of graphical
|
||||
environment, the solution to this kind of "echo" problems will be different.
|
||||
|
||||
|
||||
@subsection select_loop A more elaborate way to get the remote data
|
||||
|
||||
*** Warning: ssh_select() and ssh_channel_select() are not relevant anymore,
|
||||
since libssh is about to provide an easier system for asynchronous
|
||||
communications. This subsection should be removed then. ***
|
||||
|
||||
ssh_channel_read() and ssh_channel_read_nonblocking() functions are simple,
|
||||
but they are not adapted when you expect data from more than one SSH channel,
|
||||
or from other file descriptors. Last example showed how getting data from
|
||||
the standard input (the keyboard) at the same time as data from the SSH
|
||||
channel was complicated. The functions ssh_select() and ssh_channel_select()
|
||||
provide a more elegant way to wait for data coming from many sources.
|
||||
|
||||
The functions ssh_select() and ssh_channel_select() remind of the standard
|
||||
UNIX select(2) function. The idea is to wait for "something" to happen:
|
||||
incoming data to be read, outcoming data to block, or an exception to
|
||||
occur. Both these functions do a "passive wait", i.e. you can safely use
|
||||
them repeatedly in a loop, it will not consume exaggerate processor time
|
||||
and make your computer unresponsive. It is quite common to use these
|
||||
functions in your application's main loop.
|
||||
|
||||
The difference between ssh_select() and ssh_channel_select() is that
|
||||
ssh_channel_select() is simpler, but allows you only to watch SSH channels.
|
||||
ssh_select() is more complete and enables watching regular file descriptors
|
||||
as well, in the same function call.
|
||||
|
||||
Below is an example of a function that waits both for remote SSH data to come,
|
||||
as well as standard input from the keyboard:
|
||||
|
||||
@code
|
||||
int interactive_shell_session(ssh_session session, ssh_channel channel)
|
||||
{
|
||||
/* Session and terminal initialization skipped */
|
||||
...
|
||||
|
||||
char buffer[256];
|
||||
int nbytes, nwritten;
|
||||
|
||||
while (ssh_channel_is_open(channel) &&
|
||||
!ssh_channel_is_eof(channel))
|
||||
{
|
||||
struct timeval timeout;
|
||||
ssh_channel in_channels[2], out_channels[2];
|
||||
fd_set fds;
|
||||
int maxfd;
|
||||
|
||||
timeout.tv_sec = 30;
|
||||
timeout.tv_usec = 0;
|
||||
in_channels[0] = channel;
|
||||
in_channels[1] = NULL;
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(0, &fds);
|
||||
FD_SET(ssh_get_fd(session), &fds);
|
||||
maxfd = ssh_get_fd(session) + 1;
|
||||
|
||||
ssh_select(in_channels, out_channels, maxfd, &fds, &timeout);
|
||||
|
||||
if (out_channels[0] != NULL)
|
||||
{
|
||||
nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
|
||||
if (nbytes < 0) return SSH_ERROR;
|
||||
if (nbytes > 0)
|
||||
{
|
||||
nwritten = write(1, buffer, nbytes);
|
||||
if (nwritten != nbytes) return SSH_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
if (FD_ISSET(0, &fds))
|
||||
{
|
||||
nbytes = read(0, buffer, sizeof(buffer));
|
||||
if (nbytes < 0) return SSH_ERROR;
|
||||
if (nbytes > 0)
|
||||
{
|
||||
nwritten = ssh_channel_write(channel, buffer, nbytes);
|
||||
if (nbytes != nwritten) return SSH_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
@endcode
|
||||
|
||||
|
||||
@subsection x11 Using graphical applications on the remote side
|
||||
|
||||
If your remote application is graphical, you can forward the X11 protocol to
|
||||
your local computer.
|
||||
|
||||
To do that, you first declare that you accept X11 connections with
|
||||
ssh_channel_accept_x11(). Then you create the forwarding tunnel for
|
||||
the X11 protocol with ssh_channel_request_x11().
|
||||
|
||||
The following code performs channel initialization and shell session
|
||||
opening, and handles a parallel X11 connection:
|
||||
|
||||
@code
|
||||
int interactive_shell_session(ssh_channel channel)
|
||||
{
|
||||
int rc;
|
||||
ssh_channel x11channel;
|
||||
|
||||
rc = ssh_channel_request_pty(channel);
|
||||
if (rc != SSH_OK) return rc;
|
||||
|
||||
rc = ssh_channel_change_pty_size(channel, 80, 24);
|
||||
if (rc != SSH_OK) return rc;
|
||||
|
||||
rc = ssh_channel_request_x11(channel, 0, NULL, NULL, 0);
|
||||
if (rc != SSH_OK) return rc;
|
||||
|
||||
rc = ssh_channel_request_shell(channel);
|
||||
if (rc != SSH_OK) return rc;
|
||||
|
||||
/* Read the data sent by the remote computer here */
|
||||
...
|
||||
}
|
||||
@endcode
|
||||
|
||||
Don't forget to set the $DISPLAY environment variable on the remote
|
||||
side, or the remote applications won't try using the X11 tunnel:
|
||||
|
||||
@code
|
||||
$ export DISPLAY=:0
|
||||
$ xclock &
|
||||
@endcode
|
||||
|
||||
*/
|
||||
184
doc/style.css
Normal file
184
doc/style.css
Normal file
@@ -0,0 +1,184 @@
|
||||
|
||||
body {
|
||||
background-color:#ddf;
|
||||
/*background-image:url(../back6.jpg);*/
|
||||
margin:10px 10px 10px 10px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-family:verdana, sans-serif;
|
||||
font-size:80%;
|
||||
color:black;
|
||||
background-color:transparent;
|
||||
text-align:left;
|
||||
}
|
||||
h2 {
|
||||
font-family:verdana, sans-serif;
|
||||
font-size:100%;
|
||||
color:black;
|
||||
background-color:transparent;
|
||||
text-align:left;
|
||||
}
|
||||
h3 {
|
||||
font-family:verdana, sans-serif;
|
||||
font-size:80%;
|
||||
color:black;
|
||||
background-color:transparent;
|
||||
text-align:left;
|
||||
}
|
||||
p {
|
||||
font-family:verdana, sans-serif;
|
||||
font-size:80%;
|
||||
color:black;
|
||||
background-color:transparent;
|
||||
text-align:left;
|
||||
margin-left:0px;
|
||||
margin-right:0px;
|
||||
}
|
||||
li {
|
||||
font-family:verdana, sans-serif;
|
||||
font-size:80%;
|
||||
color:black;
|
||||
background-color:transparent;
|
||||
text-align:left;
|
||||
margin-left:0px;
|
||||
margin-right:0px;
|
||||
}
|
||||
a:link {
|
||||
font-family:verdana, sans-serif;
|
||||
font-size:100%;
|
||||
color:black;
|
||||
background-color:transparent;
|
||||
text-decoration:underline;
|
||||
}
|
||||
a:visited {
|
||||
font-family:verdana, sans-serif;
|
||||
font-size:100%;
|
||||
color:black;
|
||||
background-color:transparent;
|
||||
text-decoration:underline;
|
||||
}
|
||||
a:hover {
|
||||
font-family:verdana, sans-serif;
|
||||
font-size:100%;
|
||||
color:black;
|
||||
background-color:transparent;
|
||||
text-decoration:underline;
|
||||
}
|
||||
|
||||
table {
|
||||
border-color:transparent;
|
||||
border-style:solid;
|
||||
border-width:1px;
|
||||
}
|
||||
|
||||
td {
|
||||
font-family:verdana, sans-serif;
|
||||
font-size:80%;
|
||||
color:black;
|
||||
text-align:left;
|
||||
background-color:transparent;
|
||||
border-color:transparent;
|
||||
border-style:solid;
|
||||
border-width:1px;
|
||||
}
|
||||
|
||||
.tout {
|
||||
margin: 5px;
|
||||
padding: 0px;
|
||||
border: 2px solid #aac;
|
||||
background: #eef;
|
||||
}
|
||||
|
||||
.prot {
|
||||
border-style:solid;
|
||||
border-width:2px;
|
||||
border-color:#88F;
|
||||
padding: 4px;
|
||||
background-color:#cce;
|
||||
margin: 5px 5px 5px 5px;
|
||||
}
|
||||
|
||||
.ex {
|
||||
border-style:solid;
|
||||
border-width:2px;
|
||||
border-color:#aaF;
|
||||
padding: 4px;
|
||||
background-color:#dde;
|
||||
margin: 5px 5px 5px 5px;
|
||||
}
|
||||
.desc {
|
||||
border-style:solid;
|
||||
border-width:3px;
|
||||
border-color:#66F;
|
||||
padding: 4px;
|
||||
background-color:#aac;
|
||||
margin: 15px 5px 20px 5px;
|
||||
}
|
||||
|
||||
#titre {
|
||||
margin: 5px;
|
||||
padding: 0px;
|
||||
border: 5px solid #aac;
|
||||
background: #eef;
|
||||
}
|
||||
|
||||
#gauche {
|
||||
float:left;
|
||||
margin: 5px;
|
||||
padding: 4px;
|
||||
border: 5px solid #aac;
|
||||
background: #bbf;
|
||||
width: 130px;
|
||||
}
|
||||
|
||||
#droite {
|
||||
position: relative;
|
||||
top:5px;
|
||||
left:165px;
|
||||
margin: 5px 170px 5px 5px;
|
||||
padding: 10px;
|
||||
border: 5px solid #aac;
|
||||
background: #bbf;
|
||||
}
|
||||
|
||||
/* boutons */
|
||||
|
||||
a.bouton:link{
|
||||
width:128px;
|
||||
height:34px;
|
||||
text-decoration:none;
|
||||
color:#aaa;
|
||||
text-align:center;
|
||||
font-weight:bold;
|
||||
/*background-color:#444;*/
|
||||
background-image:url(noclicked.png);
|
||||
}
|
||||
|
||||
a.bouton:visited{
|
||||
width:128px;
|
||||
height:34px;
|
||||
text-decoration:none;
|
||||
color:#aaa;
|
||||
text-align:center;
|
||||
font-weight:bold;
|
||||
/*background-color:#444;*/
|
||||
background-image:url(noclicked.png);
|
||||
}
|
||||
|
||||
a.bouton:hover{
|
||||
width:128px;
|
||||
height:34px;
|
||||
text-decoration:none;
|
||||
color:white;
|
||||
text-align:center;
|
||||
font-weight:bold;
|
||||
/*background-color:#888;*/
|
||||
background-image:url(clicked.png);
|
||||
}
|
||||
|
||||
.bouton{
|
||||
text-align:center;
|
||||
display:block;
|
||||
}
|
||||
|
||||
14
doc/tbd.dox
14
doc/tbd.dox
@@ -1,14 +0,0 @@
|
||||
/**
|
||||
@page libssh_tutor_todo To be done
|
||||
|
||||
*** To be written ***
|
||||
|
||||
@section sshd Writing a libssh-based server
|
||||
|
||||
*** To be written ***
|
||||
|
||||
@section cpp The libssh C++ wrapper
|
||||
|
||||
*** To be written ***
|
||||
|
||||
*/
|
||||
@@ -1,66 +0,0 @@
|
||||
/**
|
||||
@page libssh_tutor_threads Chapter 8: Threads with libssh
|
||||
@section threads_with_libssh How to use libssh with threads
|
||||
|
||||
libssh may be used in multithreaded applications, but under several conditions :
|
||||
- Threading must be initialized during the initialization of libssh. This
|
||||
initialization must be done outside of any threading context.
|
||||
- If pthreads is being used by your application (or your framework's backend),
|
||||
you must link with libssh_threads dynamic library and initialize
|
||||
threading with the ssh_threads_pthreads threading object.
|
||||
- If an other threading library is being used by your application, you must
|
||||
implement all the methods of the ssh_threads_callbacks_struct structure
|
||||
and initialize libssh with it.
|
||||
- At all times, you may use different sessions inside threads, make parallel
|
||||
connections, read/write on different sessions and so on. You *cannot* use a
|
||||
single session (or channels for a single session) in several threads at the same
|
||||
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().
|
||||
|
||||
@code
|
||||
#include <libssh/callbacks.h>
|
||||
...
|
||||
ssh_threads_set_callbacks(ssh_threads_get_noop());
|
||||
ssh_init();
|
||||
@endcode
|
||||
|
||||
ssh_threads_noop is the threading structure that does nothing. It's the
|
||||
threading callbacks being used by default when you're not using threading.
|
||||
|
||||
@subsection threads_pthread Using libpthread with libssh
|
||||
|
||||
If your application is using libpthread, you may simply use the libpthread
|
||||
threading backend:
|
||||
|
||||
@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
|
||||
|
||||
|
||||
@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
|
||||
|
||||
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 !
|
||||
*/
|
||||
@@ -1,4 +1,4 @@
|
||||
project(libssh-examples C CXX)
|
||||
project(libssh-examples C)
|
||||
|
||||
set(examples_SRCS
|
||||
authentication.c
|
||||
@@ -6,61 +6,33 @@ set(examples_SRCS
|
||||
connect_ssh.c
|
||||
)
|
||||
|
||||
include_directories(
|
||||
${LIBSSH_PUBLIC_INCLUDE_DIRS}
|
||||
${LIBSSH_PRIVATE_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
add_executable(libssh_scp libssh_scp.c ${examples_SRCS})
|
||||
add_executable(scp_download scp_download.c ${examples_SRCS})
|
||||
add_executable(samplessh sample.c ${examples_SRCS})
|
||||
add_executable(exec exec.c ${examples_SRCS})
|
||||
|
||||
target_link_libraries(libssh_scp ${LIBSSH_SHARED_LIBRARY})
|
||||
target_link_libraries(scp_download ${LIBSSH_SHARED_LIBRARY})
|
||||
target_link_libraries(samplessh ${LIBSSH_SHARED_LIBRARY})
|
||||
target_link_libraries(exec ${LIBSSH_SHARED_LIBRARY})
|
||||
|
||||
include_directories(
|
||||
${LIBSSH_PUBLIC_INCLUDE_DIRS}
|
||||
${CMAKE_BINARY_DIR}
|
||||
)
|
||||
|
||||
if (BSD OR SOLARIS OR OSX)
|
||||
find_package(Argp)
|
||||
endif (BSD OR SOLARIS OR OSX)
|
||||
if (WITH_SFTP)
|
||||
add_executable(samplesftp samplesftp.c ${examples_SRCS})
|
||||
target_link_libraries(samplesftp ${LIBSSH_SHARED_LIBRARY})
|
||||
endif (WITH_SFTP)
|
||||
|
||||
if (UNIX AND NOT WIN32)
|
||||
add_executable(libssh_scp libssh_scp.c ${examples_SRCS})
|
||||
target_link_libraries(libssh_scp ${LIBSSH_SHARED_LIBRARY})
|
||||
if (WITH_SERVER)
|
||||
add_executable(samplesshd samplesshd.c)
|
||||
target_link_libraries(samplesshd ${LIBSSH_SHARED_LIBRARY})
|
||||
endif (WITH_SERVER)
|
||||
|
||||
add_executable(scp_download scp_download.c ${examples_SRCS})
|
||||
target_link_libraries(scp_download ${LIBSSH_SHARED_LIBRARY})
|
||||
|
||||
add_executable(sshnetcat sshnetcat.c ${examples_SRCS})
|
||||
target_link_libraries(sshnetcat ${LIBSSH_SHARED_LIBRARY})
|
||||
|
||||
if (WITH_SFTP)
|
||||
add_executable(samplesftp samplesftp.c ${examples_SRCS})
|
||||
target_link_libraries(samplesftp ${LIBSSH_SHARED_LIBRARY})
|
||||
endif (WITH_SFTP)
|
||||
|
||||
add_executable(samplessh sample.c ${examples_SRCS})
|
||||
target_link_libraries(samplessh ${LIBSSH_SHARED_LIBRARY})
|
||||
|
||||
if (WITH_SERVER)
|
||||
if (HAVE_LIBUTIL)
|
||||
add_executable(ssh_server_fork ssh_server_fork.c)
|
||||
target_link_libraries(ssh_server_fork ${LIBSSH_SHARED_LIBRARY} ${ARGP_LIBRARIES} util)
|
||||
endif (HAVE_LIBUTIL)
|
||||
|
||||
if (WITH_GSSAPI AND GSSAPI_FOUND)
|
||||
add_executable(samplesshd-cb samplesshd-cb.c)
|
||||
target_link_libraries(samplesshd-cb ${LIBSSH_SHARED_LIBRARY} ${ARGP_LIBRARIES})
|
||||
|
||||
add_executable(proxy proxy.c)
|
||||
target_link_libraries(proxy ${LIBSSH_SHARED_LIBRARY} ${ARGP_LIBRARIES})
|
||||
endif (WITH_GSSAPI AND GSSAPI_FOUND)
|
||||
|
||||
add_executable(samplesshd-kbdint samplesshd-kbdint.c)
|
||||
target_link_libraries(samplesshd-kbdint ${LIBSSH_SHARED_LIBRARY} ${ARGP_LIBRARIES})
|
||||
|
||||
endif (WITH_SERVER)
|
||||
endif (UNIX AND NOT WIN32)
|
||||
|
||||
add_executable(exec exec.c ${examples_SRCS})
|
||||
target_link_libraries(exec ${LIBSSH_SHARED_LIBRARY})
|
||||
|
||||
add_executable(senddata senddata.c ${examples_SRCS})
|
||||
target_link_libraries(senddata ${LIBSSH_SHARED_LIBRARY})
|
||||
|
||||
add_executable(libsshpp libsshpp.cpp)
|
||||
target_link_libraries(libsshpp ${LIBSSH_SHARED_LIBRARY})
|
||||
|
||||
add_executable(libsshpp_noexcept libsshpp_noexcept.cpp)
|
||||
target_link_libraries(libsshpp_noexcept ${LIBSSH_SHARED_LIBRARY})
|
||||
|
||||
@@ -18,121 +18,74 @@ clients must be made or how a client should react.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <libssh/libssh.h>
|
||||
#include "examples_common.h"
|
||||
|
||||
int authenticate_kbdint(ssh_session session, const char *password) {
|
||||
int err;
|
||||
|
||||
err = ssh_userauth_kbdint(session, NULL, NULL);
|
||||
while (err == SSH_AUTH_INFO) {
|
||||
const char *instruction;
|
||||
const char *name;
|
||||
char buffer[128];
|
||||
int i, n;
|
||||
|
||||
name = ssh_userauth_kbdint_getname(session);
|
||||
instruction = ssh_userauth_kbdint_getinstruction(session);
|
||||
n = ssh_userauth_kbdint_getnprompts(session);
|
||||
|
||||
if (name && strlen(name) > 0) {
|
||||
printf("%s\n", name);
|
||||
int authenticate_kbdint(ssh_session session){
|
||||
int err=ssh_userauth_kbdint(session,NULL,NULL);
|
||||
const char *name, *instruction, *prompt;
|
||||
char *ptr;
|
||||
char buffer[128];
|
||||
int i,n;
|
||||
char echo;
|
||||
while (err==SSH_AUTH_INFO){
|
||||
name=ssh_userauth_kbdint_getname(session);
|
||||
instruction=ssh_userauth_kbdint_getinstruction(session);
|
||||
n=ssh_userauth_kbdint_getnprompts(session);
|
||||
if(strlen(name)>0)
|
||||
printf("%s\n",name);
|
||||
if(strlen(instruction)>0)
|
||||
printf("%s\n",instruction);
|
||||
for(i=0;i<n;++i){
|
||||
prompt=ssh_userauth_kbdint_getprompt(session,i,&echo);
|
||||
if(echo){
|
||||
printf("%s",prompt);
|
||||
fgets(buffer,sizeof(buffer),stdin);
|
||||
buffer[sizeof(buffer)-1]=0;
|
||||
if((ptr=strchr(buffer,'\n')))
|
||||
*ptr=0;
|
||||
if (ssh_userauth_kbdint_setanswer(session,i,buffer) < 0) {
|
||||
return SSH_AUTH_ERROR;
|
||||
}
|
||||
|
||||
if (instruction && strlen(instruction) > 0) {
|
||||
printf("%s\n", instruction);
|
||||
memset(buffer,0,strlen(buffer));
|
||||
} else {
|
||||
ptr=getpass(prompt);
|
||||
if (ssh_userauth_kbdint_setanswer(session,i,ptr) < 0) {
|
||||
return SSH_AUTH_ERROR;
|
||||
}
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
const char *answer;
|
||||
const char *prompt;
|
||||
char echo;
|
||||
|
||||
prompt = ssh_userauth_kbdint_getprompt(session, i, &echo);
|
||||
if (prompt == NULL) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (echo) {
|
||||
char *p;
|
||||
|
||||
printf("%s", prompt);
|
||||
|
||||
if (fgets(buffer, sizeof(buffer), stdin) == NULL) {
|
||||
return SSH_AUTH_ERROR;
|
||||
}
|
||||
|
||||
buffer[sizeof(buffer) - 1] = '\0';
|
||||
if ((p = strchr(buffer, '\n'))) {
|
||||
*p = '\0';
|
||||
}
|
||||
|
||||
if (ssh_userauth_kbdint_setanswer(session, i, buffer) < 0) {
|
||||
return SSH_AUTH_ERROR;
|
||||
}
|
||||
|
||||
memset(buffer, 0, strlen(buffer));
|
||||
} else {
|
||||
if (password && strstr(prompt, "Password:")) {
|
||||
answer = password;
|
||||
} else {
|
||||
buffer[0] = '\0';
|
||||
|
||||
if (ssh_getpass(prompt, buffer, sizeof(buffer), 0, 0) < 0) {
|
||||
return SSH_AUTH_ERROR;
|
||||
}
|
||||
answer = buffer;
|
||||
}
|
||||
err = ssh_userauth_kbdint_setanswer(session, i, answer);
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
if (err < 0) {
|
||||
return SSH_AUTH_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
err=ssh_userauth_kbdint(session,NULL,NULL);
|
||||
}
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static void error(ssh_session session){
|
||||
fprintf(stderr,"Authentication failed: %s\n",ssh_get_error(session));
|
||||
err=ssh_userauth_kbdint(session,NULL,NULL);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
int authenticate_console(ssh_session session){
|
||||
int rc;
|
||||
int method;
|
||||
char password[128] = {0};
|
||||
char *password;
|
||||
char *banner;
|
||||
|
||||
// Try to authenticate
|
||||
rc = ssh_userauth_none(session, NULL);
|
||||
if (rc == SSH_AUTH_ERROR) {
|
||||
error(session);
|
||||
perror("Authentication failed.");
|
||||
return rc;
|
||||
}
|
||||
|
||||
method = ssh_userauth_list(session, NULL);
|
||||
method = ssh_auth_list(session);
|
||||
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);
|
||||
rc = ssh_userauth_autopubkey(session, NULL);
|
||||
if (rc == SSH_AUTH_ERROR) {
|
||||
error(session);
|
||||
return rc;
|
||||
perror("Authentication failed.");
|
||||
return rc;
|
||||
} else if (rc == SSH_AUTH_SUCCESS) {
|
||||
break;
|
||||
}
|
||||
@@ -140,36 +93,32 @@ int authenticate_console(ssh_session session){
|
||||
|
||||
// Try to authenticate with keyboard interactive";
|
||||
if (method & SSH_AUTH_METHOD_INTERACTIVE) {
|
||||
rc = authenticate_kbdint(session, NULL);
|
||||
rc = authenticate_kbdint(session);
|
||||
if (rc == SSH_AUTH_ERROR) {
|
||||
error(session);
|
||||
perror("Authentication failed.");
|
||||
return rc;
|
||||
} else if (rc == SSH_AUTH_SUCCESS) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ssh_getpass("Password: ", password, sizeof(password), 0, 0) < 0) {
|
||||
return SSH_AUTH_ERROR;
|
||||
}
|
||||
|
||||
password=getpass("Password: ");
|
||||
// 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);
|
||||
perror("Authentication failed.");
|
||||
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);
|
||||
free(banner);
|
||||
}
|
||||
|
||||
return rc;
|
||||
|
||||
@@ -32,25 +32,22 @@ ssh_session connect_ssh(const char *host, const char *user,int verbosity){
|
||||
|
||||
if(user != NULL){
|
||||
if (ssh_options_set(session, SSH_OPTIONS_USER, user) < 0) {
|
||||
ssh_free(session);
|
||||
ssh_disconnect(session);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (ssh_options_set(session, SSH_OPTIONS_HOST, host) < 0) {
|
||||
ssh_free(session);
|
||||
return NULL;
|
||||
}
|
||||
ssh_options_set(session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity);
|
||||
if(ssh_connect(session)){
|
||||
fprintf(stderr,"Connection failed : %s\n",ssh_get_error(session));
|
||||
ssh_disconnect(session);
|
||||
ssh_free(session);
|
||||
return NULL;
|
||||
}
|
||||
if(verify_knownhost(session)<0){
|
||||
ssh_disconnect(session);
|
||||
ssh_free(session);
|
||||
return NULL;
|
||||
}
|
||||
auth=authenticate_console(session);
|
||||
@@ -62,6 +59,5 @@ ssh_session connect_ssh(const char *host, const char *user,int verbosity){
|
||||
fprintf(stderr,"Error while authenticating : %s\n",ssh_get_error(session));
|
||||
}
|
||||
ssh_disconnect(session);
|
||||
ssh_free(session);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ clients must be made or how a client should react.
|
||||
|
||||
#include <libssh/libssh.h>
|
||||
int authenticate_console(ssh_session session);
|
||||
int authenticate_kbdint(ssh_session session, const char *password);
|
||||
int authenticate_kbdint(ssh_session session);
|
||||
int verify_knownhost(ssh_session session);
|
||||
ssh_session connect_ssh(const char *hostname, const char *user, int verbosity);
|
||||
|
||||
|
||||
103
examples/exec.c
103
examples/exec.c
@@ -5,62 +5,53 @@
|
||||
#include "examples_common.h"
|
||||
|
||||
int main(void) {
|
||||
ssh_session session;
|
||||
ssh_channel channel;
|
||||
char buffer[256];
|
||||
int nbytes;
|
||||
int rc;
|
||||
|
||||
session = connect_ssh("localhost", NULL, 0);
|
||||
if (session == NULL) {
|
||||
ssh_finalize();
|
||||
return 1;
|
||||
}
|
||||
|
||||
channel = ssh_channel_new(session);;
|
||||
if (channel == NULL) {
|
||||
ssh_disconnect(session);
|
||||
ssh_free(session);
|
||||
ssh_finalize();
|
||||
return 1;
|
||||
}
|
||||
|
||||
rc = ssh_channel_open_session(channel);
|
||||
if (rc < 0) {
|
||||
goto failed;
|
||||
}
|
||||
|
||||
rc = ssh_channel_request_exec(channel, "lsof");
|
||||
if (rc < 0) {
|
||||
goto failed;
|
||||
}
|
||||
|
||||
nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
|
||||
while (nbytes > 0) {
|
||||
if (fwrite(buffer, 1, nbytes, stdout) != (unsigned int) nbytes) {
|
||||
goto failed;
|
||||
}
|
||||
nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
|
||||
}
|
||||
|
||||
if (nbytes < 0) {
|
||||
goto failed;
|
||||
}
|
||||
|
||||
ssh_channel_send_eof(channel);
|
||||
ssh_channel_close(channel);
|
||||
ssh_channel_free(channel);
|
||||
ssh_disconnect(session);
|
||||
ssh_free(session);
|
||||
ssh_finalize();
|
||||
|
||||
return 0;
|
||||
failed:
|
||||
ssh_channel_close(channel);
|
||||
ssh_channel_free(channel);
|
||||
ssh_disconnect(session);
|
||||
ssh_free(session);
|
||||
ssh_finalize();
|
||||
ssh_session session;
|
||||
ssh_channel channel;
|
||||
char buf[4096];
|
||||
int rc;
|
||||
|
||||
session = connect_ssh("localhost", NULL, 0);
|
||||
if (session == NULL) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
channel = channel_new(session);;
|
||||
if (channel == NULL) {
|
||||
ssh_disconnect(session);
|
||||
ssh_finalize();
|
||||
return 1;
|
||||
}
|
||||
|
||||
rc = channel_open_session(channel);
|
||||
if (rc < 0) {
|
||||
channel_close(channel);
|
||||
ssh_disconnect(session);
|
||||
ssh_finalize();
|
||||
return 1;
|
||||
}
|
||||
|
||||
rc = channel_request_exec(channel, "ps aux");
|
||||
if (rc < 0) {
|
||||
channel_close(channel);
|
||||
ssh_disconnect(session);
|
||||
ssh_finalize();
|
||||
return 1;
|
||||
}
|
||||
|
||||
do {
|
||||
if (channel_is_open(channel)) {
|
||||
rc = channel_read(channel, buf, sizeof(buf), 0);
|
||||
if(rc > 0){
|
||||
fwrite(buf,1,rc,stdout);
|
||||
}
|
||||
}
|
||||
} while(rc > 0);
|
||||
|
||||
channel_send_eof(channel);
|
||||
channel_close(channel);
|
||||
|
||||
ssh_disconnect(session);
|
||||
ssh_finalize();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -20,47 +20,32 @@ clients must be made or how a client should react.
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <libssh/libssh.h>
|
||||
#include "examples_common.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#define strncasecmp _strnicmp
|
||||
#endif
|
||||
|
||||
int verify_knownhost(ssh_session session){
|
||||
char *hexa;
|
||||
int state;
|
||||
char buf[10];
|
||||
unsigned char *hash = NULL;
|
||||
size_t hlen;
|
||||
ssh_key srv_pubkey;
|
||||
int rc;
|
||||
int hlen;
|
||||
|
||||
state=ssh_is_server_known(session);
|
||||
|
||||
rc = ssh_get_publickey(session, &srv_pubkey);
|
||||
if (rc < 0) {
|
||||
return -1;
|
||||
hlen = ssh_get_pubkey_hash(session, &hash);
|
||||
if (hlen < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
rc = ssh_get_publickey_hash(srv_pubkey,
|
||||
SSH_PUBLICKEY_HASH_SHA1,
|
||||
&hash,
|
||||
&hlen);
|
||||
ssh_key_free(srv_pubkey);
|
||||
if (rc < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch(state){
|
||||
case SSH_SERVER_KNOWN_OK:
|
||||
break; /* ok */
|
||||
case SSH_SERVER_KNOWN_CHANGED:
|
||||
fprintf(stderr,"Host key for server changed : server's one is now :\n");
|
||||
ssh_print_hexa("Public key hash",hash, hlen);
|
||||
ssh_clean_pubkey_hash(&hash);
|
||||
free(hash);
|
||||
fprintf(stderr,"For security reason, connection will be stopped\n");
|
||||
return -1;
|
||||
case SSH_SERVER_FOUND_OTHER:
|
||||
@@ -77,23 +62,16 @@ int verify_knownhost(ssh_session session){
|
||||
hexa = ssh_get_hexa(hash, hlen);
|
||||
fprintf(stderr,"The server is unknown. Do you trust the host key ?\n");
|
||||
fprintf(stderr, "Public key hash: %s\n", hexa);
|
||||
ssh_string_free_char(hexa);
|
||||
if (fgets(buf, sizeof(buf), stdin) == NULL) {
|
||||
ssh_clean_pubkey_hash(&hash);
|
||||
return -1;
|
||||
}
|
||||
free(hexa);
|
||||
fgets(buf,sizeof(buf),stdin);
|
||||
if(strncasecmp(buf,"yes",3)!=0){
|
||||
ssh_clean_pubkey_hash(&hash);
|
||||
return -1;
|
||||
}
|
||||
fprintf(stderr,"This new key will be written on disk for further usage. do you agree ?\n");
|
||||
if (fgets(buf, sizeof(buf), stdin) == NULL) {
|
||||
ssh_clean_pubkey_hash(&hash);
|
||||
return -1;
|
||||
}
|
||||
fgets(buf,sizeof(buf),stdin);
|
||||
if(strncasecmp(buf,"yes",3)==0){
|
||||
if (ssh_write_knownhost(session) < 0) {
|
||||
ssh_clean_pubkey_hash(&hash);
|
||||
free(hash);
|
||||
fprintf(stderr, "error %s\n", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
@@ -101,10 +79,10 @@ int verify_knownhost(ssh_session session){
|
||||
|
||||
break;
|
||||
case SSH_SERVER_ERROR:
|
||||
ssh_clean_pubkey_hash(&hash);
|
||||
free(hash);
|
||||
fprintf(stderr,"%s",ssh_get_error(session));
|
||||
return -1;
|
||||
}
|
||||
ssh_clean_pubkey_hash(&hash);
|
||||
free(hash);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -22,10 +22,10 @@ program.
|
||||
#include <libssh/libssh.h>
|
||||
#include "examples_common.h"
|
||||
|
||||
static char **sources;
|
||||
static int nsources;
|
||||
static char *destination;
|
||||
static int verbosity=0;
|
||||
char **sources;
|
||||
int nsources;
|
||||
char *destination;
|
||||
int verbosity=0;
|
||||
|
||||
struct location {
|
||||
int is_ssh;
|
||||
@@ -84,15 +84,9 @@ static int opts(int argc, char **argv){
|
||||
}
|
||||
|
||||
static struct location *parse_location(char *loc){
|
||||
struct location *location;
|
||||
struct location *location=malloc(sizeof(struct location));
|
||||
char *ptr;
|
||||
|
||||
location = malloc(sizeof(struct location));
|
||||
if (location == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
memset(location, 0, sizeof(struct location));
|
||||
|
||||
location->host=location->user=NULL;
|
||||
ptr=strchr(loc,':');
|
||||
if(ptr != NULL){
|
||||
@@ -129,7 +123,6 @@ static int open_location(struct location *loc, int flag){
|
||||
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;
|
||||
@@ -147,7 +140,6 @@ static int open_location(struct location *loc, int flag){
|
||||
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;
|
||||
@@ -182,22 +174,15 @@ static int do_copy(struct location *src, struct location *dest, int recursive){
|
||||
char buffer[16384];
|
||||
int total=0;
|
||||
int mode;
|
||||
char *filename = NULL;
|
||||
char *filename;
|
||||
/* 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;
|
||||
}
|
||||
fd=fileno(src->file);
|
||||
fstat(fd,&s);
|
||||
size=s.st_size;
|
||||
mode = s.st_mode & ~S_IFMT;
|
||||
mode=s.st_mode;
|
||||
filename=ssh_basename(src->path);
|
||||
} else {
|
||||
size=0;
|
||||
@@ -216,20 +201,17 @@ static int do_copy(struct location *src, struct location *dest, int recursive){
|
||||
}
|
||||
if(r==SSH_ERROR){
|
||||
fprintf(stderr,"Error: %s\n",ssh_get_error(src->session));
|
||||
ssh_string_free_char(filename);
|
||||
return -1;
|
||||
}
|
||||
} while(r != SSH_SCP_REQUEST_NEWFILE);
|
||||
}
|
||||
|
||||
if(dest->is_ssh){
|
||||
r=ssh_scp_push_file(dest->scp,src->path, size, mode);
|
||||
r=ssh_scp_push_file(dest->scp,src->path,size,0644);
|
||||
// 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 {
|
||||
@@ -239,7 +221,6 @@ static int do_copy(struct location *src, struct location *dest, int recursive){
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -252,7 +233,6 @@ static int do_copy(struct location *src, struct location *dest, int recursive){
|
||||
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)
|
||||
@@ -263,7 +243,6 @@ static int do_copy(struct location *src, struct location *dest, int recursive){
|
||||
break;
|
||||
if(r<0){
|
||||
fprintf(stderr,"Error reading file: %s\n",strerror(errno));
|
||||
ssh_string_free_char(filename);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@@ -273,21 +252,18 @@ static int do_copy(struct location *src, struct location *dest, int recursive){
|
||||
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;
|
||||
}
|
||||
@@ -310,7 +286,7 @@ int main(int argc, char **argv){
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (dest->is_ssh && dest->scp != NULL) {
|
||||
if(dest->is_ssh){
|
||||
r=ssh_scp_close(dest->scp);
|
||||
if(r == SSH_ERROR){
|
||||
fprintf(stderr,"Error closing scp: %s\n",ssh_get_error(dest->session));
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
/*
|
||||
Copyright 2010 Aris Adamantiadis
|
||||
|
||||
This file is part of the SSH Library
|
||||
|
||||
You are free to copy this file, modify it in any way, consider it being public
|
||||
domain. This does not apply to the rest of the library though, but it is
|
||||
allowed to cut-and-paste working code from this file to any license of
|
||||
program.
|
||||
*/
|
||||
|
||||
/* This file demonstrates the use of the C++ wrapper to libssh */
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <libssh/libsshpp.hpp>
|
||||
|
||||
int main(int argc, const char **argv){
|
||||
ssh::Session session;
|
||||
try {
|
||||
if(argc>1)
|
||||
session.setOption(SSH_OPTIONS_HOST,argv[1]);
|
||||
else
|
||||
session.setOption(SSH_OPTIONS_HOST,"localhost");
|
||||
session.connect();
|
||||
session.userauthPublickeyAuto();
|
||||
session.disconnect();
|
||||
} catch (ssh::SshException e){
|
||||
std::cout << "Error during connection : ";
|
||||
std::cout << e.getError() << std::endl;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
/*
|
||||
Copyright 2010 Aris Adamantiadis
|
||||
|
||||
This file is part of the SSH Library
|
||||
|
||||
You are free to copy this file, modify it in any way, consider it being public
|
||||
domain. This does not apply to the rest of the library though, but it is
|
||||
allowed to cut-and-paste working code from this file to any license of
|
||||
program.
|
||||
*/
|
||||
|
||||
/* This file demonstrates the use of the C++ wrapper to libssh
|
||||
* specifically, without C++ exceptions
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#define SSH_NO_CPP_EXCEPTIONS
|
||||
#include <libssh/libsshpp.hpp>
|
||||
|
||||
int main(int argc, const char **argv){
|
||||
ssh::Session session,s2;
|
||||
int err;
|
||||
if(argc>1)
|
||||
err=session.setOption(SSH_OPTIONS_HOST,argv[1]);
|
||||
else
|
||||
err=session.setOption(SSH_OPTIONS_HOST,"localhost");
|
||||
if(err==SSH_ERROR)
|
||||
goto error;
|
||||
err=session.connect();
|
||||
if(err==SSH_ERROR)
|
||||
goto error;
|
||||
err=session.userauthPublickeyAuto();
|
||||
if(err==SSH_ERROR)
|
||||
goto error;
|
||||
|
||||
return 0;
|
||||
error:
|
||||
std::cout << "Error during connection : ";
|
||||
std::cout << session.getError() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
347
examples/proxy.c
347
examples/proxy.c
@@ -1,347 +0,0 @@
|
||||
/* This is a sample implementation of a libssh based SSH proxy */
|
||||
/*
|
||||
Copyright 2003-2013 Aris Adamantiadis
|
||||
|
||||
This file is part of the SSH Library
|
||||
|
||||
You are free to copy this file, modify it in any way, consider it being public
|
||||
domain. This does not apply to the rest of the library though, but it is
|
||||
allowed to cut-and-paste working code from this file to any license of
|
||||
program.
|
||||
The goal is to show the API in action. It's not a reference on how terminal
|
||||
clients must be made or how a client should react.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <libssh/libssh.h>
|
||||
#include <libssh/server.h>
|
||||
#include <libssh/callbacks.h>
|
||||
|
||||
#ifdef HAVE_ARGP_H
|
||||
#include <argp.h>
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define USER "myuser"
|
||||
#define PASSWORD "mypassword"
|
||||
|
||||
static int authenticated=0;
|
||||
static int tries = 0;
|
||||
static int error = 0;
|
||||
static ssh_channel chan=NULL;
|
||||
static char *username;
|
||||
static ssh_gssapi_creds client_creds = NULL;
|
||||
|
||||
static int auth_password(ssh_session session, const char *user,
|
||||
const char *password, void *userdata){
|
||||
|
||||
(void)userdata;
|
||||
|
||||
printf("Authenticating user %s pwd %s\n",user, password);
|
||||
if(strcmp(user,USER) == 0 && strcmp(password, PASSWORD) == 0){
|
||||
authenticated = 1;
|
||||
printf("Authenticated\n");
|
||||
return SSH_AUTH_SUCCESS;
|
||||
}
|
||||
if (tries >= 3){
|
||||
printf("Too many authentication tries\n");
|
||||
ssh_disconnect(session);
|
||||
error = 1;
|
||||
return SSH_AUTH_DENIED;
|
||||
}
|
||||
tries++;
|
||||
return SSH_AUTH_DENIED;
|
||||
}
|
||||
|
||||
static int auth_gssapi_mic(ssh_session session, const char *user, const char *principal, void *userdata){
|
||||
(void)userdata;
|
||||
client_creds = ssh_gssapi_get_creds(session);
|
||||
printf("Authenticating user %s with gssapi principal %s\n",user, principal);
|
||||
if (client_creds != NULL)
|
||||
printf("Received some gssapi credentials\n");
|
||||
else
|
||||
printf("Not received any forwardable creds\n");
|
||||
printf("authenticated\n");
|
||||
authenticated = 1;
|
||||
username = strdup(principal);
|
||||
return SSH_AUTH_SUCCESS;
|
||||
}
|
||||
|
||||
static int pty_request(ssh_session session, ssh_channel channel, const char *term,
|
||||
int x,int y, int px, int py, void *userdata){
|
||||
(void) session;
|
||||
(void) channel;
|
||||
(void) term;
|
||||
(void) x;
|
||||
(void) y;
|
||||
(void) px;
|
||||
(void) py;
|
||||
(void) userdata;
|
||||
printf("Allocated terminal\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int shell_request(ssh_session session, ssh_channel channel, void *userdata){
|
||||
(void)session;
|
||||
(void)channel;
|
||||
(void)userdata;
|
||||
printf("Allocated shell\n");
|
||||
return 0;
|
||||
}
|
||||
struct ssh_channel_callbacks_struct channel_cb = {
|
||||
.channel_pty_request_function = pty_request,
|
||||
.channel_shell_request_function = shell_request
|
||||
};
|
||||
|
||||
static ssh_channel new_session_channel(ssh_session session, void *userdata){
|
||||
(void) session;
|
||||
(void) userdata;
|
||||
if(chan != NULL)
|
||||
return NULL;
|
||||
printf("Allocated session channel\n");
|
||||
chan = ssh_channel_new(session);
|
||||
ssh_callbacks_init(&channel_cb);
|
||||
ssh_set_channel_callbacks(chan, &channel_cb);
|
||||
return chan;
|
||||
}
|
||||
|
||||
|
||||
#ifdef HAVE_ARGP_H
|
||||
const char *argp_program_version = "libssh proxy example "
|
||||
SSH_STRINGIFY(LIBSSH_VERSION);
|
||||
const char *argp_program_bug_address = "<libssh@libssh.org>";
|
||||
|
||||
/* Program documentation. */
|
||||
static char doc[] = "libssh -- a Secure Shell protocol implementation";
|
||||
|
||||
/* A description of the arguments we accept. */
|
||||
static char args_doc[] = "BINDADDR";
|
||||
|
||||
/* The options we understand. */
|
||||
static struct argp_option options[] = {
|
||||
{
|
||||
.name = "port",
|
||||
.key = 'p',
|
||||
.arg = "PORT",
|
||||
.flags = 0,
|
||||
.doc = "Set the port to bind.",
|
||||
.group = 0
|
||||
},
|
||||
{
|
||||
.name = "hostkey",
|
||||
.key = 'k',
|
||||
.arg = "FILE",
|
||||
.flags = 0,
|
||||
.doc = "Set the host key.",
|
||||
.group = 0
|
||||
},
|
||||
{
|
||||
.name = "dsakey",
|
||||
.key = 'd',
|
||||
.arg = "FILE",
|
||||
.flags = 0,
|
||||
.doc = "Set the dsa key.",
|
||||
.group = 0
|
||||
},
|
||||
{
|
||||
.name = "rsakey",
|
||||
.key = 'r',
|
||||
.arg = "FILE",
|
||||
.flags = 0,
|
||||
.doc = "Set the rsa key.",
|
||||
.group = 0
|
||||
},
|
||||
{
|
||||
.name = "verbose",
|
||||
.key = 'v',
|
||||
.arg = NULL,
|
||||
.flags = 0,
|
||||
.doc = "Get verbose output.",
|
||||
.group = 0
|
||||
},
|
||||
{NULL, 0, NULL, 0, NULL, 0}
|
||||
};
|
||||
|
||||
/* Parse a single option. */
|
||||
static error_t parse_opt (int key, char *arg, struct argp_state *state) {
|
||||
/* Get the input argument from argp_parse, which we
|
||||
* know is a pointer to our arguments structure.
|
||||
*/
|
||||
ssh_bind sshbind = state->input;
|
||||
|
||||
switch (key) {
|
||||
case 'p':
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_BINDPORT_STR, arg);
|
||||
break;
|
||||
case 'd':
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_DSAKEY, arg);
|
||||
break;
|
||||
case 'k':
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_HOSTKEY, arg);
|
||||
break;
|
||||
case 'r':
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_RSAKEY, arg);
|
||||
break;
|
||||
case 'v':
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_LOG_VERBOSITY_STR, "3");
|
||||
break;
|
||||
case ARGP_KEY_ARG:
|
||||
if (state->arg_num >= 1) {
|
||||
/* Too many arguments. */
|
||||
argp_usage (state);
|
||||
}
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_BINDADDR, arg);
|
||||
break;
|
||||
case ARGP_KEY_END:
|
||||
if (state->arg_num < 1) {
|
||||
/* Not enough arguments. */
|
||||
argp_usage (state);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return ARGP_ERR_UNKNOWN;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Our argp parser. */
|
||||
static struct argp argp = {options, parse_opt, args_doc, doc, NULL, NULL, NULL};
|
||||
#endif /* HAVE_ARGP_H */
|
||||
|
||||
int main(int argc, char **argv){
|
||||
ssh_session session;
|
||||
ssh_bind sshbind;
|
||||
ssh_event mainloop;
|
||||
ssh_session client_session;
|
||||
|
||||
struct ssh_server_callbacks_struct cb = {
|
||||
.userdata = NULL,
|
||||
.auth_password_function = auth_password,
|
||||
.auth_gssapi_mic_function = auth_gssapi_mic,
|
||||
.channel_open_request_session_function = new_session_channel
|
||||
};
|
||||
|
||||
char buf[2048];
|
||||
char host[128]="";
|
||||
char *ptr;
|
||||
int i,r, rc;
|
||||
|
||||
sshbind=ssh_bind_new();
|
||||
session=ssh_new();
|
||||
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_RSAKEY, "sshd_rsa");
|
||||
|
||||
#ifdef HAVE_ARGP_H
|
||||
/*
|
||||
* Parse our arguments; every option seen by parse_opt will
|
||||
* be reflected in arguments.
|
||||
*/
|
||||
argp_parse (&argp, argc, argv, 0, 0, sshbind);
|
||||
#else
|
||||
(void) argc;
|
||||
(void) argv;
|
||||
#endif
|
||||
|
||||
if(ssh_bind_listen(sshbind)<0){
|
||||
printf("Error listening to socket: %s\n",ssh_get_error(sshbind));
|
||||
return 1;
|
||||
}
|
||||
r=ssh_bind_accept(sshbind,session);
|
||||
if(r==SSH_ERROR){
|
||||
printf("error accepting a connection : %s\n",ssh_get_error(sshbind));
|
||||
return 1;
|
||||
}
|
||||
ssh_callbacks_init(&cb);
|
||||
ssh_set_server_callbacks(session, &cb);
|
||||
|
||||
if (ssh_handle_key_exchange(session)) {
|
||||
printf("ssh_handle_key_exchange: %s\n", ssh_get_error(session));
|
||||
return 1;
|
||||
}
|
||||
ssh_set_auth_methods(session,SSH_AUTH_METHOD_PASSWORD | SSH_AUTH_METHOD_GSSAPI_MIC);
|
||||
mainloop = ssh_event_new();
|
||||
ssh_event_add_session(mainloop, session);
|
||||
|
||||
while (!(authenticated && chan != NULL)){
|
||||
if(error)
|
||||
break;
|
||||
r = ssh_event_dopoll(mainloop, -1);
|
||||
if (r == SSH_ERROR){
|
||||
printf("Error : %s\n",ssh_get_error(session));
|
||||
ssh_disconnect(session);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if(error){
|
||||
printf("Error, exiting loop\n");
|
||||
return 1;
|
||||
} else
|
||||
printf("Authenticated and got a channel\n");
|
||||
if (!client_creds){
|
||||
snprintf(buf,sizeof(buf), "Sorry, but you do not have forwardable tickets. Try again with -K\r\n");
|
||||
ssh_channel_write(chan,buf,strlen(buf));
|
||||
printf("%s",buf);
|
||||
ssh_disconnect(session);
|
||||
return 1;
|
||||
}
|
||||
snprintf(buf,sizeof(buf), "Hello %s, welcome to the Sample SSH proxy.\r\nPlease select your destination: ", username);
|
||||
ssh_channel_write(chan, buf, strlen(buf));
|
||||
do{
|
||||
i=ssh_channel_read(chan,buf, 2048, 0);
|
||||
if(i>0) {
|
||||
ssh_channel_write(chan, buf, i);
|
||||
if(strlen(host) + i < sizeof(host)){
|
||||
strncat(host, buf, i);
|
||||
}
|
||||
if (strchr(host, '\x0d')) {
|
||||
*strchr(host, '\x0d')='\0';
|
||||
ssh_channel_write(chan, "\n", 1);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
printf ("Error: %s\n", ssh_get_error(session) );
|
||||
return 1;
|
||||
}
|
||||
} while (i>0);
|
||||
snprintf(buf,sizeof(buf),"Trying to connect to \"%s\"\r\n", host);
|
||||
ssh_channel_write(chan, buf, strlen(buf));
|
||||
printf("%s",buf);
|
||||
|
||||
client_session = ssh_new();
|
||||
|
||||
/* ssh servers expect username without realm */
|
||||
ptr = strchr(username,'@');
|
||||
if(ptr)
|
||||
*ptr= '\0';
|
||||
ssh_options_set(client_session, SSH_OPTIONS_HOST, host);
|
||||
ssh_options_set(client_session, SSH_OPTIONS_USER, username);
|
||||
ssh_gssapi_set_creds(client_session, client_creds);
|
||||
rc = ssh_connect(client_session);
|
||||
if (rc != SSH_OK){
|
||||
printf("Error connecting to %s: %s", host, ssh_get_error(client_session));
|
||||
return 1;
|
||||
}
|
||||
rc = ssh_userauth_none(client_session, NULL);
|
||||
if(rc == SSH_AUTH_SUCCESS){
|
||||
printf("Authenticated using method none\n");
|
||||
} else {
|
||||
rc = ssh_userauth_gssapi(client_session);
|
||||
if(rc != SSH_AUTH_SUCCESS){
|
||||
printf("GSSAPI Authentication failed: %s\n",ssh_get_error(client_session));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
snprintf(buf,sizeof(buf), "Authentication success\r\n");
|
||||
printf("%s",buf);
|
||||
ssh_channel_write(chan,buf,strlen(buf));
|
||||
ssh_disconnect(client_session);
|
||||
ssh_disconnect(session);
|
||||
ssh_bind_free(sshbind);
|
||||
ssh_finalize();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -14,50 +14,64 @@ clients must be made or how a client should react.
|
||||
|
||||
#include "config.h"
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <termios.h>
|
||||
|
||||
#include <sys/select.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#ifdef HAVE_TERMIOS_H
|
||||
#include <termios.h>
|
||||
#endif
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#ifdef HAVE_PTY_H
|
||||
#include <pty.h>
|
||||
#endif
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#include <signal.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <libssh/callbacks.h>
|
||||
#include <libssh/libssh.h>
|
||||
#include <libssh/sftp.h>
|
||||
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "examples_common.h"
|
||||
#define MAXCMD 10
|
||||
char *host;
|
||||
char *user;
|
||||
char *cmds[MAXCMD];
|
||||
struct termios terminal;
|
||||
|
||||
static char *host;
|
||||
static char *user;
|
||||
static char *cmds[MAXCMD];
|
||||
static struct termios terminal;
|
||||
#ifdef WITH_PCAP
|
||||
/* this header file won't be necessary in the future */
|
||||
#include <libssh/pcap.h>
|
||||
char *pcap_file=NULL;
|
||||
#endif
|
||||
|
||||
static char *pcap_file=NULL;
|
||||
|
||||
static char *proxycommand;
|
||||
char *proxycommand;
|
||||
|
||||
static int auth_callback(const char *prompt, char *buf, size_t len,
|
||||
int echo, int verify, void *userdata) {
|
||||
(void) verify;
|
||||
(void) userdata;
|
||||
char *answer = NULL;
|
||||
char *ptr;
|
||||
|
||||
return ssh_getpass(prompt, buf, len, echo, verify);
|
||||
(void) verify;
|
||||
(void) userdata;
|
||||
|
||||
if (echo) {
|
||||
while ((answer = fgets(buf, len, stdin)) == NULL);
|
||||
if ((ptr = strchr(buf, '\n'))) {
|
||||
ptr = '\0';
|
||||
}
|
||||
} else {
|
||||
answer = getpass(prompt);
|
||||
}
|
||||
|
||||
if (answer == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
strncpy(buf, answer, len);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct ssh_callbacks_struct cb = {
|
||||
@@ -67,12 +81,9 @@ struct ssh_callbacks_struct cb = {
|
||||
|
||||
static void add_cmd(char *cmd){
|
||||
int n;
|
||||
|
||||
for (n = 0; (n < MAXCMD) && cmds[n] != NULL; n++);
|
||||
|
||||
if (n == MAXCMD) {
|
||||
for(n=0;cmds[n] && (n<MAXCMD);n++);
|
||||
if(n==MAXCMD)
|
||||
return;
|
||||
}
|
||||
cmds[n]=strdup(cmd);
|
||||
}
|
||||
|
||||
@@ -102,15 +113,17 @@ static int opts(int argc, char **argv){
|
||||
/* insert your own arguments here */
|
||||
while((i=getopt(argc,argv,"T:P:"))!=-1){
|
||||
switch(i){
|
||||
#ifdef WITH_PCAP
|
||||
case 'P':
|
||||
pcap_file=optarg;
|
||||
break;
|
||||
#endif
|
||||
#ifndef _WIN32
|
||||
case 'T':
|
||||
proxycommand=optarg;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
default:
|
||||
fprintf(stderr,"unknown option %c\n",optopt);
|
||||
usage();
|
||||
}
|
||||
@@ -166,7 +179,7 @@ static void setsignal(void){
|
||||
static void sizechanged(void){
|
||||
struct winsize win = { 0, 0, 0, 0 };
|
||||
ioctl(1, TIOCGWINSZ, &win);
|
||||
ssh_channel_change_pty_size(chan,win.ws_col, win.ws_row);
|
||||
channel_change_pty_size(chan,win.ws_col, win.ws_row);
|
||||
// printf("Changed pty size\n");
|
||||
setsignal();
|
||||
}
|
||||
@@ -189,7 +202,7 @@ static void select_loop(ssh_session session,ssh_channel channel){
|
||||
fd_set fds;
|
||||
struct timeval timeout;
|
||||
char buffer[4096];
|
||||
ssh_buffer readbuf=ssh_buffer_new();
|
||||
ssh_buffer readbuf=buffer_new();
|
||||
ssh_channel channels[2];
|
||||
int lus;
|
||||
int eof=0;
|
||||
@@ -217,10 +230,10 @@ static void select_loop(ssh_session session,ssh_channel channel){
|
||||
if(FD_ISSET(0,&fds)){
|
||||
lus=read(0,buffer,sizeof(buffer));
|
||||
if(lus)
|
||||
ssh_channel_write(channel,buffer,lus);
|
||||
channel_write(channel,buffer,lus);
|
||||
else {
|
||||
eof=1;
|
||||
ssh_channel_send_eof(channel);
|
||||
channel_send_eof(channel);
|
||||
}
|
||||
}
|
||||
if(FD_ISSET(ssh_get_fd(session),&fds)){
|
||||
@@ -228,20 +241,22 @@ static void select_loop(ssh_session session,ssh_channel channel){
|
||||
}
|
||||
channels[0]=channel; // set the first channel we want to read from
|
||||
channels[1]=NULL;
|
||||
ret=ssh_channel_select(channels,NULL,NULL,NULL); // no specific timeout - just poll
|
||||
ret=channel_select(channels,NULL,NULL,NULL); // no specific timeout - just poll
|
||||
if(signal_delayed)
|
||||
sizechanged();
|
||||
} while (ret==EINTR || ret==SSH_EINTR);
|
||||
|
||||
// we already looked for input from stdin. Now, we are looking for input from the channel
|
||||
|
||||
if(channel && ssh_channel_is_closed(channel)){
|
||||
ssh_channel_free(channel);
|
||||
if(channel && channel_is_closed(channel)){
|
||||
ssh_log(session,SSH_LOG_RARE,"exit-status : %d\n",channel_get_exit_status(channel));
|
||||
|
||||
channel_free(channel);
|
||||
channel=NULL;
|
||||
channels[0]=NULL;
|
||||
}
|
||||
if(channels[0]){
|
||||
while(channel && ssh_channel_is_open(channel) && ssh_channel_poll(channel,0)>0){
|
||||
while(channel && channel_is_open(channel) && channel_poll(channel,0)){
|
||||
lus=channel_read_buffer(channel,readbuf,0,0);
|
||||
if(lus==-1){
|
||||
fprintf(stderr, "Error reading channel: %s\n",
|
||||
@@ -249,15 +264,15 @@ static void select_loop(ssh_session session,ssh_channel channel){
|
||||
return;
|
||||
}
|
||||
if(lus==0){
|
||||
ssh_channel_free(channel);
|
||||
ssh_log(session,SSH_LOG_RARE,"EOF received\n");
|
||||
ssh_log(session,SSH_LOG_RARE,"exit-status : %d\n",channel_get_exit_status(channel));
|
||||
|
||||
channel_free(channel);
|
||||
channel=channels[0]=NULL;
|
||||
} else
|
||||
if (write(1,ssh_buffer_get_begin(readbuf),lus) < 0) {
|
||||
fprintf(stderr, "Error writing to buffer\n");
|
||||
return;
|
||||
}
|
||||
write(1,buffer_get(readbuf),lus);
|
||||
}
|
||||
while(channel && ssh_channel_is_open(channel) && ssh_channel_poll(channel,1)>0){ /* stderr */
|
||||
while(channel && channel_is_open(channel) && channel_poll(channel,1)){ /* stderr */
|
||||
lus=channel_read_buffer(channel,readbuf,0,1);
|
||||
if(lus==-1){
|
||||
fprintf(stderr, "Error reading channel: %s\n",
|
||||
@@ -265,21 +280,20 @@ static void select_loop(ssh_session session,ssh_channel channel){
|
||||
return;
|
||||
}
|
||||
if(lus==0){
|
||||
ssh_channel_free(channel);
|
||||
ssh_log(session,SSH_LOG_RARE,"EOF received\n");
|
||||
ssh_log(session,SSH_LOG_RARE,"exit-status : %d\n",channel_get_exit_status(channel));
|
||||
channel_free(channel);
|
||||
channel=channels[0]=NULL;
|
||||
} else
|
||||
if (write(2,ssh_buffer_get_begin(readbuf),lus) < 0) {
|
||||
fprintf(stderr, "Error writing to buffer\n");
|
||||
return;
|
||||
}
|
||||
write(2,buffer_get(readbuf),lus);
|
||||
}
|
||||
}
|
||||
if(channel && ssh_channel_is_closed(channel)){
|
||||
ssh_channel_free(channel);
|
||||
if(channel && channel_is_closed(channel)){
|
||||
channel_free(channel);
|
||||
channel=NULL;
|
||||
}
|
||||
}
|
||||
ssh_buffer_free(readbuf);
|
||||
buffer_free(readbuf);
|
||||
}
|
||||
#else /* CHANNEL_SELECT */
|
||||
|
||||
@@ -294,26 +308,16 @@ static void select_loop(ssh_session session,ssh_channel channel){
|
||||
int lus;
|
||||
int eof=0;
|
||||
int maxfd;
|
||||
unsigned int r;
|
||||
int ret;
|
||||
while(channel){
|
||||
do{
|
||||
int fd;
|
||||
|
||||
FD_ZERO(&fds);
|
||||
if(!eof)
|
||||
FD_SET(0,&fds);
|
||||
timeout.tv_sec=30;
|
||||
timeout.tv_usec=0;
|
||||
|
||||
fd = ssh_get_fd(session);
|
||||
if (fd < 0) {
|
||||
fprintf(stderr, "Error getting fd\n");
|
||||
return;
|
||||
}
|
||||
FD_SET(fd, &fds);
|
||||
maxfd = fd + 1;
|
||||
|
||||
FD_SET(ssh_get_fd(session),&fds);
|
||||
maxfd=ssh_get_fd(session)+1;
|
||||
channels[0]=channel; // set the first channel we want to read from
|
||||
channels[1]=NULL;
|
||||
ret=ssh_select(channels,outchannels,maxfd,&fds,&timeout);
|
||||
@@ -324,53 +328,54 @@ static void select_loop(ssh_session session,ssh_channel channel){
|
||||
if(FD_ISSET(0,&fds)){
|
||||
lus=read(0,buffer,sizeof(buffer));
|
||||
if(lus)
|
||||
ssh_channel_write(channel,buffer,lus);
|
||||
channel_write(channel,buffer,lus);
|
||||
else {
|
||||
eof=1;
|
||||
ssh_channel_send_eof(channel);
|
||||
channel_send_eof(channel);
|
||||
}
|
||||
}
|
||||
if(channel && ssh_channel_is_closed(channel)){
|
||||
ssh_channel_free(channel);
|
||||
if(channel && channel_is_closed(channel)){
|
||||
ssh_log(session,SSH_LOG_RARE,"exit-status : %d\n",channel_get_exit_status(channel));
|
||||
|
||||
channel_free(channel);
|
||||
channel=NULL;
|
||||
channels[0]=NULL;
|
||||
}
|
||||
if(outchannels[0]){
|
||||
while(channel && ssh_channel_is_open(channel) && (r = ssh_channel_poll(channel,0))!=0){
|
||||
lus=ssh_channel_read(channel,buffer,sizeof(buffer) > r ? r : sizeof(buffer),0);
|
||||
while(channel && channel_is_open(channel) && channel_poll(channel,0)){
|
||||
lus=channel_read(channel,buffer,sizeof(buffer),0);
|
||||
if(lus==-1){
|
||||
fprintf(stderr, "Error reading channel: %s\n",
|
||||
ssh_get_error(session));
|
||||
return;
|
||||
}
|
||||
if(lus==0){
|
||||
ssh_channel_free(channel);
|
||||
ssh_log(session,SSH_LOG_RARE,"EOF received\n");
|
||||
ssh_log(session,SSH_LOG_RARE,"exit-status : %d\n",channel_get_exit_status(channel));
|
||||
|
||||
channel_free(channel);
|
||||
channel=channels[0]=NULL;
|
||||
} else
|
||||
if (write(1,buffer,lus) < 0) {
|
||||
fprintf(stderr, "Error writing to buffer\n");
|
||||
return;
|
||||
}
|
||||
write(1,buffer,lus);
|
||||
}
|
||||
while(channel && ssh_channel_is_open(channel) && (r = ssh_channel_poll(channel,1))!=0){ /* stderr */
|
||||
lus=ssh_channel_read(channel,buffer,sizeof(buffer) > r ? r : sizeof(buffer),1);
|
||||
while(channel && channel_is_open(channel) && channel_poll(channel,1)){ /* stderr */
|
||||
lus=channel_read(channel,buffer,sizeof(buffer),1);
|
||||
if(lus==-1){
|
||||
fprintf(stderr, "Error reading channel: %s\n",
|
||||
ssh_get_error(session));
|
||||
return;
|
||||
}
|
||||
if(lus==0){
|
||||
ssh_channel_free(channel);
|
||||
ssh_log(session,SSH_LOG_RARE,"EOF received\n");
|
||||
ssh_log(session,SSH_LOG_RARE,"exit-status : %d\n",channel_get_exit_status(channel));
|
||||
channel_free(channel);
|
||||
channel=channels[0]=NULL;
|
||||
} else
|
||||
if (write(2,buffer,lus) < 0) {
|
||||
fprintf(stderr, "Error writing to buffer\n");
|
||||
return;
|
||||
}
|
||||
write(2,buffer,lus);
|
||||
}
|
||||
}
|
||||
if(channel && ssh_channel_is_closed(channel)){
|
||||
ssh_channel_free(channel);
|
||||
if(channel && channel_is_closed(channel)){
|
||||
channel_free(channel);
|
||||
channel=NULL;
|
||||
}
|
||||
} while (ret==EINTR || ret==SSH_EINTR);
|
||||
@@ -384,21 +389,21 @@ static void shell(ssh_session session){
|
||||
ssh_channel channel;
|
||||
struct termios terminal_local;
|
||||
int interactive=isatty(0);
|
||||
channel = ssh_channel_new(session);
|
||||
channel = channel_new(session);
|
||||
if(interactive){
|
||||
tcgetattr(0,&terminal_local);
|
||||
memcpy(&terminal,&terminal_local,sizeof(struct termios));
|
||||
}
|
||||
if(ssh_channel_open_session(channel)){
|
||||
if(channel_open_session(channel)){
|
||||
printf("error opening channel : %s\n",ssh_get_error(session));
|
||||
return;
|
||||
}
|
||||
chan=channel;
|
||||
if(interactive){
|
||||
ssh_channel_request_pty(channel);
|
||||
channel_request_pty(channel);
|
||||
sizechanged();
|
||||
}
|
||||
if(ssh_channel_request_shell(channel)){
|
||||
if(channel_request_shell(channel)){
|
||||
printf("Requesting shell : %s\n",ssh_get_error(session));
|
||||
return;
|
||||
}
|
||||
@@ -417,14 +422,11 @@ 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) {
|
||||
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)){
|
||||
channel=channel_new(session);
|
||||
channel_open_session(channel);
|
||||
if(channel_request_exec(channel,buffer)){
|
||||
printf("error executing \"%s\" : %s\n",buffer,ssh_get_error(session));
|
||||
return;
|
||||
}
|
||||
@@ -463,6 +465,7 @@ static int client(ssh_session session){
|
||||
if(auth != SSH_AUTH_SUCCESS){
|
||||
return -1;
|
||||
}
|
||||
ssh_log(session, SSH_LOG_FUNCTIONS, "Authentication success");
|
||||
if(!cmds[0])
|
||||
shell(session);
|
||||
else
|
||||
@@ -470,14 +473,13 @@ static int client(ssh_session session){
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef WITH_PCAP
|
||||
ssh_pcap_file pcap;
|
||||
void set_pcap(ssh_session session);
|
||||
void set_pcap(ssh_session session){
|
||||
if(!pcap_file)
|
||||
return;
|
||||
pcap=ssh_pcap_file_new();
|
||||
if(!pcap)
|
||||
return;
|
||||
if(ssh_pcap_file_open(pcap,pcap_file) == SSH_ERROR){
|
||||
printf("Error opening pcap file\n");
|
||||
ssh_pcap_file_free(pcap);
|
||||
@@ -489,10 +491,10 @@ void set_pcap(ssh_session session){
|
||||
|
||||
void cleanup_pcap(void);
|
||||
void cleanup_pcap(){
|
||||
if(pcap)
|
||||
ssh_pcap_file_free(pcap);
|
||||
ssh_pcap_file_free(pcap);
|
||||
pcap=NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
int main(int argc, char **argv){
|
||||
ssh_session session;
|
||||
@@ -509,13 +511,16 @@ int main(int argc, char **argv){
|
||||
}
|
||||
opts(argc,argv);
|
||||
signal(SIGTERM, do_exit);
|
||||
|
||||
#ifdef WITH_PCAP
|
||||
set_pcap(session);
|
||||
#endif
|
||||
client(session);
|
||||
|
||||
ssh_disconnect(session);
|
||||
ssh_free(session);
|
||||
#ifdef WITH_PCAP
|
||||
cleanup_pcap();
|
||||
#endif
|
||||
|
||||
ssh_finalize();
|
||||
|
||||
|
||||
@@ -15,13 +15,11 @@ clients must be made or how a client should react.
|
||||
|
||||
#include <sys/statvfs.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <libssh/libssh.h>
|
||||
#include <libssh/sftp.h>
|
||||
@@ -29,10 +27,9 @@ clients must be made or how a client should react.
|
||||
#include "examples_common.h"
|
||||
#ifdef WITH_SFTP
|
||||
|
||||
static int verbosity;
|
||||
static char *destination;
|
||||
int verbosity;
|
||||
char *destination;
|
||||
|
||||
#define DATALEN 65536
|
||||
static void do_sftp(ssh_session session){
|
||||
sftp_session sftp=sftp_new(session);
|
||||
sftp_dir dir;
|
||||
@@ -43,7 +40,7 @@ static void do_sftp(ssh_session session){
|
||||
sftp_file to;
|
||||
int len=1;
|
||||
unsigned int i;
|
||||
char data[DATALEN]={0};
|
||||
char data[8000]={0};
|
||||
char *lnk;
|
||||
|
||||
unsigned int count;
|
||||
@@ -205,9 +202,9 @@ static void do_sftp(ssh_session session){
|
||||
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);
|
||||
len=sftp_write(to,data,8000);
|
||||
printf("wrote %d bytes\n",len);
|
||||
if(len != DATALEN){
|
||||
if(len != 8000){
|
||||
printf("chunk %d : %d (%s)\n",i,len,ssh_get_error(session));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,306 +0,0 @@
|
||||
/* This is a sample implementation of a libssh based SSH server */
|
||||
/*
|
||||
Copyright 2003-2009 Aris Adamantiadis
|
||||
|
||||
This file is part of the SSH Library
|
||||
|
||||
You are free to copy this file, modify it in any way, consider it being public
|
||||
domain. This does not apply to the rest of the library though, but it is
|
||||
allowed to cut-and-paste working code from this file to any license of
|
||||
program.
|
||||
The goal is to show the API in action. It's not a reference on how terminal
|
||||
clients must be made or how a client should react.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <libssh/libssh.h>
|
||||
#include <libssh/server.h>
|
||||
#include <libssh/callbacks.h>
|
||||
|
||||
#ifdef HAVE_ARGP_H
|
||||
#include <argp.h>
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifndef KEYS_FOLDER
|
||||
#ifdef _WIN32
|
||||
#define KEYS_FOLDER
|
||||
#else
|
||||
#define KEYS_FOLDER "/etc/ssh/"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define USER "myuser"
|
||||
#define PASSWORD "mypassword"
|
||||
|
||||
static int authenticated=0;
|
||||
static int tries = 0;
|
||||
static int error = 0;
|
||||
static ssh_channel chan=NULL;
|
||||
|
||||
static int auth_password(ssh_session session, const char *user,
|
||||
const char *password, void *userdata){
|
||||
(void)userdata;
|
||||
printf("Authenticating user %s pwd %s\n",user, password);
|
||||
if(strcmp(user,USER) == 0 && strcmp(password, PASSWORD) == 0){
|
||||
authenticated = 1;
|
||||
printf("Authenticated\n");
|
||||
return SSH_AUTH_SUCCESS;
|
||||
}
|
||||
if (tries >= 3){
|
||||
printf("Too many authentication tries\n");
|
||||
ssh_disconnect(session);
|
||||
error = 1;
|
||||
return SSH_AUTH_DENIED;
|
||||
}
|
||||
tries++;
|
||||
return SSH_AUTH_DENIED;
|
||||
}
|
||||
|
||||
static int auth_gssapi_mic(ssh_session session, const char *user, const char *principal, void *userdata){
|
||||
ssh_gssapi_creds creds = ssh_gssapi_get_creds(session);
|
||||
(void)userdata;
|
||||
printf("Authenticating user %s with gssapi principal %s\n",user, principal);
|
||||
if (creds != NULL)
|
||||
printf("Received some gssapi credentials\n");
|
||||
else
|
||||
printf("Not received any forwardable creds\n");
|
||||
printf("authenticated\n");
|
||||
authenticated = 1;
|
||||
return SSH_AUTH_SUCCESS;
|
||||
}
|
||||
|
||||
static int pty_request(ssh_session session, ssh_channel channel, const char *term,
|
||||
int x,int y, int px, int py, void *userdata){
|
||||
(void) session;
|
||||
(void) channel;
|
||||
(void) term;
|
||||
(void) x;
|
||||
(void) y;
|
||||
(void) px;
|
||||
(void) py;
|
||||
(void) userdata;
|
||||
printf("Allocated terminal\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int shell_request(ssh_session session, ssh_channel channel, void *userdata){
|
||||
(void)session;
|
||||
(void)channel;
|
||||
(void)userdata;
|
||||
printf("Allocated shell\n");
|
||||
return 0;
|
||||
}
|
||||
struct ssh_channel_callbacks_struct channel_cb = {
|
||||
.channel_pty_request_function = pty_request,
|
||||
.channel_shell_request_function = shell_request
|
||||
};
|
||||
|
||||
static ssh_channel new_session_channel(ssh_session session, void *userdata){
|
||||
(void) session;
|
||||
(void) userdata;
|
||||
if(chan != NULL)
|
||||
return NULL;
|
||||
printf("Allocated session channel\n");
|
||||
chan = ssh_channel_new(session);
|
||||
ssh_callbacks_init(&channel_cb);
|
||||
ssh_set_channel_callbacks(chan, &channel_cb);
|
||||
return chan;
|
||||
}
|
||||
|
||||
|
||||
#ifdef HAVE_ARGP_H
|
||||
const char *argp_program_version = "libssh server example "
|
||||
SSH_STRINGIFY(LIBSSH_VERSION);
|
||||
const char *argp_program_bug_address = "<libssh@libssh.org>";
|
||||
|
||||
/* Program documentation. */
|
||||
static char doc[] = "libssh -- a Secure Shell protocol implementation";
|
||||
|
||||
/* A description of the arguments we accept. */
|
||||
static char args_doc[] = "BINDADDR";
|
||||
|
||||
/* The options we understand. */
|
||||
static struct argp_option options[] = {
|
||||
{
|
||||
.name = "port",
|
||||
.key = 'p',
|
||||
.arg = "PORT",
|
||||
.flags = 0,
|
||||
.doc = "Set the port to bind.",
|
||||
.group = 0
|
||||
},
|
||||
{
|
||||
.name = "hostkey",
|
||||
.key = 'k',
|
||||
.arg = "FILE",
|
||||
.flags = 0,
|
||||
.doc = "Set the host key.",
|
||||
.group = 0
|
||||
},
|
||||
{
|
||||
.name = "dsakey",
|
||||
.key = 'd',
|
||||
.arg = "FILE",
|
||||
.flags = 0,
|
||||
.doc = "Set the dsa key.",
|
||||
.group = 0
|
||||
},
|
||||
{
|
||||
.name = "rsakey",
|
||||
.key = 'r',
|
||||
.arg = "FILE",
|
||||
.flags = 0,
|
||||
.doc = "Set the rsa key.",
|
||||
.group = 0
|
||||
},
|
||||
{
|
||||
.name = "verbose",
|
||||
.key = 'v',
|
||||
.arg = NULL,
|
||||
.flags = 0,
|
||||
.doc = "Get verbose output.",
|
||||
.group = 0
|
||||
},
|
||||
{NULL, 0, NULL, 0, NULL, 0}
|
||||
};
|
||||
|
||||
/* Parse a single option. */
|
||||
static error_t parse_opt (int key, char *arg, struct argp_state *state) {
|
||||
/* Get the input argument from argp_parse, which we
|
||||
* know is a pointer to our arguments structure.
|
||||
*/
|
||||
ssh_bind sshbind = state->input;
|
||||
|
||||
switch (key) {
|
||||
case 'p':
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_BINDPORT_STR, arg);
|
||||
break;
|
||||
case 'd':
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_DSAKEY, arg);
|
||||
break;
|
||||
case 'k':
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_HOSTKEY, arg);
|
||||
break;
|
||||
case 'r':
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_RSAKEY, arg);
|
||||
break;
|
||||
case 'v':
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_LOG_VERBOSITY_STR, "3");
|
||||
break;
|
||||
case ARGP_KEY_ARG:
|
||||
if (state->arg_num >= 1) {
|
||||
/* Too many arguments. */
|
||||
argp_usage (state);
|
||||
}
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_BINDADDR, arg);
|
||||
break;
|
||||
case ARGP_KEY_END:
|
||||
if (state->arg_num < 1) {
|
||||
/* Not enough arguments. */
|
||||
argp_usage (state);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return ARGP_ERR_UNKNOWN;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Our argp parser. */
|
||||
static struct argp argp = {options, parse_opt, args_doc, doc, NULL, NULL, NULL};
|
||||
#endif /* HAVE_ARGP_H */
|
||||
|
||||
int main(int argc, char **argv){
|
||||
ssh_session session;
|
||||
ssh_bind sshbind;
|
||||
ssh_event mainloop;
|
||||
struct ssh_server_callbacks_struct cb = {
|
||||
.userdata = NULL,
|
||||
.auth_password_function = auth_password,
|
||||
.auth_gssapi_mic_function = auth_gssapi_mic,
|
||||
.channel_open_request_session_function = new_session_channel
|
||||
};
|
||||
|
||||
char buf[2048];
|
||||
int i;
|
||||
int r;
|
||||
|
||||
sshbind=ssh_bind_new();
|
||||
session=ssh_new();
|
||||
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_DSAKEY, KEYS_FOLDER "ssh_host_dsa_key");
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_RSAKEY, KEYS_FOLDER "ssh_host_rsa_key");
|
||||
|
||||
#ifdef HAVE_ARGP_H
|
||||
/*
|
||||
* Parse our arguments; every option seen by parse_opt will
|
||||
* be reflected in arguments.
|
||||
*/
|
||||
argp_parse (&argp, argc, argv, 0, 0, sshbind);
|
||||
#else
|
||||
(void) argc;
|
||||
(void) argv;
|
||||
#endif
|
||||
|
||||
if(ssh_bind_listen(sshbind)<0){
|
||||
printf("Error listening to socket: %s\n",ssh_get_error(sshbind));
|
||||
return 1;
|
||||
}
|
||||
r=ssh_bind_accept(sshbind,session);
|
||||
if(r==SSH_ERROR){
|
||||
printf("error accepting a connection : %s\n",ssh_get_error(sshbind));
|
||||
return 1;
|
||||
}
|
||||
ssh_callbacks_init(&cb);
|
||||
ssh_set_server_callbacks(session, &cb);
|
||||
|
||||
if (ssh_handle_key_exchange(session)) {
|
||||
printf("ssh_handle_key_exchange: %s\n", ssh_get_error(session));
|
||||
return 1;
|
||||
}
|
||||
ssh_set_auth_methods(session,SSH_AUTH_METHOD_PASSWORD | SSH_AUTH_METHOD_GSSAPI_MIC);
|
||||
mainloop = ssh_event_new();
|
||||
ssh_event_add_session(mainloop, session);
|
||||
|
||||
while (!(authenticated && chan != NULL)){
|
||||
if(error)
|
||||
break;
|
||||
r = ssh_event_dopoll(mainloop, -1);
|
||||
if (r == SSH_ERROR){
|
||||
printf("Error : %s\n",ssh_get_error(session));
|
||||
ssh_disconnect(session);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if(error){
|
||||
printf("Error, exiting loop\n");
|
||||
} else
|
||||
printf("Authenticated and got a channel\n");
|
||||
do{
|
||||
i=ssh_channel_read(chan,buf, 2048, 0);
|
||||
if(i>0) {
|
||||
ssh_channel_write(chan, buf, i);
|
||||
if (write(1,buf,i) < 0) {
|
||||
printf("error writing to buffer\n");
|
||||
return 1;
|
||||
}
|
||||
if (buf[0] == '\x0d') {
|
||||
if (write(1, "\n", 1) < 0) {
|
||||
printf("error writing to buffer\n");
|
||||
return 1;
|
||||
}
|
||||
ssh_channel_write(chan, "\n", 1);
|
||||
}
|
||||
}
|
||||
} while (i>0);
|
||||
ssh_disconnect(session);
|
||||
ssh_bind_free(sshbind);
|
||||
ssh_finalize();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,413 +0,0 @@
|
||||
/* This is a sample implementation of a libssh based SSH server */
|
||||
/*
|
||||
Copyright 2003-2011 Aris Adamantiadis
|
||||
|
||||
This file is part of the SSH Library
|
||||
|
||||
You are free to copy this file, modify it in any way, consider it being public
|
||||
domain. This does not apply to the rest of the library though, but it is
|
||||
allowed to cut-and-paste working code from this file to any license of
|
||||
program.
|
||||
The goal is to show the API in action. It's not a reference on how terminal
|
||||
clients must be made or how a client should react.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <libssh/libssh.h>
|
||||
#include <libssh/server.h>
|
||||
|
||||
#ifdef HAVE_ARGP_H
|
||||
#include <argp.h>
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define SSHD_USER "libssh"
|
||||
#define SSHD_PASSWORD "libssh"
|
||||
|
||||
#ifndef KEYS_FOLDER
|
||||
#ifdef _WIN32
|
||||
#define KEYS_FOLDER
|
||||
#else
|
||||
#define KEYS_FOLDER "/etc/ssh/"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static int port = 22;
|
||||
|
||||
#ifdef WITH_PCAP
|
||||
static const char *pcap_file = "debug.server.pcap";
|
||||
static ssh_pcap_file pcap;
|
||||
|
||||
static void set_pcap(ssh_session session){
|
||||
if(!pcap_file)
|
||||
return;
|
||||
pcap=ssh_pcap_file_new();
|
||||
if(ssh_pcap_file_open(pcap,pcap_file) == SSH_ERROR){
|
||||
printf("Error opening pcap file\n");
|
||||
ssh_pcap_file_free(pcap);
|
||||
pcap=NULL;
|
||||
return;
|
||||
}
|
||||
ssh_set_pcap_file(session,pcap);
|
||||
}
|
||||
|
||||
static void cleanup_pcap(void) {
|
||||
ssh_pcap_file_free(pcap);
|
||||
pcap=NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static int auth_password(const char *user, const char *password){
|
||||
if(strcmp(user, SSHD_USER))
|
||||
return 0;
|
||||
if(strcmp(password, SSHD_PASSWORD))
|
||||
return 0;
|
||||
return 1; // authenticated
|
||||
}
|
||||
#ifdef HAVE_ARGP_H
|
||||
const char *argp_program_version = "libssh server example "
|
||||
SSH_STRINGIFY(LIBSSH_VERSION);
|
||||
const char *argp_program_bug_address = "<libssh@libssh.org>";
|
||||
|
||||
/* Program documentation. */
|
||||
static char doc[] = "libssh -- a Secure Shell protocol implementation";
|
||||
|
||||
/* A description of the arguments we accept. */
|
||||
static char args_doc[] = "BINDADDR";
|
||||
|
||||
/* The options we understand. */
|
||||
static struct argp_option options[] = {
|
||||
{
|
||||
.name = "port",
|
||||
.key = 'p',
|
||||
.arg = "PORT",
|
||||
.flags = 0,
|
||||
.doc = "Set the port to bind.",
|
||||
.group = 0
|
||||
},
|
||||
{
|
||||
.name = "hostkey",
|
||||
.key = 'k',
|
||||
.arg = "FILE",
|
||||
.flags = 0,
|
||||
.doc = "Set the host key.",
|
||||
.group = 0
|
||||
},
|
||||
{
|
||||
.name = "dsakey",
|
||||
.key = 'd',
|
||||
.arg = "FILE",
|
||||
.flags = 0,
|
||||
.doc = "Set the dsa key.",
|
||||
.group = 0
|
||||
},
|
||||
{
|
||||
.name = "rsakey",
|
||||
.key = 'r',
|
||||
.arg = "FILE",
|
||||
.flags = 0,
|
||||
.doc = "Set the rsa key.",
|
||||
.group = 0
|
||||
},
|
||||
{
|
||||
.name = "verbose",
|
||||
.key = 'v',
|
||||
.arg = NULL,
|
||||
.flags = 0,
|
||||
.doc = "Get verbose output.",
|
||||
.group = 0
|
||||
},
|
||||
{NULL, 0, 0, 0, NULL, 0}
|
||||
};
|
||||
|
||||
/* Parse a single option. */
|
||||
static error_t parse_opt (int key, char *arg, struct argp_state *state) {
|
||||
/* Get the input argument from argp_parse, which we
|
||||
* know is a pointer to our arguments structure.
|
||||
*/
|
||||
ssh_bind sshbind = state->input;
|
||||
|
||||
switch (key) {
|
||||
case 'p':
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_BINDPORT_STR, arg);
|
||||
port = atoi(arg);
|
||||
break;
|
||||
case 'd':
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_DSAKEY, arg);
|
||||
break;
|
||||
case 'k':
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_HOSTKEY, arg);
|
||||
break;
|
||||
case 'r':
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_RSAKEY, arg);
|
||||
break;
|
||||
case 'v':
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_LOG_VERBOSITY_STR, "3");
|
||||
break;
|
||||
case ARGP_KEY_ARG:
|
||||
if (state->arg_num >= 1) {
|
||||
/* Too many arguments. */
|
||||
argp_usage (state);
|
||||
}
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_BINDADDR, arg);
|
||||
break;
|
||||
case ARGP_KEY_END:
|
||||
if (state->arg_num < 1) {
|
||||
/* Not enough arguments. */
|
||||
argp_usage (state);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return ARGP_ERR_UNKNOWN;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Our argp parser. */
|
||||
static struct argp argp = {options, parse_opt, args_doc, doc, NULL, NULL, NULL};
|
||||
#endif /* HAVE_ARGP_H */
|
||||
|
||||
static const char *name;
|
||||
static const char *instruction;
|
||||
static const char *prompts[2];
|
||||
static char echo[] = { 1, 0 };
|
||||
|
||||
static int kbdint_check_response(ssh_session session) {
|
||||
int count;
|
||||
|
||||
count = ssh_userauth_kbdint_getnanswers(session);
|
||||
if(count != 2) {
|
||||
instruction = "Something weird happened :(";
|
||||
return 0;
|
||||
}
|
||||
if(strcasecmp("Arthur Dent",
|
||||
ssh_userauth_kbdint_getanswer(session, 0)) != 0) {
|
||||
instruction = "OK, this is not YOUR name, "
|
||||
"but it's a reference to the HGTG...";
|
||||
prompts[0] = "The main character's full name: ";
|
||||
return 0;
|
||||
}
|
||||
if(strcmp("42", ssh_userauth_kbdint_getanswer(session, 1)) != 0) {
|
||||
instruction = "Make an effort !!! What is the Answer to the Ultimate "
|
||||
"Question of Life, the Universe, and Everything ?";
|
||||
prompts[1] = "Answer to the Ultimate Question of Life, the Universe, "
|
||||
"and Everything: ";
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int authenticate(ssh_session session) {
|
||||
ssh_message message;
|
||||
|
||||
name = "\n\nKeyboard-Interactive Fancy Authentication\n";
|
||||
instruction = "Please enter your real name and your password";
|
||||
prompts[0] = "Real name: ";
|
||||
prompts[1] = "Password: ";
|
||||
|
||||
do {
|
||||
message=ssh_message_get(session);
|
||||
if(!message)
|
||||
break;
|
||||
switch(ssh_message_type(message)){
|
||||
case SSH_REQUEST_AUTH:
|
||||
switch(ssh_message_subtype(message)){
|
||||
case SSH_AUTH_METHOD_PASSWORD:
|
||||
printf("User %s wants to auth with pass %s\n",
|
||||
ssh_message_auth_user(message),
|
||||
ssh_message_auth_password(message));
|
||||
if(auth_password(ssh_message_auth_user(message),
|
||||
ssh_message_auth_password(message))){
|
||||
ssh_message_auth_reply_success(message,0);
|
||||
ssh_message_free(message);
|
||||
return 1;
|
||||
}
|
||||
ssh_message_auth_set_methods(message,
|
||||
SSH_AUTH_METHOD_PASSWORD |
|
||||
SSH_AUTH_METHOD_INTERACTIVE);
|
||||
// not authenticated, send default message
|
||||
ssh_message_reply_default(message);
|
||||
break;
|
||||
|
||||
case SSH_AUTH_METHOD_INTERACTIVE:
|
||||
if(!ssh_message_auth_kbdint_is_response(message)) {
|
||||
printf("User %s wants to auth with kbdint\n",
|
||||
ssh_message_auth_user(message));
|
||||
ssh_message_auth_interactive_request(message, name,
|
||||
instruction, 2, prompts, echo);
|
||||
} else {
|
||||
if(kbdint_check_response(session)) {
|
||||
ssh_message_auth_reply_success(message,0);
|
||||
ssh_message_free(message);
|
||||
return 1;
|
||||
}
|
||||
ssh_message_auth_set_methods(message,
|
||||
SSH_AUTH_METHOD_PASSWORD |
|
||||
SSH_AUTH_METHOD_INTERACTIVE);
|
||||
ssh_message_reply_default(message);
|
||||
}
|
||||
break;
|
||||
case SSH_AUTH_METHOD_NONE:
|
||||
default:
|
||||
printf("User %s wants to auth with unknown auth %d\n",
|
||||
ssh_message_auth_user(message),
|
||||
ssh_message_subtype(message));
|
||||
ssh_message_auth_set_methods(message,
|
||||
SSH_AUTH_METHOD_PASSWORD |
|
||||
SSH_AUTH_METHOD_INTERACTIVE);
|
||||
ssh_message_reply_default(message);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ssh_message_auth_set_methods(message,
|
||||
SSH_AUTH_METHOD_PASSWORD |
|
||||
SSH_AUTH_METHOD_INTERACTIVE);
|
||||
ssh_message_reply_default(message);
|
||||
}
|
||||
ssh_message_free(message);
|
||||
} while (1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv){
|
||||
ssh_session session;
|
||||
ssh_bind sshbind;
|
||||
ssh_message message;
|
||||
ssh_channel chan=0;
|
||||
char buf[2048];
|
||||
int auth=0;
|
||||
int shell=0;
|
||||
int i;
|
||||
int r;
|
||||
|
||||
sshbind=ssh_bind_new();
|
||||
session=ssh_new();
|
||||
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_DSAKEY,
|
||||
KEYS_FOLDER "ssh_host_dsa_key");
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_RSAKEY,
|
||||
KEYS_FOLDER "ssh_host_rsa_key");
|
||||
|
||||
#ifdef HAVE_ARGP_H
|
||||
/*
|
||||
* Parse our arguments; every option seen by parse_opt will
|
||||
* be reflected in arguments.
|
||||
*/
|
||||
argp_parse (&argp, argc, argv, 0, 0, sshbind);
|
||||
#else
|
||||
(void) argc;
|
||||
(void) argv;
|
||||
#endif
|
||||
#ifdef WITH_PCAP
|
||||
set_pcap(session);
|
||||
#endif
|
||||
|
||||
if(ssh_bind_listen(sshbind)<0){
|
||||
printf("Error listening to socket: %s\n", ssh_get_error(sshbind));
|
||||
return 1;
|
||||
}
|
||||
printf("Started sample libssh sshd on port %d\n", port);
|
||||
printf("You can login as the user %s with the password %s\n", SSHD_USER,
|
||||
SSHD_PASSWORD);
|
||||
r = ssh_bind_accept(sshbind, session);
|
||||
if(r==SSH_ERROR){
|
||||
printf("Error accepting a connection: %s\n", ssh_get_error(sshbind));
|
||||
return 1;
|
||||
}
|
||||
if (ssh_handle_key_exchange(session)) {
|
||||
printf("ssh_handle_key_exchange: %s\n", ssh_get_error(session));
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* proceed to authentication */
|
||||
auth = authenticate(session);
|
||||
if(!auth){
|
||||
printf("Authentication error: %s\n", ssh_get_error(session));
|
||||
ssh_disconnect(session);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* wait for a channel session */
|
||||
do {
|
||||
message = ssh_message_get(session);
|
||||
if(message){
|
||||
if(ssh_message_type(message) == SSH_REQUEST_CHANNEL_OPEN &&
|
||||
ssh_message_subtype(message) == SSH_CHANNEL_SESSION) {
|
||||
chan = ssh_message_channel_request_open_reply_accept(message);
|
||||
ssh_message_free(message);
|
||||
break;
|
||||
} else {
|
||||
ssh_message_reply_default(message);
|
||||
ssh_message_free(message);
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
} while(!chan);
|
||||
|
||||
if(!chan) {
|
||||
printf("Error: cleint did not ask for a channel session (%s)\n",
|
||||
ssh_get_error(session));
|
||||
ssh_finalize();
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* wait for a shell */
|
||||
do {
|
||||
message = ssh_message_get(session);
|
||||
if(message != NULL) {
|
||||
if(ssh_message_type(message) == SSH_REQUEST_CHANNEL &&
|
||||
ssh_message_subtype(message) == SSH_CHANNEL_REQUEST_SHELL) {
|
||||
shell = 1;
|
||||
ssh_message_channel_request_reply_success(message);
|
||||
ssh_message_free(message);
|
||||
break;
|
||||
}
|
||||
ssh_message_reply_default(message);
|
||||
ssh_message_free(message);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
} while(!shell);
|
||||
|
||||
if(!shell) {
|
||||
printf("Error: No shell requested (%s)\n", ssh_get_error(session));
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
printf("it works !\n");
|
||||
do{
|
||||
i=ssh_channel_read(chan,buf, 2048, 0);
|
||||
if(i>0) {
|
||||
if(*buf == '' || *buf == '')
|
||||
break;
|
||||
if(i == 1 && *buf == '\r')
|
||||
ssh_channel_write(chan, "\r\n", 2);
|
||||
else
|
||||
ssh_channel_write(chan, buf, i);
|
||||
if (write(1,buf,i) < 0) {
|
||||
printf("error writing to buffer\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
} while (i>0);
|
||||
ssh_channel_close(chan);
|
||||
ssh_disconnect(session);
|
||||
ssh_bind_free(sshbind);
|
||||
#ifdef WITH_PCAP
|
||||
cleanup_pcap();
|
||||
#endif
|
||||
ssh_finalize();
|
||||
return 0;
|
||||
}
|
||||
|
||||
269
examples/samplesshd.c
Normal file
269
examples/samplesshd.c
Normal file
@@ -0,0 +1,269 @@
|
||||
/* This is a sample implementation of a libssh based SSH server */
|
||||
/*
|
||||
Copyright 2003-2009 Aris Adamantiadis
|
||||
|
||||
This file is part of the SSH Library
|
||||
|
||||
You are free to copy this file, modify it in any way, consider it being public
|
||||
domain. This does not apply to the rest of the library though, but it is
|
||||
allowed to cut-and-paste working code from this file to any license of
|
||||
program.
|
||||
The goal is to show the API in action. It's not a reference on how terminal
|
||||
clients must be made or how a client should react.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <libssh/libssh.h>
|
||||
#include <libssh/server.h>
|
||||
|
||||
#ifdef HAVE_ARGP_H
|
||||
#include <argp.h>
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#ifndef KEYS_FOLDER
|
||||
#ifdef _WIN32
|
||||
#define KEYS_FOLDER
|
||||
#else
|
||||
#define KEYS_FOLDER "/etc/ssh/"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static int auth_password(char *user, char *password){
|
||||
if(strcmp(user,"aris"))
|
||||
return 0;
|
||||
if(strcmp(password,"lala"))
|
||||
return 0;
|
||||
return 1; // authenticated
|
||||
}
|
||||
#ifdef HAVE_ARGP_H
|
||||
const char *argp_program_version = "libssh server example "
|
||||
SSH_STRINGIFY(LIBSSH_VERSION);
|
||||
const char *argp_program_bug_address = "<libssh@libssh.org>";
|
||||
|
||||
/* Program documentation. */
|
||||
static char doc[] = "libssh -- a Secure Shell protocol implementation";
|
||||
|
||||
/* A description of the arguments we accept. */
|
||||
static char args_doc[] = "BINDADDR";
|
||||
|
||||
/* The options we understand. */
|
||||
static struct argp_option options[] = {
|
||||
{
|
||||
.name = "port",
|
||||
.key = 'p',
|
||||
.arg = "PORT",
|
||||
.flags = 0,
|
||||
.doc = "Set the port to bind.",
|
||||
.group = 0
|
||||
},
|
||||
{
|
||||
.name = "hostkey",
|
||||
.key = 'k',
|
||||
.arg = "FILE",
|
||||
.flags = 0,
|
||||
.doc = "Set the host key.",
|
||||
.group = 0
|
||||
},
|
||||
{
|
||||
.name = "dsakey",
|
||||
.key = 'd',
|
||||
.arg = "FILE",
|
||||
.flags = 0,
|
||||
.doc = "Set the dsa key.",
|
||||
.group = 0
|
||||
},
|
||||
{
|
||||
.name = "rsakey",
|
||||
.key = 'r',
|
||||
.arg = "FILE",
|
||||
.flags = 0,
|
||||
.doc = "Set the rsa key.",
|
||||
.group = 0
|
||||
},
|
||||
{
|
||||
.name = "verbose",
|
||||
.key = 'v',
|
||||
.arg = NULL,
|
||||
.flags = 0,
|
||||
.doc = "Get verbose output.",
|
||||
.group = 0
|
||||
},
|
||||
{NULL, 0, 0, 0, NULL, 0}
|
||||
};
|
||||
|
||||
/* Parse a single option. */
|
||||
static error_t parse_opt (int key, char *arg, struct argp_state *state) {
|
||||
/* Get the input argument from argp_parse, which we
|
||||
* know is a pointer to our arguments structure.
|
||||
*/
|
||||
ssh_bind sshbind = state->input;
|
||||
|
||||
switch (key) {
|
||||
case 'p':
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_BINDPORT_STR, arg);
|
||||
break;
|
||||
case 'd':
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_DSAKEY, arg);
|
||||
break;
|
||||
case 'k':
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_HOSTKEY, arg);
|
||||
break;
|
||||
case 'r':
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_RSAKEY, arg);
|
||||
break;
|
||||
case 'v':
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_LOG_VERBOSITY_STR, "3");
|
||||
break;
|
||||
case ARGP_KEY_ARG:
|
||||
if (state->arg_num >= 1) {
|
||||
/* Too many arguments. */
|
||||
argp_usage (state);
|
||||
}
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_BINDADDR, arg);
|
||||
break;
|
||||
case ARGP_KEY_END:
|
||||
if (state->arg_num < 1) {
|
||||
/* Not enough arguments. */
|
||||
argp_usage (state);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return ARGP_ERR_UNKNOWN;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Our argp parser. */
|
||||
static struct argp argp = {options, parse_opt, args_doc, doc, NULL, NULL, NULL};
|
||||
#endif /* HAVE_ARGP_H */
|
||||
|
||||
int main(int argc, char **argv){
|
||||
ssh_session session;
|
||||
ssh_bind sshbind;
|
||||
ssh_message message;
|
||||
ssh_channel chan=0;
|
||||
ssh_buffer buf;
|
||||
int auth=0;
|
||||
int sftp=0;
|
||||
int i;
|
||||
int r;
|
||||
|
||||
sshbind=ssh_bind_new();
|
||||
session=ssh_new();
|
||||
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_DSAKEY, KEYS_FOLDER "ssh_host_dsa_key");
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_RSAKEY, KEYS_FOLDER "ssh_host_rsa_key");
|
||||
|
||||
#ifdef HAVE_ARGP_H
|
||||
/*
|
||||
* Parse our arguments; every option seen by parse_opt will
|
||||
* be reflected in arguments.
|
||||
*/
|
||||
argp_parse (&argp, argc, argv, 0, 0, sshbind);
|
||||
#endif
|
||||
if(ssh_bind_listen(sshbind)<0){
|
||||
printf("Error listening to socket: %s\n",ssh_get_error(sshbind));
|
||||
return 1;
|
||||
}
|
||||
r=ssh_bind_accept(sshbind,session);
|
||||
if(r==SSH_ERROR){
|
||||
printf("error accepting a connection : %s\n",ssh_get_error(sshbind));
|
||||
return 1;
|
||||
}
|
||||
if(ssh_accept(session)){
|
||||
printf("ssh_accept: %s\n",ssh_get_error(session));
|
||||
return 1;
|
||||
}
|
||||
do {
|
||||
message=ssh_message_get(session);
|
||||
if(!message)
|
||||
break;
|
||||
switch(ssh_message_type(message)){
|
||||
case SSH_REQUEST_AUTH:
|
||||
switch(ssh_message_subtype(message)){
|
||||
case SSH_AUTH_METHOD_PASSWORD:
|
||||
printf("User %s wants to auth with pass %s\n",
|
||||
ssh_message_auth_user(message),
|
||||
ssh_message_auth_password(message));
|
||||
if(auth_password(ssh_message_auth_user(message),
|
||||
ssh_message_auth_password(message))){
|
||||
auth=1;
|
||||
ssh_message_auth_reply_success(message,0);
|
||||
break;
|
||||
}
|
||||
// not authenticated, send default message
|
||||
case SSH_AUTH_METHOD_NONE:
|
||||
default:
|
||||
ssh_message_auth_set_methods(message,SSH_AUTH_METHOD_PASSWORD);
|
||||
ssh_message_reply_default(message);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ssh_message_reply_default(message);
|
||||
}
|
||||
ssh_message_free(message);
|
||||
} while (!auth);
|
||||
if(!auth){
|
||||
printf("auth error: %s\n",ssh_get_error(session));
|
||||
ssh_disconnect(session);
|
||||
return 1;
|
||||
}
|
||||
do {
|
||||
message=ssh_message_get(session);
|
||||
if(message){
|
||||
switch(ssh_message_type(message)){
|
||||
case SSH_REQUEST_CHANNEL_OPEN:
|
||||
if(ssh_message_subtype(message)==SSH_CHANNEL_SESSION){
|
||||
chan=ssh_message_channel_request_open_reply_accept(message);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
ssh_message_reply_default(message);
|
||||
}
|
||||
ssh_message_free(message);
|
||||
}
|
||||
} while(message && !chan);
|
||||
if(!chan){
|
||||
printf("error : %s\n",ssh_get_error(session));
|
||||
ssh_finalize();
|
||||
return 1;
|
||||
}
|
||||
do {
|
||||
message=ssh_message_get(session);
|
||||
if(message && ssh_message_type(message)==SSH_REQUEST_CHANNEL &&
|
||||
ssh_message_subtype(message)==SSH_CHANNEL_REQUEST_SHELL){
|
||||
// if(!strcmp(ssh_message_channel_request_subsystem(message),"sftp")){
|
||||
sftp=1;
|
||||
ssh_message_channel_request_reply_success(message);
|
||||
break;
|
||||
// }
|
||||
}
|
||||
if(!sftp){
|
||||
ssh_message_reply_default(message);
|
||||
}
|
||||
ssh_message_free(message);
|
||||
} while (message && !sftp);
|
||||
if(!sftp){
|
||||
printf("error : %s\n",ssh_get_error(session));
|
||||
return 1;
|
||||
}
|
||||
printf("it works !\n");
|
||||
buf=buffer_new();
|
||||
do{
|
||||
i=channel_read_buffer(chan,buf,0,0);
|
||||
if(i>0)
|
||||
write(1,buffer_get(buf),buffer_get_len(buf));
|
||||
} while (i>0);
|
||||
buffer_free(buf);
|
||||
ssh_disconnect(session);
|
||||
ssh_bind_free(sshbind);
|
||||
ssh_finalize();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -56,44 +56,26 @@ static int opts(int argc, char **argv){
|
||||
}
|
||||
|
||||
static void create_files(ssh_session session){
|
||||
ssh_channel channel=ssh_channel_new(session);
|
||||
ssh_channel channel=channel_new(session);
|
||||
char buffer[1];
|
||||
int rc;
|
||||
|
||||
if(channel == NULL){
|
||||
fprintf(stderr,"Error creating channel: %s\n",ssh_get_error(session));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if(ssh_channel_open_session(channel) != SSH_OK){
|
||||
if(channel_open_session(channel) != SSH_OK){
|
||||
fprintf(stderr,"Error creating channel: %s\n",ssh_get_error(session));
|
||||
ssh_channel_free(channel);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if(ssh_channel_request_exec(channel,createcommand) != SSH_OK){
|
||||
if(channel_request_exec(channel,createcommand) != SSH_OK){
|
||||
fprintf(stderr,"Error executing command: %s\n",ssh_get_error(session));
|
||||
ssh_channel_close(channel);
|
||||
ssh_channel_free(channel);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
while(!ssh_channel_is_eof(channel)){
|
||||
rc = ssh_channel_read(channel,buffer,1,1);
|
||||
if (rc != 1) {
|
||||
fprintf(stderr, "Error reading from channel\n");
|
||||
ssh_channel_close(channel);
|
||||
ssh_channel_free(channel);
|
||||
return;
|
||||
}
|
||||
|
||||
rc = write(1, buffer, 1);
|
||||
if (rc < 0) {
|
||||
fprintf(stderr, "Error writing to buffer\n");
|
||||
ssh_channel_close(channel);
|
||||
ssh_channel_free(channel);
|
||||
return;
|
||||
}
|
||||
while(!channel_is_eof(channel)){
|
||||
channel_read(channel,buffer,1,1);
|
||||
write(1,buffer,1);
|
||||
}
|
||||
ssh_channel_close(channel);
|
||||
ssh_channel_free(channel);
|
||||
channel_close(channel);
|
||||
channel_free(channel);
|
||||
}
|
||||
|
||||
|
||||
@@ -106,7 +88,6 @@ static int fetch_files(ssh_session session){
|
||||
ssh_scp scp=ssh_scp_new(session, SSH_SCP_READ | SSH_SCP_RECURSIVE, "/tmp/libssh_tests/*");
|
||||
if(ssh_scp_init(scp) != SSH_OK){
|
||||
fprintf(stderr,"error initializing scp: %s\n",ssh_get_error(session));
|
||||
ssh_scp_free(scp);
|
||||
return -1;
|
||||
}
|
||||
printf("Trying to download 3 files (a,b,d) and 1 directory (c)\n");
|
||||
@@ -124,16 +105,12 @@ static int fetch_files(ssh_session session){
|
||||
r=ssh_scp_read(scp,buffer,sizeof(buffer));
|
||||
if(r==SSH_ERROR){
|
||||
fprintf(stderr,"Error reading scp: %s\n",ssh_get_error(session));
|
||||
ssh_scp_close(scp);
|
||||
ssh_scp_free(scp);
|
||||
return -1;
|
||||
}
|
||||
printf("done\n");
|
||||
break;
|
||||
case SSH_ERROR:
|
||||
fprintf(stderr,"Error: %s\n",ssh_get_error(session));
|
||||
ssh_scp_close(scp);
|
||||
ssh_scp_free(scp);
|
||||
return -1;
|
||||
case SSH_SCP_REQUEST_WARNING:
|
||||
fprintf(stderr,"Warning: %s\n",ssh_scp_request_get_warning(scp));
|
||||
@@ -154,8 +131,6 @@ static int fetch_files(ssh_session session){
|
||||
}
|
||||
} while (1);
|
||||
end:
|
||||
ssh_scp_close(scp);
|
||||
ssh_scp_free(scp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -169,7 +144,6 @@ int main(int argc, char **argv){
|
||||
create_files(session);
|
||||
fetch_files(session);
|
||||
ssh_disconnect(session);
|
||||
ssh_free(session);
|
||||
ssh_finalize();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,64 +0,0 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include <libssh/libssh.h>
|
||||
#include "examples_common.h"
|
||||
|
||||
#define LIMIT 0x100000000
|
||||
|
||||
int main(void) {
|
||||
ssh_session session;
|
||||
ssh_channel channel;
|
||||
char buffer[1024*1024];
|
||||
int rc;
|
||||
uint64_t total=0;
|
||||
uint64_t lastshown=4096;
|
||||
session = connect_ssh("localhost", NULL, 0);
|
||||
if (session == NULL) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
channel = ssh_channel_new(session);;
|
||||
if (channel == NULL) {
|
||||
ssh_disconnect(session);
|
||||
return 1;
|
||||
}
|
||||
|
||||
rc = ssh_channel_open_session(channel);
|
||||
if (rc < 0) {
|
||||
ssh_channel_close(channel);
|
||||
ssh_disconnect(session);
|
||||
return 1;
|
||||
}
|
||||
|
||||
rc = ssh_channel_request_exec(channel, "cat > /dev/null");
|
||||
if (rc < 0) {
|
||||
ssh_channel_close(channel);
|
||||
ssh_disconnect(session);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
while ((rc = ssh_channel_write(channel, buffer, sizeof(buffer))) > 0) {
|
||||
total += rc;
|
||||
if(total/2 >= lastshown){
|
||||
printf("written %llx\n", (long long unsigned int) total);
|
||||
lastshown=total;
|
||||
}
|
||||
if(total > LIMIT)
|
||||
break;
|
||||
}
|
||||
|
||||
if (rc < 0) {
|
||||
printf("error : %s\n",ssh_get_error(session));
|
||||
ssh_channel_close(channel);
|
||||
ssh_disconnect(session);
|
||||
return 1;
|
||||
}
|
||||
|
||||
ssh_channel_send_eof(channel);
|
||||
ssh_channel_close(channel);
|
||||
|
||||
ssh_disconnect(session);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,697 +0,0 @@
|
||||
/* This is a sample implementation of a libssh based SSH server */
|
||||
/*
|
||||
Copyright 2014 Audrius Butkevicius
|
||||
|
||||
This file is part of the SSH Library
|
||||
|
||||
You are free to copy this file, modify it in any way, consider it being public
|
||||
domain. This does not apply to the rest of the library though, but it is
|
||||
allowed to cut-and-paste working code from this file to any license of
|
||||
program.
|
||||
The goal is to show the API in action.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <libssh/callbacks.h>
|
||||
#include <libssh/poll.h>
|
||||
#include <libssh/server.h>
|
||||
|
||||
#ifdef HAVE_ARGP_H
|
||||
#include <argp.h>
|
||||
#endif
|
||||
#include <fcntl.h>
|
||||
#ifdef HAVE_LIBUTIL_H
|
||||
#include <libutil.h>
|
||||
#endif
|
||||
#ifdef HAVE_PTY_H
|
||||
#include <pty.h>
|
||||
#endif
|
||||
#include <signal.h>
|
||||
#include <stdlib.h>
|
||||
#ifdef HAVE_UTMP_H
|
||||
#include <utmp.h>
|
||||
#endif
|
||||
#ifdef HAVE_UTIL_H
|
||||
#include <util.h>
|
||||
#endif
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/wait.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifndef KEYS_FOLDER
|
||||
#ifdef _WIN32
|
||||
#define KEYS_FOLDER
|
||||
#else
|
||||
#define KEYS_FOLDER "/etc/ssh/"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define USER "myuser"
|
||||
#define PASS "mypassword"
|
||||
#define BUF_SIZE 1048576
|
||||
#define SESSION_END (SSH_CLOSED | SSH_CLOSED_ERROR)
|
||||
#define SFTP_SERVER_PATH "/usr/lib/sftp-server"
|
||||
|
||||
static void set_default_keys(ssh_bind sshbind,
|
||||
int rsa_already_set,
|
||||
int dsa_already_set,
|
||||
int ecdsa_already_set) {
|
||||
if (!rsa_already_set) {
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_RSAKEY,
|
||||
KEYS_FOLDER "ssh_host_rsa_key");
|
||||
}
|
||||
if (!dsa_already_set) {
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_DSAKEY,
|
||||
KEYS_FOLDER "ssh_host_dsa_key");
|
||||
}
|
||||
if (!ecdsa_already_set) {
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_ECDSAKEY,
|
||||
KEYS_FOLDER "ssh_host_ecdsa_key");
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_ARGP_H
|
||||
const char *argp_program_version = "libssh server example "
|
||||
SSH_STRINGIFY(LIBSSH_VERSION);
|
||||
const char *argp_program_bug_address = "<libssh@libssh.org>";
|
||||
|
||||
/* Program documentation. */
|
||||
static char doc[] = "libssh -- a Secure Shell protocol implementation";
|
||||
|
||||
/* A description of the arguments we accept. */
|
||||
static char args_doc[] = "BINDADDR";
|
||||
|
||||
/* The options we understand. */
|
||||
static struct argp_option options[] = {
|
||||
{
|
||||
.name = "port",
|
||||
.key = 'p',
|
||||
.arg = "PORT",
|
||||
.flags = 0,
|
||||
.doc = "Set the port to bind.",
|
||||
.group = 0
|
||||
},
|
||||
{
|
||||
.name = "hostkey",
|
||||
.key = 'k',
|
||||
.arg = "FILE",
|
||||
.flags = 0,
|
||||
.doc = "Set a host key. Can be used multiple times. "
|
||||
"Implies no default keys.",
|
||||
.group = 0
|
||||
},
|
||||
{
|
||||
.name = "dsakey",
|
||||
.key = 'd',
|
||||
.arg = "FILE",
|
||||
.flags = 0,
|
||||
.doc = "Set the dsa key.",
|
||||
.group = 0
|
||||
},
|
||||
{
|
||||
.name = "rsakey",
|
||||
.key = 'r',
|
||||
.arg = "FILE",
|
||||
.flags = 0,
|
||||
.doc = "Set the rsa key.",
|
||||
.group = 0
|
||||
},
|
||||
{
|
||||
.name = "ecdsakey",
|
||||
.key = 'e',
|
||||
.arg = "FILE",
|
||||
.flags = 0,
|
||||
.doc = "Set the ecdsa key.",
|
||||
.group = 0
|
||||
},
|
||||
{
|
||||
.name = "no-default-keys",
|
||||
.key = 'n',
|
||||
.arg = NULL,
|
||||
.flags = 0,
|
||||
.doc = "Do not set default key locations.",
|
||||
.group = 0
|
||||
},
|
||||
{
|
||||
.name = "verbose",
|
||||
.key = 'v',
|
||||
.arg = NULL,
|
||||
.flags = 0,
|
||||
.doc = "Get verbose output.",
|
||||
.group = 0
|
||||
},
|
||||
{NULL, 0, NULL, 0, NULL, 0}
|
||||
};
|
||||
|
||||
/* Parse a single option. */
|
||||
static error_t parse_opt (int key, char *arg, struct argp_state *state) {
|
||||
/* Get the input argument from argp_parse, which we
|
||||
* know is a pointer to our arguments structure. */
|
||||
ssh_bind sshbind = state->input;
|
||||
static int no_default_keys = 0;
|
||||
static int rsa_already_set = 0, dsa_already_set = 0, ecdsa_already_set = 0;
|
||||
|
||||
switch (key) {
|
||||
case 'n':
|
||||
no_default_keys = 1;
|
||||
break;
|
||||
case 'p':
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_BINDPORT_STR, arg);
|
||||
break;
|
||||
case 'd':
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_DSAKEY, arg);
|
||||
dsa_already_set = 1;
|
||||
break;
|
||||
case 'k':
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_HOSTKEY, arg);
|
||||
/* We can't track the types of keys being added with this
|
||||
option, so let's ensure we keep the keys we're adding
|
||||
by just not setting the default keys */
|
||||
no_default_keys = 1;
|
||||
break;
|
||||
case 'r':
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_RSAKEY, arg);
|
||||
rsa_already_set = 1;
|
||||
break;
|
||||
case 'e':
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_ECDSAKEY, arg);
|
||||
ecdsa_already_set = 1;
|
||||
break;
|
||||
case 'v':
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_LOG_VERBOSITY_STR,
|
||||
"3");
|
||||
break;
|
||||
case ARGP_KEY_ARG:
|
||||
if (state->arg_num >= 1) {
|
||||
/* Too many arguments. */
|
||||
argp_usage (state);
|
||||
}
|
||||
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_BINDADDR, arg);
|
||||
break;
|
||||
case ARGP_KEY_END:
|
||||
if (state->arg_num < 1) {
|
||||
/* Not enough arguments. */
|
||||
argp_usage (state);
|
||||
}
|
||||
|
||||
if (!no_default_keys) {
|
||||
set_default_keys(sshbind,
|
||||
rsa_already_set,
|
||||
dsa_already_set,
|
||||
ecdsa_already_set);
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
return ARGP_ERR_UNKNOWN;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Our argp parser. */
|
||||
static struct argp argp = {options, parse_opt, args_doc, doc, NULL, NULL, NULL};
|
||||
#endif /* HAVE_ARGP_H */
|
||||
|
||||
/* A userdata struct for channel. */
|
||||
struct channel_data_struct {
|
||||
/* pid of the child process the channel will spawn. */
|
||||
pid_t pid;
|
||||
/* For PTY allocation */
|
||||
socket_t pty_master;
|
||||
socket_t pty_slave;
|
||||
/* For communication with the child process. */
|
||||
socket_t child_stdin;
|
||||
socket_t child_stdout;
|
||||
/* Only used for subsystem and exec requests. */
|
||||
socket_t child_stderr;
|
||||
/* Event which is used to poll the above descriptors. */
|
||||
ssh_event event;
|
||||
/* Terminal size struct. */
|
||||
struct winsize *winsize;
|
||||
};
|
||||
|
||||
/* A userdata struct for session. */
|
||||
struct session_data_struct {
|
||||
/* Pointer to the channel the session will allocate. */
|
||||
ssh_channel channel;
|
||||
int auth_attempts;
|
||||
int authenticated;
|
||||
};
|
||||
|
||||
static int data_function(ssh_session session, ssh_channel channel, void *data,
|
||||
uint32_t len, int is_stderr, void *userdata) {
|
||||
struct channel_data_struct *cdata = (struct channel_data_struct *) userdata;
|
||||
|
||||
(void) session;
|
||||
(void) channel;
|
||||
(void) is_stderr;
|
||||
|
||||
if (len == 0 || cdata->pid < 1 || kill(cdata->pid, 0) < 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return write(cdata->child_stdin, (char *) data, len);
|
||||
}
|
||||
|
||||
static int pty_request(ssh_session session, ssh_channel channel,
|
||||
const char *term, int cols, int rows, int py, int px,
|
||||
void *userdata) {
|
||||
struct channel_data_struct *cdata = (struct channel_data_struct *)userdata;
|
||||
|
||||
(void) session;
|
||||
(void) channel;
|
||||
(void) term;
|
||||
|
||||
cdata->winsize->ws_row = rows;
|
||||
cdata->winsize->ws_col = cols;
|
||||
cdata->winsize->ws_xpixel = px;
|
||||
cdata->winsize->ws_ypixel = py;
|
||||
|
||||
if (openpty(&cdata->pty_master, &cdata->pty_slave, NULL, NULL,
|
||||
cdata->winsize) != 0) {
|
||||
fprintf(stderr, "Failed to open pty\n");
|
||||
return SSH_ERROR;
|
||||
}
|
||||
return SSH_OK;
|
||||
}
|
||||
|
||||
static int pty_resize(ssh_session session, ssh_channel channel, int cols,
|
||||
int rows, int py, int px, void *userdata) {
|
||||
struct channel_data_struct *cdata = (struct channel_data_struct *)userdata;
|
||||
|
||||
(void) session;
|
||||
(void) channel;
|
||||
|
||||
cdata->winsize->ws_row = rows;
|
||||
cdata->winsize->ws_col = cols;
|
||||
cdata->winsize->ws_xpixel = px;
|
||||
cdata->winsize->ws_ypixel = py;
|
||||
|
||||
if (cdata->pty_master != -1) {
|
||||
return ioctl(cdata->pty_master, TIOCSWINSZ, cdata->winsize);
|
||||
}
|
||||
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
static int exec_pty(const char *mode, const char *command,
|
||||
struct channel_data_struct *cdata) {
|
||||
switch(cdata->pid = fork()) {
|
||||
case -1:
|
||||
close(cdata->pty_master);
|
||||
close(cdata->pty_slave);
|
||||
fprintf(stderr, "Failed to fork\n");
|
||||
return SSH_ERROR;
|
||||
case 0:
|
||||
close(cdata->pty_master);
|
||||
if (login_tty(cdata->pty_slave) != 0) {
|
||||
exit(1);
|
||||
}
|
||||
execl("/bin/sh", "sh", mode, command, NULL);
|
||||
exit(0);
|
||||
default:
|
||||
close(cdata->pty_slave);
|
||||
/* pty fd is bi-directional */
|
||||
cdata->child_stdout = cdata->child_stdin = cdata->pty_master;
|
||||
}
|
||||
return SSH_OK;
|
||||
}
|
||||
|
||||
static int exec_nopty(const char *command, struct channel_data_struct *cdata) {
|
||||
int in[2], out[2], err[2];
|
||||
|
||||
/* Do the plumbing to be able to talk with the child process. */
|
||||
if (pipe(in) != 0) {
|
||||
goto stdin_failed;
|
||||
}
|
||||
if (pipe(out) != 0) {
|
||||
goto stdout_failed;
|
||||
}
|
||||
if (pipe(err) != 0) {
|
||||
goto stderr_failed;
|
||||
}
|
||||
|
||||
switch(cdata->pid = fork()) {
|
||||
case -1:
|
||||
goto fork_failed;
|
||||
case 0:
|
||||
/* Finish the plumbing in the child process. */
|
||||
close(in[1]);
|
||||
close(out[0]);
|
||||
close(err[0]);
|
||||
dup2(in[0], STDIN_FILENO);
|
||||
dup2(out[1], STDOUT_FILENO);
|
||||
dup2(err[1], STDERR_FILENO);
|
||||
close(in[0]);
|
||||
close(out[1]);
|
||||
close(err[1]);
|
||||
/* exec the requested command. */
|
||||
execl("/bin/sh", "sh", "-c", command, NULL);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
close(in[0]);
|
||||
close(out[1]);
|
||||
close(err[1]);
|
||||
|
||||
cdata->child_stdin = in[1];
|
||||
cdata->child_stdout = out[0];
|
||||
cdata->child_stderr = err[0];
|
||||
|
||||
return SSH_OK;
|
||||
|
||||
fork_failed:
|
||||
close(err[0]);
|
||||
close(err[1]);
|
||||
stderr_failed:
|
||||
close(out[0]);
|
||||
close(out[1]);
|
||||
stdout_failed:
|
||||
close(in[0]);
|
||||
close(in[1]);
|
||||
stdin_failed:
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
static int exec_request(ssh_session session, ssh_channel channel,
|
||||
const char *command, void *userdata) {
|
||||
struct channel_data_struct *cdata = (struct channel_data_struct *) userdata;
|
||||
|
||||
|
||||
(void) session;
|
||||
(void) channel;
|
||||
|
||||
if(cdata->pid > 0) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
if (cdata->pty_master != -1 && cdata->pty_slave != -1) {
|
||||
return exec_pty("-c", command, cdata);
|
||||
}
|
||||
return exec_nopty(command, cdata);
|
||||
}
|
||||
|
||||
static int shell_request(ssh_session session, ssh_channel channel,
|
||||
void *userdata) {
|
||||
struct channel_data_struct *cdata = (struct channel_data_struct *) userdata;
|
||||
|
||||
(void) session;
|
||||
(void) channel;
|
||||
|
||||
if(cdata->pid > 0) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
if (cdata->pty_master != -1 && cdata->pty_slave != -1) {
|
||||
return exec_pty("-l", NULL, cdata);
|
||||
}
|
||||
/* Client requested a shell without a pty, let's pretend we allow that */
|
||||
return SSH_OK;
|
||||
}
|
||||
|
||||
static int subsystem_request(ssh_session session, ssh_channel channel,
|
||||
const char *subsystem, void *userdata) {
|
||||
/* subsystem requests behave simillarly to exec requests. */
|
||||
if (strcmp(subsystem, "sftp") == 0) {
|
||||
return exec_request(session, channel, SFTP_SERVER_PATH, userdata);
|
||||
}
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
static int auth_password(ssh_session session, const char *user,
|
||||
const char *pass, void *userdata) {
|
||||
struct session_data_struct *sdata = (struct session_data_struct *) userdata;
|
||||
|
||||
(void) session;
|
||||
|
||||
if (strcmp(user, USER) == 0 && strcmp(pass, PASS) == 0) {
|
||||
sdata->authenticated = 1;
|
||||
return SSH_AUTH_SUCCESS;
|
||||
}
|
||||
|
||||
sdata->auth_attempts++;
|
||||
return SSH_AUTH_DENIED;
|
||||
}
|
||||
|
||||
static ssh_channel channel_open(ssh_session session, void *userdata) {
|
||||
struct session_data_struct *sdata = (struct session_data_struct *) userdata;
|
||||
|
||||
sdata->channel = ssh_channel_new(session);
|
||||
return sdata->channel;
|
||||
}
|
||||
|
||||
static int process_stdout(socket_t fd, int revents, void *userdata) {
|
||||
char buf[BUF_SIZE];
|
||||
int n = -1;
|
||||
ssh_channel channel = (ssh_channel) userdata;
|
||||
|
||||
if (channel != NULL && (revents & POLLIN) != 0) {
|
||||
n = read(fd, buf, BUF_SIZE);
|
||||
if (n > 0) {
|
||||
ssh_channel_write(channel, buf, n);
|
||||
}
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
static int process_stderr(socket_t fd, int revents, void *userdata) {
|
||||
char buf[BUF_SIZE];
|
||||
int n = -1;
|
||||
ssh_channel channel = (ssh_channel) userdata;
|
||||
|
||||
if (channel != NULL && (revents & POLLIN) != 0) {
|
||||
n = read(fd, buf, BUF_SIZE);
|
||||
if (n > 0) {
|
||||
ssh_channel_write_stderr(channel, buf, n);
|
||||
}
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
static void handle_session(ssh_event event, ssh_session session) {
|
||||
int n, rc;
|
||||
|
||||
/* Structure for storing the pty size. */
|
||||
struct winsize wsize = {
|
||||
.ws_row = 0,
|
||||
.ws_col = 0,
|
||||
.ws_xpixel = 0,
|
||||
.ws_ypixel = 0
|
||||
};
|
||||
|
||||
/* Our struct holding information about the channel. */
|
||||
struct channel_data_struct cdata = {
|
||||
.pid = 0,
|
||||
.pty_master = -1,
|
||||
.pty_slave = -1,
|
||||
.child_stdin = -1,
|
||||
.child_stdout = -1,
|
||||
.child_stderr = -1,
|
||||
.event = NULL,
|
||||
.winsize = &wsize
|
||||
};
|
||||
|
||||
/* Our struct holding information about the session. */
|
||||
struct session_data_struct sdata = {
|
||||
.channel = NULL,
|
||||
.auth_attempts = 0,
|
||||
.authenticated = 0
|
||||
};
|
||||
|
||||
struct ssh_channel_callbacks_struct channel_cb = {
|
||||
.userdata = &cdata,
|
||||
.channel_pty_request_function = pty_request,
|
||||
.channel_pty_window_change_function = pty_resize,
|
||||
.channel_shell_request_function = shell_request,
|
||||
.channel_exec_request_function = exec_request,
|
||||
.channel_data_function = data_function,
|
||||
.channel_subsystem_request_function = subsystem_request
|
||||
};
|
||||
|
||||
struct ssh_server_callbacks_struct server_cb = {
|
||||
.userdata = &sdata,
|
||||
.auth_password_function = auth_password,
|
||||
.channel_open_request_session_function = channel_open,
|
||||
};
|
||||
|
||||
ssh_callbacks_init(&server_cb);
|
||||
ssh_callbacks_init(&channel_cb);
|
||||
|
||||
ssh_set_server_callbacks(session, &server_cb);
|
||||
|
||||
if (ssh_handle_key_exchange(session) != SSH_OK) {
|
||||
fprintf(stderr, "%s\n", ssh_get_error(session));
|
||||
return;
|
||||
}
|
||||
|
||||
ssh_set_auth_methods(session, SSH_AUTH_METHOD_PASSWORD);
|
||||
ssh_event_add_session(event, session);
|
||||
|
||||
n = 0;
|
||||
while (sdata.authenticated == 0 || sdata.channel == NULL) {
|
||||
/* If the user has used up all attempts, or if he hasn't been able to
|
||||
* authenticate in 10 seconds (n * 100ms), disconnect. */
|
||||
if (sdata.auth_attempts >= 3 || n >= 100) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (ssh_event_dopoll(event, 100) == SSH_ERROR) {
|
||||
fprintf(stderr, "%s\n", ssh_get_error(session));
|
||||
return;
|
||||
}
|
||||
n++;
|
||||
}
|
||||
|
||||
ssh_set_channel_callbacks(sdata.channel, &channel_cb);
|
||||
|
||||
do {
|
||||
/* Poll the main event which takes care of the session, the channel and
|
||||
* even our child process's stdout/stderr (once it's started). */
|
||||
if (ssh_event_dopoll(event, -1) == SSH_ERROR) {
|
||||
ssh_channel_close(sdata.channel);
|
||||
}
|
||||
|
||||
/* If child process's stdout/stderr has been registered with the event,
|
||||
* or the child process hasn't started yet, continue. */
|
||||
if (cdata.event != NULL || cdata.pid == 0) {
|
||||
continue;
|
||||
}
|
||||
/* Executed only once, once the child process starts. */
|
||||
cdata.event = event;
|
||||
/* If stdout valid, add stdout to be monitored by the poll event. */
|
||||
if (cdata.child_stdout != -1) {
|
||||
if (ssh_event_add_fd(event, cdata.child_stdout, POLLIN, process_stdout,
|
||||
sdata.channel) != SSH_OK) {
|
||||
fprintf(stderr, "Failed to register stdout to poll context\n");
|
||||
ssh_channel_close(sdata.channel);
|
||||
}
|
||||
}
|
||||
|
||||
/* If stderr valid, add stderr to be monitored by the poll event. */
|
||||
if (cdata.child_stderr != -1){
|
||||
if (ssh_event_add_fd(event, cdata.child_stderr, POLLIN, process_stderr,
|
||||
sdata.channel) != SSH_OK) {
|
||||
fprintf(stderr, "Failed to register stderr to poll context\n");
|
||||
ssh_channel_close(sdata.channel);
|
||||
}
|
||||
}
|
||||
} while(ssh_channel_is_open(sdata.channel) &&
|
||||
(cdata.pid == 0 || waitpid(cdata.pid, &rc, WNOHANG) == 0));
|
||||
|
||||
close(cdata.pty_master);
|
||||
close(cdata.child_stdin);
|
||||
close(cdata.child_stdout);
|
||||
close(cdata.child_stderr);
|
||||
|
||||
/* Remove the descriptors from the polling context, since they are now
|
||||
* closed, they will always trigger during the poll calls. */
|
||||
ssh_event_remove_fd(event, cdata.child_stdout);
|
||||
ssh_event_remove_fd(event, cdata.child_stderr);
|
||||
|
||||
/* If the child process exited. */
|
||||
if (kill(cdata.pid, 0) < 0 && WIFEXITED(rc)) {
|
||||
rc = WEXITSTATUS(rc);
|
||||
ssh_channel_request_send_exit_status(sdata.channel, rc);
|
||||
/* If client terminated the channel or the process did not exit nicely,
|
||||
* but only if something has been forked. */
|
||||
} else if (cdata.pid > 0) {
|
||||
kill(cdata.pid, SIGKILL);
|
||||
}
|
||||
|
||||
ssh_channel_send_eof(sdata.channel);
|
||||
ssh_channel_close(sdata.channel);
|
||||
|
||||
/* Wait up to 5 seconds for the client to terminate the session. */
|
||||
for (n = 0; n < 50 && (ssh_get_status(session) & SESSION_END) == 0; n++) {
|
||||
ssh_event_dopoll(event, 100);
|
||||
}
|
||||
}
|
||||
|
||||
/* SIGCHLD handler for cleaning up dead children. */
|
||||
static void sigchld_handler(int signo) {
|
||||
(void) signo;
|
||||
while (waitpid(-1, NULL, WNOHANG) > 0);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
ssh_bind sshbind;
|
||||
ssh_session session;
|
||||
ssh_event event;
|
||||
struct sigaction sa;
|
||||
|
||||
/* Set up SIGCHLD handler. */
|
||||
sa.sa_handler = sigchld_handler;
|
||||
sigemptyset(&sa.sa_mask);
|
||||
sa.sa_flags = SA_RESTART | SA_NOCLDSTOP;
|
||||
if (sigaction(SIGCHLD, &sa, NULL) != 0) {
|
||||
fprintf(stderr, "Failed to register SIGCHLD handler\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
ssh_init();
|
||||
sshbind = ssh_bind_new();
|
||||
|
||||
#ifdef HAVE_ARGP_H
|
||||
argp_parse(&argp, argc, argv, 0, 0, sshbind);
|
||||
#else
|
||||
(void) argc;
|
||||
(void) argv;
|
||||
|
||||
set_default_keys(sshbind, 0, 0, 0);
|
||||
#endif /* HAVE_ARGP_H */
|
||||
|
||||
if(ssh_bind_listen(sshbind) < 0) {
|
||||
fprintf(stderr, "%s\n", ssh_get_error(sshbind));
|
||||
return 1;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
session = ssh_new();
|
||||
if (session == NULL) {
|
||||
fprintf(stderr, "Failed to allocate session\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Blocks until there is a new incoming connection. */
|
||||
if(ssh_bind_accept(sshbind, session) != SSH_ERROR) {
|
||||
switch(fork()) {
|
||||
case 0:
|
||||
/* Remove the SIGCHLD handler inherited from parent. */
|
||||
sa.sa_handler = SIG_DFL;
|
||||
sigaction(SIGCHLD, &sa, NULL);
|
||||
/* Remove socket binding, which allows us to restart the
|
||||
* parent process, without terminating existing sessions. */
|
||||
ssh_bind_free(sshbind);
|
||||
|
||||
event = ssh_event_new();
|
||||
if (event != NULL) {
|
||||
/* Blocks until the SSH session ends by either
|
||||
* child process exiting, or client disconnecting. */
|
||||
handle_session(event, session);
|
||||
ssh_event_free(event);
|
||||
} else {
|
||||
fprintf(stderr, "Could not create polling context\n");
|
||||
}
|
||||
ssh_disconnect(session);
|
||||
ssh_free(session);
|
||||
|
||||
exit(0);
|
||||
case -1:
|
||||
fprintf(stderr, "Failed to fork\n");
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "%s\n", ssh_get_error(sshbind));
|
||||
}
|
||||
/* Since the session has been passed to a child fork, do some cleaning
|
||||
* up at the parent process. */
|
||||
ssh_disconnect(session);
|
||||
ssh_free(session);
|
||||
}
|
||||
|
||||
ssh_bind_free(sshbind);
|
||||
ssh_finalize();
|
||||
return 0;
|
||||
}
|
||||
@@ -1,265 +0,0 @@
|
||||
/*
|
||||
Copyright 2010 Aris Adamantiadis
|
||||
|
||||
This file is part of the SSH Library
|
||||
|
||||
You are free to copy this file, modify it in any way, consider it being public
|
||||
domain. This does not apply to the rest of the library though, but it is
|
||||
allowed to cut-and-paste working code from this file to any license of
|
||||
program.
|
||||
The goal is to show the API in action. It's not a reference on how terminal
|
||||
clients must be made or how a client should react.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#ifdef HAVE_TERMIOS_H
|
||||
#include <termios.h>
|
||||
#endif
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <sys/select.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#include <errno.h>
|
||||
#include <libssh/callbacks.h>
|
||||
#include <libssh/libssh.h>
|
||||
#include <libssh/sftp.h>
|
||||
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "examples_common.h"
|
||||
char *host;
|
||||
const char *desthost="localhost";
|
||||
const char *port="22";
|
||||
|
||||
#ifdef WITH_PCAP
|
||||
#include <libssh/pcap.h>
|
||||
char *pcap_file=NULL;
|
||||
#endif
|
||||
|
||||
static void usage(){
|
||||
fprintf(stderr,"Usage : sshnetcat [user@]host forwarded_host forwarded_port\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static int opts(int argc, char **argv){
|
||||
int i;
|
||||
while((i=getopt(argc,argv,"P:"))!=-1){
|
||||
switch(i){
|
||||
#ifdef WITH_PCAP
|
||||
case 'P':
|
||||
pcap_file=optarg;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
fprintf(stderr,"unknown option %c\n",optopt);
|
||||
usage();
|
||||
}
|
||||
}
|
||||
if(optind < argc)
|
||||
host=argv[optind++];
|
||||
if(optind < argc)
|
||||
desthost=argv[optind++];
|
||||
if(optind < argc)
|
||||
port=argv[optind++];
|
||||
if(host==NULL)
|
||||
usage();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void select_loop(ssh_session session,ssh_channel channel){
|
||||
fd_set fds;
|
||||
struct timeval timeout;
|
||||
char buffer[4096];
|
||||
/* channels will be set to the channels to poll.
|
||||
* outchannels will contain the result of the poll
|
||||
*/
|
||||
ssh_channel channels[2], outchannels[2];
|
||||
int lus;
|
||||
int eof=0;
|
||||
int maxfd;
|
||||
int ret;
|
||||
while(channel){
|
||||
do{
|
||||
int fd;
|
||||
|
||||
FD_ZERO(&fds);
|
||||
if(!eof)
|
||||
FD_SET(0,&fds);
|
||||
timeout.tv_sec=30;
|
||||
timeout.tv_usec=0;
|
||||
|
||||
fd = ssh_get_fd(session);
|
||||
if (fd == -1) {
|
||||
fprintf(stderr, "Error getting the session file descriptor: %s\n",
|
||||
ssh_get_error(session));
|
||||
return;
|
||||
}
|
||||
FD_SET(fd, &fds);
|
||||
maxfd = fd + 1;
|
||||
|
||||
channels[0]=channel; // set the first channel we want to read from
|
||||
channels[1]=NULL;
|
||||
ret=ssh_select(channels,outchannels,maxfd,&fds,&timeout);
|
||||
if(ret==EINTR)
|
||||
continue;
|
||||
if(FD_ISSET(0,&fds)){
|
||||
lus=read(0,buffer,sizeof(buffer));
|
||||
if(lus)
|
||||
ssh_channel_write(channel,buffer,lus);
|
||||
else {
|
||||
eof=1;
|
||||
ssh_channel_send_eof(channel);
|
||||
}
|
||||
}
|
||||
if(channel && ssh_channel_is_closed(channel)){
|
||||
ssh_channel_free(channel);
|
||||
channel=NULL;
|
||||
channels[0]=NULL;
|
||||
}
|
||||
if(outchannels[0]){
|
||||
while(channel && ssh_channel_is_open(channel) && ssh_channel_poll(channel,0)){
|
||||
lus = ssh_channel_read(channel,buffer,sizeof(buffer),0);
|
||||
if(lus==-1){
|
||||
fprintf(stderr, "Error reading channel: %s\n",
|
||||
ssh_get_error(session));
|
||||
return;
|
||||
}
|
||||
if(lus==0){
|
||||
ssh_channel_free(channel);
|
||||
channel=channels[0]=NULL;
|
||||
} else {
|
||||
ret = write(1, buffer, lus);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "Error writing to stdin: %s",
|
||||
strerror(errno));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
while(channel && ssh_channel_is_open(channel) && ssh_channel_poll(channel,1)){ /* stderr */
|
||||
lus = ssh_channel_read(channel, buffer, sizeof(buffer), 1);
|
||||
if(lus==-1){
|
||||
fprintf(stderr, "Error reading channel: %s\n",
|
||||
ssh_get_error(session));
|
||||
return;
|
||||
}
|
||||
if(lus==0){
|
||||
ssh_channel_free(channel);
|
||||
channel=channels[0]=NULL;
|
||||
} else {
|
||||
ret = write(2, buffer, lus);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "Error writing to stderr: %s",
|
||||
strerror(errno));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(channel && ssh_channel_is_closed(channel)){
|
||||
ssh_channel_free(channel);
|
||||
channel=NULL;
|
||||
}
|
||||
} while (ret==EINTR || ret==SSH_EINTR);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static void forwarding(ssh_session session){
|
||||
ssh_channel channel;
|
||||
int r;
|
||||
channel = ssh_channel_new(session);
|
||||
r = ssh_channel_open_forward(channel, desthost, atoi(port), "localhost", 22);
|
||||
if(r<0) {
|
||||
printf("error forwarding port : %s\n",ssh_get_error(session));
|
||||
return;
|
||||
}
|
||||
select_loop(session,channel);
|
||||
}
|
||||
|
||||
static int client(ssh_session session){
|
||||
int auth=0;
|
||||
char *banner;
|
||||
int state;
|
||||
|
||||
if (ssh_options_set(session, SSH_OPTIONS_HOST ,host) < 0)
|
||||
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;
|
||||
}
|
||||
forwarding(session);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef WITH_PCAP
|
||||
ssh_pcap_file pcap;
|
||||
void set_pcap(ssh_session session);
|
||||
void set_pcap(ssh_session session){
|
||||
if(!pcap_file)
|
||||
return;
|
||||
pcap=ssh_pcap_file_new();
|
||||
if(ssh_pcap_file_open(pcap,pcap_file) == SSH_ERROR){
|
||||
printf("Error opening pcap file\n");
|
||||
ssh_pcap_file_free(pcap);
|
||||
pcap=NULL;
|
||||
return;
|
||||
}
|
||||
ssh_set_pcap_file(session,pcap);
|
||||
}
|
||||
|
||||
void cleanup_pcap(void);
|
||||
void cleanup_pcap(){
|
||||
ssh_pcap_file_free(pcap);
|
||||
pcap=NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
int main(int argc, char **argv){
|
||||
ssh_session session;
|
||||
|
||||
session = ssh_new();
|
||||
|
||||
if(ssh_options_getopt(session, &argc, argv)) {
|
||||
fprintf(stderr, "error parsing command line :%s\n",
|
||||
ssh_get_error(session));
|
||||
usage();
|
||||
}
|
||||
opts(argc,argv);
|
||||
#ifdef WITH_PCAP
|
||||
set_pcap(session);
|
||||
#endif
|
||||
client(session);
|
||||
|
||||
ssh_disconnect(session);
|
||||
ssh_free(session);
|
||||
#ifdef WITH_PCAP
|
||||
cleanup_pcap();
|
||||
#endif
|
||||
|
||||
ssh_finalize();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,3 +1,3 @@
|
||||
project(libssh-headers-x C)
|
||||
project(headers C)
|
||||
|
||||
add_subdirectory(libssh)
|
||||
|
||||
@@ -4,8 +4,6 @@ set(libssh_HDRS
|
||||
callbacks.h
|
||||
libssh.h
|
||||
ssh2.h
|
||||
legacy.h
|
||||
libsshpp.hpp
|
||||
)
|
||||
|
||||
if (WITH_SFTP)
|
||||
|
||||
@@ -1,23 +1,3 @@
|
||||
/*
|
||||
* This file is part of the SSH Library
|
||||
*
|
||||
* Copyright (c) 2008-2009 Andreas Schneider <asn@cryptomilk.org>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef __AGENT_H
|
||||
#define __AGENT_H
|
||||
|
||||
@@ -68,10 +48,9 @@
|
||||
#define SSH_AGENT_OLD_SIGNATURE 0x01
|
||||
|
||||
struct ssh_agent_struct {
|
||||
struct ssh_socket_struct *sock;
|
||||
struct socket *sock;
|
||||
ssh_buffer ident;
|
||||
unsigned int count;
|
||||
ssh_channel channel;
|
||||
};
|
||||
|
||||
#ifndef _WIN32
|
||||
@@ -101,17 +80,17 @@ void agent_free(struct ssh_agent_struct *agent);
|
||||
*/
|
||||
int agent_is_running(struct ssh_session_struct *session);
|
||||
|
||||
int ssh_agent_get_ident_count(struct ssh_session_struct *session);
|
||||
int agent_get_ident_count(struct ssh_session_struct *session);
|
||||
|
||||
ssh_key ssh_agent_get_next_ident(struct ssh_session_struct *session,
|
||||
char **comment);
|
||||
struct ssh_public_key_struct *agent_get_next_ident(struct ssh_session_struct *session,
|
||||
char **comment);
|
||||
|
||||
ssh_key ssh_agent_get_first_ident(struct ssh_session_struct *session,
|
||||
char **comment);
|
||||
struct ssh_public_key_struct *agent_get_first_ident(struct ssh_session_struct *session,
|
||||
char **comment);
|
||||
|
||||
ssh_string ssh_agent_sign_data(ssh_session session,
|
||||
const ssh_key pubkey,
|
||||
struct ssh_buffer_struct *data);
|
||||
ssh_string agent_sign_data(struct ssh_session_struct *session,
|
||||
struct ssh_buffer_struct *data,
|
||||
struct ssh_public_key_struct *pubkey);
|
||||
#endif
|
||||
|
||||
#endif /* __AGENT_H */
|
||||
|
||||
@@ -1,111 +0,0 @@
|
||||
/*
|
||||
* This file is part of the SSH Library
|
||||
*
|
||||
* Copyright (c) 2009 by Aris Adamantiadis
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef AUTH_H_
|
||||
#define AUTH_H_
|
||||
#include "config.h"
|
||||
#include "libssh/callbacks.h"
|
||||
|
||||
SSH_PACKET_CALLBACK(ssh_packet_userauth_banner);
|
||||
SSH_PACKET_CALLBACK(ssh_packet_userauth_failure);
|
||||
SSH_PACKET_CALLBACK(ssh_packet_userauth_success);
|
||||
SSH_PACKET_CALLBACK(ssh_packet_userauth_pk_ok);
|
||||
SSH_PACKET_CALLBACK(ssh_packet_userauth_info_request);
|
||||
SSH_PACKET_CALLBACK(ssh_packet_userauth_info_response);
|
||||
|
||||
/** @internal
|
||||
* kdbint structure must be shared with message.c
|
||||
* and server.c
|
||||
*/
|
||||
struct ssh_kbdint_struct {
|
||||
uint32_t nprompts;
|
||||
uint32_t nanswers;
|
||||
char *name;
|
||||
char *instruction;
|
||||
char **prompts;
|
||||
unsigned char *echo; /* bool array */
|
||||
char **answers;
|
||||
};
|
||||
typedef struct ssh_kbdint_struct* ssh_kbdint;
|
||||
|
||||
ssh_kbdint ssh_kbdint_new(void);
|
||||
void ssh_kbdint_clean(ssh_kbdint kbd);
|
||||
void ssh_kbdint_free(ssh_kbdint kbd);
|
||||
|
||||
|
||||
#ifdef WITH_SSH1
|
||||
void ssh_auth1_handler(ssh_session session, uint8_t type);
|
||||
|
||||
/* auth1.c */
|
||||
int ssh_userauth1_none(ssh_session session, const char *username);
|
||||
int ssh_userauth1_offer_pubkey(ssh_session session, const char *username,
|
||||
int type, ssh_string pubkey);
|
||||
int ssh_userauth1_password(ssh_session session, const char *username,
|
||||
const char *password);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
/** @internal
|
||||
* States of authentication in the client-side. They describe
|
||||
* what was the last response from the server
|
||||
*/
|
||||
enum ssh_auth_state_e {
|
||||
/** No authentication asked */
|
||||
SSH_AUTH_STATE_NONE=0,
|
||||
/** Last authentication response was a partial success */
|
||||
SSH_AUTH_STATE_PARTIAL,
|
||||
/** Last authentication response was a success */
|
||||
SSH_AUTH_STATE_SUCCESS,
|
||||
/** Last authentication response was failed */
|
||||
SSH_AUTH_STATE_FAILED,
|
||||
/** Last authentication was erroneous */
|
||||
SSH_AUTH_STATE_ERROR,
|
||||
/** Last state was a keyboard-interactive ask for info */
|
||||
SSH_AUTH_STATE_INFO,
|
||||
/** Last state was a public key accepted for authentication */
|
||||
SSH_AUTH_STATE_PK_OK,
|
||||
/** We asked for a keyboard-interactive authentication */
|
||||
SSH_AUTH_STATE_KBDINT_SENT,
|
||||
/** We have sent an userauth request with gssapi-with-mic */
|
||||
SSH_AUTH_STATE_GSSAPI_REQUEST_SENT,
|
||||
/** We are exchanging tokens until authentication */
|
||||
SSH_AUTH_STATE_GSSAPI_TOKEN,
|
||||
/** We have sent the MIC and expecting to be authenticated */
|
||||
SSH_AUTH_STATE_GSSAPI_MIC_SENT,
|
||||
};
|
||||
|
||||
/** @internal
|
||||
* @brief states of the authentication service request
|
||||
*/
|
||||
enum ssh_auth_service_state_e {
|
||||
/** initial state */
|
||||
SSH_AUTH_SERVICE_NONE=0,
|
||||
/** Authentication service request packet sent */
|
||||
SSH_AUTH_SERVICE_SENT,
|
||||
/** Service accepted */
|
||||
SSH_AUTH_SERVICE_ACCEPTED,
|
||||
/** Access to service denied (fatal) */
|
||||
SSH_AUTH_SERVICE_DENIED,
|
||||
/** Specific to SSH1 */
|
||||
SSH_AUTH_SERVICE_USER_SENT
|
||||
};
|
||||
|
||||
#endif /* AUTH_H_ */
|
||||
@@ -1,33 +0,0 @@
|
||||
/*
|
||||
* This file is part of the SSH Library
|
||||
*
|
||||
* Copyright (c) 2014 by Aris Adamantiadis <aris@badcode.be>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef BIGNUM_H_
|
||||
#define BIGNUM_H_
|
||||
|
||||
#include "libssh/libcrypto.h"
|
||||
#include "libssh/libgcrypt.h"
|
||||
|
||||
bignum make_string_bn(ssh_string string);
|
||||
void make_string_bn_inplace(ssh_string string, bignum bnout);
|
||||
ssh_string make_bignum_string(bignum num);
|
||||
void ssh_print_bignum(const char *which,bignum num);
|
||||
|
||||
|
||||
#endif /* BIGNUM_H_ */
|
||||
@@ -1,55 +0,0 @@
|
||||
/*
|
||||
* This file is part of the SSH Library
|
||||
*
|
||||
* Copyright (c) 2010 by Aris Adamantiadis
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef BIND_H_
|
||||
#define BIND_H_
|
||||
|
||||
#include "libssh/priv.h"
|
||||
#include "libssh/session.h"
|
||||
|
||||
struct ssh_bind_struct {
|
||||
struct ssh_common_struct common; /* stuff common to ssh_bind and ssh_session */
|
||||
struct ssh_bind_callbacks_struct *bind_callbacks;
|
||||
void *bind_callbacks_userdata;
|
||||
|
||||
struct ssh_poll_handle_struct *poll;
|
||||
/* options */
|
||||
char *wanted_methods[10];
|
||||
char *banner;
|
||||
char *ecdsakey;
|
||||
char *dsakey;
|
||||
char *rsakey;
|
||||
char *ed25519key;
|
||||
ssh_key ecdsa;
|
||||
ssh_key dsa;
|
||||
ssh_key rsa;
|
||||
ssh_key ed25519;
|
||||
char *bindaddr;
|
||||
socket_t bindfd;
|
||||
unsigned int bindport;
|
||||
int blocking;
|
||||
int toaccept;
|
||||
};
|
||||
|
||||
struct ssh_poll_handle_struct *ssh_bind_get_poll(struct ssh_bind_struct
|
||||
*sshbind);
|
||||
|
||||
|
||||
#endif /* BIND_H_ */
|
||||
@@ -1,87 +0,0 @@
|
||||
/* $OpenBSD: blf.h,v 1.7 2007/03/14 17:59:41 grunk Exp $ */
|
||||
/*
|
||||
* Blowfish - a fast block cipher designed by Bruce Schneier
|
||||
*
|
||||
* Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by Niels Provos.
|
||||
* 4. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _BLF_H_
|
||||
#define _BLF_H_
|
||||
|
||||
//#include "includes.h"
|
||||
|
||||
#if !defined(HAVE_BCRYPT_PBKDF) && !defined(HAVE_BLH_H)
|
||||
|
||||
/* Schneier specifies a maximum key length of 56 bytes.
|
||||
* This ensures that every key bit affects every cipher
|
||||
* bit. However, the subkeys can hold up to 72 bytes.
|
||||
* Warning: For normal blowfish encryption only 56 bytes
|
||||
* of the key affect all cipherbits.
|
||||
*/
|
||||
|
||||
#define BLF_N 16 /* Number of Subkeys */
|
||||
#define BLF_MAXKEYLEN ((BLF_N-2)*4) /* 448 bits */
|
||||
#define BLF_MAXUTILIZED ((BLF_N+2)*4) /* 576 bits */
|
||||
|
||||
/* Blowfish context */
|
||||
typedef struct BlowfishContext {
|
||||
uint32_t S[4][256]; /* S-Boxes */
|
||||
uint32_t P[BLF_N + 2]; /* Subkeys */
|
||||
} blf_ctx;
|
||||
|
||||
/* Raw access to customized Blowfish
|
||||
* blf_key is just:
|
||||
* Blowfish_initstate( state )
|
||||
* Blowfish_expand0state( state, key, keylen )
|
||||
*/
|
||||
|
||||
void Blowfish_encipher(blf_ctx *, uint32_t *, uint32_t *);
|
||||
void Blowfish_decipher(blf_ctx *, uint32_t *, uint32_t *);
|
||||
void Blowfish_initstate(blf_ctx *);
|
||||
void Blowfish_expand0state(blf_ctx *, const uint8_t *, uint16_t);
|
||||
void Blowfish_expandstate
|
||||
(blf_ctx *, const uint8_t *, uint16_t, const uint8_t *, uint16_t);
|
||||
|
||||
/* Standard Blowfish */
|
||||
|
||||
void blf_key(blf_ctx *, const uint8_t *, uint16_t);
|
||||
void blf_enc(blf_ctx *, uint32_t *, uint16_t);
|
||||
void blf_dec(blf_ctx *, uint32_t *, uint16_t);
|
||||
|
||||
void blf_ecb_encrypt(blf_ctx *, uint8_t *, uint32_t);
|
||||
void blf_ecb_decrypt(blf_ctx *, uint8_t *, uint32_t);
|
||||
|
||||
void blf_cbc_encrypt(blf_ctx *, uint8_t *, uint8_t *, uint32_t);
|
||||
void blf_cbc_decrypt(blf_ctx *, uint8_t *, uint8_t *, uint32_t);
|
||||
|
||||
/* Converts uint8_t to uint32_t */
|
||||
uint32_t Blowfish_stream2word(const uint8_t *, uint16_t , uint16_t *);
|
||||
|
||||
#endif /* !defined(HAVE_BCRYPT_PBKDF) && !defined(HAVE_BLH_H) */
|
||||
#endif /* _BLF_H */
|
||||
@@ -3,80 +3,42 @@
|
||||
*
|
||||
* Copyright (c) 2009 by Aris Adamantiadis
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
* The SSH Library is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation; either version 2.1 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
* The SSH Library is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with the SSH Library; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
|
||||
* MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef BUFFER_H_
|
||||
#define BUFFER_H_
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "libssh/libssh.h"
|
||||
/*
|
||||
* Describes a buffer state
|
||||
* [XXXXXXXXXXXXDATA PAYLOAD XXXXXXXXXXXXXXXXXXXXXXXX]
|
||||
* ^ ^ ^ ^]
|
||||
* \_data points\_pos points here \_used points here | /
|
||||
* here Allocated
|
||||
*/
|
||||
/* Describes a buffer state */
|
||||
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)
|
||||
|
||||
LIBSSH_API void ssh_buffer_free(ssh_buffer buffer);
|
||||
LIBSSH_API void *ssh_buffer_get_begin(ssh_buffer buffer);
|
||||
LIBSSH_API uint32_t ssh_buffer_get_len(ssh_buffer buffer);
|
||||
LIBSSH_API ssh_buffer ssh_buffer_new(void);
|
||||
void ssh_buffer_set_secure(ssh_buffer buffer);
|
||||
int buffer_add_ssh_string(ssh_buffer buffer, ssh_string string);
|
||||
int buffer_add_u8(ssh_buffer buffer, uint8_t data);
|
||||
int buffer_add_u16(ssh_buffer buffer, uint16_t data);
|
||||
int buffer_add_u32(ssh_buffer buffer, uint32_t data);
|
||||
int buffer_add_u64(ssh_buffer buffer, uint64_t data);
|
||||
int ssh_buffer_add_data(ssh_buffer buffer, const void *data, uint32_t len);
|
||||
|
||||
int ssh_buffer_pack_va(struct ssh_buffer_struct *buffer,
|
||||
const char *format,
|
||||
int argc,
|
||||
va_list ap);
|
||||
int _ssh_buffer_pack(struct ssh_buffer_struct *buffer,
|
||||
const char *format,
|
||||
int argc,
|
||||
...);
|
||||
#define ssh_buffer_pack(buffer, format, ...) \
|
||||
_ssh_buffer_pack((buffer), (format), __VA_NARG__(__VA_ARGS__), __VA_ARGS__, SSH_BUFFER_PACK_END)
|
||||
|
||||
int ssh_buffer_unpack_va(struct ssh_buffer_struct *buffer,
|
||||
const char *format, int argc,
|
||||
va_list ap);
|
||||
int _ssh_buffer_unpack(struct ssh_buffer_struct *buffer,
|
||||
const char *format,
|
||||
int argc,
|
||||
...);
|
||||
#define ssh_buffer_unpack(buffer, format, ...) \
|
||||
_ssh_buffer_unpack((buffer), (format), __VA_NARG__(__VA_ARGS__), __VA_ARGS__, SSH_BUFFER_PACK_END)
|
||||
|
||||
int buffer_add_data(ssh_buffer buffer, const void *data, uint32_t len);
|
||||
int buffer_prepend_data(ssh_buffer buffer, const void *data, uint32_t len);
|
||||
int buffer_add_buffer(ssh_buffer buffer, ssh_buffer source);
|
||||
int ssh_buffer_reinit(ssh_buffer buffer);
|
||||
int buffer_reinit(ssh_buffer buffer);
|
||||
|
||||
/* buffer_get_rest returns a pointer to the current position into the buffer */
|
||||
void *buffer_get_rest(ssh_buffer buffer);
|
||||
|
||||
@@ -3,19 +3,20 @@
|
||||
*
|
||||
* Copyright (c) 2009 Aris Adamantiadis <aris@0xbadc0de.be>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
* The SSH Library is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation; either version 2.1 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
* The SSH Library is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with the SSH Library; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
|
||||
* MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/* callback.h
|
||||
@@ -33,370 +34,45 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @defgroup libssh_callbacks The libssh callbacks
|
||||
* @ingroup libssh
|
||||
* @brief SSH authentication callback.
|
||||
*
|
||||
* Callback which can be replaced in libssh.
|
||||
* @param prompt Prompt to be displayed.
|
||||
* @param buf Buffer to save the password. You should null-terminate it.
|
||||
* @param len Length of the buffer.
|
||||
* @param echo Enable or disable the echo of what you type.
|
||||
* @param verify Should the password be verified?
|
||||
* @param userdata Userdata to be passed to the callback function. Useful
|
||||
* for GUI applications.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @internal
|
||||
* @brief callback to process simple codes
|
||||
* @param code value to transmit
|
||||
* @param user Userdata to pass in callback
|
||||
*/
|
||||
typedef void (*ssh_callback_int) (int code, void *user);
|
||||
|
||||
/** @internal
|
||||
* @brief callback for data received messages.
|
||||
* @param data data retrieved from the socket or stream
|
||||
* @param len number of bytes available from this stream
|
||||
* @param user user-supplied pointer sent along with all callback messages
|
||||
* @returns number of bytes processed by the callee. The remaining bytes will
|
||||
* be sent in the next callback message, when more data is available.
|
||||
*/
|
||||
typedef int (*ssh_callback_data) (const void *data, size_t len, void *user);
|
||||
|
||||
typedef void (*ssh_callback_int_int) (int code, int errno_code, void *user);
|
||||
|
||||
typedef int (*ssh_message_callback) (ssh_session, ssh_message message, void *user);
|
||||
typedef int (*ssh_channel_callback_int) (ssh_channel channel, int code, void *user);
|
||||
typedef int (*ssh_channel_callback_data) (ssh_channel channel, int code, void *data, size_t len, void *user);
|
||||
|
||||
/**
|
||||
* @brief SSH log callback. All logging messages will go through this callback
|
||||
* @param session Current session handler
|
||||
* @param priority Priority of the log, the smaller being the more important
|
||||
* @param message the actual message
|
||||
* @param userdata Userdata to be passed to the callback function.
|
||||
* @return 0 on success, < 0 on error.
|
||||
*/
|
||||
typedef int (*ssh_auth_callback) (const char *prompt, char *buf, size_t len,
|
||||
int echo, int verify, void *userdata);
|
||||
typedef void (*ssh_log_callback) (ssh_session session, int priority,
|
||||
const char *message, void *userdata);
|
||||
|
||||
/**
|
||||
* @brief SSH log callback.
|
||||
*
|
||||
* All logging messages will go through this callback.
|
||||
*
|
||||
* @param priority Priority of the log, the smaller being the more important.
|
||||
*
|
||||
* @param function The function name calling the the logging fucntions.
|
||||
*
|
||||
* @param message The actual message
|
||||
*
|
||||
* @param userdata Userdata to be passed to the callback function.
|
||||
*/
|
||||
typedef void (*ssh_logging_callback) (int priority,
|
||||
const char *function,
|
||||
const char *buffer,
|
||||
void *userdata);
|
||||
|
||||
/**
|
||||
* @brief SSH Connection status callback.
|
||||
* @param session Current session handler
|
||||
* @param status Percentage of connection status, going from 0.0 to 1.0
|
||||
* once connection is done.
|
||||
* @param userdata Userdata to be passed to the callback function.
|
||||
*/
|
||||
/** this callback will be called with status going from 0.0 to 1.0 during
|
||||
* connection */
|
||||
typedef void (*ssh_status_callback) (ssh_session session, float status,
|
||||
void *userdata);
|
||||
|
||||
/**
|
||||
* @brief SSH global request callback. All global request will go through this
|
||||
* callback.
|
||||
* @param session Current session handler
|
||||
* @param message the actual message
|
||||
* @param userdata Userdata to be passed to the callback function.
|
||||
*/
|
||||
typedef void (*ssh_global_request_callback) (ssh_session session,
|
||||
ssh_message message, void *userdata);
|
||||
|
||||
/**
|
||||
* @brief Handles an SSH new channel open X11 request. This happens when the server
|
||||
* sends back an X11 connection attempt. This is a client-side API
|
||||
* @param session current session handler
|
||||
* @param userdata Userdata to be passed to the callback function.
|
||||
* @returns a valid ssh_channel handle if the request is to be allowed
|
||||
* @returns NULL if the request should not be allowed
|
||||
* @warning The channel pointer returned by this callback must be closed by the application.
|
||||
*/
|
||||
typedef ssh_channel (*ssh_channel_open_request_x11_callback) (ssh_session session,
|
||||
const char * originator_address, int originator_port, void *userdata);
|
||||
|
||||
/**
|
||||
* The structure to replace libssh functions with appropriate callbacks.
|
||||
*/
|
||||
struct ssh_callbacks_struct {
|
||||
/** DON'T SET THIS use ssh_callbacks_init() instead. */
|
||||
size_t size;
|
||||
/**
|
||||
* User-provided data. User is free to set anything he wants here
|
||||
*/
|
||||
void *userdata;
|
||||
/**
|
||||
* This functions will be called if e.g. a keyphrase is needed.
|
||||
*/
|
||||
ssh_auth_callback auth_function;
|
||||
/**
|
||||
* This function will be called each time a loggable event happens.
|
||||
*/
|
||||
ssh_log_callback log_function;
|
||||
/**
|
||||
* This function gets called during connection time to indicate the
|
||||
* percentage of connection steps completed.
|
||||
*/
|
||||
void (*connect_status_function)(void *userdata, float status);
|
||||
/**
|
||||
* This function will be called each time a global request is received.
|
||||
*/
|
||||
ssh_global_request_callback global_request_function;
|
||||
/** This function will be called when an incoming X11 request is received.
|
||||
*/
|
||||
ssh_channel_open_request_x11_callback channel_open_request_x11_function;
|
||||
};
|
||||
typedef struct ssh_callbacks_struct *ssh_callbacks;
|
||||
|
||||
/** These are callbacks used specifically in SSH servers.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief SSH authentication callback.
|
||||
* @param session Current session handler
|
||||
* @param user User that wants to authenticate
|
||||
* @param password Password used for authentication
|
||||
* @param userdata Userdata to be passed to the callback function.
|
||||
* @returns SSH_AUTH_SUCCESS Authentication is accepted.
|
||||
* @returns SSH_AUTH_PARTIAL Partial authentication, more authentication means are needed.
|
||||
* @returns SSH_AUTH_DENIED Authentication failed.
|
||||
*/
|
||||
typedef int (*ssh_auth_password_callback) (ssh_session session, const char *user, const char *password,
|
||||
void *userdata);
|
||||
|
||||
/**
|
||||
* @brief SSH authentication callback. Tries to authenticates user with the "none" method
|
||||
* which is anonymous or passwordless.
|
||||
* @param session Current session handler
|
||||
* @param user User that wants to authenticate
|
||||
* @param userdata Userdata to be passed to the callback function.
|
||||
* @returns SSH_AUTH_SUCCESS Authentication is accepted.
|
||||
* @returns SSH_AUTH_PARTIAL Partial authentication, more authentication means are needed.
|
||||
* @returns SSH_AUTH_DENIED Authentication failed.
|
||||
*/
|
||||
typedef int (*ssh_auth_none_callback) (ssh_session session, const char *user, void *userdata);
|
||||
|
||||
/**
|
||||
* @brief SSH authentication callback. Tries to authenticates user with the "gssapi-with-mic" method
|
||||
* @param session Current session handler
|
||||
* @param user Username of the user (can be spoofed)
|
||||
* @param principal Authenticated principal of the user, including realm.
|
||||
* @param userdata Userdata to be passed to the callback function.
|
||||
* @returns SSH_AUTH_SUCCESS Authentication is accepted.
|
||||
* @returns SSH_AUTH_PARTIAL Partial authentication, more authentication means are needed.
|
||||
* @returns SSH_AUTH_DENIED Authentication failed.
|
||||
* @warning Implementations should verify that parameter user matches in some way the principal.
|
||||
* user and principal can be different. Only the latter is guaranteed to be safe.
|
||||
*/
|
||||
typedef int (*ssh_auth_gssapi_mic_callback) (ssh_session session, const char *user, const char *principal,
|
||||
void *userdata);
|
||||
|
||||
/**
|
||||
* @brief SSH authentication callback.
|
||||
* @param session Current session handler
|
||||
* @param user User that wants to authenticate
|
||||
* @param pubkey public key used for authentication
|
||||
* @param signature_state SSH_PUBLICKEY_STATE_NONE if the key is not signed (simple public key probe),
|
||||
* SSH_PUBLICKEY_STATE_VALID if the signature is valid. Others values should be
|
||||
* replied with a SSH_AUTH_DENIED.
|
||||
* @param userdata Userdata to be passed to the callback function.
|
||||
* @returns SSH_AUTH_SUCCESS Authentication is accepted.
|
||||
* @returns SSH_AUTH_PARTIAL Partial authentication, more authentication means are needed.
|
||||
* @returns SSH_AUTH_DENIED Authentication failed.
|
||||
*/
|
||||
typedef int (*ssh_auth_pubkey_callback) (ssh_session session, const char *user, struct ssh_key_struct *pubkey,
|
||||
char signature_state, void *userdata);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Handles an SSH service request
|
||||
* @param session current session handler
|
||||
* @param service name of the service (e.g. "ssh-userauth") requested
|
||||
* @param userdata Userdata to be passed to the callback function.
|
||||
* @returns 0 if the request is to be allowed
|
||||
* @returns -1 if the request should not be allowed
|
||||
*/
|
||||
|
||||
typedef int (*ssh_service_request_callback) (ssh_session session, const char *service, void *userdata);
|
||||
|
||||
/**
|
||||
* @brief Handles an SSH new channel open session request
|
||||
* @param session current session handler
|
||||
* @param userdata Userdata to be passed to the callback function.
|
||||
* @returns a valid ssh_channel handle if the request is to be allowed
|
||||
* @returns NULL if the request should not be allowed
|
||||
* @warning The channel pointer returned by this callback must be closed by the application.
|
||||
*/
|
||||
typedef ssh_channel (*ssh_channel_open_request_session_callback) (ssh_session session, void *userdata);
|
||||
|
||||
/*
|
||||
* @brief handle the beginning of a GSSAPI authentication, server side.
|
||||
* @param session current session handler
|
||||
* @param user the username of the client
|
||||
* @param n_oid number of available oids
|
||||
* @param oids OIDs provided by the client
|
||||
* @returns an ssh_string containing the chosen OID, that's supported by both
|
||||
* client and server.
|
||||
* @warning It is not necessary to fill this callback in if libssh is linked
|
||||
* with libgssapi.
|
||||
*/
|
||||
typedef ssh_string (*ssh_gssapi_select_oid_callback) (ssh_session session, const char *user,
|
||||
int n_oid, ssh_string *oids, void *userdata);
|
||||
|
||||
/*
|
||||
* @brief handle the negociation of a security context, server side.
|
||||
* @param session current session handler
|
||||
* @param[in] input_token input token provided by client
|
||||
* @param[out] output_token output of the gssapi accept_sec_context method,
|
||||
* NULL after completion.
|
||||
* @returns SSH_OK if the token was generated correctly or accept_sec_context
|
||||
* returned GSS_S_COMPLETE
|
||||
* @returns SSH_ERROR in case of error
|
||||
* @warning It is not necessary to fill this callback in if libssh is linked
|
||||
* with libgssapi.
|
||||
*/
|
||||
typedef int (*ssh_gssapi_accept_sec_ctx_callback) (ssh_session session,
|
||||
ssh_string input_token, ssh_string *output_token, void *userdata);
|
||||
|
||||
/*
|
||||
* @brief Verify and authenticates a MIC, server side.
|
||||
* @param session current session handler
|
||||
* @param[in] mic input mic to be verified provided by client
|
||||
* @param[in] mic_buffer buffer of data to be signed.
|
||||
* @param[in] mic_buffer_size size of mic_buffer
|
||||
* @returns SSH_OK if the MIC was authenticated correctly
|
||||
* @returns SSH_ERROR in case of error
|
||||
* @warning It is not necessary to fill this callback in if libssh is linked
|
||||
* with libgssapi.
|
||||
*/
|
||||
typedef int (*ssh_gssapi_verify_mic_callback) (ssh_session session,
|
||||
ssh_string mic, void *mic_buffer, size_t mic_buffer_size, void *userdata);
|
||||
|
||||
|
||||
/**
|
||||
* This structure can be used to implement a libssh server, with appropriate callbacks.
|
||||
*/
|
||||
|
||||
struct ssh_server_callbacks_struct {
|
||||
/** DON'T SET THIS use ssh_callbacks_init() instead. */
|
||||
size_t size;
|
||||
/**
|
||||
* User-provided data. User is free to set anything he wants here
|
||||
*/
|
||||
void *userdata;
|
||||
/** This function gets called when a client tries to authenticate through
|
||||
* password method.
|
||||
*/
|
||||
ssh_auth_password_callback auth_password_function;
|
||||
|
||||
/** This function gets called when a client tries to authenticate through
|
||||
* none method.
|
||||
*/
|
||||
ssh_auth_none_callback auth_none_function;
|
||||
|
||||
/** This function gets called when a client tries to authenticate through
|
||||
* gssapi-mic method.
|
||||
*/
|
||||
ssh_auth_gssapi_mic_callback auth_gssapi_mic_function;
|
||||
|
||||
/** this function gets called when a client tries to authenticate or offer
|
||||
* a public key.
|
||||
*/
|
||||
ssh_auth_pubkey_callback auth_pubkey_function;
|
||||
|
||||
/** This functions gets called when a service request is issued by the
|
||||
* client
|
||||
*/
|
||||
ssh_service_request_callback service_request_function;
|
||||
/** This functions gets called when a new channel request is issued by
|
||||
* the client
|
||||
*/
|
||||
ssh_channel_open_request_session_callback channel_open_request_session_function;
|
||||
/** This function will be called when a new gssapi authentication is attempted.
|
||||
*/
|
||||
ssh_gssapi_select_oid_callback gssapi_select_oid_function;
|
||||
/** This function will be called when a gssapi token comes in.
|
||||
*/
|
||||
ssh_gssapi_accept_sec_ctx_callback gssapi_accept_sec_ctx_function;
|
||||
/* This function will be called when a MIC needs to be verified.
|
||||
*/
|
||||
ssh_gssapi_verify_mic_callback gssapi_verify_mic_function;
|
||||
};
|
||||
typedef struct ssh_server_callbacks_struct *ssh_server_callbacks;
|
||||
|
||||
/**
|
||||
* @brief Set the session server callback functions.
|
||||
*
|
||||
* This functions sets the callback structure to use your own callback
|
||||
* functions for user authentication, new channels and requests.
|
||||
*
|
||||
* @code
|
||||
* struct ssh_server_callbacks_struct cb = {
|
||||
* .userdata = data,
|
||||
* .auth_password_function = my_auth_function
|
||||
* };
|
||||
* ssh_callbacks_init(&cb);
|
||||
* ssh_set_server_callbacks(session, &cb);
|
||||
* @endcode
|
||||
*
|
||||
* @param session The session to set the callback structure.
|
||||
*
|
||||
* @param cb The callback structure itself.
|
||||
*
|
||||
* @return SSH_OK on success, SSH_ERROR on error.
|
||||
*/
|
||||
LIBSSH_API int ssh_set_server_callbacks(ssh_session session, ssh_server_callbacks cb);
|
||||
|
||||
/**
|
||||
* These are the callbacks exported by the socket structure
|
||||
* They are called by the socket module when a socket event appears
|
||||
*/
|
||||
struct ssh_socket_callbacks_struct {
|
||||
/**
|
||||
* User-provided data. User is free to set anything he wants here
|
||||
*/
|
||||
void *userdata;
|
||||
/**
|
||||
* This function will be called each time data appears on socket. The data
|
||||
* not consumed will appear on the next data event.
|
||||
/** size of this structure. internal, shoud be set with ssh_callbacks_init()*/
|
||||
size_t size;
|
||||
/** User-provided data. User is free to set anything he wants here */
|
||||
void *userdata;
|
||||
/** this functions will be called if e.g. a keyphrase is needed. */
|
||||
ssh_auth_callback auth_function;
|
||||
/** this function will be called each time a loggable event happens. */
|
||||
ssh_log_callback log_function;
|
||||
/** this function gets called during connection time to indicate the percentage
|
||||
* of connection steps completed.
|
||||
*/
|
||||
ssh_callback_data data;
|
||||
/** This function will be called each time a controlflow state changes, i.e.
|
||||
* the socket is available for reading or writing.
|
||||
*/
|
||||
ssh_callback_int controlflow;
|
||||
/** This function will be called each time an exception appears on socket. An
|
||||
* exception can be a socket problem (timeout, ...) or an end-of-file.
|
||||
*/
|
||||
ssh_callback_int_int exception;
|
||||
/** This function is called when the ssh_socket_connect was used on the socket
|
||||
* on nonblocking state, and the connection successed.
|
||||
*/
|
||||
ssh_callback_int_int connected;
|
||||
void (*connect_status_function)(void *userdata, float status);
|
||||
};
|
||||
typedef struct ssh_socket_callbacks_struct *ssh_socket_callbacks;
|
||||
|
||||
#define SSH_SOCKET_FLOW_WRITEWILLBLOCK 1
|
||||
#define SSH_SOCKET_FLOW_WRITEWONTBLOCK 2
|
||||
typedef struct ssh_callbacks_struct * ssh_callbacks;
|
||||
|
||||
#define SSH_SOCKET_EXCEPTION_EOF 1
|
||||
#define SSH_SOCKET_EXCEPTION_ERROR 2
|
||||
|
||||
#define SSH_SOCKET_CONNECTED_OK 1
|
||||
#define SSH_SOCKET_CONNECTED_ERROR 2
|
||||
#define SSH_SOCKET_CONNECTED_TIMEOUT 3
|
||||
|
||||
/**
|
||||
* @brief Initializes an ssh_callbacks_struct
|
||||
/** Initializes an ssh_callbacks_struct
|
||||
* A call to this macro is mandatory when you have set a new
|
||||
* ssh_callback_struct structure. Its goal is to maintain the binary
|
||||
* compatibility with future versions of libssh as the structure
|
||||
@@ -407,449 +83,31 @@ typedef struct ssh_socket_callbacks_struct *ssh_socket_callbacks;
|
||||
} while(0);
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* @brief tests if a callback can be called without crash
|
||||
* verifies that the struct size if big enough
|
||||
* verifies that the callback pointer exists
|
||||
* @param p callback pointer
|
||||
* @param c callback name
|
||||
* @returns nonzero if callback can be called
|
||||
*/
|
||||
#define ssh_callbacks_exists(p,c) (\
|
||||
(p != NULL) && ( (char *)&((p)-> c) < (char *)(p) + (p)->size ) && \
|
||||
((p)-> c != NULL) \
|
||||
)
|
||||
|
||||
/** @brief Prototype for a packet callback, to be called when a new packet arrives
|
||||
* @param session The current session of the packet
|
||||
* @param type packet type (see ssh2.h)
|
||||
* @param packet buffer containing the packet, excluding size, type and padding fields
|
||||
* @param user user argument to the callback
|
||||
* and are called each time a packet shows up
|
||||
* @returns SSH_PACKET_USED Packet was parsed and used
|
||||
* @returns SSH_PACKET_NOT_USED Packet was not used or understood, processing must continue
|
||||
*/
|
||||
typedef int (*ssh_packet_callback) (ssh_session session, uint8_t type, ssh_buffer packet, void *user);
|
||||
|
||||
/** return values for a ssh_packet_callback */
|
||||
/** Packet was used and should not be parsed by another callback */
|
||||
#define SSH_PACKET_USED 1
|
||||
/** Packet was not used and should be passed to any other callback
|
||||
* available */
|
||||
#define SSH_PACKET_NOT_USED 2
|
||||
|
||||
|
||||
/** @brief This macro declares a packet callback handler
|
||||
* @code
|
||||
* SSH_PACKET_CALLBACK(mycallback){
|
||||
* ...
|
||||
* }
|
||||
* @endcode
|
||||
*/
|
||||
#define SSH_PACKET_CALLBACK(name) \
|
||||
int name (ssh_session session, uint8_t type, ssh_buffer packet, void *user)
|
||||
|
||||
struct ssh_packet_callbacks_struct {
|
||||
/** Index of the first packet type being handled */
|
||||
uint8_t start;
|
||||
/** Number of packets being handled by this callback struct */
|
||||
uint8_t n_callbacks;
|
||||
/** A pointer to n_callbacks packet callbacks */
|
||||
ssh_packet_callback *callbacks;
|
||||
/**
|
||||
* User-provided data. User is free to set anything he wants here
|
||||
*/
|
||||
void *user;
|
||||
};
|
||||
|
||||
typedef struct ssh_packet_callbacks_struct *ssh_packet_callbacks;
|
||||
|
||||
/**
|
||||
* @brief Set the session callback functions.
|
||||
* @brief Set the callback functions.
|
||||
*
|
||||
* This functions sets the callback structure to use your own callback
|
||||
* functions for auth, logging and status.
|
||||
*
|
||||
* @code
|
||||
* struct ssh_callbacks_struct cb = {
|
||||
* .userdata = data,
|
||||
* .auth_function = my_auth_function
|
||||
* };
|
||||
* struct ssh_callbacks_struct cb;
|
||||
* memset(&cb, 0, sizeof(struct ssh_callbacks_struct));
|
||||
* cb.userdata = data;
|
||||
* cb.auth_function = my_auth_function;
|
||||
*
|
||||
* ssh_callbacks_init(&cb);
|
||||
* ssh_set_callbacks(session, &cb);
|
||||
* @endcode
|
||||
*
|
||||
* @param session The session to set the callback structure.
|
||||
*
|
||||
* @param cb The callback structure itself.
|
||||
* @param cb The callback itself.
|
||||
*
|
||||
* @return SSH_OK on success, SSH_ERROR on error.
|
||||
* @return 0 on success, < 0 on error.
|
||||
*/
|
||||
LIBSSH_API int ssh_set_callbacks(ssh_session session, ssh_callbacks cb);
|
||||
|
||||
/**
|
||||
* @brief SSH channel data callback. Called when data is available on a channel
|
||||
* @param session Current session handler
|
||||
* @param channel the actual channel
|
||||
* @param data the data that has been read on the channel
|
||||
* @param len the length of the data
|
||||
* @param is_stderr is 0 for stdout or 1 for stderr
|
||||
* @param userdata Userdata to be passed to the callback function.
|
||||
* @returns number of bytes processed by the callee. The remaining bytes will
|
||||
* be sent in the next callback message, when more data is available.
|
||||
*/
|
||||
typedef int (*ssh_channel_data_callback) (ssh_session session,
|
||||
ssh_channel channel,
|
||||
void *data,
|
||||
uint32_t len,
|
||||
int is_stderr,
|
||||
void *userdata);
|
||||
|
||||
/**
|
||||
* @brief SSH channel eof callback. Called when a channel receives EOF
|
||||
* @param session Current session handler
|
||||
* @param channel the actual channel
|
||||
* @param userdata Userdata to be passed to the callback function.
|
||||
*/
|
||||
typedef void (*ssh_channel_eof_callback) (ssh_session session,
|
||||
ssh_channel channel,
|
||||
void *userdata);
|
||||
|
||||
/**
|
||||
* @brief SSH channel close callback. Called when a channel is closed by remote peer
|
||||
* @param session Current session handler
|
||||
* @param channel the actual channel
|
||||
* @param userdata Userdata to be passed to the callback function.
|
||||
*/
|
||||
typedef void (*ssh_channel_close_callback) (ssh_session session,
|
||||
ssh_channel channel,
|
||||
void *userdata);
|
||||
|
||||
/**
|
||||
* @brief SSH channel signal callback. Called when a channel has received a signal
|
||||
* @param session Current session handler
|
||||
* @param channel the actual channel
|
||||
* @param signal the signal name (without the SIG prefix)
|
||||
* @param userdata Userdata to be passed to the callback function.
|
||||
*/
|
||||
typedef void (*ssh_channel_signal_callback) (ssh_session session,
|
||||
ssh_channel channel,
|
||||
const char *signal,
|
||||
void *userdata);
|
||||
|
||||
/**
|
||||
* @brief SSH channel exit status callback. Called when a channel has received an exit status
|
||||
* @param session Current session handler
|
||||
* @param channel the actual channel
|
||||
* @param userdata Userdata to be passed to the callback function.
|
||||
*/
|
||||
typedef void (*ssh_channel_exit_status_callback) (ssh_session session,
|
||||
ssh_channel channel,
|
||||
int exit_status,
|
||||
void *userdata);
|
||||
|
||||
/**
|
||||
* @brief SSH channel exit signal callback. Called when a channel has received an exit signal
|
||||
* @param session Current session handler
|
||||
* @param channel the actual channel
|
||||
* @param signal the signal name (without the SIG prefix)
|
||||
* @param core a boolean telling wether a core has been dumped or not
|
||||
* @param errmsg the description of the exception
|
||||
* @param lang the language of the description (format: RFC 3066)
|
||||
* @param userdata Userdata to be passed to the callback function.
|
||||
*/
|
||||
typedef void (*ssh_channel_exit_signal_callback) (ssh_session session,
|
||||
ssh_channel channel,
|
||||
const char *signal,
|
||||
int core,
|
||||
const char *errmsg,
|
||||
const char *lang,
|
||||
void *userdata);
|
||||
|
||||
/**
|
||||
* @brief SSH channel PTY request from a client.
|
||||
* @param channel the channel
|
||||
* @param term The type of terminal emulation
|
||||
* @param width width of the terminal, in characters
|
||||
* @param height height of the terminal, in characters
|
||||
* @param pxwidth width of the terminal, in pixels
|
||||
* @param pxheight height of the terminal, in pixels
|
||||
* @param userdata Userdata to be passed to the callback function.
|
||||
* @returns 0 if the pty request is accepted
|
||||
* @returns -1 if the request is denied
|
||||
*/
|
||||
typedef int (*ssh_channel_pty_request_callback) (ssh_session session,
|
||||
ssh_channel channel,
|
||||
const char *term,
|
||||
int width, int height,
|
||||
int pxwidth, int pwheight,
|
||||
void *userdata);
|
||||
|
||||
/**
|
||||
* @brief SSH channel Shell request from a client.
|
||||
* @param channel the channel
|
||||
* @param userdata Userdata to be passed to the callback function.
|
||||
* @returns 0 if the shell request is accepted
|
||||
* @returns 1 if the request is denied
|
||||
*/
|
||||
typedef int (*ssh_channel_shell_request_callback) (ssh_session session,
|
||||
ssh_channel channel,
|
||||
void *userdata);
|
||||
/**
|
||||
* @brief SSH auth-agent-request from the client. This request is
|
||||
* sent by a client when agent forwarding is available.
|
||||
* Server is free to ignore this callback, no answer is expected.
|
||||
* @param channel the channel
|
||||
* @param userdata Userdata to be passed to the callback function.
|
||||
*/
|
||||
typedef void (*ssh_channel_auth_agent_req_callback) (ssh_session session,
|
||||
ssh_channel channel,
|
||||
void *userdata);
|
||||
|
||||
/**
|
||||
* @brief SSH X11 request from the client. This request is
|
||||
* sent by a client when X11 forwarding is requested(and available).
|
||||
* Server is free to ignore this callback, no answer is expected.
|
||||
* @param channel the channel
|
||||
* @param userdata Userdata to be passed to the callback function.
|
||||
*/
|
||||
typedef void (*ssh_channel_x11_req_callback) (ssh_session session,
|
||||
ssh_channel channel,
|
||||
int single_connection,
|
||||
const char *auth_protocol,
|
||||
const char *auth_cookie,
|
||||
uint32_t screen_number,
|
||||
void *userdata);
|
||||
/**
|
||||
* @brief SSH channel PTY windows change (terminal size) from a client.
|
||||
* @param channel the channel
|
||||
* @param width width of the terminal, in characters
|
||||
* @param height height of the terminal, in characters
|
||||
* @param pxwidth width of the terminal, in pixels
|
||||
* @param pxheight height of the terminal, in pixels
|
||||
* @param userdata Userdata to be passed to the callback function.
|
||||
* @returns 0 if the pty request is accepted
|
||||
* @returns -1 if the request is denied
|
||||
*/
|
||||
typedef int (*ssh_channel_pty_window_change_callback) (ssh_session session,
|
||||
ssh_channel channel,
|
||||
int width, int height,
|
||||
int pxwidth, int pwheight,
|
||||
void *userdata);
|
||||
|
||||
/**
|
||||
* @brief SSH channel Exec request from a client.
|
||||
* @param channel the channel
|
||||
* @param command the shell command to be executed
|
||||
* @param userdata Userdata to be passed to the callback function.
|
||||
* @returns 0 if the exec request is accepted
|
||||
* @returns 1 if the request is denied
|
||||
*/
|
||||
typedef int (*ssh_channel_exec_request_callback) (ssh_session session,
|
||||
ssh_channel channel,
|
||||
const char *command,
|
||||
void *userdata);
|
||||
|
||||
/**
|
||||
* @brief SSH channel environment request from a client.
|
||||
* @param channel the channel
|
||||
* @param env_name name of the environment value to be set
|
||||
* @param env_value value of the environment value to be set
|
||||
* @param userdata Userdata to be passed to the callback function.
|
||||
* @returns 0 if the env request is accepted
|
||||
* @returns 1 if the request is denied
|
||||
* @warning some environment variables can be dangerous if changed (e.g.
|
||||
* LD_PRELOAD) and should not be fulfilled.
|
||||
*/
|
||||
typedef int (*ssh_channel_env_request_callback) (ssh_session session,
|
||||
ssh_channel channel,
|
||||
const char *env_name,
|
||||
const char *env_value,
|
||||
void *userdata);
|
||||
/**
|
||||
* @brief SSH channel subsystem request from a client.
|
||||
* @param channel the channel
|
||||
* @param subsystem the subsystem required
|
||||
* @param userdata Userdata to be passed to the callback function.
|
||||
* @returns 0 if the subsystem request is accepted
|
||||
* @returns 1 if the request is denied
|
||||
*/
|
||||
typedef int (*ssh_channel_subsystem_request_callback) (ssh_session session,
|
||||
ssh_channel channel,
|
||||
const char *subsystem,
|
||||
void *userdata);
|
||||
|
||||
|
||||
struct ssh_channel_callbacks_struct {
|
||||
/** DON'T SET THIS use ssh_callbacks_init() instead. */
|
||||
size_t size;
|
||||
/**
|
||||
* User-provided data. User is free to set anything he wants here
|
||||
*/
|
||||
void *userdata;
|
||||
/**
|
||||
* This functions will be called when there is data available.
|
||||
*/
|
||||
ssh_channel_data_callback channel_data_function;
|
||||
/**
|
||||
* This functions will be called when the channel has received an EOF.
|
||||
*/
|
||||
ssh_channel_eof_callback channel_eof_function;
|
||||
/**
|
||||
* This functions will be called when the channel has been closed by remote
|
||||
*/
|
||||
ssh_channel_close_callback channel_close_function;
|
||||
/**
|
||||
* This functions will be called when a signal has been received
|
||||
*/
|
||||
ssh_channel_signal_callback channel_signal_function;
|
||||
/**
|
||||
* This functions will be called when an exit status has been received
|
||||
*/
|
||||
ssh_channel_exit_status_callback channel_exit_status_function;
|
||||
/**
|
||||
* This functions will be called when an exit signal has been received
|
||||
*/
|
||||
ssh_channel_exit_signal_callback channel_exit_signal_function;
|
||||
/**
|
||||
* This function will be called when a client requests a PTY
|
||||
*/
|
||||
ssh_channel_pty_request_callback channel_pty_request_function;
|
||||
/**
|
||||
* This function will be called when a client requests a shell
|
||||
*/
|
||||
ssh_channel_shell_request_callback channel_shell_request_function;
|
||||
/** This function will be called when a client requests agent
|
||||
* authentication forwarding.
|
||||
*/
|
||||
ssh_channel_auth_agent_req_callback channel_auth_agent_req_function;
|
||||
/** This function will be called when a client requests X11
|
||||
* forwarding.
|
||||
*/
|
||||
ssh_channel_x11_req_callback channel_x11_req_function;
|
||||
/** This function will be called when a client requests a
|
||||
* window change.
|
||||
*/
|
||||
ssh_channel_pty_window_change_callback channel_pty_window_change_function;
|
||||
/** This function will be called when a client requests a
|
||||
* command execution.
|
||||
*/
|
||||
ssh_channel_exec_request_callback channel_exec_request_function;
|
||||
/** This function will be called when a client requests an environment
|
||||
* variable to be set.
|
||||
*/
|
||||
ssh_channel_env_request_callback channel_env_request_function;
|
||||
/** This function will be called when a client requests a subsystem
|
||||
* (like sftp).
|
||||
*/
|
||||
ssh_channel_subsystem_request_callback channel_subsystem_request_function;
|
||||
};
|
||||
|
||||
typedef struct ssh_channel_callbacks_struct *ssh_channel_callbacks;
|
||||
|
||||
/**
|
||||
* @brief Set the channel callback functions.
|
||||
*
|
||||
* This functions sets the callback structure to use your own callback
|
||||
* functions for channel data and exceptions
|
||||
*
|
||||
* @code
|
||||
* struct ssh_channel_callbacks_struct cb = {
|
||||
* .userdata = data,
|
||||
* .channel_data = my_channel_data_function
|
||||
* };
|
||||
* ssh_callbacks_init(&cb);
|
||||
* ssh_set_channel_callbacks(channel, &cb);
|
||||
* @endcode
|
||||
*
|
||||
* @param channel The channel to set the callback structure.
|
||||
*
|
||||
* @param cb The callback structure itself.
|
||||
*
|
||||
* @return SSH_OK on success, SSH_ERROR on error.
|
||||
*/
|
||||
LIBSSH_API int ssh_set_channel_callbacks(ssh_channel channel,
|
||||
ssh_channel_callbacks cb);
|
||||
|
||||
/** @} */
|
||||
|
||||
/** @group libssh_threads
|
||||
* @{
|
||||
*/
|
||||
|
||||
typedef int (*ssh_thread_callback) (void **lock);
|
||||
|
||||
typedef unsigned long (*ssh_thread_id_callback) (void);
|
||||
struct ssh_threads_callbacks_struct {
|
||||
const char *type;
|
||||
ssh_thread_callback mutex_init;
|
||||
ssh_thread_callback mutex_destroy;
|
||||
ssh_thread_callback mutex_lock;
|
||||
ssh_thread_callback mutex_unlock;
|
||||
ssh_thread_id_callback thread_id;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Set the thread callbacks structure.
|
||||
*
|
||||
* This is necessary if your program is using libssh in a multithreaded fashion.
|
||||
* This function must be called first, outside of any threading context (in your
|
||||
* main() function for instance), before you call ssh_init().
|
||||
*
|
||||
* @param[in] cb A pointer to a ssh_threads_callbacks_struct structure, which
|
||||
* contains the different callbacks to be set.
|
||||
*
|
||||
* @returns Always returns SSH_OK.
|
||||
*
|
||||
* @see ssh_threads_callbacks_struct
|
||||
* @see SSH_THREADS_PTHREAD
|
||||
* @bug libgcrypt 1.6 and bigger backend does not support custom callback.
|
||||
* Using anything else than pthreads here will fail.
|
||||
*/
|
||||
LIBSSH_API int ssh_threads_set_callbacks(struct ssh_threads_callbacks_struct
|
||||
*cb);
|
||||
|
||||
/**
|
||||
* @brief returns a pointer on the pthread threads callbacks, to be used with
|
||||
* ssh_threads_set_callbacks.
|
||||
* @warning you have to link with the library ssh_threads.
|
||||
* @see ssh_threads_set_callbacks
|
||||
*/
|
||||
LIBSSH_API struct ssh_threads_callbacks_struct *ssh_threads_get_pthread(void);
|
||||
|
||||
/**
|
||||
* @brief Get the noop threads callbacks structure
|
||||
*
|
||||
* This can be used with ssh_threads_set_callbacks. These callbacks do nothing
|
||||
* and are being used by default.
|
||||
*
|
||||
* @return Always returns a valid pointer to the noop callbacks structure.
|
||||
*
|
||||
* @see ssh_threads_set_callbacks
|
||||
*/
|
||||
LIBSSH_API struct ssh_threads_callbacks_struct *ssh_threads_get_noop(void);
|
||||
|
||||
/**
|
||||
* @brief Set the logging callback function.
|
||||
*
|
||||
* @param[in] cb The callback to set.
|
||||
*
|
||||
* @return 0 on success, < 0 on errror.
|
||||
*/
|
||||
LIBSSH_API int ssh_set_log_callback(ssh_logging_callback cb);
|
||||
|
||||
/**
|
||||
* @brief Get the pointer to the logging callback function.
|
||||
*
|
||||
* @return The pointer the the callback or NULL if none set.
|
||||
*/
|
||||
LIBSSH_API ssh_logging_callback ssh_get_log_callback(void);
|
||||
|
||||
/** @} */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /*_SSH_CALLBACK_H */
|
||||
|
||||
/* @} */
|
||||
|
||||
@@ -3,58 +3,29 @@
|
||||
*
|
||||
* Copyright (c) 2009 by Aris Adamantiadis
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
* The SSH Library is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation; either version 2.1 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
* The SSH Library is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with the SSH Library; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
|
||||
* MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef CHANNELS_H_
|
||||
#define CHANNELS_H_
|
||||
#include "libssh/priv.h"
|
||||
|
||||
/** @internal
|
||||
* Describes the different possible states in a
|
||||
* outgoing (client) channel request
|
||||
*/
|
||||
enum ssh_channel_request_state_e {
|
||||
/** No request has been made */
|
||||
SSH_CHANNEL_REQ_STATE_NONE = 0,
|
||||
/** A request has been made and answer is pending */
|
||||
SSH_CHANNEL_REQ_STATE_PENDING,
|
||||
/** A request has been replied and accepted */
|
||||
SSH_CHANNEL_REQ_STATE_ACCEPTED,
|
||||
/** A request has been replied and refused */
|
||||
SSH_CHANNEL_REQ_STATE_DENIED,
|
||||
/** A request has been replied and an error happend */
|
||||
SSH_CHANNEL_REQ_STATE_ERROR
|
||||
};
|
||||
|
||||
enum ssh_channel_state_e {
|
||||
SSH_CHANNEL_STATE_NOT_OPEN = 0,
|
||||
SSH_CHANNEL_STATE_OPENING,
|
||||
SSH_CHANNEL_STATE_OPEN_DENIED,
|
||||
SSH_CHANNEL_STATE_OPEN,
|
||||
SSH_CHANNEL_STATE_CLOSED
|
||||
};
|
||||
|
||||
/* The channel has been closed by the remote side */
|
||||
#define SSH_CHANNEL_FLAG_CLOSED_REMOTE 0x1
|
||||
/* The channel has been freed by the calling program */
|
||||
#define SSH_CHANNEL_FLAG_FREED_LOCAL 0x2
|
||||
/* the channel has not yet been bound to a remote one */
|
||||
#define SSH_CHANNEL_FLAG_NOT_BOUND 0x4
|
||||
|
||||
struct ssh_channel_struct {
|
||||
struct ssh_channel_struct *prev;
|
||||
struct ssh_channel_struct *next;
|
||||
ssh_session session; /* SSH_SESSION pointer */
|
||||
uint32_t local_channel;
|
||||
uint32_t local_window;
|
||||
@@ -65,54 +36,23 @@ struct ssh_channel_struct {
|
||||
uint32_t remote_window;
|
||||
int remote_eof; /* end of file received */
|
||||
uint32_t remote_maxpacket;
|
||||
enum ssh_channel_state_e state;
|
||||
int open; /* shows if the channel is still opened */
|
||||
int delayed_close;
|
||||
int flags;
|
||||
ssh_buffer stdout_buffer;
|
||||
ssh_buffer stderr_buffer;
|
||||
void *userarg;
|
||||
int version;
|
||||
int blocking;
|
||||
int exit_status;
|
||||
enum ssh_channel_request_state_e request_state;
|
||||
ssh_channel_callbacks callbacks;
|
||||
/* counters */
|
||||
ssh_counter counter;
|
||||
};
|
||||
|
||||
SSH_PACKET_CALLBACK(ssh_packet_channel_open_conf);
|
||||
SSH_PACKET_CALLBACK(ssh_packet_channel_open_fail);
|
||||
SSH_PACKET_CALLBACK(ssh_packet_channel_success);
|
||||
SSH_PACKET_CALLBACK(ssh_packet_channel_failure);
|
||||
SSH_PACKET_CALLBACK(ssh_request_success);
|
||||
SSH_PACKET_CALLBACK(ssh_request_denied);
|
||||
|
||||
SSH_PACKET_CALLBACK(channel_rcv_change_window);
|
||||
SSH_PACKET_CALLBACK(channel_rcv_eof);
|
||||
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);
|
||||
void channel_handle(ssh_session session, int type);
|
||||
ssh_channel 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);
|
||||
uint32_t ssh_channel_new_id(ssh_session session);
|
||||
ssh_channel ssh_channel_from_local(ssh_session session, uint32_t id);
|
||||
void ssh_channel_do_free(ssh_channel channel);
|
||||
#ifdef WITH_SSH1
|
||||
SSH_PACKET_CALLBACK(ssh_packet_data1);
|
||||
SSH_PACKET_CALLBACK(ssh_packet_close1);
|
||||
SSH_PACKET_CALLBACK(ssh_packet_exist_status1);
|
||||
|
||||
/* channels1.c */
|
||||
int channel_open_session1(ssh_channel channel);
|
||||
int channel_request_pty_size1(ssh_channel channel, const char *terminal,
|
||||
int cols, int rows);
|
||||
int channel_change_pty_size1(ssh_channel channel, int cols, int rows);
|
||||
int channel_request_shell1(ssh_channel channel);
|
||||
int channel_request_exec1(ssh_channel channel, const char *cmd);
|
||||
int channel_write1(ssh_channel channel, const void *data, int len);
|
||||
ssh_channel ssh_get_channel1(ssh_session session);
|
||||
#endif
|
||||
int channel_write_common(ssh_channel channel, const void *data,
|
||||
uint32_t len, int is_stderr);
|
||||
|
||||
#endif /* CHANNELS_H_ */
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
/*
|
||||
* crc32.c - simple CRC32 code
|
||||
*
|
||||
* This file is part of the SSH Library
|
||||
*
|
||||
* Copyright (c) 2005 by Aris Adamantiadis
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef _CRC32_H
|
||||
#define _CRC32_H
|
||||
|
||||
uint32_t ssh_crc32(const char *buf, uint32_t len);
|
||||
|
||||
#endif /* _CRC32_H */
|
||||
@@ -1,21 +1,22 @@
|
||||
/*
|
||||
* This file is part of the SSH Library
|
||||
*
|
||||
* Copyright (c) 2003-2009 by Aris Adamantiadis
|
||||
* Copyright (c) 2003,2009 by Aris Adamantiadis
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
* The SSH Library is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation; either version 2.1 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
* The SSH Library is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with the SSH Library; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
|
||||
* MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
@@ -39,69 +40,29 @@
|
||||
#undef cbc_decrypt
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_OPENSSL_ECDH_H
|
||||
#include <openssl/ecdh.h>
|
||||
#endif
|
||||
#include "libssh/ecdh.h"
|
||||
#include "libssh/kex.h"
|
||||
#include "libssh/curve25519.h"
|
||||
|
||||
#define DIGEST_MAX_LEN 64
|
||||
|
||||
enum ssh_key_exchange_e {
|
||||
/* diffie-hellman-group1-sha1 */
|
||||
SSH_KEX_DH_GROUP1_SHA1=1,
|
||||
/* diffie-hellman-group14-sha1 */
|
||||
SSH_KEX_DH_GROUP14_SHA1,
|
||||
/* ecdh-sha2-nistp256 */
|
||||
SSH_KEX_ECDH_SHA2_NISTP256,
|
||||
/* curve25519-sha256@libssh.org */
|
||||
SSH_KEX_CURVE25519_SHA256_LIBSSH_ORG
|
||||
};
|
||||
|
||||
struct ssh_crypto_struct {
|
||||
bignum e,f,x,k,y;
|
||||
#ifdef HAVE_ECDH
|
||||
EC_KEY *ecdh_privkey;
|
||||
ssh_string ecdh_client_pubkey;
|
||||
ssh_string ecdh_server_pubkey;
|
||||
#endif
|
||||
#ifdef HAVE_CURVE25519
|
||||
ssh_curve25519_privkey curve25519_privkey;
|
||||
ssh_curve25519_pubkey curve25519_client_pubkey;
|
||||
ssh_curve25519_pubkey curve25519_server_pubkey;
|
||||
#endif
|
||||
ssh_string dh_server_signature; /* information used by dh_handshake. */
|
||||
size_t digest_len; /* len of all the fields below */
|
||||
unsigned char *session_id;
|
||||
unsigned char *secret_hash; /* Secret hash is same as session id until re-kex */
|
||||
unsigned char *encryptIV;
|
||||
unsigned char *decryptIV;
|
||||
unsigned char *decryptkey;
|
||||
unsigned char *encryptkey;
|
||||
unsigned char *encryptMAC;
|
||||
unsigned char *decryptMAC;
|
||||
unsigned char hmacbuf[DIGEST_MAX_LEN];
|
||||
struct ssh_cipher_struct *in_cipher, *out_cipher; /* the cipher structures/objects */
|
||||
enum ssh_hmac_e in_hmac, out_hmac; /* the MAC algorithms used */
|
||||
unsigned char session_id[SHA_DIGEST_LEN];
|
||||
|
||||
unsigned char encryptIV[SHA_DIGEST_LEN*2];
|
||||
unsigned char decryptIV[SHA_DIGEST_LEN*2];
|
||||
|
||||
unsigned char decryptkey[SHA_DIGEST_LEN*2];
|
||||
unsigned char encryptkey[SHA_DIGEST_LEN*2];
|
||||
|
||||
unsigned char encryptMAC[SHA_DIGEST_LEN];
|
||||
unsigned char decryptMAC[SHA_DIGEST_LEN];
|
||||
unsigned char hmacbuf[EVP_MAX_MD_SIZE];
|
||||
struct crypto_struct *in_cipher, *out_cipher; /* the cipher structures/objects */
|
||||
ssh_string server_pubkey;
|
||||
const char *server_pubkey_type;
|
||||
int do_compress_out; /* idem */
|
||||
int do_compress_in; /* don't set them, set the option instead */
|
||||
int delayed_compress_in; /* Use of zlib@openssh.org */
|
||||
int delayed_compress_out;
|
||||
void *compress_out_ctx; /* don't touch it */
|
||||
void *compress_in_ctx; /* really, don't */
|
||||
/* kex sent by server, client, and mutually elected methods */
|
||||
struct ssh_kex_struct server_kex;
|
||||
struct ssh_kex_struct client_kex;
|
||||
char *kex_methods[SSH_KEX_METHODS];
|
||||
enum ssh_key_exchange_e kex_type;
|
||||
enum ssh_mac_e mac_type; /* Mac operations to use for key gen */
|
||||
};
|
||||
|
||||
struct ssh_cipher_struct {
|
||||
struct crypto_struct {
|
||||
const char *name; /* ssh name of the algorithm */
|
||||
unsigned int blocksize; /* blocksize of the algo */
|
||||
unsigned int keylen; /* length of the key structure */
|
||||
@@ -109,16 +70,25 @@ struct ssh_cipher_struct {
|
||||
gcry_cipher_hd_t *key;
|
||||
#elif defined HAVE_LIBCRYPTO
|
||||
void *key; /* a key buffer allocated for the algo */
|
||||
void *IV;
|
||||
#endif
|
||||
unsigned int keysize; /* bytes of key used. != keylen */
|
||||
#ifdef HAVE_LIBGCRYPT
|
||||
/* sets the new key for immediate use */
|
||||
int (*set_encrypt_key)(struct ssh_cipher_struct *cipher, void *key, void *IV);
|
||||
int (*set_decrypt_key)(struct ssh_cipher_struct *cipher, void *key, void *IV);
|
||||
void (*encrypt)(struct ssh_cipher_struct *cipher, void *in, void *out,
|
||||
int (*set_encrypt_key)(struct crypto_struct *cipher, void *key, void *IV);
|
||||
int (*set_decrypt_key)(struct crypto_struct *cipher, void *key, void *IV);
|
||||
void (*cbc_encrypt)(struct crypto_struct *cipher, void *in, void *out,
|
||||
unsigned long len);
|
||||
void (*decrypt)(struct ssh_cipher_struct *cipher, void *in, void *out,
|
||||
void (*cbc_decrypt)(struct crypto_struct *cipher, void *in, void *out,
|
||||
unsigned long len);
|
||||
#elif defined HAVE_LIBCRYPTO
|
||||
/* sets the new key for immediate use */
|
||||
int (*set_encrypt_key)(struct crypto_struct *cipher, void *key);
|
||||
int (*set_decrypt_key)(struct crypto_struct *cipher, void *key);
|
||||
void (*cbc_encrypt)(struct crypto_struct *cipher, void *in, void *out,
|
||||
unsigned long len, void *IV);
|
||||
void (*cbc_decrypt)(struct crypto_struct *cipher, void *in, void *out,
|
||||
unsigned long len, void *IV);
|
||||
#endif
|
||||
};
|
||||
|
||||
/* vim: set ts=2 sw=2 et cindent: */
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
/*
|
||||
* This file is part of the SSH Library
|
||||
*
|
||||
* Copyright (c) 2013 by Aris Adamantiadis <aris@badcode.be>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation,
|
||||
* version 2.1 of the License.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef CURVE25519_H_
|
||||
#define CURVE25519_H_
|
||||
|
||||
#include "config.h"
|
||||
#include "libssh.h"
|
||||
|
||||
#ifdef WITH_NACL
|
||||
|
||||
#include <nacl/crypto_scalarmult_curve25519.h>
|
||||
#define CURVE25519_PUBKEY_SIZE crypto_scalarmult_curve25519_BYTES
|
||||
#define CURVE25519_PRIVKEY_SIZE crypto_scalarmult_curve25519_SCALARBYTES
|
||||
#define crypto_scalarmult_base crypto_scalarmult_curve25519_base
|
||||
#define crypto_scalarmult crypto_scalarmult_curve25519
|
||||
#else
|
||||
|
||||
#define CURVE25519_PUBKEY_SIZE 32
|
||||
#define CURVE25519_PRIVKEY_SIZE 32
|
||||
int crypto_scalarmult_base(unsigned char *q, const unsigned char *n);
|
||||
int crypto_scalarmult(unsigned char *q, const unsigned char *n, const unsigned char *p);
|
||||
#endif /* WITH_NACL */
|
||||
|
||||
#ifdef HAVE_ECC
|
||||
#define HAVE_CURVE25519 1
|
||||
#endif
|
||||
|
||||
typedef unsigned char ssh_curve25519_pubkey[CURVE25519_PUBKEY_SIZE];
|
||||
typedef unsigned char ssh_curve25519_privkey[CURVE25519_PRIVKEY_SIZE];
|
||||
|
||||
|
||||
int ssh_client_curve25519_init(ssh_session session);
|
||||
int ssh_client_curve25519_reply(ssh_session session, ssh_buffer packet);
|
||||
|
||||
#ifdef WITH_SERVER
|
||||
int ssh_server_curve25519_init(ssh_session session, ssh_buffer packet);
|
||||
#endif /* WITH_SERVER */
|
||||
|
||||
#endif /* CURVE25519_H_ */
|
||||
@@ -3,28 +3,30 @@
|
||||
*
|
||||
* Copyright (c) 2009 by Aris Adamantiadis
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
* The SSH Library is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation; either version 2.1 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
* The SSH Library is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with the SSH Library; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
|
||||
* MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef DH_H_
|
||||
#define DH_H_
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "libssh/crypto.h"
|
||||
/* DH key generation */
|
||||
#include "libssh/keys.h"
|
||||
|
||||
void ssh_print_bignum(const char *which,bignum num);
|
||||
int dh_generate_e(ssh_session session);
|
||||
int dh_generate_f(ssh_session session);
|
||||
int dh_generate_x(ssh_session session);
|
||||
@@ -39,13 +41,17 @@ int dh_import_f(ssh_session session,ssh_string f_string);
|
||||
int dh_import_e(ssh_session session, ssh_string e_string);
|
||||
void dh_import_pubkey(ssh_session session,ssh_string pubkey_string);
|
||||
int dh_build_k(ssh_session session);
|
||||
int ssh_client_dh_init(ssh_session session);
|
||||
int ssh_client_dh_reply(ssh_session session, ssh_buffer packet);
|
||||
|
||||
int make_sessionid(ssh_session session);
|
||||
/* add data for the final cookie */
|
||||
int hashbufin_add_cookie(ssh_session session, unsigned char *cookie);
|
||||
int hashbufout_add_cookie(ssh_session session);
|
||||
int generate_session_keys(ssh_session session);
|
||||
int sig_verify(ssh_session session, ssh_public_key pubkey,
|
||||
SIGNATURE *signature, unsigned char *digest, int size);
|
||||
/* returns 1 if server signature ok, 0 otherwise. The NEXT crypto is checked, not the current one */
|
||||
int signature_verify(ssh_session session,ssh_string signature);
|
||||
bignum make_string_bn(ssh_string string);
|
||||
ssh_string make_bignum_string(bignum num);
|
||||
|
||||
|
||||
#endif /* DH_H_ */
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
/*
|
||||
* This file is part of the SSH Library
|
||||
*
|
||||
* Copyright (c) 2011 by Aris Adamantiadis
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef ECDH_H_
|
||||
#define ECDH_H_
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifdef HAVE_LIBCRYPTO
|
||||
#ifdef HAVE_OPENSSL_ECDH_H
|
||||
|
||||
#ifdef HAVE_ECC
|
||||
#define HAVE_ECDH 1
|
||||
#endif
|
||||
|
||||
#endif /* HAVE_OPENSSL_ECDH_H */
|
||||
#endif /* HAVE_LIBCRYPTO */
|
||||
|
||||
int ssh_client_ecdh_init(ssh_session session);
|
||||
int ssh_client_ecdh_reply(ssh_session session, ssh_buffer packet);
|
||||
|
||||
#ifdef WITH_SERVER
|
||||
int ssh_server_ecdh_init(ssh_session session, ssh_buffer packet);
|
||||
#endif /* WITH_SERVER */
|
||||
|
||||
#endif /* ECDH_H_ */
|
||||
@@ -1,79 +0,0 @@
|
||||
/*
|
||||
* This file is part of the SSH Library
|
||||
*
|
||||
* Copyright (c) 2014 by Aris Adamantiadis
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef ED25519_H_
|
||||
#define ED25519_H_
|
||||
#include "libssh/priv.h"
|
||||
|
||||
/**
|
||||
* @defgroup ed25519 ed25519 API
|
||||
* @internal
|
||||
* @brief API for DJB's ed25519
|
||||
*
|
||||
* @{ */
|
||||
|
||||
#define ED25519_PK_LEN 32
|
||||
#define ED25519_SK_LEN 64
|
||||
#define ED25519_SIG_LEN 64
|
||||
|
||||
typedef uint8_t ed25519_pubkey[ED25519_PK_LEN];
|
||||
typedef uint8_t ed25519_privkey[ED25519_SK_LEN];
|
||||
typedef uint8_t ed25519_signature[ED25519_SIG_LEN];
|
||||
|
||||
/** @internal
|
||||
* @brief generate an ed25519 key pair
|
||||
* @param[out] pk generated public key
|
||||
* @param[out] sk generated secret key
|
||||
* @return 0 on success, -1 on error.
|
||||
* */
|
||||
int crypto_sign_ed25519_keypair(ed25519_pubkey pk, ed25519_privkey sk);
|
||||
|
||||
/** @internal
|
||||
* @brief sign a message with ed25519
|
||||
* @param[out] sm location to store the signed message.
|
||||
* Its length should be mlen + 64.
|
||||
* @param[out] smlen pointer to the size of the signed message
|
||||
* @param[in] m message to be signed
|
||||
* @param[in] mlen length of the message to be signed
|
||||
* @param[in] sk secret key to sign the message with
|
||||
* @return 0 on success.
|
||||
*/
|
||||
int crypto_sign_ed25519(
|
||||
unsigned char *sm,unsigned long long *smlen,
|
||||
const unsigned char *m,unsigned long long mlen,
|
||||
const ed25519_privkey sk);
|
||||
|
||||
/** @internal
|
||||
* @brief "open" and verify the signature of a signed message
|
||||
* @param[out] m location to store the verified message.
|
||||
* Its length should be equal to smlen.
|
||||
* @param[out] mlen pointer to the size of the verified message
|
||||
* @param[in] sm signed message to verify
|
||||
* @param[in] smlen length of the signed message to verify
|
||||
* @param[in] pk public key used to sign the message
|
||||
* @returns 0 on success (supposedly).
|
||||
*/
|
||||
int crypto_sign_ed25519_open(
|
||||
unsigned char *m,unsigned long long *mlen,
|
||||
const unsigned char *sm,unsigned long long smlen,
|
||||
const ed25519_pubkey pk);
|
||||
|
||||
/** @} */
|
||||
#endif /* ED25519_H_ */
|
||||
@@ -1,68 +0,0 @@
|
||||
/* $OpenBSD: fe25519.h,v 1.3 2013/12/09 11:03:45 markus Exp $ */
|
||||
|
||||
/*
|
||||
* Public Domain, Authors: Daniel J. Bernstein, Niels Duif, Tanja Lange,
|
||||
* Peter Schwabe, Bo-Yin Yang.
|
||||
* Copied from supercop-20130419/crypto_sign/ed25519/ref/fe25519.h
|
||||
*/
|
||||
|
||||
#ifndef FE25519_H
|
||||
#define FE25519_H
|
||||
|
||||
#include "libssh/priv.h"
|
||||
|
||||
#define fe25519 crypto_sign_ed25519_ref_fe25519
|
||||
#define fe25519_freeze crypto_sign_ed25519_ref_fe25519_freeze
|
||||
#define fe25519_unpack crypto_sign_ed25519_ref_fe25519_unpack
|
||||
#define fe25519_pack crypto_sign_ed25519_ref_fe25519_pack
|
||||
#define fe25519_iszero crypto_sign_ed25519_ref_fe25519_iszero
|
||||
#define fe25519_iseq_vartime crypto_sign_ed25519_ref_fe25519_iseq_vartime
|
||||
#define fe25519_cmov crypto_sign_ed25519_ref_fe25519_cmov
|
||||
#define fe25519_setone crypto_sign_ed25519_ref_fe25519_setone
|
||||
#define fe25519_setzero crypto_sign_ed25519_ref_fe25519_setzero
|
||||
#define fe25519_neg crypto_sign_ed25519_ref_fe25519_neg
|
||||
#define fe25519_getparity crypto_sign_ed25519_ref_fe25519_getparity
|
||||
#define fe25519_add crypto_sign_ed25519_ref_fe25519_add
|
||||
#define fe25519_sub crypto_sign_ed25519_ref_fe25519_sub
|
||||
#define fe25519_mul crypto_sign_ed25519_ref_fe25519_mul
|
||||
#define fe25519_square crypto_sign_ed25519_ref_fe25519_square
|
||||
#define fe25519_invert crypto_sign_ed25519_ref_fe25519_invert
|
||||
#define fe25519_pow2523 crypto_sign_ed25519_ref_fe25519_pow2523
|
||||
|
||||
typedef struct {
|
||||
uint32_t v[32];
|
||||
} fe25519;
|
||||
|
||||
void fe25519_freeze(fe25519 *r);
|
||||
|
||||
void fe25519_unpack(fe25519 *r, const unsigned char x[32]);
|
||||
|
||||
void fe25519_pack(unsigned char r[32], const fe25519 *x);
|
||||
|
||||
int fe25519_iszero(const fe25519 *x);
|
||||
|
||||
int fe25519_iseq_vartime(const fe25519 *x, const fe25519 *y);
|
||||
|
||||
void fe25519_cmov(fe25519 *r, const fe25519 *x, unsigned char b);
|
||||
|
||||
void fe25519_setone(fe25519 *r);
|
||||
|
||||
void fe25519_setzero(fe25519 *r);
|
||||
|
||||
void fe25519_neg(fe25519 *r, const fe25519 *x);
|
||||
|
||||
unsigned char fe25519_getparity(const fe25519 *x);
|
||||
|
||||
void fe25519_add(fe25519 *r, const fe25519 *x, const fe25519 *y);
|
||||
|
||||
void fe25519_sub(fe25519 *r, const fe25519 *x, const fe25519 *y);
|
||||
|
||||
void fe25519_mul(fe25519 *r, const fe25519 *x, const fe25519 *y);
|
||||
|
||||
void fe25519_square(fe25519 *r, const fe25519 *x);
|
||||
|
||||
void fe25519_invert(fe25519 *r, const fe25519 *x);
|
||||
|
||||
void fe25519_pow2523(fe25519 *r, const fe25519 *x);
|
||||
|
||||
#endif
|
||||
@@ -1,43 +0,0 @@
|
||||
/* $OpenBSD: ge25519.h,v 1.3 2013/12/09 11:03:45 markus Exp $ */
|
||||
|
||||
/*
|
||||
* Public Domain, Authors: Daniel J. Bernstein, Niels Duif, Tanja Lange,
|
||||
* Peter Schwabe, Bo-Yin Yang.
|
||||
* Copied from supercop-20130419/crypto_sign/ed25519/ref/ge25519.h
|
||||
*/
|
||||
|
||||
#ifndef GE25519_H
|
||||
#define GE25519_H
|
||||
|
||||
#include "fe25519.h"
|
||||
#include "sc25519.h"
|
||||
|
||||
#define ge25519 crypto_sign_ed25519_ref_ge25519
|
||||
#define ge25519_base crypto_sign_ed25519_ref_ge25519_base
|
||||
#define ge25519_unpackneg_vartime crypto_sign_ed25519_ref_unpackneg_vartime
|
||||
#define ge25519_pack crypto_sign_ed25519_ref_pack
|
||||
#define ge25519_isneutral_vartime crypto_sign_ed25519_ref_isneutral_vartime
|
||||
#define ge25519_double_scalarmult_vartime crypto_sign_ed25519_ref_double_scalarmult_vartime
|
||||
#define ge25519_scalarmult_base crypto_sign_ed25519_ref_scalarmult_base
|
||||
|
||||
typedef struct
|
||||
{
|
||||
fe25519 x;
|
||||
fe25519 y;
|
||||
fe25519 z;
|
||||
fe25519 t;
|
||||
} ge25519;
|
||||
|
||||
const ge25519 ge25519_base;
|
||||
|
||||
int ge25519_unpackneg_vartime(ge25519 *r, const unsigned char p[32]);
|
||||
|
||||
void ge25519_pack(unsigned char r[32], const ge25519 *p);
|
||||
|
||||
int ge25519_isneutral_vartime(const ge25519 *p);
|
||||
|
||||
void ge25519_double_scalarmult_vartime(ge25519 *r, const ge25519 *p1, const sc25519 *s1, const ge25519 *p2, const sc25519 *s2);
|
||||
|
||||
void ge25519_scalarmult_base(ge25519 *r, const sc25519 *s);
|
||||
|
||||
#endif
|
||||
@@ -1,45 +0,0 @@
|
||||
/*
|
||||
* This file is part of the SSH Library
|
||||
*
|
||||
* Copyright (c) 2013 by Aris Adamantiadis
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef GSSAPI_H_
|
||||
#define GSSAPI_H_
|
||||
|
||||
#include "config.h"
|
||||
#include "session.h"
|
||||
|
||||
/* all OID begin with the tag identifier + length */
|
||||
#define SSH_OID_TAG 06
|
||||
|
||||
typedef struct ssh_gssapi_struct *ssh_gssapi;
|
||||
|
||||
#ifdef WITH_SERVER
|
||||
int ssh_gssapi_handle_userauth(ssh_session session, const char *user, uint32_t n_oid, ssh_string *oids);
|
||||
SSH_PACKET_CALLBACK(ssh_packet_userauth_gssapi_token_server);
|
||||
SSH_PACKET_CALLBACK(ssh_packet_userauth_gssapi_mic);
|
||||
#endif /* WITH_SERVER */
|
||||
|
||||
SSH_PACKET_CALLBACK(ssh_packet_userauth_gssapi_token);
|
||||
SSH_PACKET_CALLBACK(ssh_packet_userauth_gssapi_token_client);
|
||||
SSH_PACKET_CALLBACK(ssh_packet_userauth_gssapi_response);
|
||||
|
||||
|
||||
int ssh_gssapi_auth_mic(ssh_session session);
|
||||
|
||||
#endif /* GSSAPI_H */
|
||||
@@ -1,50 +0,0 @@
|
||||
/*
|
||||
* This file is part of the SSH Library
|
||||
*
|
||||
* Copyright (c) 2009 by Aris Adamantiadis
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef KEX_H_
|
||||
#define KEX_H_
|
||||
|
||||
#include "libssh/priv.h"
|
||||
#include "libssh/callbacks.h"
|
||||
|
||||
#define SSH_KEX_METHODS 10
|
||||
|
||||
struct ssh_kex_struct {
|
||||
unsigned char cookie[16];
|
||||
char *methods[SSH_KEX_METHODS];
|
||||
};
|
||||
|
||||
SSH_PACKET_CALLBACK(ssh_packet_kexinit);
|
||||
#ifdef WITH_SSH1
|
||||
SSH_PACKET_CALLBACK(ssh_packet_publickey1);
|
||||
#endif
|
||||
|
||||
int ssh_send_kex(ssh_session session, int server_kex);
|
||||
void ssh_list_kex(struct ssh_kex_struct *kex);
|
||||
int set_client_kex(ssh_session session);
|
||||
int ssh_kex_select_methods(ssh_session session);
|
||||
int verify_existing_algo(int algo, const char *name);
|
||||
char **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_description(uint32_t algo);
|
||||
|
||||
#endif /* KEX_H_ */
|
||||
33
include/libssh/keyfiles.h
Normal file
33
include/libssh/keyfiles.h
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* This file is part of the SSH Library
|
||||
*
|
||||
* Copyright (c) 2009 by Aris Adamantiadis
|
||||
*
|
||||
* The SSH Library is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation; either version 2.1 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* The SSH Library is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with the SSH Library; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
|
||||
* MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef KEYFILES_H_
|
||||
#define KEYFILES_H_
|
||||
|
||||
/* in keyfiles.c */
|
||||
|
||||
ssh_private_key _privatekey_from_file(void *session, const char *filename,
|
||||
int type);
|
||||
ssh_string try_publickey_from_file(ssh_session session,
|
||||
struct ssh_keys_struct keytab,
|
||||
char **privkeyfile, int *type);
|
||||
|
||||
#endif /* KEYFILES_H_ */
|
||||
@@ -3,19 +3,20 @@
|
||||
*
|
||||
* Copyright (c) 2009 by Aris Adamantiadis
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
* The SSH Library is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation; either version 2.1 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
* The SSH Library is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with the SSH Library; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
|
||||
* MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef KEYS_H_
|
||||
@@ -48,9 +49,36 @@ struct ssh_private_key_struct {
|
||||
#endif
|
||||
};
|
||||
|
||||
typedef struct signature_struct {
|
||||
int type;
|
||||
#ifdef HAVE_LIBGCRYPT
|
||||
gcry_sexp_t dsa_sign;
|
||||
gcry_sexp_t rsa_sign;
|
||||
#elif defined HAVE_LIBCRYPTO
|
||||
DSA_SIG *dsa_sign;
|
||||
ssh_string rsa_sign;
|
||||
#endif
|
||||
} SIGNATURE;
|
||||
|
||||
const char *ssh_type_to_char(int type);
|
||||
int ssh_type_from_name(const char *name);
|
||||
ssh_buffer ssh_userauth_build_digest(ssh_session session, ssh_message msg, char *service);
|
||||
|
||||
ssh_private_key privatekey_make_dss(ssh_session session, ssh_buffer buffer);
|
||||
ssh_private_key privatekey_make_rsa(ssh_session session, ssh_buffer buffer,
|
||||
const char *type);
|
||||
ssh_private_key privatekey_from_string(ssh_session session, ssh_string privkey_s);
|
||||
|
||||
ssh_public_key publickey_make_dss(ssh_session session, ssh_buffer buffer);
|
||||
ssh_public_key publickey_make_rsa(ssh_session session, ssh_buffer buffer, int type);
|
||||
ssh_public_key publickey_from_string(ssh_session session, ssh_string pubkey_s);
|
||||
SIGNATURE *signature_from_string(ssh_session session, ssh_string signature,ssh_public_key pubkey,int needed_type);
|
||||
void signature_free(SIGNATURE *sign);
|
||||
ssh_string ssh_do_sign_with_agent(struct ssh_session_struct *session,
|
||||
struct ssh_buffer_struct *buf, struct ssh_public_key_struct *publickey);
|
||||
ssh_string ssh_do_sign(ssh_session session,ssh_buffer sigbuf,
|
||||
ssh_private_key privatekey);
|
||||
ssh_string ssh_sign_session_id(ssh_session session, ssh_private_key privatekey);
|
||||
ssh_string ssh_encrypt_rsa1(ssh_session session, ssh_string data, ssh_public_key key);
|
||||
|
||||
#endif /* KEYS_H_ */
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
/*
|
||||
* This file is part of the SSH Library
|
||||
*
|
||||
* Copyright (c) 20014 by Aris Adamantiadis <aris@badcode.be>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
|
||||
#ifndef KNOWNHOSTS_H_
|
||||
#define KNOWNHOSTS_H_
|
||||
|
||||
char **ssh_knownhosts_algorithms(ssh_session session);
|
||||
|
||||
#endif /* KNOWNHOSTS_H_ */
|
||||
@@ -1,120 +0,0 @@
|
||||
/*
|
||||
* This file is part of the SSH Library
|
||||
*
|
||||
* Copyright (c) 2010 by Aris Adamantiadis
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/* Since libssh.h includes legacy.h, it's important that libssh.h is included
|
||||
* first. we don't define LEGACY_H now because we want it to be defined when
|
||||
* included from libssh.h
|
||||
* All function calls declared in this header are deprecated and meant to be
|
||||
* removed in future.
|
||||
*/
|
||||
|
||||
#ifndef LEGACY_H_
|
||||
#define LEGACY_H_
|
||||
|
||||
typedef struct ssh_private_key_struct* ssh_private_key;
|
||||
typedef struct ssh_public_key_struct* ssh_public_key;
|
||||
|
||||
LIBSSH_API int ssh_auth_list(ssh_session session);
|
||||
LIBSSH_API int ssh_userauth_offer_pubkey(ssh_session session, const char *username, int type, ssh_string publickey);
|
||||
LIBSSH_API int ssh_userauth_pubkey(ssh_session session, const char *username, ssh_string publickey, ssh_private_key privatekey);
|
||||
#ifndef _WIN32
|
||||
LIBSSH_API int ssh_userauth_agent_pubkey(ssh_session session, const char *username,
|
||||
ssh_public_key publickey);
|
||||
#endif
|
||||
LIBSSH_API int ssh_userauth_autopubkey(ssh_session session, const char *passphrase);
|
||||
LIBSSH_API int ssh_userauth_privatekey_file(ssh_session session, const char *username,
|
||||
const char *filename, const char *passphrase);
|
||||
|
||||
SSH_DEPRECATED LIBSSH_API void buffer_free(ssh_buffer buffer);
|
||||
SSH_DEPRECATED LIBSSH_API void *buffer_get(ssh_buffer buffer);
|
||||
SSH_DEPRECATED LIBSSH_API uint32_t buffer_get_len(ssh_buffer buffer);
|
||||
SSH_DEPRECATED LIBSSH_API ssh_buffer buffer_new(void);
|
||||
|
||||
SSH_DEPRECATED LIBSSH_API ssh_channel channel_accept_x11(ssh_channel channel, int timeout_ms);
|
||||
SSH_DEPRECATED LIBSSH_API int channel_change_pty_size(ssh_channel channel,int cols,int rows);
|
||||
SSH_DEPRECATED LIBSSH_API ssh_channel channel_forward_accept(ssh_session session, int timeout_ms);
|
||||
SSH_DEPRECATED LIBSSH_API int channel_close(ssh_channel channel);
|
||||
SSH_DEPRECATED LIBSSH_API int channel_forward_cancel(ssh_session session, const char *address, int port);
|
||||
SSH_DEPRECATED LIBSSH_API int channel_forward_listen(ssh_session session, const char *address, int port, int *bound_port);
|
||||
SSH_DEPRECATED LIBSSH_API void channel_free(ssh_channel channel);
|
||||
SSH_DEPRECATED LIBSSH_API int channel_get_exit_status(ssh_channel channel);
|
||||
SSH_DEPRECATED LIBSSH_API ssh_session channel_get_session(ssh_channel channel);
|
||||
SSH_DEPRECATED LIBSSH_API int channel_is_closed(ssh_channel channel);
|
||||
SSH_DEPRECATED LIBSSH_API int channel_is_eof(ssh_channel channel);
|
||||
SSH_DEPRECATED LIBSSH_API int channel_is_open(ssh_channel channel);
|
||||
SSH_DEPRECATED LIBSSH_API ssh_channel channel_new(ssh_session session);
|
||||
SSH_DEPRECATED LIBSSH_API int channel_open_forward(ssh_channel channel, const char *remotehost,
|
||||
int remoteport, const char *sourcehost, int localport);
|
||||
SSH_DEPRECATED LIBSSH_API int channel_open_session(ssh_channel channel);
|
||||
SSH_DEPRECATED LIBSSH_API int channel_poll(ssh_channel channel, int is_stderr);
|
||||
SSH_DEPRECATED LIBSSH_API int channel_read(ssh_channel channel, void *dest, uint32_t count, int is_stderr);
|
||||
|
||||
SSH_DEPRECATED LIBSSH_API int channel_read_buffer(ssh_channel channel, ssh_buffer buffer, uint32_t count,
|
||||
int is_stderr);
|
||||
|
||||
SSH_DEPRECATED LIBSSH_API int channel_read_nonblocking(ssh_channel channel, void *dest, uint32_t count,
|
||||
int is_stderr);
|
||||
SSH_DEPRECATED LIBSSH_API int channel_request_env(ssh_channel channel, const char *name, const char *value);
|
||||
SSH_DEPRECATED LIBSSH_API int channel_request_exec(ssh_channel channel, const char *cmd);
|
||||
SSH_DEPRECATED LIBSSH_API int channel_request_pty(ssh_channel channel);
|
||||
SSH_DEPRECATED LIBSSH_API int channel_request_pty_size(ssh_channel channel, const char *term,
|
||||
int cols, int rows);
|
||||
SSH_DEPRECATED LIBSSH_API int channel_request_shell(ssh_channel channel);
|
||||
SSH_DEPRECATED LIBSSH_API int channel_request_send_signal(ssh_channel channel, const char *signum);
|
||||
SSH_DEPRECATED LIBSSH_API int channel_request_sftp(ssh_channel channel);
|
||||
SSH_DEPRECATED LIBSSH_API int channel_request_subsystem(ssh_channel channel, const char *subsystem);
|
||||
SSH_DEPRECATED LIBSSH_API int channel_request_x11(ssh_channel channel, int single_connection, const char *protocol,
|
||||
const char *cookie, int screen_number);
|
||||
SSH_DEPRECATED LIBSSH_API int channel_send_eof(ssh_channel channel);
|
||||
SSH_DEPRECATED LIBSSH_API int channel_select(ssh_channel *readchans, ssh_channel *writechans, ssh_channel *exceptchans, struct
|
||||
timeval * timeout);
|
||||
SSH_DEPRECATED LIBSSH_API void channel_set_blocking(ssh_channel channel, int blocking);
|
||||
SSH_DEPRECATED LIBSSH_API int channel_write(ssh_channel channel, const void *data, uint32_t len);
|
||||
|
||||
LIBSSH_API void privatekey_free(ssh_private_key prv);
|
||||
LIBSSH_API ssh_private_key privatekey_from_file(ssh_session session, const char *filename,
|
||||
int type, const char *passphrase);
|
||||
LIBSSH_API void publickey_free(ssh_public_key key);
|
||||
LIBSSH_API int ssh_publickey_to_file(ssh_session session, const char *file,
|
||||
ssh_string pubkey, int type);
|
||||
LIBSSH_API ssh_string publickey_from_file(ssh_session session, const char *filename,
|
||||
int *type);
|
||||
LIBSSH_API ssh_public_key publickey_from_privatekey(ssh_private_key prv);
|
||||
LIBSSH_API ssh_string publickey_to_string(ssh_public_key key);
|
||||
LIBSSH_API int ssh_try_publickey_from_file(ssh_session session, const char *keyfile,
|
||||
ssh_string *publickey, int *type);
|
||||
LIBSSH_API enum ssh_keytypes_e ssh_privatekey_type(ssh_private_key privatekey);
|
||||
|
||||
LIBSSH_API ssh_string ssh_get_pubkey(ssh_session session);
|
||||
|
||||
LIBSSH_API ssh_message ssh_message_retrieve(ssh_session session, uint32_t packettype);
|
||||
LIBSSH_API ssh_public_key ssh_message_auth_publickey(ssh_message msg);
|
||||
|
||||
SSH_DEPRECATED LIBSSH_API void string_burn(ssh_string str);
|
||||
SSH_DEPRECATED LIBSSH_API ssh_string string_copy(ssh_string str);
|
||||
SSH_DEPRECATED LIBSSH_API void *string_data(ssh_string str);
|
||||
SSH_DEPRECATED LIBSSH_API int string_fill(ssh_string str, const void *data, size_t len);
|
||||
SSH_DEPRECATED LIBSSH_API void string_free(ssh_string str);
|
||||
SSH_DEPRECATED LIBSSH_API ssh_string string_from_char(const char *what);
|
||||
SSH_DEPRECATED LIBSSH_API size_t string_len(ssh_string str);
|
||||
SSH_DEPRECATED LIBSSH_API ssh_string string_new(size_t size);
|
||||
SSH_DEPRECATED LIBSSH_API char *string_to_char(ssh_string str);
|
||||
|
||||
#endif /* LEGACY_H_ */
|
||||
@@ -1,104 +0,0 @@
|
||||
/*
|
||||
* This file is part of the SSH Library
|
||||
*
|
||||
* Copyright (c) 2009 by Aris Adamantiadis
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef LIBCRYPTO_H_
|
||||
#define LIBCRYPTO_H_
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifdef HAVE_LIBCRYPTO
|
||||
|
||||
#include <openssl/dsa.h>
|
||||
#include <openssl/rsa.h>
|
||||
#include <openssl/sha.h>
|
||||
#include <openssl/md5.h>
|
||||
#include <openssl/hmac.h>
|
||||
#ifdef HAVE_OPENSSL_ECC
|
||||
#include <openssl/evp.h>
|
||||
#endif
|
||||
|
||||
typedef SHA_CTX* SHACTX;
|
||||
typedef SHA256_CTX* SHA256CTX;
|
||||
typedef SHA512_CTX* SHA384CTX;
|
||||
typedef SHA512_CTX* SHA512CTX;
|
||||
typedef MD5_CTX* MD5CTX;
|
||||
typedef HMAC_CTX* HMACCTX;
|
||||
#ifdef HAVE_ECC
|
||||
typedef EVP_MD_CTX *EVPCTX;
|
||||
#else
|
||||
typedef void *EVPCTX;
|
||||
#endif
|
||||
|
||||
#define SHA_DIGEST_LEN SHA_DIGEST_LENGTH
|
||||
#define SHA256_DIGEST_LEN SHA256_DIGEST_LENGTH
|
||||
#define SHA384_DIGEST_LEN SHA384_DIGEST_LENGTH
|
||||
#define SHA512_DIGEST_LEN SHA512_DIGEST_LENGTH
|
||||
#ifdef MD5_DIGEST_LEN
|
||||
#undef MD5_DIGEST_LEN
|
||||
#endif
|
||||
#define MD5_DIGEST_LEN MD5_DIGEST_LENGTH
|
||||
|
||||
#ifdef HAVE_OPENSSL_ECC
|
||||
#define EVP_DIGEST_LEN EVP_MAX_MD_SIZE
|
||||
#endif
|
||||
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/opensslv.h>
|
||||
#define OPENSSL_0_9_7b 0x0090702fL
|
||||
#if (OPENSSL_VERSION_NUMBER <= OPENSSL_0_9_7b)
|
||||
#define BROKEN_AES_CTR
|
||||
#endif
|
||||
typedef BIGNUM* bignum;
|
||||
typedef BN_CTX* bignum_CTX;
|
||||
|
||||
#define bignum_new() BN_new()
|
||||
#define bignum_free(num) BN_clear_free(num)
|
||||
#define bignum_set_word(bn,n) BN_set_word(bn,n)
|
||||
#define bignum_bin2bn(bn,datalen,data) BN_bin2bn(bn,datalen,data)
|
||||
#define bignum_bn2dec(num) BN_bn2dec(num)
|
||||
#define bignum_dec2bn(bn,data) BN_dec2bn(data,bn)
|
||||
#define bignum_bn2hex(num) BN_bn2hex(num)
|
||||
#define bignum_rand(rnd, bits, top, bottom) BN_rand(rnd,bits,top,bottom)
|
||||
#define bignum_ctx_new() BN_CTX_new()
|
||||
#define bignum_ctx_free(num) BN_CTX_free(num)
|
||||
#define bignum_mod_exp(dest,generator,exp,modulo,ctx) BN_mod_exp(dest,generator,exp,modulo,ctx)
|
||||
#define bignum_num_bytes(num) BN_num_bytes(num)
|
||||
#define bignum_num_bits(num) BN_num_bits(num)
|
||||
#define bignum_is_bit_set(num,bit) BN_is_bit_set(num,bit)
|
||||
#define bignum_bn2bin(num,ptr) BN_bn2bin(num,ptr)
|
||||
#define bignum_cmp(num1,num2) BN_cmp(num1,num2)
|
||||
|
||||
SHA256CTX sha256_init(void);
|
||||
void sha256_update(SHA256CTX c, const void *data, unsigned long len);
|
||||
void sha256_final(unsigned char *md, SHA256CTX c);
|
||||
|
||||
SHA384CTX sha384_init(void);
|
||||
void sha384_update(SHA384CTX c, const void *data, unsigned long len);
|
||||
void sha384_final(unsigned char *md, SHA384CTX c);
|
||||
|
||||
SHA512CTX sha512_init(void);
|
||||
void sha512_update(SHA512CTX c, const void *data, unsigned long len);
|
||||
void sha512_final(unsigned char *md, SHA512CTX c);
|
||||
|
||||
struct ssh_cipher_struct *ssh_get_ciphertab(void);
|
||||
|
||||
#endif /* HAVE_LIBCRYPTO */
|
||||
|
||||
#endif /* LIBCRYPTO_H_ */
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user